aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPAlertSheets.h32
-rw-r--r--Source/SPAlertSheets.m148
-rw-r--r--Source/SPCustomQuery.h1
-rw-r--r--Source/SPCustomQuery.m27
-rw-r--r--Source/SPDatabaseDocument.m138
-rw-r--r--Source/SPDatabaseStructure.m18
-rw-r--r--Source/SPDotExporter.m4
-rw-r--r--Source/SPEditorPreferencePane.m25
-rw-r--r--Source/SPExtendedTableInfo.m140
-rw-r--r--Source/SPFavoritesOutlineView.h1
-rw-r--r--Source/SPNavigatorController.m14
-rw-r--r--Source/SPProcessListController.m70
-rw-r--r--Source/SPProcessListControllerDataSource.h35
-rw-r--r--Source/SPProcessListControllerDataSource.m98
-rw-r--r--Source/SPSQLExporter.m6
-rw-r--r--Source/SPTableContent.m2
-rw-r--r--Source/SPTableData.m12
-rw-r--r--Source/SPTableFieldValidation.m2
-rw-r--r--Source/SPTableRelations.m6
-rw-r--r--Source/SPTableStructure.m2
-rw-r--r--Source/SPTableStructureDelegate.m4
-rw-r--r--Source/SPTableStructureLoading.m2
22 files changed, 473 insertions, 314 deletions
diff --git a/Source/SPAlertSheets.h b/Source/SPAlertSheets.h
index ab6f1812..fd5b46cf 100644
--- a/Source/SPAlertSheets.h
+++ b/Source/SPAlertSheets.h
@@ -30,6 +30,23 @@
//
// More info at <http://code.google.com/p/sequel-pro/>
+@interface SPAlertSheets : NSObject
+
++ (void)beginWaitingAlertSheetWithTitle:(NSString *)title
+ defaultButton:(NSString *)defaultButton
+ alternateButton:(NSString *)alternateButton
+ otherButton:(NSString *)otherButton
+ alertStyle:(NSAlertStyle)alertStyle
+ docWindow:(NSWindow *)docWindow
+ modalDelegate:(id)modalDelegate
+ didEndSelector:(SEL)didEndSelector
+ contextInfo:(void *)contextInfo
+ msg:(NSString *)msg
+ infoText:(NSString *)infoText
+ returnCode:(NSInteger *)returnCode;
+
+@end
+
void SPBeginAlertSheet(
NSString *title,
NSString *defaultButton,
@@ -41,18 +58,3 @@ void SPBeginAlertSheet(
void *contextInfo,
NSString *msg
);
-
-void SPBeginWaitingAlertSheet(
- NSString *title,
- NSString *defaultButton,
- NSString *alternateButton,
- NSString *otherButton,
-NSAlertStyle alertStyle,
- NSWindow *docWindow,
- id modalDelegate,
- SEL didEndSelector,
- void *contextInfo,
- NSString *msg,
- NSString *infoText,
- NSInteger *returnCode
-);
diff --git a/Source/SPAlertSheets.m b/Source/SPAlertSheets.m
index fe45741e..f30e6d33 100644
--- a/Source/SPAlertSheets.m
+++ b/Source/SPAlertSheets.m
@@ -31,54 +31,9 @@
// More info at <http://code.google.com/p/sequel-pro/>
#import "SPAlertSheets.h"
+#import "SPMainThreadTrampoline.h"
-/**
- * Provide a simple alias of NSBeginAlertSheet, with a few differences:
- * - printf-type format strings are no longer supported within the "msg"
- * message text argument, preventing access of random stack areas for
- * error text which contains inadvertant printf formatting.
- * - The didDismissSelector is no longer supported
- * - The sheet no longer needs to be orderOut:ed after use
- * - The alert is always shown on the main thread.
- */
-void SPBeginAlertSheet(
- NSString *title,
- NSString *defaultButton,
- NSString *alternateButton,
- NSString *otherButton,
- NSWindow *docWindow,
- id modalDelegate,
- SEL didEndSelector,
- void *contextInfo,
- NSString *msg)
-{
- NSButton *aButton;
-
- // Set up an NSAlert with the supplied details
- NSAlert *alert = [[[NSAlert alloc] init] autorelease];
- [alert setMessageText:title];
- aButton = [alert addButtonWithTitle:defaultButton];
- [aButton setTag:NSAlertDefaultReturn];
-
- // Add 'alternate' and 'other' buttons as appropriate
- if (alternateButton) {
- aButton = [alert addButtonWithTitle:alternateButton];
- [aButton setTag:NSAlertAlternateReturn];
- }
- if (otherButton) {
- aButton = [alert addButtonWithTitle:otherButton];
- [aButton setTag:NSAlertOtherReturn];
- }
-
- // Set the informative message if supplied
- if (msg) [alert setInformativeText:msg];
-
- // Run the alert on the main thread
- [[alert onMainThread] beginSheetModalForWindow:docWindow modalDelegate:modalDelegate didEndSelector:didEndSelector contextInfo:contextInfo];
-
- // Ensure the alerting window is frontmost
- [[docWindow onMainThread] makeKeyWindow];
-}
+@implementation SPAlertSheets
/**
* Provide a simple alias of a NSApp-wide modal NSBeginAlertSheet which waits
@@ -91,21 +46,36 @@ void SPBeginAlertSheet(
* - The sheet no longer needs to be orderOut:ed after use
* - The alert is always shown on the main thread.
*/
-void SPBeginWaitingAlertSheet(
- NSString *title,
- NSString *defaultButton,
- NSString *alternateButton,
- NSString *otherButton,
- NSAlertStyle alertStyle,
- NSWindow *docWindow,
- id modalDelegate,
- SEL didEndSelector,
- void *contextInfo,
- NSString *msg,
- NSString *infoText,
- NSInteger *returnCode)
++ (void)beginWaitingAlertSheetWithTitle:(NSString *)title
+ defaultButton:(NSString *)defaultButton
+ alternateButton:(NSString *)alternateButton
+ otherButton:(NSString *)otherButton
+ alertStyle:(NSAlertStyle)alertStyle
+ docWindow:(NSWindow *)docWindow
+ modalDelegate:(id)modalDelegate
+ didEndSelector:(SEL)didEndSelector
+ contextInfo:(void *)contextInfo
+ msg:(NSString *)msg
+ infoText:(NSString *)infoText
+ returnCode:(NSInteger *)returnCode
{
+ // Ensure execution on the main thread
+ if (![[NSThread currentThread] isMainThread]) {
+ return [[self onMainThread] beginWaitingAlertSheetWithTitle:title
+ defaultButton:defaultButton
+ alternateButton:alternateButton
+ otherButton:otherButton
+ alertStyle:alertStyle
+ docWindow:docWindow
+ modalDelegate:modalDelegate
+ didEndSelector:didEndSelector
+ contextInfo:contextInfo
+ msg:msg
+ infoText:infoText
+ returnCode:returnCode];
+ }
+
NSButton *aButton;
// Initialize returnCode with a value which can't be returned as
@@ -142,10 +112,10 @@ void SPBeginWaitingAlertSheet(
if (msg) [alert setMessageText:msg];
// Run the alert on the main thread
- [[alert onMainThread] beginSheetModalForWindow:docWindow modalDelegate:modalDelegate didEndSelector:didEndSelector contextInfo:contextInfo];
+ [alert beginSheetModalForWindow:docWindow modalDelegate:modalDelegate didEndSelector:didEndSelector contextInfo:contextInfo];
// wait for the sheet
- NSModalSession session = [[NSApp onMainThread] beginModalSessionForWindow:[alert window]];
+ NSModalSession session = [NSApp beginModalSessionForWindow:[alert window]];
for (;;) {
// Since the returnCode can only be -1, 0, or 1
@@ -169,6 +139,56 @@ void SPBeginWaitingAlertSheet(
}
- [[NSApp onMainThread] endModalSession:session];
- [[NSApp onMainThread] endSheet:[alert window]];
+ [NSApp endModalSession:session];
+ [NSApp endSheet:[alert window]];
+}
+
+@end
+
+/**
+ * Provide a simple alias of NSBeginAlertSheet, with a few differences:
+ * - printf-type format strings are no longer supported within the "msg"
+ * message text argument, preventing access of random stack areas for
+ * error text which contains inadvertant printf formatting.
+ * - The didDismissSelector is no longer supported
+ * - The sheet no longer needs to be orderOut:ed after use
+ * - The alert is always shown on the main thread.
+ */
+void SPBeginAlertSheet(
+ NSString *title,
+ NSString *defaultButton,
+ NSString *alternateButton,
+ NSString *otherButton,
+ NSWindow *docWindow,
+ id modalDelegate,
+ SEL didEndSelector,
+ void *contextInfo,
+ NSString *msg)
+{
+ NSButton *aButton;
+
+ // Set up an NSAlert with the supplied details
+ NSAlert *alert = [[[NSAlert alloc] init] autorelease];
+ [alert setMessageText:title];
+ aButton = [alert addButtonWithTitle:defaultButton];
+ [aButton setTag:NSAlertDefaultReturn];
+
+ // Add 'alternate' and 'other' buttons as appropriate
+ if (alternateButton) {
+ aButton = [alert addButtonWithTitle:alternateButton];
+ [aButton setTag:NSAlertAlternateReturn];
+ }
+ if (otherButton) {
+ aButton = [alert addButtonWithTitle:otherButton];
+ [aButton setTag:NSAlertOtherReturn];
+ }
+
+ // Set the informative message if supplied
+ if (msg) [alert setInformativeText:msg];
+
+ // Run the alert on the main thread
+ [[alert onMainThread] beginSheetModalForWindow:docWindow modalDelegate:modalDelegate didEndSelector:didEndSelector contextInfo:contextInfo];
+
+ // Ensure the alerting window is frontmost
+ [[docWindow onMainThread] makeKeyWindow];
}
diff --git a/Source/SPCustomQuery.h b/Source/SPCustomQuery.h
index ffca796b..a9dc3180 100644
--- a/Source/SPCustomQuery.h
+++ b/Source/SPCustomQuery.h
@@ -91,6 +91,7 @@
IBOutlet SPCopyTable *customQueryView;
IBOutlet NSScrollView *customQueryScrollView;
IBOutlet id errorText;
+ IBOutlet NSTextField *errorTextTitle;
IBOutlet NSScrollView *errorTextScrollView;
IBOutlet id affectedRowsText;
IBOutlet id valueSheet;
diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m
index b5a99a37..9090dd1a 100644
--- a/Source/SPCustomQuery.m
+++ b/Source/SPCustomQuery.m
@@ -574,6 +574,7 @@
}
[tableDocumentInstance startTaskWithDescription:taskString];
+ [errorTextTitle setStringValue:NSLocalizedString(@"Query Status", @"Query Status")];
[errorText setString:taskString];
[affectedRowsText setStringValue:@""];
@@ -740,21 +741,26 @@
[errors appendFormat:NSLocalizedString(@"[ERROR in query %ld] %@\n", @"error text when multiple custom query failed"),
(long)(i+1),
errorString];
+ [[errorTextTitle onMainThread] setStringValue:NSLocalizedString(@"Last Error Message", @"Last Error Message")];
[[errorText onMainThread] setString:errors];
// ask the user to continue after detecting an error
if (![mySQLConnection lastQueryWasCancelled]) {
[tableDocumentInstance setTaskIndicatorShouldAnimate:NO];
- SPBeginWaitingAlertSheet(@"title",
- NSLocalizedString(@"Run All", @"run all button"), NSLocalizedString(@"Continue", @"continue button"), NSLocalizedString(@"Stop", @"stop button"),
- NSWarningAlertStyle, [tableDocumentInstance parentWindow], self,
- @selector(sheetDidEnd:returnCode:contextInfo:),
- @"runAllContinueStopSheet",
- NSLocalizedString(@"MySQL Error", @"mysql error message"),
- [mySQLConnection lastErrorMessage],
- &runAllContinueStopSheetReturnCode
- );
+ [SPAlertSheets beginWaitingAlertSheetWithTitle:@"title"
+ defaultButton:NSLocalizedString(@"Run All", @"run all button")
+ alternateButton:NSLocalizedString(@"Continue", @"continue button")
+ otherButton:NSLocalizedString(@"Stop", @"stop button")
+ alertStyle:NSWarningAlertStyle
+ docWindow:[tableDocumentInstance parentWindow]
+ modalDelegate:self
+ didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
+ contextInfo:@"runAllContinueStopSheet"
+ msg:NSLocalizedString(@"MySQL Error", @"mysql error message")
+ infoText:[mySQLConnection lastErrorMessage]
+ returnCode:&runAllContinueStopSheetReturnCode];
+
[tableDocumentInstance setTaskIndicatorShouldAnimate:YES];
switch (runAllContinueStopSheetReturnCode) {
@@ -1309,6 +1315,7 @@
#ifndef SP_REFACTOR
// set the error text
+ [errorTextTitle setStringValue:NSLocalizedString(@"Last Error Message", @"Last Error Message")];
[errorText setString:[errorsString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
[[errorTextScrollView verticalScroller] setFloatValue:1.0f];
#endif
@@ -1370,6 +1377,7 @@
}
} else if ( [errorsString length] && queryIsTableSorter ) {
+ [errorTextTitle setStringValue:NSLocalizedString(@"Last Error Message", @"Last Error Message")];
[errorText setString:NSLocalizedString(@"Couldn't sort column.", @"text shown if an error occured while sorting the result table")];
NSBeep();
} else {
@@ -1976,6 +1984,7 @@
NSString *tableForColumn = [columnDefinition objectForKey:@"org_table"];
if(!tableForColumn || ![tableForColumn length]) {
+ [errorTextTitle setStringValue:NSLocalizedString(@"Last Error Message", @"Last Error Message")];
[errorText setString:[NSString stringWithFormat:NSLocalizedString(@"Couldn't identify field origin unambiguously. The column '%@' contains data from more than one table.", @"Custom Query result editing error - could not identify a corresponding column"), [columnDefinition objectForKey:@"name"]]];
NSBeep();
return;
diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m
index fc4fd335..39d67245 100644
--- a/Source/SPDatabaseDocument.m
+++ b/Source/SPDatabaseDocument.m
@@ -3171,15 +3171,18 @@ static NSString *SPRenameDatabaseAction = @"SPRenameDatabase";
if(!spf || ![spf count] || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) {
- SPBeginWaitingAlertSheet(@"title",
- NSLocalizedString(@"OK", @"OK button"), NSLocalizedString(@"Ignore", @"ignore button"), nil,
- NSCriticalAlertStyle, parentWindow, self,
- @selector(sheetDidEnd:returnCode:contextInfo:),
- @"saveDocPrefSheetStatus",
- [NSString stringWithFormat:NSLocalizedString(@"Error while reading connection data file", @"error while reading connection data file")],
- [NSString stringWithFormat:NSLocalizedString(@"Connection data file “%@” couldn't be read. Please try to save the document under a different name.", @"message error while reading connection data file and suggesting to save it under a differnet name"), [fileName lastPathComponent]],
- &saveDocPrefSheetStatus
- );
+ [SPAlertSheets beginWaitingAlertSheetWithTitle:@"title"
+ defaultButton:NSLocalizedString(@"OK", @"OK button")
+ alternateButton:NSLocalizedString(@"Ignore", @"ignore button")
+ otherButton:nil
+ alertStyle:NSCriticalAlertStyle
+ docWindow:parentWindow
+ modalDelegate:self
+ didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
+ contextInfo:@"saveDocPrefSheetStatus"
+ msg:[NSString stringWithFormat:NSLocalizedString(@"Error while reading connection data file", @"error while reading connection data file")]
+ infoText:[NSString stringWithFormat:NSLocalizedString(@"Connection data file “%@” couldn't be read. Please try to save the document under a different name.", @"message error while reading connection data file and suggesting to save it under a differnet name"), [fileName lastPathComponent]]
+ returnCode:&saveDocPrefSheetStatus];
if (spf) [spf release];
if(saveDocPrefSheetStatus == NSAlertAlternateReturn)
@@ -3416,17 +3419,19 @@ static NSString *SPRenameDatabaseAction = @"SPRenameDatabase";
*/
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
+ SEL action = [menuItem action];
+
if ([menuItem menu] == chooseDatabaseButton) {
return (_isConnected && databaseListIsSelectable);
}
if (!_isConnected || _isWorkingLevel) {
- return ([menuItem action] == @selector(newWindow:) ||
- [menuItem action] == @selector(terminate:) ||
- [menuItem action] == @selector(closeTab:));
+ return (action == @selector(newWindow:) ||
+ action == @selector(terminate:) ||
+ action == @selector(closeTab:));
}
- if ([menuItem action] == @selector(openCurrentConnectionInNewWindow:))
+ if (action == @selector(openCurrentConnectionInNewWindow:))
{
if ([self isUntitled]) {
[menuItem setTitle:NSLocalizedString(@"Open in New Window", @"menu item open in new window")];
@@ -3439,12 +3444,12 @@ static NSString *SPRenameDatabaseAction = @"SPRenameDatabase";
}
// Data export
- if ([menuItem action] == @selector(export:)) {
+ if (action == @selector(export:)) {
return (([self database] != nil) && ([[tablesListInstance tables] count] > 1));
}
// Selected tables data export
- if ([menuItem action] == @selector(exportSelectedTablesAs:)) {
+ if (action == @selector(exportSelectedTablesAs:)) {
NSInteger tag = [menuItem tag];
NSInteger type = [tablesListInstance tableType];
@@ -3470,39 +3475,56 @@ static NSString *SPRenameDatabaseAction = @"SPRenameDatabase";
return (enable && (tag == SPSQLExport));
}
}
+
+ // Can only be enabled on mysql 4.1+
+ if (action == @selector(alterDatabase:)) {
+ return (([self database] != nil) && [serverSupport supportsPost41CharacterSetHandling]);
+ }
+
+ // Table specific actions
+ if (action == @selector(viewStructure:) ||
+ action == @selector(viewContent:) ||
+ action == @selector(viewRelations:) ||
+ action == @selector(viewStatus:) ||
+ action == @selector(viewTriggers:))
+ {
+ return [self database] != nil && [[[tablesListInstance valueForKeyPath:@"tablesListView"] selectedRowIndexes] count];
+
+ }
- if ([menuItem action] == @selector(import:) ||
- [menuItem action] == @selector(removeDatabase:) ||
- [menuItem action] == @selector(copyDatabase:) ||
- [menuItem action] == @selector(renameDatabase:) ||
- [menuItem action] == @selector(openDatabaseInNewTab:) ||
- [menuItem action] == @selector(refreshTables:))
+ // Database specific actions
+ if (action == @selector(import:) ||
+ action == @selector(removeDatabase:) ||
+ action == @selector(copyDatabase:) ||
+ action == @selector(renameDatabase:) ||
+ action == @selector(openDatabaseInNewTab:) ||
+ action == @selector(refreshTables:))
{
- return ([self database] != nil);
+ return [self database] != nil;
}
- if ([menuItem action] == @selector(importFromClipboard:))
- {
+ if (action == @selector(importFromClipboard:)){
return [self database] && [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObjects:NSStringPboardType, nil]];
-
}
// Change "Save Query/Queries" menu item title dynamically
// and disable it if no query in the editor
- if ([menuItem action] == @selector(saveConnectionSheet:) && [menuItem tag] == 0) {
- if([customQueryInstance numberOfQueries] < 1) {
+ if (action == @selector(saveConnectionSheet:) && [menuItem tag] == 0) {
+ if ([customQueryInstance numberOfQueries] < 1) {
[menuItem setTitle:NSLocalizedString(@"Save Query…", @"Save Query…")];
+
return NO;
}
- else if([customQueryInstance numberOfQueries] == 1)
- [menuItem setTitle:NSLocalizedString(@"Save Query…", @"Save Query…")];
- else
- [menuItem setTitle:NSLocalizedString(@"Save Queries…", @"Save Queries…")];
+ else {
+ [menuItem setTitle:[customQueryInstance numberOfQueries] == 1 ?
+ NSLocalizedString(@"Save Query…", @"Save Query…") :
+ NSLocalizedString(@"Save Queries…", @"Save Queries…")];
+ }
return YES;
}
- if ([menuItem action] == @selector(printDocument:)) {
+ if (action == @selector(printDocument:)) {
return (([self database] != nil && [[tablesListInstance valueForKeyPath:@"tablesListView"] numberOfSelectedRows] == 1) ||
// If Custom Query Tab is active the textView will handle printDocument by itself
// if it is first responder; otherwise allow to print the Query Result table even
@@ -3510,70 +3532,70 @@ static NSString *SPRenameDatabaseAction = @"SPRenameDatabase";
[tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]] == 2);
}
- if ([menuItem action] == @selector(chooseEncoding:)) {
+ if (action == @selector(chooseEncoding:)) {
return [self supportsEncoding];
}
- if ([menuItem action] == @selector(analyzeTable:) ||
- [menuItem action] == @selector(optimizeTable:) ||
- [menuItem action] == @selector(repairTable:) ||
- [menuItem action] == @selector(flushTable:) ||
- [menuItem action] == @selector(checkTable:) ||
- [menuItem action] == @selector(checksumTable:) ||
- [menuItem action] == @selector(showCreateTableSyntax:) ||
- [menuItem action] == @selector(copyCreateTableSyntax:))
+ // Table actions and view switching
+ if (action == @selector(analyzeTable:) ||
+ action == @selector(optimizeTable:) ||
+ action == @selector(repairTable:) ||
+ action == @selector(flushTable:) ||
+ action == @selector(checkTable:) ||
+ action == @selector(checksumTable:) ||
+ action == @selector(showCreateTableSyntax:) ||
+ action == @selector(copyCreateTableSyntax:))
{
return [[[tablesListInstance valueForKeyPath:@"tablesListView"] selectedRowIndexes] count];
}
- if ([menuItem action] == @selector(addConnectionToFavorites:)) {
- return ![connectionController selectedFavorite];
+ if (action == @selector(addConnectionToFavorites:)) {
+ return ![connectionController selectedFavorite] || [connectionController isEditingConnection];
}
// Backward in history menu item
- if (([menuItem action] == @selector(backForwardInHistory:)) && ([menuItem tag] == 0)) {
+ if ((action == @selector(backForwardInHistory:)) && ([menuItem tag] == 0)) {
return (([[spHistoryControllerInstance history] count]) && ([spHistoryControllerInstance historyPosition] > 0));
}
// Forward in history menu item
- if (([menuItem action] == @selector(backForwardInHistory:)) && ([menuItem tag] == 1)) {
+ if ((action == @selector(backForwardInHistory:)) && ([menuItem tag] == 1)) {
return (([[spHistoryControllerInstance history] count]) && (([spHistoryControllerInstance historyPosition] + 1) < [[spHistoryControllerInstance history] count]));
}
// Show/hide console
- if ([menuItem action] == @selector(toggleConsole:)) {
+ if (action == @selector(toggleConsole:)) {
[menuItem setTitle:([[[SPQueryController sharedQueryController] window] isVisible] && [[[NSApp keyWindow] windowController] isKindOfClass:[SPQueryController class]]) ? NSLocalizedString(@"Hide Console", @"hide console") : NSLocalizedString(@"Show Console", @"show console")];
}
// Clear console
- if ([menuItem action] == @selector(clearConsole:)) {
+ if (action == @selector(clearConsole:)) {
return ([[SPQueryController sharedQueryController] consoleMessageCount] > 0);
}
// Show/hide console
- if ([menuItem action] == @selector(toggleNavigator:)) {
+ if (action == @selector(toggleNavigator:)) {
[menuItem setTitle:([[[SPNavigatorController sharedNavigatorController] window] isVisible]) ? NSLocalizedString(@"Hide Navigator", @"hide navigator") : NSLocalizedString(@"Show Navigator", @"show navigator")];
}
// Focus on table content filter
- if ([menuItem action] == @selector(focusOnTableContentFilter:) || [menuItem action] == @selector(showFilterTable:)) {
+ if (action == @selector(focusOnTableContentFilter:) || [menuItem action] == @selector(showFilterTable:)) {
return ([self table] != nil && [[self table] isNotEqualTo:@""]);
}
// Focus on table list or filter resp.
- if ([menuItem action] == @selector(makeTableListFilterHaveFocus:)) {
+ if (action == @selector(makeTableListFilterHaveFocus:)) {
- if([[tablesListInstance valueForKeyPath:@"tables"] count] > 20)
- [menuItem setTitle:NSLocalizedString(@"Filter Tables", @"filter tables menu item")];
- else
- [menuItem setTitle:NSLocalizedString(@"Change Focus to Table List", @"change focus to table list menu item")];
+ [menuItem setTitle:[[tablesListInstance valueForKeyPath:@"tables"] count] > 20 ?
+ NSLocalizedString(@"Filter Tables", @"filter tables menu item") :
+ NSLocalizedString(@"Change Focus to Table List", @"change focus to table list menu item")];
- return ([[tablesListInstance valueForKeyPath:@"tables"] count] > 1);
+ return [[tablesListInstance valueForKeyPath:@"tables"] count] > 1;
}
// If validation for the sort favorites tableview items reaches here then the preferences window isn't
// open return NO.
- if (([menuItem action] == @selector(sortFavorites:)) || ([menuItem action] == @selector(reverseSortFavorites:))) {
+ if ((action == @selector(sortFavorites:)) || ([menuItem action] == @selector(reverseSortFavorites:))) {
return NO;
}
@@ -3589,10 +3611,10 @@ static NSString *SPRenameDatabaseAction = @"SPRenameDatabase";
// Obviously don't add if it already exists. We shouldn't really need this as the menu item validation
// enables or disables the menu item based on the same method. Although to be safe do the check anyway
// as we don't know what's calling this method.
- if ([connectionController selectedFavorite]) return;
+ if ([connectionController selectedFavorite] && ![connectionController isEditingConnection]) return;
// Request the connection controller to add its details to favorites
- [connectionController addFavorite:self];
+ [connectionController addFavoriteUsingCurrentDetails:self];
}
/**
diff --git a/Source/SPDatabaseStructure.m b/Source/SPDatabaseStructure.m
index c342e2cb..399fe3f7 100644
--- a/Source/SPDatabaseStructure.m
+++ b/Source/SPDatabaseStructure.m
@@ -480,19 +480,19 @@
return;
}
- // Retrieve the column details
- theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT * FROM `information_schema`.`ROUTINES` WHERE `information_schema`.`ROUTINES`.`ROUTINE_SCHEMA` = '%@'", [currentDatabase stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]]];
+ // Retrieve the column details (only those we need so we don't fetch the whole function body which might be huge)
+ theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT SPECIFIC_NAME, ROUTINE_TYPE, DTD_IDENTIFIER, IS_DETERMINISTIC, SQL_DATA_ACCESS, SECURITY_TYPE, DEFINER FROM `information_schema`.`ROUTINES` WHERE `ROUTINE_SCHEMA` = %@", [currentDatabase tickQuotedString]]];
[theResult setDefaultRowReturnType:SPMySQLResultRowAsArray];
// Loop through the rows and extract the function details
for (NSArray *row in theResult) {
- NSString *fname = [row objectAtIndex:0];
- NSString *type = ([[row objectAtIndex:4] isEqualToString:@"FUNCTION"]) ? @"3" : @"2";
- NSString *dtd = [row objectAtIndex:5];
- NSString *det = [row objectAtIndex:11];
- NSString *dataaccess = [row objectAtIndex:12];
- NSString *security_type = [row objectAtIndex:14];
- NSString *definer = [row objectAtIndex:19];
+ NSString *fname = [row objectAtIndex:0];
+ NSString *type = ([[row objectAtIndex:1] isEqualToString:@"FUNCTION"]) ? @"3" : @"2";
+ NSString *dtd = [row objectAtIndex:2];
+ NSString *det = [row objectAtIndex:3];
+ NSString *dataaccess = [row objectAtIndex:4];
+ NSString *security_type = [row objectAtIndex:5];
+ NSString *definer = [row objectAtIndex:6];
// Generate "table" and "field" names and add to structure key store
NSString *table_id = [NSString stringWithFormat:@"%@%@%@", db_id, SPUniqueSchemaDelimiter, fname];
diff --git a/Source/SPDotExporter.m b/Source/SPDotExporter.m
index 62cfbc48..13bf13a5 100644
--- a/Source/SPDotExporter.m
+++ b/Source/SPDotExporter.m
@@ -175,10 +175,10 @@
}
// Get the column references. Currently the columns themselves are an array,
- // while reference columns and tables are comma separated if there are more than
+ // while tables are comma separated if there are more than
// one. Only use the first of each for the time being.
NSArray *originColumns = [constraint objectForKey:@"columns"];
- NSArray *referenceColumns = [[constraint objectForKey:@"ref_columns"] componentsSeparatedByString:@","];
+ NSArray *referenceColumns = [constraint objectForKey:@"ref_columns"];
NSString *extra = @"";
diff --git a/Source/SPEditorPreferencePane.m b/Source/SPEditorPreferencePane.m
index b9df9845..186af05a 100644
--- a/Source/SPEditorPreferencePane.m
+++ b/Source/SPEditorPreferencePane.m
@@ -758,19 +758,18 @@ static NSString *SPCustomColorSchemeNameLC = @"user-defined";
[[NSColorPanel sharedColorPanel] close];
- SPBeginWaitingAlertSheet(@"title",
- NSLocalizedString(@"Proceed", @"proceed button"),
- NSLocalizedString(@"Cancel", @"cancel button"),
- nil,
- NSWarningAlertStyle,
- [[self view] window],
- self,
- @selector(checkForUnsavedThemeDidEndSheet:returnCode:contextInfo:),
- nil,
- NSLocalizedString(@"Unsaved Theme", @"unsaved theme message"),
- NSLocalizedString(@"The current color theme is unsaved. Do you want to proceed without saving it?", @"unsaved theme informative message"),
- &checkForUnsavedThemeSheetStatus
- );
+ [SPAlertSheets beginWaitingAlertSheetWithTitle:@"title"
+ defaultButton:NSLocalizedString(@"Proceed", @"proceed button")
+ alternateButton:NSLocalizedString(@"Cancel", @"cancel button")
+ otherButton:nil
+ alertStyle:NSWarningAlertStyle
+ docWindow:[[self view] window]
+ modalDelegate:self
+ didEndSelector:@selector(checkForUnsavedThemeDidEndSheet:returnCode:contextInfo:)
+ contextInfo:nil
+ msg:NSLocalizedString(@"Unsaved Theme", @"unsaved theme message")
+ infoText:NSLocalizedString(@"The current color theme is unsaved. Do you want to proceed without saving it?", @"unsaved theme informative message")
+ returnCode:&checkForUnsavedThemeSheetStatus];
return (checkForUnsavedThemeSheetStatus == NSAlertDefaultReturn);
}
diff --git a/Source/SPExtendedTableInfo.m b/Source/SPExtendedTableInfo.m
index 91c51a36..ce9e6e7f 100644
--- a/Source/SPExtendedTableInfo.m
+++ b/Source/SPExtendedTableInfo.m
@@ -44,8 +44,24 @@
#import <SPMySQL/SPMySQL.h>
-static NSString *SPUpdateTableTypeCurrentType = @"SPUpdateTableTypeCurrentType";
static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
+static NSString *SPUpdateTableTypeCurrentType = @"SPUpdateTableTypeCurrentType";
+
+// MySQL status field names
+static NSString *SPMySQLEngineField = @"Engine";
+static NSString *SPMySQLRowFormatField = @"Row_format";
+static NSString *SPMySQLRowsField = @"Rows";
+static NSString *SPMySQLAverageRowLengthField = @"Avg_row_length";
+static NSString *SPMySQLDataLengthField = @"Data_length";
+static NSString *SPMySQLMaxDataLengthField = @"Max_data_length";
+static NSString *SPMySQLIndexLengthField = @"Index_length";
+static NSString *SPMySQLDataFreeField = @"Data_free";
+static NSString *SPMySQLAutoIncrementField = @"Auto_increment";
+static NSString *SPMySQLCreateTimeField = @"Create_time";
+static NSString *SPMySQLUpdateTimeField = @"Update_time";
+static NSString *SPMySQLCheckTimeField = @"Check_time";
+static NSString *SPMySQLCollationField = @"Collation";
+static NSString *SPMySQLCommentField = @"Comment";
@interface SPExtendedTableInfo ()
@@ -100,13 +116,13 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
- (IBAction)updateTableType:(id)sender
{
NSString *newType = [sender titleOfSelectedItem];
- NSString *currentType = [tableDataInstance statusValueForKey:@"Engine"];
+ NSString *currentType = [tableDataInstance statusValueForKey:SPMySQLEngineField];
// Check if the user selected the same type
if ([currentType isEqualToString:newType]) return;
// If the table is empty, perform the change directly
- if ([[[tableDataInstance statusValues] objectForKey:@"Rows"] isEqualToString:@"0"]) {
+ if ([[[tableDataInstance statusValues] objectForKey:SPMySQLRowsField] isEqualToString:@"0"]) {
[self _changeCurrentTableTypeFrom:currentType to:newType];
return;
}
@@ -170,7 +186,7 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
- (IBAction)updateTableCollation:(id)sender
{
NSString *newCollation = [sender titleOfSelectedItem];
- NSString *currentCollation = [tableDataInstance statusValueForKey:@"Collation"];
+ NSString *currentCollation = [tableDataInstance statusValueForKey:SPMySQLCollationField];
// Check if the user selected the same collation
if ([currentCollation isEqualToString:newCollation]) return;
@@ -252,7 +268,7 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
[tableEncodingPopUpButton setEnabled:NO];
[tableCollationPopUpButton setEnabled:NO];
- if ([[statusFields objectForKey:@"Engine"] isEqualToString:@"View"]) {
+ if ([[statusFields objectForKey:SPMySQLEngineField] isEqualToString:@"View"]) {
[tableTypePopUpButton addItemWithTitle:@"View"];
// Set create syntax
[tableCreateSyntaxTextView setEditable:YES];
@@ -297,9 +313,12 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
[tableCommentsTextView setString:@""];
[tableCommentsTextView didChangeText];
- if([[statusFields objectForKey:@"Engine"] isEqualToString:@"View"] && [statusFields objectForKey:@"CharacterSetClient"] && [statusFields objectForKey:@"Collation"]) {
+ if ([[statusFields objectForKey:SPMySQLEngineField] isEqualToString:@"View"] &&
+ [statusFields objectForKey:@"CharacterSetClient"] &&
+ [statusFields objectForKey:SPMySQLCollationField])
+ {
[tableEncodingPopUpButton addItemWithTitle:[statusFields objectForKey:@"CharacterSetClient"]];
- [tableCollationPopUpButton addItemWithTitle:[statusFields objectForKey:@"Collation"]];
+ [tableCollationPopUpButton addItemWithTitle:[statusFields objectForKey:SPMySQLCollationField]];
}
return;
@@ -309,15 +328,15 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
NSArray *encodings = [databaseDataInstance getDatabaseCharacterSetEncodings];
NSArray *collations = [databaseDataInstance getDatabaseCollationsForEncoding:[tableDataInstance tableEncoding]];
- if (([engines count] > 0) && ([statusFields objectForKey:@"Engine"])) {
+ if (([engines count] > 0) && ([statusFields objectForKey:SPMySQLEngineField])) {
// Populate type popup button
for (NSDictionary *engine in engines)
{
- [tableTypePopUpButton addItemWithTitle:[engine objectForKey:@"Engine"]];
+ [tableTypePopUpButton addItemWithTitle:[engine objectForKey:SPMySQLEngineField]];
}
- [tableTypePopUpButton selectItemWithTitle:[statusFields objectForKey:@"Engine"]];
+ [tableTypePopUpButton selectItemWithTitle:[statusFields objectForKey:SPMySQLEngineField]];
[tableTypePopUpButton setEnabled:enableInteraction];
}
else {
@@ -346,37 +365,38 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
[tableEncodingPopUpButton addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")];
}
- if (([collations count] > 0) && ([statusFields objectForKey:@"Collation"])) {
+ if (([collations count] > 0) && ([statusFields objectForKey:SPMySQLCollationField])) {
+
// Populate collation popup button
for (NSDictionary *collation in collations)
{
[tableCollationPopUpButton addItemWithTitle:[collation objectForKey:@"COLLATION_NAME"]];
}
- [tableCollationPopUpButton selectItemWithTitle:[statusFields objectForKey:@"Collation"]];
+ [tableCollationPopUpButton selectItemWithTitle:[statusFields objectForKey:SPMySQLCollationField]];
[tableCollationPopUpButton setEnabled:enableInteraction];
}
else {
[tableCollationPopUpButton addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")];
}
- [tableCreatedAt setStringValue:[self _formatValueWithKey:@"Create_time" inDictionary:statusFields]];
- [tableUpdatedAt setStringValue:[self _formatValueWithKey:@"Update_time" inDictionary:statusFields]];
+ [tableCreatedAt setStringValue:[self _formatValueWithKey:SPMySQLCreateTimeField inDictionary:statusFields]];
+ [tableUpdatedAt setStringValue:[self _formatValueWithKey:SPMySQLUpdateTimeField inDictionary:statusFields]];
// Set row values
- [tableRowNumber setStringValue:[self _formatValueWithKey:@"Rows" inDictionary:statusFields]];
- [tableRowFormat setStringValue:[self _formatValueWithKey:@"Row_format" inDictionary:statusFields]];
- [tableRowAvgLength setStringValue:[self _formatValueWithKey:@"Avg_row_length" inDictionary:statusFields]];
- [tableRowAutoIncrement setStringValue:[self _formatValueWithKey:@"Auto_increment" inDictionary:statusFields]];
+ [tableRowNumber setStringValue:[self _formatValueWithKey:SPMySQLRowsField inDictionary:statusFields]];
+ [tableRowFormat setStringValue:[self _formatValueWithKey:SPMySQLRowFormatField inDictionary:statusFields]];
+ [tableRowAvgLength setStringValue:[self _formatValueWithKey:SPMySQLAverageRowLengthField inDictionary:statusFields]];
+ [tableRowAutoIncrement setStringValue:[self _formatValueWithKey:SPMySQLAutoIncrementField inDictionary:statusFields]];
// Set size values
- [tableDataSize setStringValue:[self _formatValueWithKey:@"Data_length" inDictionary:statusFields]];
- [tableMaxDataSize setStringValue:[self _formatValueWithKey:@"Max_data_length" inDictionary:statusFields]];
- [tableIndexSize setStringValue:[self _formatValueWithKey:@"Index_length" inDictionary:statusFields]];
- [tableSizeFree setStringValue:[self _formatValueWithKey:@"Data_free" inDictionary:statusFields]];
+ [tableDataSize setStringValue:[self _formatValueWithKey:SPMySQLDataLengthField inDictionary:statusFields]];
+ [tableMaxDataSize setStringValue:[self _formatValueWithKey:SPMySQLMaxDataLengthField inDictionary:statusFields]];
+ [tableIndexSize setStringValue:[self _formatValueWithKey:SPMySQLIndexLengthField inDictionary:statusFields]];
+ [tableSizeFree setStringValue:[self _formatValueWithKey:SPMySQLDataFreeField inDictionary:statusFields]];
// Set comments
- NSString *commentText = [statusFields objectForKey:@"Comment"];
+ NSString *commentText = [statusFields objectForKey:SPMySQLCommentField];
if (!commentText) commentText = @"";
@@ -401,7 +421,7 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
[tableCreateSyntaxTextView setEditable:NO];
// Validate Reset AUTO_INCREMENT button
- if ([statusFields objectForKey:@"Auto_increment"] && ![[statusFields objectForKey:@"Auto_increment"] isNSNull]) {
+ if ([statusFields objectForKey:SPMySQLAutoIncrementField] && ![[statusFields objectForKey:SPMySQLAutoIncrementField] isNSNull]) {
[resetAutoIncrementResetButton setHidden:NO];
}
}
@@ -429,43 +449,43 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
[tableInfo setObject:[tableCollationPopUpButton titleOfSelectedItem] forKey:@"collation"];
}
- if ([self _formatValueWithKey:@"Create_time" inDictionary:statusFields]) {
- [tableInfo setObject:[self _formatValueWithKey:@"Create_time" inDictionary:statusFields] forKey:@"createdAt"];
+ if ([self _formatValueWithKey:SPMySQLCreateTimeField inDictionary:statusFields]) {
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLCreateTimeField inDictionary:statusFields] forKey:@"createdAt"];
}
- if ([self _formatValueWithKey:@"Update_time" inDictionary:statusFields]) {
- [tableInfo setObject:[self _formatValueWithKey:@"Update_time" inDictionary:statusFields] forKey:@"updatedAt"];
+ if ([self _formatValueWithKey:SPMySQLUpdateTimeField inDictionary:statusFields]) {
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLUpdateTimeField inDictionary:statusFields] forKey:@"updatedAt"];
}
- if ([self _formatValueWithKey:@"Rows" inDictionary:statusFields]) {
- [tableInfo setObject:[self _formatValueWithKey:@"Rows" inDictionary:statusFields] forKey:@"rowNumber"];
+ if ([self _formatValueWithKey:SPMySQLRowsField inDictionary:statusFields]) {
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLRowsField inDictionary:statusFields] forKey:@"rowNumber"];
}
- if ([self _formatValueWithKey:@"Row_format" inDictionary:statusFields]) {
- [tableInfo setObject:[self _formatValueWithKey:@"Row_format" inDictionary:statusFields] forKey:@"rowFormat"];
+ if ([self _formatValueWithKey:SPMySQLRowFormatField inDictionary:statusFields]) {
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLRowFormatField inDictionary:statusFields] forKey:@"rowFormat"];
}
- if ([self _formatValueWithKey:@"Avg_row_length" inDictionary:statusFields]) {
- [tableInfo setObject:[self _formatValueWithKey:@"Avg_row_length" inDictionary:statusFields] forKey:@"rowAvgLength"];
+ if ([self _formatValueWithKey:SPMySQLAverageRowLengthField inDictionary:statusFields]) {
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLAverageRowLengthField inDictionary:statusFields] forKey:@"rowAvgLength"];
}
- if ([self _formatValueWithKey:@"Auto_increment" inDictionary:statusFields]) {
- [tableInfo setObject:[self _formatValueWithKey:@"Auto_increment" inDictionary:statusFields] forKey:@"rowAutoIncrement"];
+ if ([self _formatValueWithKey:SPMySQLAutoIncrementField inDictionary:statusFields]) {
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLAutoIncrementField inDictionary:statusFields] forKey:@"rowAutoIncrement"];
}
- if ([self _formatValueWithKey:@"Data_length" inDictionary:statusFields]) {
- [tableInfo setObject:[self _formatValueWithKey:@"Data_length" inDictionary:statusFields] forKey:@"dataSize"];
+ if ([self _formatValueWithKey:SPMySQLDataLengthField inDictionary:statusFields]) {
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLDataLengthField inDictionary:statusFields] forKey:@"dataSize"];
}
- if ([self _formatValueWithKey:@"Max_data_length" inDictionary:statusFields]) {
- [tableInfo setObject:[self _formatValueWithKey:@"Max_data_length" inDictionary:statusFields] forKey:@"maxDataSize"];
+ if ([self _formatValueWithKey:SPMySQLMaxDataLengthField inDictionary:statusFields]) {
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLMaxDataLengthField inDictionary:statusFields] forKey:@"maxDataSize"];
}
- if ([self _formatValueWithKey:@"Index_length" inDictionary:statusFields]) {
- [tableInfo setObject:[self _formatValueWithKey:@"Index_length" inDictionary:statusFields] forKey:@"indexSize"];
+ if ([self _formatValueWithKey:SPMySQLIndexLengthField inDictionary:statusFields]) {
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLIndexLengthField inDictionary:statusFields] forKey:@"indexSize"];
}
- [tableInfo setObject:[self _formatValueWithKey:@"Data_free" inDictionary:statusFields] forKey:@"sizeFree"];
+ [tableInfo setObject:[self _formatValueWithKey:SPMySQLDataFreeField inDictionary:statusFields] forKey:@"sizeFree"];
if ([tableCommentsTextView string]) {
[tableInfo setObject:[tableCommentsTextView string] forKey:@"comments"];
@@ -541,6 +561,7 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
- (void)confirmChangeTableTypeDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(NSDictionary *)contextInfo
{
[[alert window] orderOut:self];
+
if (returnCode == NSAlertDefaultReturn) {
[self _changeCurrentTableTypeFrom:[contextInfo objectForKey:SPUpdateTableTypeCurrentType]
to:[contextInfo objectForKey:SPUpdateTableTypeNewType]];
@@ -579,7 +600,7 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
NSDictionary *statusFields = [tableDataInstance statusValues];
- if (!selectedTable || ![selectedTable length] || [[statusFields objectForKey:@"Engine"] isEqualToString:@"View"]) return;
+ if (!selectedTable || ![selectedTable length] || [[statusFields objectForKey:SPMySQLEngineField] isEqualToString:@"View"]) return;
// If we are viewing tables in the information_schema database, then disable all controls that cause table
// changes as these tables are not modifiable by anyone.
@@ -588,15 +609,18 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
[[tableDocumentInstance database] isEqualToString:SPMySQLPerformanceSchemaDatabase] ||
[[tableDocumentInstance database] isEqualToString:SPMySQLDatabase]);
- if ([[databaseDataInstance getDatabaseStorageEngines] count] && [statusFields objectForKey:@"Engine"]) {
+ if ([[databaseDataInstance getDatabaseStorageEngines] count] && [statusFields objectForKey:SPMySQLEngineField]) {
[tableTypePopUpButton setEnabled:(!isSystemSchemaDb)];
}
- if ([[databaseDataInstance getDatabaseCharacterSetEncodings] count] && [tableDataInstance tableEncoding] && [[tableDocumentInstance serverSupport] supportsPost41CharacterSetHandling]) {
+ if ([[databaseDataInstance getDatabaseCharacterSetEncodings] count] && [tableDataInstance tableEncoding] &&
+ [[tableDocumentInstance serverSupport] supportsPost41CharacterSetHandling])
+ {
[tableEncodingPopUpButton setEnabled:(!isSystemSchemaDb)];
}
- if ([[databaseDataInstance getDatabaseCollationsForEncoding:[tableDataInstance tableEncoding]] count] && [statusFields objectForKey:@"Collation"])
+ if ([[databaseDataInstance getDatabaseCollationsForEncoding:[tableDataInstance tableEncoding]] count] &&
+ [statusFields objectForKey:SPMySQLCollationField])
{
[tableCollationPopUpButton setEnabled:(!isSystemSchemaDb)];
}
@@ -650,16 +674,16 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
}
else {
// Format size strings
- if ([key isEqualToString:@"Data_length"] ||
- [key isEqualToString:@"Max_data_length"] ||
- [key isEqualToString:@"Index_length"] ||
- [key isEqualToString:@"Data_free"]) {
+ if ([key isEqualToString:SPMySQLDataLengthField] ||
+ [key isEqualToString:SPMySQLMaxDataLengthField] ||
+ [key isEqualToString:SPMySQLIndexLengthField] ||
+ [key isEqualToString:SPMySQLDataFreeField]) {
value = [NSString stringForByteSize:[value longLongValue]];
}
// Format date strings to the user's long date format
- else if ([key isEqualToString:@"Create_time"] ||
- [key isEqualToString:@"Update_time"]) {
+ else if ([key isEqualToString:SPMySQLCreateTimeField] ||
+ [key isEqualToString:SPMySQLUpdateTimeField]) {
// Create date formatter
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
@@ -672,9 +696,9 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
value = [dateFormatter stringFromDate:[NSDate dateWithNaturalLanguageString:value]];
}
// Format numbers
- else if ([key isEqualToString:@"Rows"] ||
- [key isEqualToString:@"Avg_row_length"] ||
- [key isEqualToString:@"Auto_increment"]) {
+ else if ([key isEqualToString:SPMySQLRowsField] ||
+ [key isEqualToString:SPMySQLAverageRowLengthField] ||
+ [key isEqualToString:SPMySQLAutoIncrementField]) {
NSNumberFormatter *numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
@@ -683,13 +707,13 @@ static NSString *SPUpdateTableTypeNewType = @"SPUpdateTableTypeNewType";
value = [numberFormatter stringFromNumber:[NSNumber numberWithLongLong:[value longLongValue]]];
// Prefix number of rows with '~' if it is not an accurate count
- if ([key isEqualToString:@"Rows"] && ![[infoDict objectForKey:@"RowsCountAccurate"] boolValue]) {
+ if ([key isEqualToString:SPMySQLRowsField] && ![[infoDict objectForKey:@"RowsCountAccurate"] boolValue]) {
value = [@"~" stringByAppendingString:value];
}
}
}
- return ([value length] > 0) ? value : NSLocalizedString(@"Not available", @"not available label");
+ return [value length] ? value : NSLocalizedString(@"Not available", @"not available label");
}
#pragma mark -
diff --git a/Source/SPFavoritesOutlineView.h b/Source/SPFavoritesOutlineView.h
index d2fa0846..8eb45ed0 100644
--- a/Source/SPFavoritesOutlineView.h
+++ b/Source/SPFavoritesOutlineView.h
@@ -33,6 +33,7 @@
@interface SPFavoritesOutlineView : NSOutlineView
{
SInt32 systemVersion;
+ BOOL justGainedFocus;
}
@property (assign) BOOL justGainedFocus;
diff --git a/Source/SPNavigatorController.m b/Source/SPNavigatorController.m
index 9977773c..6e7c3d68 100644
--- a/Source/SPNavigatorController.m
+++ b/Source/SPNavigatorController.m
@@ -1250,28 +1250,28 @@ static NSComparisonResult compareStrings(NSString *s1, NSString *s2, void* conte
if(type == 2) // PROCEDURE
switch(anIndex) {
case 0:
- return @"DTD Identifier";
+ return NSLocalizedString(@"DTD Identifier",@"dtd identifier label (Navigator)");
case 1:
- return @"SQL Data Access";
+ return NSLocalizedString(@"SQL Data Access",@"sql data access label (Navigator)");
case 2:
- return @"Is Deterministic";
+ return NSLocalizedString(@"Is Deterministic",@"is deterministic label (Navigator)");
case 3:
return NSLocalizedString(@"Execution Privilege", @"execution privilege label (Navigator)");
case 4:
- return @"Definer";
+ return NSLocalizedString(@"Definer",@"definer label (Navigator)");
}
if(type == 3) // FUNCTION
switch(anIndex) {
case 0:
return NSLocalizedString(@"Return Type", @"return type label (Navigator)");
case 1:
- return @"SQL Data Access";
+ return NSLocalizedString(@"SQL Data Access",@"sql data access label (Navigator)");
case 2:
- return @"Is Deterministic";
+ return NSLocalizedString(@"Is Deterministic",@"is deterministic label (Navigator)");
case 3:
return NSLocalizedString(@"Execution Privilege", @"execution privilege label (Navigator)");
case 4:
- return @"Definer";
+ return NSLocalizedString(@"Definer",@"definer label (Navigator)");
}
return @"";
}
diff --git a/Source/SPProcessListController.m b/Source/SPProcessListController.m
index 7540ed43..2b26eb90 100644
--- a/Source/SPProcessListController.m
+++ b/Source/SPProcessListController.m
@@ -246,7 +246,7 @@ static NSString *SPTableViewIDColumnIdentifier = @"Id";
// No process selected. Interface validation should prevent this.
if ([processListTableView numberOfSelectedRows] != 1) return;
- long long processId = [[[processes objectAtIndex:[processListTableView selectedRow]] valueForKey:@"Id"] longLongValue];
+ long long processId = [[[processesFiltered objectAtIndex:[processListTableView selectedRow]] valueForKey:@"Id"] longLongValue];
NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Kill query?", @"kill query message")
defaultButton:NSLocalizedString(@"Kill", @"kill button")
@@ -274,7 +274,7 @@ static NSString *SPTableViewIDColumnIdentifier = @"Id";
// No process selected. Interface validation should prevent this.
if ([processListTableView numberOfSelectedRows] != 1) return;
- long long processId = [[[processes objectAtIndex:[processListTableView selectedRow]] valueForKey:@"Id"] longLongValue];
+ long long processId = [[[processesFiltered objectAtIndex:[processListTableView selectedRow]] valueForKey:@"Id"] longLongValue];
NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Kill connection?", @"kill connection message")
defaultButton:NSLocalizedString(@"Kill", @"kill button")
@@ -382,7 +382,7 @@ static NSString *SPTableViewIDColumnIdentifier = @"Id";
[self _startAutoRefreshTimerWithInterval:[customIntervalTextField integerValue]];
}
else {
- long long processId = [[[processes objectAtIndex:[processListTableView selectedRow]] valueForKey:@"Id"] longLongValue];
+ long long processId = [[[processesFiltered objectAtIndex:[processListTableView selectedRow]] valueForKey:@"Id"] longLongValue];
if ([contextInfo isEqualToString:SPKillProcessQueryMode]) {
[self _killProcessQueryWithId:processId];
@@ -478,70 +478,6 @@ static NSString *SPTableViewIDColumnIdentifier = @"Id";
}
#pragma mark -
-#pragma mark Tableview delegate methods
-
-/**
- * Table view delegate method. Returns the number of rows in the table veiw.
- */
-- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
-{
- return [processesFiltered count];
-}
-
-/**
- * Table view delegate method. Returns the specific object for the request column and row.
- */
-- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
-{
- id object = ((NSUInteger)row < [processesFiltered count]) ? [[processesFiltered objectAtIndex:row] valueForKey:[tableColumn identifier]] : @"";
-
- if ([object isNSNull]) {
- return [prefs stringForKey:SPNullValue];
- }
-
- // If the string is exactly 100 characters long, and FULL process lists are not enabled, it's a safe
- // bet that the string is truncated
- if (!showFullProcessList && [object isKindOfClass:[NSString class]] && [(NSString *)object length] == 100) {
- return [object stringByAppendingString:@"…"];
- }
-
- return object;
-}
-
-/**
- * Table view delegate method. Called when the user changes the sort by column.
- */
-- (void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
-{
- [processesFiltered sortUsingDescriptors:[tableView sortDescriptors]];
-
- [tableView reloadData];
-}
-
-/**
- * Table view delegate method. Called whenever the user changes a column width.
- */
-- (void)tableViewColumnDidResize:(NSNotification *)notification
-{
- NSTableColumn *column = [[notification userInfo] objectForKey:@"NSTableColumn"];
-
- // Get the existing table column widths dictionary if it exists
- NSMutableDictionary *tableColumnWidths = ([prefs objectForKey:SPProcessListTableColumnWidths]) ?
- [NSMutableDictionary dictionaryWithDictionary:[prefs objectForKey:SPProcessListTableColumnWidths]] :
- [NSMutableDictionary dictionary];
-
- // Save column size
- NSString *columnName = [[column headerCell] stringValue];
-
- if (columnName) {
- [tableColumnWidths setObject:[NSNumber numberWithDouble:[column width]] forKey:columnName];
-
- [prefs setObject:tableColumnWidths forKey:SPProcessListTableColumnWidths];
- }
-}
-
-
-#pragma mark -
#pragma mark Text field delegate methods
/**
diff --git a/Source/SPProcessListControllerDataSource.h b/Source/SPProcessListControllerDataSource.h
new file mode 100644
index 00000000..3d0cc571
--- /dev/null
+++ b/Source/SPProcessListControllerDataSource.h
@@ -0,0 +1,35 @@
+//
+// $Id$
+//
+// SPProcessListControllerDataSource.h
+// sequel-pro
+//
+// Created by Stuart Connolly (stuconnolly.com) on April 3, 2013.
+// Copyright (c) 2013 Stuart Connolly. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#import "SPProcessListController.h"
+
+@interface SPProcessListController (SPProcessListControllerDataSource)
+
+@end
diff --git a/Source/SPProcessListControllerDataSource.m b/Source/SPProcessListControllerDataSource.m
new file mode 100644
index 00000000..90e0c113
--- /dev/null
+++ b/Source/SPProcessListControllerDataSource.m
@@ -0,0 +1,98 @@
+//
+// $Id$
+//
+// SPProcessListControllerDataSource.m
+// sequel-pro
+//
+// Created by Stuart Connolly (stuconnolly.com) on April 3, 2013.
+// Copyright (c) 2013 Stuart Connolly. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#import "SPProcessListControllerDataSource.h"
+
+@implementation SPProcessListController (SPProcessListControllerDataSource)
+
+#pragma mark -
+#pragma mark Tableview delegate methods
+
+/**
+ * Table view delegate method. Returns the number of rows in the table veiw.
+ */
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
+{
+ return [processesFiltered count];
+}
+
+/**
+ * Table view delegate method. Returns the specific object for the request column and row.
+ */
+- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
+{
+ id object = ((NSUInteger)row < [processesFiltered count]) ? [[processesFiltered objectAtIndex:row] valueForKey:[tableColumn identifier]] : @"";
+
+ if ([object isNSNull]) {
+ return [prefs stringForKey:SPNullValue];
+ }
+
+ // If the string is exactly 100 characters long, and FULL process lists are not enabled, it's a safe
+ // bet that the string is truncated
+ if (!showFullProcessList && [object isKindOfClass:[NSString class]] && [(NSString *)object length] == 100) {
+ return [object stringByAppendingString:@"…"];
+ }
+
+ return object;
+}
+
+/**
+ * Table view delegate method. Called when the user changes the sort by column.
+ */
+- (void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
+{
+ [processesFiltered sortUsingDescriptors:[tableView sortDescriptors]];
+
+ [tableView reloadData];
+}
+
+/**
+ * Table view delegate method. Called whenever the user changes a column width.
+ */
+- (void)tableViewColumnDidResize:(NSNotification *)notification
+{
+ NSTableColumn *column = [[notification userInfo] objectForKey:@"NSTableColumn"];
+
+ // Get the existing table column widths dictionary if it exists
+ NSMutableDictionary *tableColumnWidths = ([prefs objectForKey:SPProcessListTableColumnWidths]) ?
+ [NSMutableDictionary dictionaryWithDictionary:[prefs objectForKey:SPProcessListTableColumnWidths]] :
+ [NSMutableDictionary dictionary];
+
+ // Save column size
+ NSString *columnName = [[column headerCell] stringValue];
+
+ if (columnName) {
+ [tableColumnWidths setObject:[NSNumber numberWithDouble:[column width]] forKey:columnName];
+
+ [prefs setObject:tableColumnWidths forKey:SPProcessListTableColumnWidths];
+ }
+}
+
+@end
diff --git a/Source/SPSQLExporter.m b/Source/SPSQLExporter.m
index c1ce7412..f2ee87bb 100644
--- a/Source/SPSQLExporter.m
+++ b/Source/SPSQLExporter.m
@@ -882,7 +882,11 @@
if ([[column objectForKey:@"unsigned"] integerValue] == 1) [fieldString appendString:@" UNSIGNED"];
if ([[column objectForKey:@"zerofill"] integerValue] == 1) [fieldString appendString:@" ZEROFILL"];
if ([[column objectForKey:@"binary"] integerValue] == 1) [fieldString appendString:@" BINARY"];
- if ([[column objectForKey:@"null"] integerValue] == 0) [fieldString appendString:@" NOT NULL"];
+ if ([[column objectForKey:@"null"] integerValue] == 0) {
+ [fieldString appendString:@" NOT NULL"];
+ } else {
+ [fieldString appendString:@" NULL"];
+ }
// Provide the field default if appropriate
if ([column objectForKey:@"default"]) {
diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m
index 136613dc..08c5c736 100644
--- a/Source/SPTableContent.m
+++ b/Source/SPTableContent.m
@@ -512,7 +512,7 @@ static NSString *SPTableFilterSetDefaultOperator = @"SPTableFilterSetDefaultOper
for (NSDictionary *constraint in constraints)
{
NSString *firstColumn = [[constraint objectForKey:@"columns"] objectAtIndex:0];
- NSString *firstRefColumn = [[[constraint objectForKey:@"ref_columns"] componentsSeparatedByString:@","] objectAtIndex:0];
+ NSString *firstRefColumn = [[constraint objectForKey:@"ref_columns"] objectAtIndex:0];
NSUInteger columnIndex = [columnNames indexOfObject:firstColumn];
if (columnIndex != NSNotFound && ![[dataColumns objectAtIndex:columnIndex] objectForKey:@"foreignkeyreference"]) {
diff --git a/Source/SPTableData.m b/Source/SPTableData.m
index a591226e..b7826264 100644
--- a/Source/SPTableData.m
+++ b/Source/SPTableData.m
@@ -645,8 +645,16 @@
[fieldsParser setString:[[parts objectAtIndex:6] stringByTrimmingCharactersInSet:bracketSet]];
[constraintDetails setObject:[fieldsParser unquotedString] forKey:@"ref_table"];
- [fieldsParser setString:[[parts objectAtIndex:7] stringByTrimmingCharactersInSet:bracketSet]];
- [constraintDetails setObject:[fieldsParser unquotedString] forKey:@"ref_columns"];
+ NSMutableArray *refKeyColumns = [NSMutableArray array];
+ NSArray *refKeyColumnStrings = [[[parts objectAtIndex:7] stringByTrimmingCharactersInSet:bracketSet] componentsSeparatedByString:@","];
+
+ for (NSString *keyColumn in refKeyColumnStrings)
+ {
+ [fieldsParser setString:[[keyColumn stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] stringByTrimmingCharactersInSet:bracketSet]];
+ [refKeyColumns addObject:[fieldsParser unquotedString]];
+ }
+
+ [constraintDetails setObject:refKeyColumns forKey:@"ref_columns"];
NSUInteger nextOffs = 12;
diff --git a/Source/SPTableFieldValidation.m b/Source/SPTableFieldValidation.m
index bcd1dc8b..3a465338 100644
--- a/Source/SPTableFieldValidation.m
+++ b/Source/SPTableFieldValidation.m
@@ -102,7 +102,7 @@
if (![fieldTypes containsObject:type]) return YES;
- return (([fieldTypes indexOfObject:type] > 17) && ([fieldTypes indexOfObject:type] < 32));
+ return ((([fieldTypes indexOfObject:type] > 17) && ([fieldTypes indexOfObject:type] < 24) || (([fieldTypes indexOfObject:type] > 29) && ([fieldTypes indexOfObject:type] < 32))));
}
/**
diff --git a/Source/SPTableRelations.m b/Source/SPTableRelations.m
index 45450bf1..26ab8195 100644
--- a/Source/SPTableRelations.m
+++ b/Source/SPTableRelations.m
@@ -589,9 +589,9 @@ static NSString *SPRelationOnDeleteKey = @"on_delete";
{
[relationData addObject:[NSDictionary dictionaryWithObjectsAndKeys:
[constraint objectForKey:SPRelationNameKey], SPRelationNameKey,
- [[constraint objectForKey:SPRelationColumnsKey] objectAtIndex:0], SPRelationColumnsKey,
+ [[constraint objectForKey:SPRelationColumnsKey] componentsJoinedByCommas], SPRelationColumnsKey,
[constraint objectForKey:@"ref_table"], SPRelationFKTableKey,
- [constraint objectForKey:@"ref_columns"], SPRelationFKColumnsKey,
+ [[constraint objectForKey:@"ref_columns"] componentsJoinedByCommas], SPRelationFKColumnsKey,
([constraint objectForKey:@"update"] ? [constraint objectForKey:@"update"] : @""), SPRelationOnUpdateKey,
([constraint objectForKey:@"delete"] ? [constraint objectForKey:@"delete"] : @""), SPRelationOnDeleteKey,
nil]];
@@ -624,7 +624,7 @@ static NSString *SPRelationOnDeleteKey = @"on_delete";
[tableDataInstance resetAllData];
NSDictionary *tableInfo = [tableDataInstance informationForTable:table];
- NSArray *columns = [tableInfo objectForKey:SPRelationColumnsKey];
+ NSArray *columns = [tableInfo objectForKey:@"columns"];
NSMutableArray *validColumns = [NSMutableArray array];
diff --git a/Source/SPTableStructure.m b/Source/SPTableStructure.m
index fcbc7d13..01ff6be9 100644
--- a/Source/SPTableStructure.m
+++ b/Source/SPTableStructure.m
@@ -796,7 +796,7 @@
}
// ADD COLLATE
- if([fieldEncoding length] && [[theRow objectForKey:@"collation"] integerValue] > 0) {
+ if([fieldEncoding length] && [[theRow objectForKey:@"collation"] integerValue] > 0 && ![[theRow objectForKey:@"binary"] integerValue]) {
NSArray *theCollations = [databaseDataInstance getDatabaseCollationsForEncoding:fieldEncoding];
NSString *col = [[theCollations objectAtIndex:[[theRow objectForKey:@"collation"] integerValue]-1] objectForKey:@"COLLATION_NAME"];
[queryString appendFormat:@"\n COLLATE %@", col];
diff --git a/Source/SPTableStructureDelegate.m b/Source/SPTableStructureDelegate.m
index d797f7ab..858f97f2 100644
--- a/Source/SPTableStructureDelegate.m
+++ b/Source/SPTableStructureDelegate.m
@@ -558,12 +558,12 @@
// Only string fields allow encoding settings
if (([[aTableColumn identifier] isEqualToString:@"encoding"])) {
- [aCell setEnabled:([fieldValidation isFieldTypeString:theRowType] && ![theRowType hasSuffix:@"BINARY"] && ![theRowType hasSuffix:@"BLOB"]) && [[tableDocumentInstance serverSupport] supportsPost41CharacterSetHandling]];
+ [aCell setEnabled:([fieldValidation isFieldTypeString:theRowType] && [[tableDocumentInstance serverSupport] supportsPost41CharacterSetHandling])];
}
// Only string fields allow collation settings and string field is not set to BINARY since BINARY sets the collation to *_bin
else if ([[aTableColumn identifier] isEqualToString:@"collation"]) {
- [aCell setEnabled:([fieldValidation isFieldTypeString:theRowType] && [[theRow objectForKey:@"binary"] integerValue] == 0 && ![theRowType hasSuffix:@"BINARY"] && ![theRowType hasSuffix:@"BLOB"] && [[tableDocumentInstance serverSupport] supportsPost41CharacterSetHandling])];
+ [aCell setEnabled:([fieldValidation isFieldTypeString:theRowType] && [[theRow objectForKey:@"binary"] integerValue] == 0 && [[tableDocumentInstance serverSupport] supportsPost41CharacterSetHandling])];
}
// Check if UNSIGNED and ZEROFILL is allowed
diff --git a/Source/SPTableStructureLoading.m b/Source/SPTableStructureLoading.m
index 4d7bb4dd..c7177720 100644
--- a/Source/SPTableStructureLoading.m
+++ b/Source/SPTableStructureLoading.m
@@ -170,7 +170,7 @@
NSString *collation = nil;
NSString *encoding = nil;
- if ([fieldValidation isFieldTypeString:type] && ![type hasSuffix:@"BINARY"] && ![type hasSuffix:@"BLOB"]) {
+ if ([fieldValidation isFieldTypeString:type]) {
collation = [theField objectForKey:@"collation"] ? [theField objectForKey:@"collation"] : [[tableDataInstance statusValues] objectForKey:@"collation"];
encoding = [theField objectForKey:@"encoding"] ? [theField objectForKey:@"encoding"] : [tableDataInstance tableEncoding];