From 8acde6bf2580ce1e2feac2b9ac74dfa34b1ddf7e Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sat, 1 May 2010 01:36:52 +0000 Subject: Review trigger fetching and storage: - Trigger queries are no longer made for MySQL < 5.0.2 - Trigger loading has been deferred until the trigger tab is active, reducing queries when switching tables and thus increasing overall responsiveness - Export triggers in MySQL dumps even if the Table Content switch is unchecked --- Interfaces/English.lproj/DBView.xib | 175 ++++++++++++++++++++++++------------ Source/SPAppController.m | 1 + Source/SPTableData.h | 1 + Source/SPTableData.m | 81 ++++++++++------- Source/SPTableTriggers.h | 2 + Source/SPTableTriggers.m | 95 ++++++++++---------- Source/TableDump.m | 80 ++++++++--------- Source/TablesList.h | 3 +- Source/TablesList.m | 53 ++++++----- 9 files changed, 289 insertions(+), 202 deletions(-) diff --git a/Interfaces/English.lproj/DBView.xib b/Interfaces/English.lproj/DBView.xib index 0f676d67..c9944020 100644 --- a/Interfaces/English.lproj/DBView.xib +++ b/Interfaces/English.lproj/DBView.xib @@ -2,8 +2,8 @@ 1050 - 10D573 - 740 + 10D2094 + 762 1038.29 460.00 @@ -16,8 +16,8 @@ YES - 740 - 740 + 762 + 762 1.2.5 @@ -281,6 +281,7 @@ {{1, 1}, {218, 38}} + 6 @@ -312,6 +313,7 @@ {{-1, -13}, {220.212, 40}} + 2 @@ -409,6 +411,7 @@ {214, 354} + 4 @@ -436,6 +439,7 @@ {214, 354} + 528 @@ -571,6 +575,7 @@ {214, 145} + 6 @@ -598,6 +603,7 @@ {214, 145} + 512 @@ -802,7 +808,6 @@ - 1 YES 1 YES @@ -3976,6 +3981,7 @@ {{1, 1}, {542, 69}} + @@ -4005,6 +4011,7 @@ {{96, 0}, {555, 71}} + 18 @@ -4112,6 +4119,7 @@ {{1, 1}, {542, 196}} + @@ -4141,6 +4149,7 @@ {{96, 0}, {555, 198}} + 18 @@ -5560,7 +5569,7 @@ {292, 112} {292, 112} - + 256 YES @@ -5569,7 +5578,6 @@ 256 {{36, 75}, {91, 14}} - YES 68288064 @@ -5586,7 +5594,6 @@ 256 {{17, 50}, {110, 14}} - YES 68288064 @@ -5603,7 +5610,6 @@ 258 {{135, 74}, {137, 18}} - YES -1804468671 @@ -5626,7 +5632,6 @@ 259 {{207, 13}, {70, 28}} - 1 YES @@ -5654,7 +5659,6 @@ 259 {{139, 13}, {70, 28}} - YES 67239424 @@ -5676,7 +5680,6 @@ 258 {{132, 45}, {143, 22}} - YES -2076049856 @@ -5997,8 +6000,6 @@ {292, 112} - - {{0, 0}, {1440, 878}} {292, 134} @@ -6014,10 +6015,10 @@ View - {292, 112} - {292, 112} + {292, 132} + {292, 132} - + 256 YES @@ -6026,6 +6027,7 @@ 256 {{17, 98}, {258, 14}} + YES 68288064 @@ -6042,6 +6044,7 @@ 258 {{20, 72}, {252, 18}} + YES -1804468671 @@ -6059,6 +6062,7 @@ 259 {{204, 13}, {77, 28}} + 1 YES @@ -6082,6 +6086,7 @@ 259 {{136, 13}, {70, 28}} + YES 67239424 @@ -6103,6 +6108,7 @@ 268 {{18, 48}, {256, 18}} + YES 67239424 @@ -6122,10 +6128,12 @@ {292, 132} + + {{0, 0}, {1280, 778}} - {292, 134} - {292, 134} + {292, 154} + {292, 154} 1 @@ -6241,7 +6249,7 @@ {600, 142} {269, 142} - + 256 YES @@ -6250,7 +6258,6 @@ 256 {{36, 105}, {71, 14}} - YES 68288064 @@ -6267,7 +6274,6 @@ 256 {{17, 80}, {90, 14}} - YES 68288064 @@ -6284,7 +6290,6 @@ 258 {{112, 104}, {137, 18}} - YES -1804468671 @@ -6302,7 +6307,6 @@ 257 {{184, 13}, {70, 28}} - 1 YES @@ -6326,7 +6330,6 @@ 256 {{109, 75}, {143, 22}} - YES -2076049856 @@ -6650,7 +6653,6 @@ 256 {{41, 54}, {66, 14}} - YES 68288064 @@ -6667,7 +6669,6 @@ 256 {{109, 50}, {143, 22}} - YES -2076049856 @@ -6703,7 +6704,6 @@ 257 {{116, 13}, {70, 28}} - YES 67239424 @@ -6722,8 +6722,6 @@ {269, 142} - - {{0, 0}, {1680, 1028}} {269, 164} @@ -6742,7 +6740,7 @@ {600, 127} {260, 127} - + 256 YES @@ -6751,7 +6749,6 @@ 266 {{17, 93}, {226, 14}} - YES 67239488 @@ -6768,7 +6765,6 @@ 258 {{20, 67}, {220, 18}} - YES -1804468671 @@ -6786,7 +6782,6 @@ 292 {{19, 43}, {189, 18}} - YES 67239424 @@ -6808,7 +6803,6 @@ 289 {{158, 13}, {87, 28}} - 1 YES @@ -6832,7 +6826,6 @@ 289 {{80, 13}, {80, 28}} - YES 67239424 @@ -6851,8 +6844,6 @@ {260, 127} - - {{0, 0}, {1440, 878}} {260, 149} @@ -7450,8 +7441,8 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 YES YES - , - . + . + , NO YES NO @@ -8811,7 +8802,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {1.79769e+308, 1.79769e+308} {350, 200} - + 256 YES @@ -8820,7 +8811,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 257 {{320, 5}, {76, 28}} - YES 67239424 @@ -8842,7 +8832,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 257 {{246, -215.5}, {76, 28}} - YES 67239424 @@ -8864,7 +8853,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 260 {{15, 5}, {111, 28}} - YES -2080244224 @@ -8885,7 +8873,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 266 {{9, 316}, {385, 14}} - YES 68288064 @@ -8912,7 +8899,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 2322 {411, 14} - @@ -8974,7 +8960,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {{1, 1}, {411, 264}} - @@ -8986,7 +8971,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 -2147483392 {{-100, -100}, {11, 133}} - 256 _doScroller: @@ -8997,7 +8981,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 -2147483392 {{-100, -100}, {87, 18}} - 1 _doScroller: @@ -9007,7 +8990,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {{-1, 42}, {413, 266}} - 514 @@ -9019,7 +9001,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 260 {{124, 5}, {76, 28}} - YES 67239424 @@ -9038,8 +9019,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {411, 341} - - {{0, 0}, {1680, 1028}} {350, 222} @@ -16858,6 +16837,14 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 7041 + + + tableTriggersInstance + + + + 7042 + @@ -27152,14 +27139,14 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{925, 531}, {292, 132}} + {{710, 531}, {292, 132}} com.apple.InterfaceBuilder.CocoaPlugin - {{925, 531}, {292, 132}} + {{710, 531}, {292, 132}} - {292, 112} - {292, 112} + {292, 132} + {292, 132} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -27341,7 +27328,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 - 7041 + 7042 @@ -28973,6 +28960,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 tableNameField tableSheet tableSourceInstance + tableTriggersInstance tableTypeButton tableWindow tablesListView @@ -29028,6 +29016,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 id id id + id @@ -30028,6 +30017,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 0 + IBCocoaFramework com.apple.InterfaceBuilder.CocoaPlugin.macosx @@ -30043,5 +30033,74 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 YES ../../sequel-pro.xcodeproj 3 + + YES + + YES + NSActionTemplate + NSAddTemplate + NSAdvanced + NSApplicationIcon + NSGoLeftTemplate + NSGoRightTemplate + NSLeftFacingTriangleTemplate + NSListViewTemplate + NSMenuCheckmark + NSMenuMixedState + NSRefreshTemplate + NSRightFacingTriangleTemplate + NSSwitch + button_action + button_add + button_bar_spacer + button_duplicate + button_edit + button_edit_mode + button_edit_mode_selected + button_left + button_pagination + button_pane_hide_icon + button_pane_show_icon + button_refresh + button_remove + button_right + grabber-horizontal + selectall + selectnone + + + YES + {10, 10} + {8, 8} + {32, 32} + {128, 128} + {9, 9} + {9, 9} + {9, 9} + {11, 10} + {9, 8} + {7, 2} + {10, 12} + {9, 9} + {15, 15} + {32, 23} + {32, 23} + {10, 23} + {33, 23} + {32, 23} + {32, 23} + {32, 23} + {32, 23} + {32, 23} + {11, 10} + {11, 10} + {32, 23} + {32, 23} + {32, 23} + {10, 8} + {14, 17} + {14, 17} + + diff --git a/Source/SPAppController.m b/Source/SPAppController.m index f0d4c9bf..f793b93c 100644 --- a/Source/SPAppController.m +++ b/Source/SPAppController.m @@ -441,6 +441,7 @@ @"queryHistory", @"tableColumnWidths", @"savePath", + @"NSRecentDocumentRecords", nil]]; return preferences; diff --git a/Source/SPTableData.h b/Source/SPTableData.h index a63f31dc..88b0a78f 100644 --- a/Source/SPTableData.h +++ b/Source/SPTableData.h @@ -64,6 +64,7 @@ - (BOOL) updateInformationForCurrentView; - (NSDictionary *) informationForView:(NSString *)viewName; - (BOOL) updateStatusInformationForCurrentTable; +- (BOOL) updateTriggersForCurrentTable; - (NSDictionary *) parseFieldDefinitionStringParts:(NSArray *)definitionParts; - (NSArray *) primaryKeyColumnNames; diff --git a/Source/SPTableData.m b/Source/SPTableData.m index 51d490d9..ab1857f6 100644 --- a/Source/SPTableData.m +++ b/Source/SPTableData.m @@ -42,8 +42,8 @@ columnNames = [[NSMutableArray alloc] init]; constraints = [[NSMutableArray alloc] init]; status = [[NSMutableDictionary alloc] init]; - triggers = [[NSMutableArray alloc] init]; - + + triggers = nil; tableEncoding = nil; tableCreateSyntax = nil; mySQLConnection = nil; @@ -121,6 +121,19 @@ - (NSArray *) triggers { + + // If triggers is nil, the triggers need to be loaded - if a table is selected on MySQL >= 5.0.2 + if (!triggers) { + if ([tableListInstance tableType] == SPTableTypeTable + && [mySQLConnection serverMajorVersion] >= 5 + && [mySQLConnection serverMinorVersion] >= 0) + { + [self updateTriggersForCurrentTable]; + } else { + return [NSArray array]; + } + } + return (NSArray *)triggers; } @@ -234,6 +247,11 @@ [columnNames removeAllObjects]; [status removeAllObjects]; + if (triggers != nil) { + [triggers release]; + triggers = nil; + } + if (tableEncoding != nil) { [tableEncoding release]; tableEncoding = nil; @@ -608,39 +626,12 @@ [createTableParser release]; [fieldParser release]; - // Triggers - theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"/*!50003 SHOW TRIGGERS WHERE `Table` = %@ */", - [tableName tickQuotedString]]]; - [theResult setReturnDataAsStrings:YES]; - - // Check for any errors, but only display them if a connection still exists - if ([mySQLConnection queryErrored]) { - if ([mySQLConnection isConnected]) { - SPBeginAlertSheet(NSLocalizedString(@"Error retrieving table information", @"error retrieving table information message"), NSLocalizedString(@"OK", @"OK button"), - nil, nil, [NSApp mainWindow], self, nil, nil, nil, - [NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving the information for table '%@'. Please try again.\n\nMySQL said: %@", @"error retrieving table information informative message"), - tableName, [mySQLConnection getLastErrorMessage]]); - } - [tableColumns release]; - if (encodingString) [encodingString release]; - - return nil; - } - - [triggers removeAllObjects]; - if( [theResult numOfRows] ) { - for(i=0; i<[theResult numOfRows]; i++){ - [triggers addObject:[theResult fetchRowAsDictionary]]; - } - } - // this will be 'Table' or 'View' [tableData setObject:[resultFieldNames objectAtIndex:0] forKey:@"type"]; [tableData setObject:[NSString stringWithString:encodingString] forKey:@"encoding"]; [tableData setObject:[NSArray arrayWithArray:tableColumns] forKey:@"columns"]; [tableData setObject:[NSArray arrayWithArray:constraints] forKey:@"constraints"]; - [tableData setObject:[NSArray arrayWithArray:triggers] forKey:@"triggers"]; [encodingString release]; [tableColumns release]; @@ -878,6 +869,36 @@ return TRUE; } +/** + * Retrieve the triggers for the current table and add to local cache for reuse. + */ +- (BOOL) updateTriggersForCurrentTable +{ + MCPResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"/*!50003 SHOW TRIGGERS WHERE `Table` = %@ */", + [[tableListInstance tableName] tickQuotedString]]]; + [theResult setReturnDataAsStrings:YES]; + + // Check for any errors, but only display them if a connection still exists + if ([mySQLConnection queryErrored]) { + if ([mySQLConnection isConnected]) { + SPBeginAlertSheet(NSLocalizedString(@"Error retrieving trigger information", @"error retrieving trigger information message"), NSLocalizedString(@"OK", @"OK button"), + nil, nil, [NSApp mainWindow], self, nil, nil, nil, + [NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving the trigger information for table '%@'. Please try again.\n\nMySQL said: %@", @"error retrieving table information informative message"), + [tableListInstance tableName], [mySQLConnection getLastErrorMessage]]); + if (triggers) [triggers release], triggers = nil; + } + + return NO; + } + + if (triggers) [triggers release]; + triggers = [[NSMutableArray alloc] init]; + for (int i=0; i<[theResult numOfRows]; i++) { + [triggers addObject:[theResult fetchRowAsDictionary]]; + } + + return YES; +} /* * Parse an array of field definition parts - not including name but including type and optionally unsigned/zerofill/null @@ -1122,9 +1143,9 @@ [columns release]; [columnNames release]; [constraints release]; - [triggers release]; [status release]; + if (triggers) [triggers release]; if (tableEncoding) [tableEncoding release]; if (tableCreateSyntax) [tableCreateSyntax release]; if (mySQLConnection) [mySQLConnection release]; diff --git a/Source/SPTableTriggers.h b/Source/SPTableTriggers.h index d492253b..8e97908a 100644 --- a/Source/SPTableTriggers.h +++ b/Source/SPTableTriggers.h @@ -57,6 +57,8 @@ @property (readwrite, assign) MCPConnection *connection; +- (void)loadTriggers; + // IB action methods - (IBAction)addTrigger:(id)sender; - (IBAction)removeTrigger:(id)sender; diff --git a/Source/SPTableTriggers.m b/Source/SPTableTriggers.m index dde516a8..c202e9c9 100644 --- a/Source/SPTableTriggers.m +++ b/Source/SPTableTriggers.m @@ -77,12 +77,7 @@ selector:@selector(triggerStatementTextDidChange:) name:NSTextStorageDidProcessEditingNotification object:[triggerStatementTextView textStorage]]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(tableSelectionChanged:) - name:SPTableChangedNotification - object:tableDocumentInstance]; - + // Add observers for document task activity [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startDocumentTaskForTab:) @@ -94,6 +89,46 @@ object:tableDocumentInstance]; } +/** + * Called whenever the user selects the triggers tab for the first time, + * or switches between tables with the triggers tab active. + */ +- (void)loadTriggers +{ + BOOL enableInteraction = ((![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableTriggers]) || (![tableDocumentInstance isWorking])); + + // Disable all interface elements by default + [addTriggerButton setEnabled:NO]; + [refreshTriggersButton setEnabled:NO]; + [triggersTableView setEnabled:NO]; + [labelTextField setStringValue:@""]; + + // Show a warning if the version of MySQL is too low to support triggers + if ([connection serverMajorVersion] < 5 + || ([connection serverMajorVersion] == 5 + && [connection serverMinorVersion] == 0 + && [connection serverReleaseVersion] < 2)) + { + [labelTextField setStringValue:NSLocalizedString(@"This version of MySQL does not support triggers. Support for triggers was added in MySQL 5.0.2", @"triggers not supported label")]; + return; + } + + // If no item is selected, or the item selected is not a table, return. + if (![tablesListInstance tableName] || [tablesListInstance tableType] != SPTableTypeTable) + return; + + // Update the text label + [labelTextField setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Triggers for table: %@", @"triggers for table label"), [tablesListInstance tableName]]]; + + // Enable interface elements + [addTriggerButton setEnabled:enableInteraction]; + [refreshTriggersButton setEnabled:enableInteraction]; + [triggersTableView setEnabled:YES]; + + // Ensure trigger data is loaded + [self _refreshTriggerDataForcingCacheRefresh:NO]; +} + #pragma mark - #pragma mark IB action methods @@ -185,49 +220,6 @@ [self _refreshTriggerDataForcingCacheRefresh:YES]; } -/** - * Called whenever the user selects a different table. - */ -- (void)tableSelectionChanged:(NSNotification *)notification -{ - BOOL enableInteraction = ((![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableTriggers]) || (![tableDocumentInstance isWorking])); - - // To begin enable all interface elements - [addTriggerButton setEnabled:enableInteraction]; - [refreshTriggersButton setEnabled:enableInteraction]; - [triggersTableView setEnabled:YES]; - - if (([connection serverMajorVersion] >= 5) && - ([connection serverMinorVersion] >= 0) && - ([connection serverReleaseVersion] >= 2)) { - - // Update the text label - [labelTextField setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Triggers for table: %@", @"triggers for table label"), [tablesListInstance tableName]]]; - - [addTriggerButton setEnabled:enableInteraction]; - [refreshTriggersButton setEnabled:enableInteraction]; - [triggersTableView setEnabled:YES]; - - [self _refreshTriggerDataForcingCacheRefresh:NO]; - } - else { - [addTriggerButton setEnabled:NO]; - [refreshTriggersButton setEnabled:NO]; - [triggersTableView setEnabled:NO]; - - [labelTextField setStringValue:NSLocalizedString(@"This version of MySQL does not support triggers. Support for triggers was added in MySQL 5.0.2", @"triggers not supported label")]; - } - - // If a proc or function is selected disable everything. - if (([tablesListInstance tableType] == SPTableTypeProc) || ([tablesListInstance tableType] == SPTableTypeFunc)) { - [addTriggerButton setEnabled:NO]; - [refreshTriggersButton setEnabled:NO]; - [triggersTableView setEnabled:NO]; - - [labelTextField setStringValue:@""]; - } -} - #pragma mark - #pragma mark Tableview datasource methods @@ -479,7 +471,10 @@ if ([tablesListInstance tableType] == SPTableTypeTable) { - if (clearAllCaches) [tableDataInstance updateInformationForCurrentTable]; + if (clearAllCaches) { + [tableDataInstance resetAllData]; + [tableDataInstance updateTriggersForCurrentTable]; + } NSArray *triggers = [tableDataInstance triggers]; diff --git a/Source/TableDump.m b/Source/TableDump.m index 9f40d90e..004a8e61 100644 --- a/Source/TableDump.m +++ b/Source/TableDump.m @@ -1921,52 +1921,52 @@ // Release the result set [streamingResult release]; + } + + // Export triggers, if any + queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"/*!50003 SHOW TRIGGERS WHERE `Table` = %@ */;", + [tableName tickQuotedString]]]; + [queryResult setReturnDataAsStrings:YES]; + if ( [queryResult numOfRows] ) { + [metaString setString:@"\n"]; + [metaString appendString:@"DELIMITER ;;\n"]; - queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"/*!50003 SHOW TRIGGERS WHERE `Table` = %@ */;", - [tableName tickQuotedString]]]; - [queryResult setReturnDataAsStrings:YES]; - if ( [queryResult numOfRows] ) { - [metaString setString:@"\n"]; - [metaString appendString:@"DELIMITER ;;\n"]; + for (int s=0; s<[queryResult numOfRows]; s++) { + NSDictionary *triggers = [[NSDictionary alloc] initWithDictionary:[queryResult fetchRowAsDictionary]]; - for (int s=0; s<[queryResult numOfRows]; s++) { - NSDictionary *triggers = [[NSDictionary alloc] initWithDictionary:[queryResult fetchRowAsDictionary]]; - - //Definer is user@host but we need to escape it to `user`@`host` - NSArray *triggersDefiner = [[triggers objectForKey:@"Definer"] componentsSeparatedByString:@"@"]; - NSString *escapedDefiner = [NSString stringWithFormat:@"%@@%@", - [[triggersDefiner objectAtIndex:0] backtickQuotedString], - [[triggersDefiner objectAtIndex:1] backtickQuotedString] - ]; - - [metaString appendString:[NSString stringWithFormat:@"/*!50003 SET SESSION SQL_MODE=\"%@\" */;;\n", - [triggers objectForKey:@"sql_mode"]]]; - [metaString appendString:@"/*!50003 CREATE */ "]; - [metaString appendString:[NSString stringWithFormat:@"/*!50017 DEFINER=%@ */ ", - escapedDefiner]]; - [metaString appendString:[NSString stringWithFormat:@"/*!50003 TRIGGER %@ %@ %@ ON %@ FOR EACH ROW %@ */;;\n", - [[triggers objectForKey:@"Trigger"] backtickQuotedString], - [triggers objectForKey:@"Timing"], - [triggers objectForKey:@"Event"], - [[triggers objectForKey:@"Table"] backtickQuotedString], - [triggers objectForKey:@"Statement"] - ]]; - [triggers release]; - } + //Definer is user@host but we need to escape it to `user`@`host` + NSArray *triggersDefiner = [[triggers objectForKey:@"Definer"] componentsSeparatedByString:@"@"]; + NSString *escapedDefiner = [NSString stringWithFormat:@"%@@%@", + [[triggersDefiner objectAtIndex:0] backtickQuotedString], + [[triggersDefiner objectAtIndex:1] backtickQuotedString] + ]; - [metaString appendString:@"DELIMITER ;\n"]; - [metaString appendString:@"/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n"]; - [fileHandle writeData:[metaString dataUsingEncoding:NSUTF8StringEncoding]]; + [metaString appendString:[NSString stringWithFormat:@"/*!50003 SET SESSION SQL_MODE=\"%@\" */;;\n", + [triggers objectForKey:@"sql_mode"]]]; + [metaString appendString:@"/*!50003 CREATE */ "]; + [metaString appendString:[NSString stringWithFormat:@"/*!50017 DEFINER=%@ */ ", + escapedDefiner]]; + [metaString appendString:[NSString stringWithFormat:@"/*!50003 TRIGGER %@ %@ %@ ON %@ FOR EACH ROW %@ */;;\n", + [[triggers objectForKey:@"Trigger"] backtickQuotedString], + [triggers objectForKey:@"Timing"], + [triggers objectForKey:@"Event"], + [[triggers objectForKey:@"Table"] backtickQuotedString], + [triggers objectForKey:@"Statement"] + ]]; + [triggers release]; } - if ([mySQLConnection queryErrored]) { - [errors appendString:[NSString stringWithFormat:@"%@\n", [mySQLConnection getLastErrorMessage]]]; - if ( [addErrorsSwitch state] == NSOnState ) { - [fileHandle writeData:[[NSString stringWithFormat:@"# Error: %@\n", [mySQLConnection getLastErrorMessage]] - dataUsingEncoding:NSUTF8StringEncoding]]; - } + [metaString appendString:@"DELIMITER ;\n"]; + [metaString appendString:@"/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n"]; + [fileHandle writeData:[metaString dataUsingEncoding:NSUTF8StringEncoding]]; + } + + if ([mySQLConnection queryErrored]) { + [errors appendString:[NSString stringWithFormat:@"%@\n", [mySQLConnection getLastErrorMessage]]]; + if ( [addErrorsSwitch state] == NSOnState ) { + [fileHandle writeData:[[NSString stringWithFormat:@"# Error: %@\n", [mySQLConnection getLastErrorMessage]] + dataUsingEncoding:NSUTF8StringEncoding]]; } - } // Add an additional separator between tables diff --git a/Source/TablesList.h b/Source/TablesList.h index 5c6ccf96..36d3ccaa 100644 --- a/Source/TablesList.h +++ b/Source/TablesList.h @@ -48,6 +48,7 @@ IBOutlet id extendedTableInfoInstance; IBOutlet id databaseDataInstance; IBOutlet id tableInfoInstance; + IBOutlet id tableTriggersInstance; IBOutlet SPHistoryController *spHistoryControllerInstance; IBOutlet id tableWindow; @@ -102,7 +103,7 @@ BOOL tableListIsSelectable; BOOL tableListContainsViews; - BOOL structureLoaded, contentLoaded, statusLoaded, alertSheetOpened; + BOOL structureLoaded, contentLoaded, statusLoaded, triggersLoaded, alertSheetOpened; } // IBAction methods diff --git a/Source/TablesList.m b/Source/TablesList.m index e39da649..15def773 100644 --- a/Source/TablesList.m +++ b/Source/TablesList.m @@ -693,40 +693,35 @@ // Restore view states as appropriate [spHistoryControllerInstance restoreViewStates]; + structureLoaded = NO; + contentLoaded = NO; + statusLoaded = NO; + triggersLoaded = NO; if( selectedTableType == SPTableTypeView || selectedTableType == SPTableTypeTable) { if ( [tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 0 ) { [tableSourceInstance loadTable:selectedTableName]; structureLoaded = YES; - contentLoaded = NO; - statusLoaded = NO; } else if ( [tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 1 ) { if(tableEncoding == nil) { [tableContentInstance loadTable:nil]; } else { [tableContentInstance loadTable:selectedTableName]; } - structureLoaded = NO; contentLoaded = YES; - statusLoaded = NO; } else if ( [tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 3 ) { - [extendedTableInfoInstance performSelectorOnMainThread:@selector(loadTable:) withObject:selectedTableName waitUntilDone:YES]; - structureLoaded = NO; - contentLoaded = NO; + [[extendedTableInfoInstance onMainThread] loadTable:selectedTableName]; statusLoaded = YES; - } else { - structureLoaded = NO; - contentLoaded = NO; - statusLoaded = NO; + } else if ( [tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 5 ) { + [[tableTriggersInstance onMainThread] loadTriggers]; + triggersLoaded = YES; } } else { // if we are not looking at a table or view, clear these [tableSourceInstance loadTable:nil]; [tableContentInstance loadTable:nil]; - [extendedTableInfoInstance performSelectorOnMainThread:@selector(loadTable:) withObject:nil waitUntilDone:YES]; - structureLoaded = NO; - contentLoaded = NO; - statusLoaded = NO; + [[extendedTableInfoInstance onMainThread] loadTable:nil]; + [[tableTriggersInstance onMainThread] loadTriggers]; } // Update the "Show Create Syntax" window if it's already opened @@ -769,10 +764,12 @@ [tableSourceInstance loadTable:nil]; [tableContentInstance loadTable:nil]; [extendedTableInfoInstance loadTable:nil]; + [tableTriggersInstance loadTriggers]; structureLoaded = NO; contentLoaded = NO; statusLoaded = NO; + triggersLoaded = NO; // Set gear menu items Remove/Duplicate table/view according to the table types // if at least one item is selected @@ -1358,24 +1355,27 @@ // if the 'table' is a view or a table, reload the currently selected view if (selectedTableType == SPTableTypeTable || selectedTableType == SPTableTypeView) { + statusLoaded = NO; + structureLoaded = NO; + contentLoaded = NO; + triggersLoaded = NO; switch ([tabView indexOfTabViewItem:[tabView selectedTabViewItem]]) { case 0: [tableSourceInstance loadTable:newTableName]; structureLoaded = YES; - contentLoaded = statusLoaded = NO; break; case 1: [tableContentInstance loadTable:newTableName]; contentLoaded = YES; - structureLoaded = statusLoaded = NO; break; case 3: [extendedTableInfoInstance loadTable:newTableName]; statusLoaded = YES; - structureLoaded = contentLoaded = NO; break; - default: - statusLoaded = structureLoaded = contentLoaded = NO; + case 5: + [tableTriggersInstance loadTriggers]; + triggersLoaded = YES; + break; } } } @@ -1560,8 +1560,9 @@ { NSAutoreleasePool *tabLoadPool = [[NSAutoreleasePool alloc] init]; - if ( [tablesListView numberOfSelectedRows] == 1 && - ([self tableType] == SPTableTypeTable || [self tableType] == SPTableTypeView) ) { + if ([tablesListView numberOfSelectedRows] == 1 + && ([self tableType] == SPTableTypeTable || [self tableType] == SPTableTypeView) ) + { if ( ([tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 0) && !structureLoaded ) { [tableSourceInstance loadTable:selectedTableName]; @@ -1574,9 +1575,14 @@ } if ( ([tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 3) && !statusLoaded ) { - [extendedTableInfoInstance performSelectorOnMainThread:@selector(loadTable:) withObject:selectedTableName waitUntilDone:YES]; + [[extendedTableInfoInstance onMainThread] loadTable:selectedTableName]; statusLoaded = YES; } + + if ( ([tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 5) && !triggersLoaded ) { + [[tableTriggersInstance onMainThread] loadTriggers]; + triggersLoaded = YES; + } } else { [tableSourceInstance loadTable:nil]; @@ -1805,6 +1811,7 @@ structureLoaded = NO; contentLoaded = NO; statusLoaded = NO; + triggersLoaded = NO; isTableListFiltered = NO; tableListIsSelectable = YES; tableListContainsViews = NO; -- cgit v1.2.3