From 61541a2b48b7f475394e7301794bca514f43ddf1 Mon Sep 17 00:00:00 2001 From: stuconnolly Date: Wed, 16 Sep 2009 14:04:33 +0000 Subject: Some more data exporter redesign changes I've been meaning to commit. --- Source/SPCSVExporter.h | 18 +- Source/SPCSVExporter.m | 61 ++---- Source/SPExportController.h | 19 +- Source/SPExportController.m | 493 +++++++++++++++++++++++++++++++------------- Source/SPExporter.h | 16 +- Source/SPExporter.m | 30 ++- Source/SPSQLExporter.h | 9 +- Source/SPSQLExporter.m | 16 -- 8 files changed, 426 insertions(+), 236 deletions(-) (limited to 'Source') diff --git a/Source/SPCSVExporter.h b/Source/SPCSVExporter.h index 3fa6f276..51569838 100644 --- a/Source/SPCSVExporter.h +++ b/Source/SPCSVExporter.h @@ -27,9 +27,8 @@ #import "MCPKit.h" #import "SPExporter.h" -#import "SPExporterAccess.h" -@interface SPCSVExporter : SPExporter +@interface SPCSVExporter : SPExporter { // CSV file NSFileHandle *csvFileHandle; @@ -46,13 +45,6 @@ NSString *csvLineEndingString; NSString *csvNULLString; NSArray *csvTableColumnNumericStatus; - - // CSV encoding - NSStringEncoding csvOutputEncoding; - - // Operational - BOOL csvExportIsRunning; - BOOL csvThreadShouldExit; } @property (readwrite, retain) NSFileHandle *csvFileHandle; @@ -68,12 +60,4 @@ @property (readwrite, retain) NSString *csvNULLString; @property (readwrite, retain) NSArray *csvTableColumnNumericStatus; -@property (readwrite, assign) NSStringEncoding csvOutputEncoding; - -@property (readwrite, assign) BOOL csvExportIsRunning; -@property (readwrite, assign) BOOL csvThreadShouldExit; - -- (BOOL)startExportProcess; -- (BOOL)stopExportProcess; - @end diff --git a/Source/SPCSVExporter.m b/Source/SPCSVExporter.m index a157b051..b508172b 100644 --- a/Source/SPCSVExporter.m +++ b/Source/SPCSVExporter.m @@ -28,7 +28,7 @@ @interface SPCSVExporter (PrivateAPI) -- (void)startCSVExportInBackgroundThread; +- (void)_startCSVExportInBackgroundThread; @end @@ -47,24 +47,6 @@ @synthesize csvNULLString; @synthesize csvTableColumnNumericStatus; -@synthesize csvOutputEncoding; - -@synthesize csvExportIsRunning; -@synthesize csvThreadShouldExit; - -/** - * Initialize an instance of the exporter setting some default values - */ -- (id)init -{ - if ((self == [super init])) { - [self setCsvExportIsRunning:NO]; - [self setCsvThreadShouldExit:NO]; - } - - return self; -} - /** * Start the CSV export process. */ @@ -76,8 +58,7 @@ (![self csvFieldSeparatorString]) || (![self csvEscapeString]) || (![self csvLineEndingString]) || - (![self csvTableColumnNumericStatus]) || - (![self csvOutputEncoding])) + (![self csvTableColumnNumericStatus])) { return NO; } @@ -99,12 +80,12 @@ [delegate exportProcessDidStart:self]; } - [self setCsvExportIsRunning:YES]; + [self setExportProcessIsRunning:YES]; // Start the export in a new thread - [NSThread detachNewThreadSelector:@selector(startCSVExportInBackgroundThread) toTarget:self withObject:nil]; + [NSThread detachNewThreadSelector:@selector(_startCSVExportInBackgroundThread) toTarget:self withObject:nil]; - [self setCsvExportIsRunning:NO]; + [self setExportProcessIsRunning:NO]; // Tell the delegate that the export process has ended if (delegate && [delegate respondsToSelector:@selector(exportProcessDidEnd:)]) { @@ -119,7 +100,7 @@ */ - (BOOL)stopExportProcess { - if (![self csvExportIsRunning]) return NO; + if (![self exportProcessIsRunning]) return NO; // Kill the running thread here @@ -151,7 +132,7 @@ /** * Starts the export process in a background thread. */ -- (void)startCSVExportInBackgroundThread +- (void)_startCSVExportInBackgroundThread { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -171,42 +152,38 @@ // Detect and restore special characters being used as terminating or line end strings NSMutableString *tempSeparatorString = [NSMutableString stringWithString:[self csvFieldSeparatorString]]; - - NSUInteger tempSeparatorStringLength = [tempSeparatorString length]; - + // Escape tabs, line endings and carriage returns [tempSeparatorString replaceOccurrencesOfString:@"\\t" withString:@"\t" options:NSLiteralSearch - range:NSMakeRange(0, tempSeparatorStringLength)]; + range:NSMakeRange(0, [tempSeparatorString length])]; [tempSeparatorString replaceOccurrencesOfString:@"\\n" withString:@"\n" options:NSLiteralSearch - range:NSMakeRange(0, tempSeparatorStringLength)]; + range:NSMakeRange(0, [tempSeparatorString length])]; [tempSeparatorString replaceOccurrencesOfString:@"\\r" withString:@"\r" options:NSLiteralSearch - range:NSMakeRange(0, tempSeparatorStringLength)]; + range:NSMakeRange(0, [tempSeparatorString length])]; // Set the new field separator string [self setCsvFieldSeparatorString:[NSString stringWithString:tempSeparatorString]]; NSMutableString *tempLineEndString = [NSMutableString stringWithString:[self csvLineEndingString]]; - - NSUInteger tempLineEndStringLength = [tempLineEndString length]; - + // Escape tabs, line endings and carriage returns [tempLineEndString replaceOccurrencesOfString:@"\\t" withString:@"\t" options:NSLiteralSearch - range:NSMakeRange(0, tempLineEndStringLength)]; + range:NSMakeRange(0, [tempLineEndString length])]; [tempLineEndString replaceOccurrencesOfString:@"\\n" withString:@"\n" options:NSLiteralSearch - range:NSMakeRange(0, tempLineEndStringLength)]; + range:NSMakeRange(0, [tempLineEndString length])]; [tempLineEndString replaceOccurrencesOfString:@"\\r" withString:@"\r" options:NSLiteralSearch - range:NSMakeRange(0, tempLineEndStringLength)]; + range:NSMakeRange(0, [tempLineEndString length])]; // Set the new line ending string [self setCsvLineEndingString:[NSString stringWithString:tempLineEndString]]; @@ -231,14 +208,14 @@ for (i = startingRow; i < totalRows; i++) { // Check if we should stop and exit the export operation - if ([self csvThreadShouldExit]) { + if ([self exportProcessShouldExit]) { [pool release]; return; } // Update the progress value - if (totalRows) [self setProgressValue:(((i + 1) * 100) / totalRows)]; + if (totalRows) [self setExportProgressValue:(((i + 1) * 100) / totalRows)]; // Retrieve the row from the supplied data if ([self csvDataArray] == nil) { @@ -264,7 +241,7 @@ // Retrieve the contents of this cell if ([NSArrayObjectAtIndex(csvRow, j) isKindOfClass:[NSData class]]) { - dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(csvRow, j) encoding:csvOutputEncoding]; + dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(csvRow, j) encoding:[self exportOutputEncoding]]; if (dataConversionString == nil) { dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(csvRow, j) encoding:NSASCIIStringEncoding]; @@ -353,7 +330,7 @@ [csvString appendString:[self csvLineEndingString]]; // Write it to the fileHandle - [csvFileHandle writeData:[csvString dataUsingEncoding:[self csvOutputEncoding]]]; + [csvFileHandle writeData:[csvString dataUsingEncoding:[self exportOutputEncoding]]]; } [pool release]; diff --git a/Source/SPExportController.h b/Source/SPExportController.h index 61447063..8653c345 100644 --- a/Source/SPExportController.h +++ b/Source/SPExportController.h @@ -53,6 +53,9 @@ typedef NSUInteger SPExportSource; // Tables list IBOutlet id tablesListInstance; + // Table data + IBOutlet id tableDataInstance; + // Export window IBOutlet id exportWindow; IBOutlet id exportToolbar; @@ -101,20 +104,20 @@ typedef NSUInteger SPExportSource; IBOutlet id exampleNameLabel; // Local variables - MCPConnection *mySQLConnection; + BOOL exportCancelled; NSMutableArray *tables; + MCPConnection *connection; } -// Export Methods +@property (readwrite, assign) BOOL exportCancelled; +@property (readwrite, assign) MCPConnection *connection; + +// IB action methods - (void)export; - (IBAction)closeSheet:(id)sender; -- (IBAction)cancelExport:(id)sender; -- (IBAction)changeExportOutputPath:(id)sender; - -// Utility Methods -- (void)setConnection:(MCPConnection *)theConnection; -- (void)loadTables; - (IBAction)switchTab:(id)sender; - (IBAction)switchInput:(id)sender; +- (IBAction)cancelExport:(id)sender; +- (IBAction)changeExportOutputPath:(id)sender; @end diff --git a/Source/SPExportController.m b/Source/SPExportController.m index 5acc40c0..ba6fab79 100644 --- a/Source/SPExportController.m +++ b/Source/SPExportController.m @@ -25,17 +25,32 @@ #import "SPExportController.h" #import "SPCSVExporter.h" #import "TablesList.h" +#import "SPTableData.h" #import "TableDocument.h" #import "SPArrayAdditions.h" +#import "SPStringAdditions.h" + +@interface SPExportController (PrivateAPI) + +- (void)_loadTables; +- (NSString *)_htmlEscapeString:(NSString *)string; +- (void)_initializeExportUsingSelectedOptions; +- (BOOL)_exportTablesAsCSV:(NSArray *)exportTables toFileHandle:(NSFileHandle *)fileHandle usingDataExporter:(SPExporter *)exporter; + +@end @implementation SPExportController +@synthesize connection; +@synthesize exportCancelled; + /** * Initializes an instance of SPExportController */ - (id)init { if ((self = [super init])) { + [self setExportCancelled:NO]; tables = [[NSMutableArray alloc] init]; } @@ -52,7 +67,7 @@ } #pragma mark - -#pragma mark Export methods +#pragma mark IB action methods /** * Display the export window allowing the user to select what and of what type to export. @@ -61,7 +76,7 @@ { if (!exportWindow) [NSBundle loadNibNamed:@"ExportDialog" owner:self]; - [self loadTables]; + [self _loadTables]; [exportPathField setStringValue:NSHomeDirectory()]; @@ -73,7 +88,7 @@ } /** - * Close the export dialog + * Closes the export dialog */ - (IBAction)closeSheet:(id)sender { @@ -84,145 +99,6 @@ /** * */ -- (IBAction)cancelExport:(id)sender -{ - // Cancel the export operation here -} - -- (IBAction)changeExportOutputPath:(id)sender -{ - NSOpenPanel *panel = [NSOpenPanel openPanel]; - - [panel setCanChooseFiles:NO]; - [panel setCanChooseDirectories:YES]; - [panel setCanCreateDirectories:YES]; - - [panel beginSheetForDirectory:NSHomeDirectory() file:nil modalForWindow:exportWindow modalDelegate:self didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) contextInfo:nil]; -} - -- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo -{ - // Perform the export - if (returnCode == NSOKButton) { - - // First determine what type of export the user selected - SPExportType exportType = 0; - - for (NSToolbarItem *item in [exportToolbar items]) - { - if ([[item itemIdentifier] isEqualToString:[exportToolbar selectedItemIdentifier]]) { - exportType = [item tag]; - break; - } - } - - // Determine what data to use (filtered result, custom query result or selected tables) for the export operation - SPExportSource exportSource = ([exportInputMatrix selectedRow] + 1); - - NSMutableArray *exportTables = [NSMutableArray array]; - - // Get the data depending on the source - switch (exportSource) - { - case SP_FILTERED_EXPORT: - - break; - case SP_CUSTOM_QUERY_EXPORT: - - break; - case SP_TABLE_EXPORT: - // Create an array of tables to export - for (NSMutableArray *table in tables) - { - if ([[table objectAtIndex:0] boolValue]) { - [exportTables addObject:[table objectAtIndex:1]]; - } - } - - break; - } - - // Create the file handle - - - SPExporter *exporter; - SPCSVExporter *csvExporter; - - // Based on the type of export create a new instance of the corresponding exporter and set it's specific options - switch (exportType) - { - case SP_SQL_EXPORT: - - break; - case SP_CSV_EXPORT: - csvExporter = [[SPCSVExporter alloc] init]; - - [csvExporter setCsvOutputFieldNames:[exportCSVIncludeFieldNamesCheck state]]; - [csvExporter setCsvFieldSeparatorString:[exportCSVFieldsTerminatedField stringValue]]; - [csvExporter setCsvEnclosingCharacterString:[exportCSVFieldsWrappedField stringValue]]; - [csvExporter setCsvLineEndingString:[exportCSVLinesTerminatedField stringValue]]; - [csvExporter setCsvEscapeString:[exportCSVFieldsEscapedField stringValue]]; - - [csvExporter setCsvOutputEncoding:[MCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]]]; - [csvExporter setCsvNULLString:[[NSUserDefaults standardUserDefaults] objectForKey:@"NullValue"]]; - - exporter = csvExporter; - break; - case SP_XML_EXPORT: - - break; - case SP_PDF_EXPORT: - - break; - case SP_HTML_EXPORT: - - break; - case SP_EXCEL_EXPORT: - - break; - } - - // Set the exporter's delegate - [exporter setDelegate:self]; - } -} - -- (void)savePanelDidEnd:(NSSavePanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo -{ - if (returnCode == NSOKButton) { - [exportPathField setStringValue:[panel directory]]; - } -} - -#pragma mark - -#pragma mark Utility methods - -- (void)setConnection:(MCPConnection *)theConnection -{ - mySQLConnection = theConnection; -} - -- (void)loadTables -{ - NSUInteger i; - - [tables removeAllObjects]; - - MCPResult *queryResult = (MCPResult *)[mySQLConnection listTables]; - - if ([queryResult numOfRows]) [queryResult dataSeek:0]; - - for ( i = 0 ; i < [queryResult numOfRows] ; i++ ) - { - [tables addObject:[NSMutableArray arrayWithObjects: - [NSNumber numberWithBool:YES], - NSArrayObjectAtIndex([queryResult fetchRowAsArray], 0), - nil]]; - } - - [exportTableList reloadData]; -} - - (IBAction)switchTab:(id)sender { if ([sender isKindOfClass:[NSToolbarItem class]]) { @@ -233,6 +109,9 @@ } } +/** + * + */ - (IBAction)switchInput:(id)sender { if ([sender isKindOfClass:[NSMatrix class]]) { @@ -240,6 +119,28 @@ } } +/** + * + */ +- (IBAction)cancelExport:(id)sender +{ + // Cancel the export operation here +} + +/** + * + */ +- (IBAction)changeExportOutputPath:(id)sender +{ + NSOpenPanel *panel = [NSOpenPanel openPanel]; + + [panel setCanChooseFiles:NO]; + [panel setCanChooseDirectories:YES]; + [panel setCanCreateDirectories:YES]; + + [panel beginSheetForDirectory:NSHomeDirectory() file:nil modalForWindow:exportWindow modalDelegate:self didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) contextInfo:nil]; +} + #pragma mark - #pragma mark Table view datasource methods @@ -294,6 +195,32 @@ #pragma mark - #pragma mark Other +/** + * Invoked when the user + */ +- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + // Perform the export + if (returnCode == NSOKButton) { + + // Initialize the export after half a second to give the export sheet a chance to close + [self performSelector:@selector(_initializeExportUsingSelectedOptions) withObject:nil afterDelay:0.5]; + } +} + +/** + * Invoked when the user dismisses the save panel. Updates the selected directory is they clicked OK. + */ +- (void)savePanelDidEnd:(NSSavePanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + if (returnCode == NSOKButton) { + [exportPathField setStringValue:[panel directory]]; + } +} + +/** + * Dealloc + */ - (void)dealloc { [tables release], tables = nil; @@ -302,3 +229,285 @@ } @end + +@implementation SPExportController (PrivateAPI) + +/** + * Loads all the available database tables in table view. + */ +- (void)_loadTables +{ + NSUInteger i; + + [tables removeAllObjects]; + + MCPResult *queryResult = (MCPResult *)[[self connection] listTables]; + + if ([queryResult numOfRows]) [queryResult dataSeek:0]; + + for ( i = 0 ; i < [queryResult numOfRows] ; i++ ) + { + [tables addObject:[NSMutableArray arrayWithObjects: + [NSNumber numberWithBool:YES], + NSArrayObjectAtIndex([queryResult fetchRowAsArray], 0), + nil]]; + } + + [exportTableList reloadData]; +} + +/** + * Escapes the supplied HTML string + */ +- (NSString *)_htmlEscapeString:(NSString *)string +{ + NSMutableString *mutableString = [NSMutableString stringWithString:string]; + + [mutableString replaceOccurrencesOfString:@"&" withString:@"&" + options:NSLiteralSearch + range:NSMakeRange(0, [mutableString length])]; + + [mutableString replaceOccurrencesOfString:@"<" withString:@"<" + options:NSLiteralSearch + range:NSMakeRange(0, [mutableString length])]; + + [mutableString replaceOccurrencesOfString:@">" withString:@">" + options:NSLiteralSearch + range:NSMakeRange(0, [mutableString length])]; + + [mutableString replaceOccurrencesOfString:@"\"" withString:@""" + options:NSLiteralSearch + range:NSMakeRange(0, [mutableString length])]; + + return [NSString stringWithString:mutableString]; +} + +/** + * + */ +- (void)_initializeExportUsingSelectedOptions +{ + // First determine what type of export the user selected + SPExportType exportType = 0; + + for (NSToolbarItem *item in [exportToolbar items]) + { + if ([[item itemIdentifier] isEqualToString:[exportToolbar selectedItemIdentifier]]) { + exportType = [item tag]; + break; + } + } + + // Determine what data to use (filtered result, custom query result or selected tables) for the export operation + SPExportSource exportSource = ([exportInputMatrix selectedRow] + 1); + + NSMutableArray *exportTables = [NSMutableArray array]; + + // Get the data depending on the source + switch (exportSource) + { + case SP_FILTERED_EXPORT: + + break; + case SP_CUSTOM_QUERY_EXPORT: + + break; + case SP_TABLE_EXPORT: + // Create an array of tables to export + for (NSMutableArray *table in tables) + { + if ([[table objectAtIndex:0] boolValue]) { + [exportTables addObject:[table objectAtIndex:1]]; + } + } + + break; + } + + SPExporter *exporter; + SPCSVExporter *csvExporter; + + // Based on the type of export create a new instance of the corresponding exporter and set it's specific options + switch (exportType) + { + case SP_SQL_EXPORT: + + break; + case SP_CSV_EXPORT: + csvExporter = [[SPCSVExporter alloc] init]; + + [csvExporter setCsvFileHandle:[NSFileHandle fileHandleForWritingAtPath:@"/Users/stuart/Desktop/output.csv"]]; + + [csvExporter setCsvOutputFieldNames:[exportCSVIncludeFieldNamesCheck state]]; + [csvExporter setCsvFieldSeparatorString:[exportCSVFieldsTerminatedField stringValue]]; + [csvExporter setCsvEnclosingCharacterString:[exportCSVFieldsWrappedField stringValue]]; + [csvExporter setCsvLineEndingString:[exportCSVLinesTerminatedField stringValue]]; + [csvExporter setCsvEscapeString:[exportCSVFieldsEscapedField stringValue]]; + + [csvExporter setExportOutputEncoding:[MCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]]]; + [csvExporter setCsvNULLString:[[NSUserDefaults standardUserDefaults] objectForKey:@"NullValue"]]; + + exporter = csvExporter; + break; + case SP_XML_EXPORT: + + break; + case SP_PDF_EXPORT: + + break; + case SP_HTML_EXPORT: + + break; + case SP_EXCEL_EXPORT: + + break; + } + + // Set the exporter's delegate + [exporter setDelegate:self]; + + switch (exportSource) + { + case SP_FILTERED_EXPORT: + + break; + case SP_CUSTOM_QUERY_EXPORT: + + break; + case SP_TABLE_EXPORT: + [self _exportTablesAsCSV:exportTables toFileHandle:[NSFileHandle fileHandleForWritingAtPath:@"/Users/stuart/Desktop/output.csv"] usingDataExporter:exporter]; + break; + } +} + +/** + * Exports the contents' of the supplied array of tables using the supplied exporter and export type. Note that + * this method currently only supports exporting in CSV and XML formats. + */ +- (BOOL)_exportTablesAsCSV:(NSArray *)exportTables toFileHandle:(NSFileHandle *)fileHandle usingDataExporter:(SPExporter *)exporter +{ + NSUInteger tableCount, i, j; + + NSMutableString *errors = [NSMutableString string]; + NSMutableString *infoString = [NSMutableString string]; + + NSDictionary *tableDetails; + NSMutableArray *tableColumnNumericStatus; + NSStringEncoding encoding = [[self connection] encoding]; + + // Reset the interface + [exportProgressTitle setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Exporting %@", @"text showing that the application is importing a supplied format"), @"CSV"]]; + [exportProgressText setStringValue:NSLocalizedString(@"Writing...", @"text showing that app is writing text file")]; + [exportProgressText displayIfNeeded]; + [exportProgressIndicator setDoubleValue:0]; + [exportProgressIndicator displayIfNeeded]; + + // Open the progress sheet + [NSApp beginSheet:exportProgressWindow + modalForWindow:tableWindow + modalDelegate:self + didEndSelector:nil + contextInfo:nil]; + + // Add a dump header to the dump file + NSMutableString *csvLineEnd = [NSMutableString stringWithString:[exportCSVLinesTerminatedField stringValue]]; + + [csvLineEnd replaceOccurrencesOfString:@"\\t" withString:@"\t" + options:NSLiteralSearch + range:NSMakeRange(0, [csvLineEnd length])]; + + [csvLineEnd replaceOccurrencesOfString:@"\\n" withString:@"\n" + options:NSLiteralSearch + range:NSMakeRange(0, [csvLineEnd length])]; + + [csvLineEnd replaceOccurrencesOfString:@"\\r" withString:@"\r" + options:NSLiteralSearch + range:NSMakeRange(0, [csvLineEnd length])]; + + if ([exportTables count] > 1) { + [infoString setString:[NSString stringWithFormat:@"Host: %@ Database: %@ Generation Time: %@%@%@", + [tableDocumentInstance host], [tableDocumentInstance database], [NSDate date], csvLineEnd, csvLineEnd]]; + } + + [fileHandle writeData:[infoString dataUsingEncoding:encoding]]; + + tableCount = [exportTables count]; + + // Loop through the tables + for (i = 0 ; i < ((tableCount) && (![self exportCancelled])); i++) + { + // Update the progress text and reset the progress bar to indeterminate status + NSString *tableName = [exportTables objectAtIndex:i]; + + [exportProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Table %i of %i (%@): fetching data...", @"text showing that app is fetching data for table dump"), (i + 1), tableCount, tableName]]; + [exportProgressText displayIfNeeded]; + + [exportProgressIndicator setIndeterminate:YES]; + [exportProgressIndicator setUsesThreadedAnimation:YES]; + [exportProgressIndicator startAnimation:self]; + + // For CSV exports of more than one table, output the name of the table + if (tableCount > 1) { + [fileHandle writeData:[[NSString stringWithFormat:@"Table %@%@%@", tableName, csvLineEnd, csvLineEnd] dataUsingEncoding:encoding]]; + } + + // Determine whether this table is a table or a view via the create table command, and get the table details + MCPResult *queryResult = [connection queryString:[NSString stringWithFormat:@"SHOW CREATE TABLE %@", [tableName backtickQuotedString]]]; + + if ([queryResult numOfRows]) { + tableDetails = [NSDictionary dictionaryWithDictionary:[queryResult fetchRowAsDictionary]]; + + tableDetails = [NSDictionary dictionaryWithDictionary:([tableDetails objectForKey:@"Create View"]) ? [tableDataInstance informationForView:tableName] : [tableDataInstance informationForTable:tableName]]; + } + + // Retrieve the table details via the data class, and use it to build an array containing column numeric status + tableColumnNumericStatus = [NSMutableArray array]; + + for (j = 0; j < [[tableDetails objectForKey:@"columns"] count]; j++) + { + NSString *tableColumnTypeGrouping = [[[tableDetails objectForKey:@"columns"] objectAtIndex:j] objectForKey:@"typegrouping"]; + + if ([tableColumnTypeGrouping isEqualToString:@"bit"] || + [tableColumnTypeGrouping isEqualToString:@"integer"] || + [tableColumnTypeGrouping isEqualToString:@"float"]) + { + [tableColumnNumericStatus addObject:[NSNumber numberWithBool:YES]]; + } + else { + [tableColumnNumericStatus addObject:[NSNumber numberWithBool:NO]]; + } + } + + // Retrieve all the content within this table + queryResult = [connection queryString:[NSString stringWithFormat:@"SELECT * FROM %@", [tableName backtickQuotedString]]]; + + // Note any errors during retrieval + if (![[connection getLastErrorMessage] isEqualToString:@""]) { + [errors appendString:[NSString stringWithFormat:@"%@\n", [connection getLastErrorMessage]]]; + } + + // Update the progress text and set the progress bar back to determinate + [exportProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Table %d of %d (%@): Writing...", @"text showing that app is writing data for table export"), (i + 1), tableCount, tableName]]; + [exportProgressText displayIfNeeded]; + + [exportProgressIndicator stopAnimation:self]; + [exportProgressIndicator setUsesThreadedAnimation:NO]; + [exportProgressIndicator setIndeterminate:NO]; + [exportProgressIndicator setDoubleValue:0]; + [exportProgressIndicator displayIfNeeded]; + + // Start the actual export process in a separate thread using the supplied exporter instance + //[exporter startExportProcess]; + + // Add a spacer to the file + [fileHandle writeData:[[NSString stringWithFormat:@"%@%@%@", csvLineEnd, csvLineEnd, csvLineEnd] dataUsingEncoding:encoding]]; + } + + // Close the progress sheet + [NSApp endSheet:exportProgressWindow returnCode:0]; + [exportProgressWindow orderOut:self]; + + return YES; +} + +@end diff --git a/Source/SPExporter.h b/Source/SPExporter.h index 9b0f80fd..d380f94e 100644 --- a/Source/SPExporter.h +++ b/Source/SPExporter.h @@ -52,14 +52,24 @@ @end -@interface SPExporter : NSObject +@interface SPExporter : NSOperation { id delegate; + + double exportProgressValue; - double progressValue; + BOOL exportProcessIsRunning; + BOOL exportProcessShouldExit; + + NSStringEncoding exportOutputEncoding; } @property (readwrite, assign) id delegate; -@property (readwrite, assign) double progressValue; +@property (readwrite, assign) double exportProgressValue; + +@property (readwrite, assign) BOOL exportProcessIsRunning; +@property (readwrite, assign) BOOL exportProcessShouldExit; + +@property (readwrite, assign) NSStringEncoding exportOutputEncoding; @end diff --git a/Source/SPExporter.m b/Source/SPExporter.m index f8f2cba0..9cc681d8 100644 --- a/Source/SPExporter.m +++ b/Source/SPExporter.m @@ -28,6 +28,34 @@ @implementation SPExporter @synthesize delegate; -@synthesize progressValue; +@synthesize exportProgressValue; +@synthesize exportProcessIsRunning; +@synthesize exportProcessShouldExit; +@synthesize exportOutputEncoding; + +/** + * Initialize an instance of the exporter setting some default values + */ +- (id)init +{ + if ((self == [super init])) { + [self setExportProgressValue:0]; + [self setExportProcessIsRunning:NO]; + [self setExportProcessShouldExit:NO]; + + // Default the output encoding to UTF-8 + [self setExportOutputEncoding:NSUTF8StringEncoding]; + } + + return self; +} + +/** + * + */ +- (void)main +{ + @throw [NSException exceptionWithName:@"NSOperation main() call" reason:@"Can't call NSOperation's main() method in SPExpoter, must be overriden in subclass." userInfo:nil]; +} @end diff --git a/Source/SPSQLExporter.h b/Source/SPSQLExporter.h index 847a882a..3b5f3be3 100644 --- a/Source/SPSQLExporter.h +++ b/Source/SPSQLExporter.h @@ -25,16 +25,11 @@ #import -#import "MCPKit.h" #import "SPExporter.h" -#import "SPExporterAccess.h" -@interface SPSQLExporter : SPExporter +@interface SPSQLExporter : SPExporter { - + } -- (BOOL)startExportProcess; -- (BOOL)stopExportProcess; - @end diff --git a/Source/SPSQLExporter.m b/Source/SPSQLExporter.m index 73f4ab56..39653abc 100644 --- a/Source/SPSQLExporter.m +++ b/Source/SPSQLExporter.m @@ -27,20 +27,4 @@ @implementation SPSQLExporter -/** - * Start the SQL export process. - */ -- (BOOL)startExportProcess -{ - return YES; -} - -/** - * Stop the SQL export process by killing the export thread and cleaning up if its running. - */ -- (BOOL)stopExportProcess -{ - return YES; -} - @end -- cgit v1.2.3