diff options
author | rowanbeentje <rowan@beent.je> | 2010-06-07 13:44:45 +0000 |
---|---|---|
committer | rowanbeentje <rowan@beent.je> | 2010-06-07 13:44:45 +0000 |
commit | 4c7cbdf882ad1e1bb1a5a11dc59dc53b90bee686 (patch) | |
tree | ffa901519ec9b970a76f6437feb39de65e04498a | |
parent | 42781adb6cfa7f01f3763aade1b5043995930756 (diff) | |
download | sequelpro-4c7cbdf882ad1e1bb1a5a11dc59dc53b90bee686.tar.gz sequelpro-4c7cbdf882ad1e1bb1a5a11dc59dc53b90bee686.tar.bz2 sequelpro-4c7cbdf882ad1e1bb1a5a11dc59dc53b90bee686.zip |
A number of exporter improvements:
- Improve interface validation on the SQL view, including fixing no-content toggling
- Fix the export of views to correctly construct placeholder tables and fix view syntax export (this addresses Issue #707)
- Fix logic controlling Stored Procedure and Function export - fix hangs and allow correct export
- Handle permission errors when retrieving Stored Pro/Function syntax
- Improve export of linebreaks in CSV quoted cells for improved Excel compatibility
- SQL export now retrieves table syntax as it progresses through the tables - more accurate progress bar and removes initial pause when exporting lots of tables
- Alter filename construction to use centralised filename string: fixes end export Growl notification
- Improve dump comments
-rw-r--r-- | Source/SPCSVExporter.m | 12 | ||||
-rw-r--r-- | Source/SPExportController.h | 4 | ||||
-rw-r--r-- | Source/SPExportController.m | 13 | ||||
-rw-r--r-- | Source/SPExportInitializer.m | 75 | ||||
-rw-r--r-- | Source/SPSQLExporter.h | 8 | ||||
-rw-r--r-- | Source/SPSQLExporter.m | 166 | ||||
-rw-r--r-- | Source/SPTableData.m | 3 |
7 files changed, 144 insertions, 137 deletions
diff --git a/Source/SPCSVExporter.m b/Source/SPCSVExporter.m index b465b4e2..49d6ade6 100644 --- a/Source/SPCSVExporter.m +++ b/Source/SPCSVExporter.m @@ -330,18 +330,16 @@ range:NSMakeRange(0, [csvCellString length])]; } - // Escape occurrences of the line end character - [csvCellString replaceOccurrencesOfString:[self csvLineEndingString] - withString:escapedLineEndString - options:NSLiteralSearch - range:NSMakeRange(0, [csvCellString length])]; - - // If the string isn't quoted or otherwise enclosed, escape occurrences of the field separators + // If the string isn't quoted or otherwise enclosed, escape occurrences of the field separators and line end character if (quoteFieldSeparators || csvCellIsNumeric) { [csvCellString replaceOccurrencesOfString:[self csvFieldSeparatorString] withString:escapedFieldSeparatorString options:NSLiteralSearch range:NSMakeRange(0, [csvCellString length])]; + [csvCellString replaceOccurrencesOfString:[self csvLineEndingString] + withString:escapedLineEndString + options:NSLiteralSearch + range:NSMakeRange(0, [csvCellString length])]; } // Write out the cell data by appending strings - this is significantly faster than stringWithFormat. diff --git a/Source/SPExportController.h b/Source/SPExportController.h index 32541d19..8d0a6969 100644 --- a/Source/SPExportController.h +++ b/Source/SPExportController.h @@ -131,7 +131,7 @@ /** * Number of tables being exported */ - NSUInteger exportTableCount; + NSUInteger exportTableCount; /** * Index of the current table being exported @@ -146,7 +146,7 @@ /** * Export filename */ - NSString *exportFilename; + NSMutableString *exportFilename; /** * Current database's tables diff --git a/Source/SPExportController.m b/Source/SPExportController.m index 6da5b544..ca4f1ac8 100644 --- a/Source/SPExportController.m +++ b/Source/SPExportController.m @@ -67,7 +67,7 @@ exportTableCount = 0; currentTableExportIndex = 0; - exportFilename = @""; + exportFilename = [[NSMutableString alloc] init]; exportTypeLabel = @""; createCustomFilename = NO; @@ -520,9 +520,7 @@ */ - (IBAction)toggleSQLIncludeContent:(id)sender { - [sender setTag:[sender state]]; - - [self selectDeselectAllTables:sender]; + [[exportTableList tableColumnWithIdentifier:@"content"] setHidden:(![sender state])]; [self _toggleExportButtonOnBackgroundThread]; } @@ -640,6 +638,7 @@ [tables release], tables = nil; [exporters release], exporters = nil; [operationQueue release], operationQueue = nil; + [exportFilename release], exportFilename = nil; if (sqlPreviousConnectionEncoding) [sqlPreviousConnectionEncoding release], sqlPreviousConnectionEncoding = nil; @@ -678,9 +677,9 @@ } } else if (isSQL) { - BOOL structureEnabled = [uiStateDict objectForKey:@"SQLExportStructureEnabled"]; - BOOL contentEnabled = [uiStateDict objectForKey:@"SQLExportContentEnabled"]; - BOOL dropEnabled = [uiStateDict objectForKey:@"SQLExportDropEnabled"]; + BOOL structureEnabled = [[uiStateDict objectForKey:@"SQLExportStructureEnabled"] integerValue]; + BOOL contentEnabled = [[uiStateDict objectForKey:@"SQLExportContentEnabled"] integerValue]; + BOOL dropEnabled = [[uiStateDict objectForKey:@"SQLExportDropEnabled"] integerValue]; // Disable if all are unchecked if ((!contentEnabled) && (!structureEnabled) && (!dropEnabled)) { diff --git a/Source/SPExportInitializer.m b/Source/SPExportInitializer.m index 0cfa88b1..c5779dc6 100644 --- a/Source/SPExportInitializer.m +++ b/Source/SPExportInitializer.m @@ -178,30 +178,28 @@ // If the user has selected to only export to a single file or this is a filtered or custom query // export, create the single file now and assign it to all subsequently created exporters. if ((![self exportToMultipleFiles]) || (exportSource == SPFilteredExport) || (exportSource == SPQueryExport)) { - - NSString *filename = @""; - + // Create custom filename if required if (createCustomFilename) { - filename = [self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:nil]; + [exportFilename setString:[self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:nil]]; } else { // Determine what the file name should be switch (exportSource) { case SPFilteredExport: - filename = [NSString stringWithFormat:@"%@_view", [tableDocumentInstance table]]; + [exportFilename setString:[NSString stringWithFormat:@"%@_view", [tableDocumentInstance table]]]; break; case SPQueryExport: - filename = @"query_result"; + [exportFilename setString:@"query_result"]; break; case SPTableExport: - filename = [tableDocumentInstance database]; + [exportFilename setString:[tableDocumentInstance database]]; break; } } - singleFileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:filename]]; + singleFileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:exportFilename]]; } // Start the export process depending on the data source @@ -294,17 +292,7 @@ sqlPreviousConnectionEncodingViaLatin1 = [tableDocumentInstance connectionEncodingViaLatin1:nil]; [tableDocumentInstance setConnectionEncoding:@"utf8" reloadingViews:NO]; - - NSMutableArray *tableTypes = [[NSMutableArray alloc] init]; - NSMutableDictionary *infoDict = [[NSMutableDictionary alloc] init]; - - // Build the table information dictionary as well as the table array with item type - for (NSArray *table in exportTables) - { - [infoDict setObject:[tableDataInstance informationForTable:[table objectAtIndex:0]] forKey:[table objectAtIndex:0]]; - } - - [sqlExporter setSqlTableInformation:infoDict]; + [sqlExporter setSqlExportTables:exportTables]; // Set the exporter's max progress @@ -313,15 +301,11 @@ // Set the progress bar's max value [exportProgressIndicator setMaxValue:[sqlExporter exportMaxProgress]]; - [infoDict release]; - [tableTypes release]; - - NSString *filename = @""; - // Create custom filename if required - filename = (createCustomFilename) ? [self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:nil] : [NSString stringWithFormat:@"%@_%@", [tableDocumentInstance database], [[NSDate date] descriptionWithCalendarFormat:@"%Y-%m-%d" timeZone:nil locale:nil]]; + [exportFilename setString:(createCustomFilename) ? [self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:nil] : [NSString stringWithFormat:@"%@_%@", [tableDocumentInstance database], [[NSDate date] descriptionWithCalendarFormat:@"%Y-%m-%d" timeZone:nil locale:nil]]]; + [exportFilename setString:[exportFilename stringByAppendingPathExtension:([exportCompressOutputFile state]) ? @"sql.gz" : @"sql"]]; - SPFileHandle *fileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:[filename stringByAppendingPathExtension:([exportCompressOutputFile state]) ? @"sql.gz" : @"sql"]]]; + SPFileHandle *fileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:exportFilename]]; [sqlExporter setExportOutputFileHandle:fileHandle]; @@ -338,29 +322,28 @@ // export, create the single file now and assign it to all subsequently created exporters. if ((![self exportToMultipleFiles]) || (exportSource == SPFilteredExport) || (exportSource == SPQueryExport)) { - NSString *filename = @""; - // Create custom filename if required if (createCustomFilename) { - filename = [self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:nil]; + [exportFilename setString:[self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:nil]]; } else { // Determine what the file name should be switch (exportSource) { case SPFilteredExport: - filename = [NSString stringWithFormat:@"%@_view", [tableDocumentInstance table]]; + [exportFilename setString:[NSString stringWithFormat:@"%@_view", [tableDocumentInstance table]]]; break; case SPQueryExport: - filename = @"query_result"; + [exportFilename setString:@"query_result"]; break; case SPTableExport: - filename = [tableDocumentInstance database]; + [exportFilename setString:[tableDocumentInstance database]]; break; } } + [exportFilename setString:[exportFilename stringByAppendingPathExtension:@"xml"]]; - singleFileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:[filename stringByAppendingPathExtension:@"xml"]]]; + singleFileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:exportFilename]]; } // Start the export process depending on the data source @@ -431,17 +414,16 @@ // Set the progress bar's max value [exportProgressIndicator setMaxValue:[dotExporter exportMaxProgress]]; - NSString *filename = @""; - // Create custom filename if required if (createCustomFilename) { - filename = [self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:nil]; + [exportFilename setString:[self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:nil]]; } else { - filename = [tableDocumentInstance database]; + [exportFilename setString:[tableDocumentInstance database]]; } - - SPFileHandle *fileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:[filename stringByAppendingPathExtension:@"dot"]]]; + [exportFilename setString:[exportFilename stringByAppendingPathExtension:@"dot"]]; + + SPFileHandle *fileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:exportFilename]]; [dotExporter setExportOutputFileHandle:fileHandle]; @@ -463,7 +445,6 @@ */ - (SPCSVExporter *)initializeCSVExporterForTable:(NSString *)table orDataArray:(NSArray *)dataArray { - NSString *filename = @""; SPFileHandle *fileHandle = nil; SPCSVExporter *csvExporter = [[SPCSVExporter alloc] initWithDelegate:self]; @@ -491,17 +472,17 @@ if (createCustomFilename) { // Create custom filename based on the selected format - filename = [self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:table]; + [exportFilename setString:[self expandCustomFilenameFormatFromString:[exportCustomFilenameTokenField stringValue] usingTableName:table]]; // If the user chose to use a custom filename format and we exporting to multiple files, make // sure the table name is included to ensure the output files are unique. - filename = ([[exportCustomFilenameTokenField stringValue] rangeOfString:@"table" options:NSLiteralSearch].location == NSNotFound) ? [filename stringByAppendingFormat:@"_%@", table] : filename; + [exportFilename setString:([[exportCustomFilenameTokenField stringValue] rangeOfString:@"table" options:NSLiteralSearch].location == NSNotFound) ? [exportFilename stringByAppendingFormat:@"_%@", table] : exportFilename]; } else { - filename = table; + [exportFilename setString:table]; } - fileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:filename]]; + fileHandle = [self getFileHandleForFilePath:[[exportPathField stringValue] stringByAppendingPathComponent:exportFilename]]; [csvExporter setExportOutputFileHandle:fileHandle]; } @@ -523,7 +504,6 @@ */ - (SPXMLExporter *)initializeXMLExporterForTable:(NSString *)table orDataArray:(NSArray *)dataArray { - NSString *filename = @""; SPFileHandle *fileHandle = nil; SPXMLExporter *xmlExporter = [[SPXMLExporter alloc] initWithDelegate:self]; @@ -544,9 +524,10 @@ // If required create separate files if ((exportSource == SPTableExport) && exportToMultipleFiles && (exportTableCount > 0)) { - filename = [[exportPathField stringValue] stringByAppendingPathComponent:table]; + [exportFilename setString:[[exportPathField stringValue] stringByAppendingPathComponent:table]]; + [exportFilename setString:[exportFilename stringByAppendingPathExtension:@"xml"]]; - fileHandle = [self getFileHandleForFilePath:[filename stringByAppendingPathExtension:@"xml"]]; + fileHandle = [self getFileHandleForFilePath:exportFilename]; // Write the file header [self writeXMLHeaderToFileHandle:fileHandle]; diff --git a/Source/SPSQLExporter.h b/Source/SPSQLExporter.h index 735056aa..12ed686e 100644 --- a/Source/SPSQLExporter.h +++ b/Source/SPSQLExporter.h @@ -28,6 +28,8 @@ #import "SPExporter.h" #import "SPSQLExporterProtocol.h" +@class SPTableData; + /** * @class SPSQLExporter SPSQLExporter.m * @@ -95,9 +97,9 @@ NSUInteger sqlCurrentTableExportIndex; /** - * Table information + * Table information fetcher and parser */ - NSDictionary *sqlTableInformation; + SPTableData *sqlTableDataInstance; } @property(readwrite, assign) NSObject *delegate; @@ -118,8 +120,6 @@ @property(readwrite, assign) NSUInteger sqlCurrentTableExportIndex; -@property(readwrite, retain) NSDictionary *sqlTableInformation; - /** * Initialise an instance of SPSQLExporter using the supplied delegate. * diff --git a/Source/SPSQLExporter.m b/Source/SPSQLExporter.m index eda13741..1c1ebadc 100644 --- a/Source/SPSQLExporter.m +++ b/Source/SPSQLExporter.m @@ -32,6 +32,7 @@ #import "SPStringAdditions.h" #import "SPFileHandle.h" #import "SPExportUtilities.h" +#import "SPTableData.h" @interface SPSQLExporter (PrivateAPI) @@ -53,7 +54,6 @@ @synthesize sqlOutputIncludeErrors; @synthesize sqlOutputCompressFile; @synthesize sqlCurrentTableExportIndex; -@synthesize sqlTableInformation; /** * Initialise an instance of SPSQLExporter using the supplied delegate. @@ -77,6 +77,9 @@ - (void)main { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + sqlTableDataInstance = [[[SPTableData alloc] init] autorelease]; + [sqlTableDataInstance setConnection:connection]; + NSAutoreleasePool *sqlExportPool = [[NSAutoreleasePool alloc] init]; MCPResult *queryResult; @@ -108,7 +111,6 @@ // Check that we have all the required info before starting the export if ((![self sqlExportTables]) || ([[self sqlExportTables] count] == 0) || - (![self sqlTableInformation]) || ([[self sqlTableInformation] count] == 0) || (![self sqlDatabaseHost]) || ([[self sqlDatabaseHost] isEqualToString:@""]) || (![self sqlDatabaseName]) || ([[self sqlDatabaseName] isEqualToString:@""]) || (![self sqlDatabaseVersion] || ([[self sqlDatabaseName] isEqualToString:@""]))) @@ -192,7 +194,7 @@ [[self exportOutputFileHandle] writeData:[metaString dataUsingEncoding:[self exportOutputEncoding]]]; // Loop through the selected tables - for (NSArray *table in [self sqlExportTables]) + for (NSArray *table in tables) { // Check for cancellation flag if ([self isCancelled]) { @@ -268,7 +270,7 @@ if (sqlOutputIncludeContent && (tableType == SPTableTypeTable)) { // Retrieve the table details via the data class, and use it to build an array containing column numeric status - tableDetails = [NSDictionary dictionaryWithDictionary:[[self sqlTableInformation] objectForKey:tableName]]; + tableDetails = [NSDictionary dictionaryWithDictionary:[sqlTableDataInstance informationForTable:tableName]]; NSUInteger colCount = [[tableDetails objectForKey:@"columns"] count]; @@ -461,63 +463,62 @@ // Release the result set [streamingResult release]; + } - queryResult = [connection queryString:[NSString stringWithFormat:@"/*!50003 SHOW TRIGGERS WHERE `Table` = %@ */;", [tableName tickQuotedString]]]; + queryResult = [connection queryString:[NSString stringWithFormat:@"/*!50003 SHOW TRIGGERS WHERE `Table` = %@ */;", [tableName tickQuotedString]]]; + + [queryResult setReturnDataAsStrings:YES]; + + if ([queryResult numOfRows]) { - [queryResult setReturnDataAsStrings:YES]; + [metaString setString:@"\n"]; + [metaString appendString:@"DELIMITER ;;\n"]; - if ([queryResult numOfRows]) { + for (s = 0; s < [queryResult numOfRows]; s++) + { + // Check for cancellation flag + if ([self isCancelled]) { + [pool release]; + return; + } - [metaString setString:@"\n"]; - [metaString appendString:@"DELIMITER ;;\n"]; + NSDictionary *triggers = [[NSDictionary alloc] initWithDictionary:[queryResult fetchRowAsDictionary]]; - for (s = 0; s < [queryResult numOfRows]; s++) - { - // Check for cancellation flag - if ([self isCancelled]) { - [pool release]; - return; - } - - 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:@"%@@%@", - [NSArrayObjectAtIndex(triggersDefiner, 0) backtickQuotedString], - [NSArrayObjectAtIndex(triggersDefiner, 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:@"@"]; - [metaString appendString:@"DELIMITER ;\n"]; - [metaString appendString:@"/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n"]; + NSString *escapedDefiner = [NSString stringWithFormat:@"%@@%@", + [NSArrayObjectAtIndex(triggersDefiner, 0) backtickQuotedString], + [NSArrayObjectAtIndex(triggersDefiner, 1) backtickQuotedString] + ]; - [[self exportOutputFileHandle] 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 ([connection queryErrored]) { - [errors appendString:[NSString stringWithFormat:@"%@\n", [connection getLastErrorMessage]]]; - - if ([self sqlOutputIncludeErrors]) { - [[self exportOutputFileHandle] writeData:[[NSString stringWithFormat:@"# Error: %@\n", [connection getLastErrorMessage]] - dataUsingEncoding:NSUTF8StringEncoding]]; - } - } + [metaString appendString:@"DELIMITER ;\n"]; + [metaString appendString:@"/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n"]; + + [[self exportOutputFileHandle] writeData:[metaString dataUsingEncoding:NSUTF8StringEncoding]]; + } + + if ([connection queryErrored]) { + [errors appendString:[NSString stringWithFormat:@"%@\n", [connection getLastErrorMessage]]]; + if ([self sqlOutputIncludeErrors]) { + [[self exportOutputFileHandle] writeData:[[NSString stringWithFormat:@"# Error: %@\n", [connection getLastErrorMessage]] + dataUsingEncoding:NSUTF8StringEncoding]]; + } } // Add an additional separator between tables @@ -534,6 +535,8 @@ } [metaString setString:@"\n\n"]; + // Add the name of table + [metaString appendFormat:@"# Replace placeholder table for %@ with correct view syntax\n# ------------------------------------------------------------\n\n", tableName]; [metaString appendFormat:@"DROP TABLE %@;\n", [tableName backtickQuotedString]]; [metaString appendFormat:@"%@;\n", [viewSyntaxes objectForKey:tableName]]; @@ -571,7 +574,7 @@ [[self sqlDatabaseName] tickQuotedString]]]; [metaString appendString:@"--\n"]; - [metaString appendString:@"DELIMITER ;;\n"]; + [metaString appendString:@"DELIMITER ;;\n\n"]; // Loop through the definitions, exporting if enabled for (s = 0; s < [queryResult numOfRows]; s++) @@ -581,32 +584,37 @@ [pool release]; return; } - + NSDictionary *proceduresList = [[NSDictionary alloc] initWithDictionary:[queryResult fetchRowAsDictionary]]; NSString *procedureName = [NSString stringWithFormat:@"%@", [proceduresList objectForKey:@"Name"]]; - - // Only proceed if the item was selected for export - if (![items containsObject:procedureName]) { - [proceduresList release]; - continue; - } - + // Only proceed if the item is in the list of items + BOOL itemFound = NO; for (NSArray *item in items) { // Check for cancellation flag if ([self isCancelled]) { + [proceduresList release]; [pool release]; return; } if ([NSArrayObjectAtIndex(item, 0) isEqualToString:procedureName]) { + itemFound = YES; sqlOutputIncludeStructure = [NSArrayObjectAtIndex(item, 1) boolValue]; sqlOutputIncludeContent = [NSArrayObjectAtIndex(item, 2) boolValue]; sqlOutputIncludeDropSyntax = [NSArrayObjectAtIndex(item, 3) boolValue]; + break; } } - + if (!itemFound) { + [proceduresList release]; + continue; + } + + if (sqlOutputIncludeStructure || sqlOutputIncludeDropSyntax) + [metaString appendFormat:@"# Dump of %@ %@\n# ------------------------------------------------------------\n\n", procedureType, procedureName]; + // Add the 'DROP' command if required if (sqlOutputIncludeDropSyntax) { [metaString appendString:[NSString stringWithFormat:@"/*!50003 DROP %@ IF EXISTS %@ */;;\n", procedureType, @@ -614,7 +622,7 @@ } // Only continue if the 'CREATE SYNTAX' is required - if (sqlOutputIncludeStructure) { + if (!sqlOutputIncludeStructure) { [proceduresList release]; continue; } @@ -629,14 +637,35 @@ MCPResult *createProcedureResult = [connection queryString:[NSString stringWithFormat:@"/*!50003 SHOW CREATE %@ %@ */;;", procedureType, [procedureName backtickQuotedString]]]; - [createProcedureResult setReturnDataAsStrings:YES]; + if ([connection queryErrored]) { + [errors appendString:[NSString stringWithFormat:@"%@\n", [connection getLastErrorMessage]]]; + + if ([self sqlOutputIncludeErrors]) { + [[self exportOutputFileHandle] writeData:[[NSString stringWithFormat:@"# Error: %@\n", [connection getLastErrorMessage]] dataUsingEncoding:NSUTF8StringEncoding]]; + } + [proceduresList release]; + continue; + } NSDictionary *procedureInfo = [[NSDictionary alloc] initWithDictionary:[createProcedureResult fetchRowAsDictionary]]; [metaString appendString:[NSString stringWithFormat:@"/*!50003 SET SESSION SQL_MODE=\"%@\"*/;;\n", [procedureInfo objectForKey:@"sql_mode"]]]; - NSString *createProcedure = [procedureInfo objectForKey:[NSString stringWithFormat:@"Create %@", [procedureType capitalizedString]]]; + NSString *createProcedure = [procedureInfo objectForKey:[NSString stringWithFormat:@"Create %@", [procedureType capitalizedString]]]; + + // A NULL result indicates a permission problem + if ([createProcedure isNSNull]) { + NSString *errorString = [NSString stringWithFormat:NSLocalizedString(@"Could not export the %@ '%@' because of a permisions error.\n", @"Procedure/function export permission error"), procedureType, procedureName]; + [errors appendString:errorString]; + if ([self sqlOutputIncludeErrors]) { + [[self exportOutputFileHandle] writeData:[[NSString stringWithFormat:@"# Error: %@\n", errorString] dataUsingEncoding:NSUTF8StringEncoding]]; + } + [proceduresList release]; + [procedureInfo release]; + continue; + } + NSRange procedureRange = [createProcedure rangeOfString:procedureType options:NSCaseInsensitiveSearch]; NSString *procedureBody = [createProcedure substringFromIndex:procedureRange.location]; @@ -646,7 +675,7 @@ // END */;; // // Build the CREATE PROCEDURE string to include MySQL Version limiters - [metaString appendString:[NSString stringWithFormat:@"/*!50003 CREATE*/ /*!50020 DEFINER=%@*/ /*!50003 %@ */;;\n", escapedDefiner, procedureBody]]; + [metaString appendString:[NSString stringWithFormat:@"/*!50003 CREATE*/ /*!50020 DEFINER=%@*/ /*!50003 %@ */;;\n\n", escapedDefiner, procedureBody]]; [procedureInfo release]; [proceduresList release]; @@ -723,12 +752,12 @@ NSMutableString *placeholderSyntax; // Get structured information for the view via the SPTableData parsers - NSDictionary *viewInformation = [[self sqlTableInformation] objectForKey:viewName]; + NSDictionary *viewInformation = [sqlTableDataInstance informationForView:viewName]; if (!viewInformation) return nil; NSArray *viewColumns = [viewInformation objectForKey:@"columns"]; - + // Set up the start of the placeholder string and initialise an empty field string placeholderSyntax = [[NSMutableString alloc] initWithFormat:@"CREATE TABLE %@ (\n", [viewName backtickQuotedString]]; @@ -788,7 +817,7 @@ } // Append the remainder of the table string - [placeholderSyntax appendString:@") ENGINE=MyISAM;"]; + [placeholderSyntax appendString:@") ENGINE=MyISAM"]; // Clean up and return [fieldString release]; @@ -806,7 +835,6 @@ [sqlDatabaseName release], sqlDatabaseName = nil; [sqlExportCurrentTable release], sqlExportCurrentTable = nil; [sqlDatabaseVersion release], sqlDatabaseVersion = nil; - [sqlTableInformation release], sqlTableInformation = nil; [super dealloc]; } diff --git a/Source/SPTableData.m b/Source/SPTableData.m index 35d7060b..6e169e09 100644 --- a/Source/SPTableData.m +++ b/Source/SPTableData.m @@ -781,7 +781,8 @@ // The character set has to be guessed at via the database encoding. // Add the details to the data object. viewData = [NSMutableDictionary dictionary]; - [viewData setObject:[NSString stringWithString:[tableDocumentInstance databaseEncoding]] forKey:@"encoding"]; + if (tableDocumentInstance) + [viewData setObject:[NSString stringWithString:[tableDocumentInstance databaseEncoding]] forKey:@"encoding"]; [viewData setObject:[NSArray arrayWithArray:tableColumns] forKey:@"columns"]; [tableColumns release]; |