aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorstuconnolly <stuart02@gmail.com>2009-10-06 00:44:48 +0000
committerstuconnolly <stuart02@gmail.com>2009-10-06 00:44:48 +0000
commit27eba105aef0a612e5a91af02a0b87b99b06ab78 (patch)
treec7324f1156d602cb798a4d4ae8ada3b4907f5bcf /Source
parent29cfd02f7828d92136fce32e0cb888e9dd9fd2ba (diff)
downloadsequelpro-27eba105aef0a612e5a91af02a0b87b99b06ab78.tar.gz
sequelpro-27eba105aef0a612e5a91af02a0b87b99b06ab78.tar.bz2
sequelpro-27eba105aef0a612e5a91af02a0b87b99b06ab78.zip
More export redesign work. CSV data generation is currently working using the old non-streaming code, but does not yet write to any files. Please note that this is still very much a work in progress.
Diffstat (limited to 'Source')
-rw-r--r--Source/SPCSVExporter.h7
-rw-r--r--Source/SPCSVExporter.m483
-rw-r--r--Source/SPExportController.h3
-rw-r--r--Source/SPExportController.m48
-rw-r--r--Source/SPExporter.h4
-rw-r--r--Source/SPExporter.m3
-rw-r--r--Source/SPSQLExporter.h3
-rw-r--r--Source/SPSQLExporter.m18
-rw-r--r--Source/SPXMLExporter.h (renamed from Source/SPExporterAccess.h)18
-rw-r--r--Source/SPXMLExporter.m48
-rw-r--r--Source/TableDocument.h2
-rw-r--r--Source/TableDocument.m21
12 files changed, 347 insertions, 311 deletions
diff --git a/Source/SPCSVExporter.h b/Source/SPCSVExporter.h
index 51569838..95f30b46 100644
--- a/Source/SPCSVExporter.h
+++ b/Source/SPCSVExporter.h
@@ -29,10 +29,7 @@
#import "SPExporter.h"
@interface SPCSVExporter : SPExporter
-{
- // CSV file
- NSFileHandle *csvFileHandle;
-
+{
// CSV data
NSArray *csvDataArray;
MCPResult *csvDataResult;
@@ -47,8 +44,6 @@
NSArray *csvTableColumnNumericStatus;
}
-@property (readwrite, retain) NSFileHandle *csvFileHandle;
-
@property (readwrite, retain) NSArray *csvDataArray;
@property (readwrite, retain) MCPResult *csvDataResult;
diff --git a/Source/SPCSVExporter.m b/Source/SPCSVExporter.m
index b508172b..82f43a79 100644
--- a/Source/SPCSVExporter.m
+++ b/Source/SPCSVExporter.m
@@ -26,16 +26,8 @@
#import "SPCSVExporter.h"
#import "SPArrayAdditions.h"
-@interface SPCSVExporter (PrivateAPI)
-
-- (void)_startCSVExportInBackgroundThread;
-
-@end
-
@implementation SPCSVExporter
-@synthesize csvFileHandle;
-
@synthesize csvDataArray;
@synthesize csvDataResult;
@@ -48,292 +40,273 @@
@synthesize csvTableColumnNumericStatus;
/**
- * Start the CSV export process.
+ * Start the CSV data conversion process. This method is automatically called when an instance of this object
+ * is placed on an NSOperationQueue. Do not call it directly as there is no manual multithreading.
*/
-- (BOOL)startExportProcess
-{
- // Check that we have all the required info before starting the export
- if ((![self csvFileHandle]) ||
- (![self csvOutputFieldNames]) ||
- (![self csvFieldSeparatorString]) ||
- (![self csvEscapeString]) ||
- (![self csvLineEndingString]) ||
- (![self csvTableColumnNumericStatus]))
- {
- return NO;
- }
-
- // Check that the CSV output options are not just empty strings or empty arrays
- if ((![[self csvFieldSeparatorString] isEqualToString:@""]) ||
- (![[self csvEscapeString] isEqualToString:@""]) ||
- (![[self csvLineEndingString] isEqualToString:@""]) ||
- ([[self csvTableColumnNumericStatus] count] != 0))
- {
- return NO;
- }
-
- // Check that we have at least some data to export
- if ((![self csvDataArray]) && (![self csvDataResult])) return NO;
-
- // Tell the delegate that we are starting the export process
- if (delegate && [delegate respondsToSelector:@selector(exportProcessDidStart:)]) {
- [delegate exportProcessDidStart:self];
- }
-
- [self setExportProcessIsRunning:YES];
+- (void)main
+{
+ @try {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- // Start the export in a new thread
- [NSThread detachNewThreadSelector:@selector(_startCSVExportInBackgroundThread) toTarget:self withObject:nil];
-
- [self setExportProcessIsRunning:NO];
-
- // Tell the delegate that the export process has ended
- if (delegate && [delegate respondsToSelector:@selector(exportProcessDidEnd:)]) {
- [delegate exportProcessDidEnd:self];
- }
-
- return YES;
-}
-
-/**
- * Stop the CSV export process by killing the export thread and cleaning up if its running.
- */
-- (BOOL)stopExportProcess
-{
- if (![self exportProcessIsRunning]) return NO;
-
- // Kill the running thread here
-
- return YES;
-}
-
-/**
- * Dealloc
- */
-- (void)dealloc
-{
- [csvFileHandle release], csvFileHandle = nil;
- [csvDataArray release], csvDataArray = nil;
- [csvDataResult release], csvDataResult = nil;
- [csvFieldSeparatorString release], csvFieldSeparatorString = nil;
- [csvEnclosingCharacterString release], csvEnclosingCharacterString = nil;
- [csvEscapeString release], csvEscapeString = nil;
- [csvLineEndingString release], csvLineEndingString = nil;
- [csvNULLString release], csvNULLString = nil;
- [csvTableColumnNumericStatus release], csvTableColumnNumericStatus = nil;
-
- [super dealloc];
-}
-
-@end
-
-@implementation SPCSVExporter (PrivateAPI)
-
-/**
- * Starts the export process in a background thread.
- */
-- (void)_startCSVExportInBackgroundThread
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSMutableArray *csvRow = [NSMutableArray array];
- NSMutableString *csvCell = [NSMutableString string];
- NSMutableString *csvString = [NSMutableString string];
-
- NSScanner *csvNumericTester;
- NSString *escapedEscapeString, *escapedFieldSeparatorString, *escapedEnclosingString, *escapedLineEndString, *dataConversionString;
-
- BOOL csvCellIsNumeric;
- BOOL quoteFieldSeparators = [[self csvEnclosingCharacterString] isEqualToString:@""];
-
- NSUInteger i, j, startingRow, totalRows;
-
- if ([self csvDataResult] != nil && [[self csvDataResult] numOfRows]) [[self csvDataResult] dataSeek:0];
-
- // Detect and restore special characters being used as terminating or line end strings
- NSMutableString *tempSeparatorString = [NSMutableString stringWithString:[self csvFieldSeparatorString]];
+ NSMutableArray *csvRow = [NSMutableArray array];
+ NSMutableString *csvCell = [NSMutableString string];
+ NSMutableString *csvString = [NSMutableString string];
+ NSMutableString *csvData = [NSMutableString string];
- // Escape tabs, line endings and carriage returns
- [tempSeparatorString replaceOccurrencesOfString:@"\\t" withString:@"\t"
- options:NSLiteralSearch
- range:NSMakeRange(0, [tempSeparatorString length])];
-
- [tempSeparatorString replaceOccurrencesOfString:@"\\n" withString:@"\n"
- options:NSLiteralSearch
- range:NSMakeRange(0, [tempSeparatorString length])];
-
- [tempSeparatorString replaceOccurrencesOfString:@"\\r" withString:@"\r"
- options:NSLiteralSearch
- range:NSMakeRange(0, [tempSeparatorString length])];
-
- // Set the new field separator string
- [self setCsvFieldSeparatorString:[NSString stringWithString:tempSeparatorString]];
-
- NSMutableString *tempLineEndString = [NSMutableString stringWithString:[self csvLineEndingString]];
+ NSScanner *csvNumericTester;
+ NSString *escapedEscapeString, *escapedFieldSeparatorString, *escapedEnclosingString, *escapedLineEndString, *dataConversionString;
- // Escape tabs, line endings and carriage returns
- [tempLineEndString replaceOccurrencesOfString:@"\\t" withString:@"\t"
- options:NSLiteralSearch
- range:NSMakeRange(0, [tempLineEndString length])];
-
-
- [tempLineEndString replaceOccurrencesOfString:@"\\n" withString:@"\n"
- options:NSLiteralSearch
- range:NSMakeRange(0, [tempLineEndString length])];
-
- [tempLineEndString replaceOccurrencesOfString:@"\\r" withString:@"\r"
- options:NSLiteralSearch
- range:NSMakeRange(0, [tempLineEndString length])];
-
- // Set the new line ending string
- [self setCsvLineEndingString:[NSString stringWithString:tempLineEndString]];
-
- // Set up escaped versions of strings for substitution within the loop
- escapedEscapeString = [[self csvEscapeString] stringByAppendingString:[self csvEscapeString]];
- escapedFieldSeparatorString = [[self csvEscapeString] stringByAppendingString:[self csvFieldSeparatorString]];
- escapedEnclosingString = [[self csvEscapeString] stringByAppendingString:[self csvEnclosingCharacterString]];
- escapedLineEndString = [[self csvEscapeString] stringByAppendingString:[self csvLineEndingString]];
-
- // Determine the total number of rows and starting row depending on supplied data format
- if ([self csvDataArray] == nil) {
- startingRow = [self csvOutputFieldNames] ? -1 : 0;
- totalRows = [[self csvDataResult] numOfRows];
- }
- else {
- startingRow = [self csvOutputFieldNames] ? 0 : 1;
- totalRows = [[self csvDataArray] count];
- }
-
- // Walk through the supplied data constructing the CSV string
- for (i = startingRow; i < totalRows; i++)
- {
- // Check if we should stop and exit the export operation
- if ([self exportProcessShouldExit]) {
- [pool release];
-
+ BOOL csvCellIsNumeric;
+ BOOL quoteFieldSeparators = [[self csvEnclosingCharacterString] isEqualToString:@""];
+
+ NSUInteger i, j, startingRow, totalRows;
+
+ // Check that we have all the required info before starting the export
+ if ((![self csvOutputFieldNames]) ||
+ (![self csvFieldSeparatorString]) ||
+ (![self csvEscapeString]) ||
+ (![self csvLineEndingString]) ||
+ (![self csvTableColumnNumericStatus]))
+ {
return;
}
+
+ // Check that the CSV output options are not just empty strings or empty arrays
+ if (([[self csvFieldSeparatorString] isEqualToString:@""]) ||
+ ([[self csvEscapeString] isEqualToString:@""]) ||
+ ([[self csvLineEndingString] isEqualToString:@""]) ||
+ ([[self csvTableColumnNumericStatus] count] == 0))
+ {
+ return;
+ }
+
+ // Check that we have at least some data to export
+ if ((![self csvDataArray]) && (![self csvDataResult])) return;
+
+ // Tell the delegate that we are starting the export process
+ if (delegate && [delegate respondsToSelector:@selector(exportProcessDidStart:)]) {
+ [delegate exportProcessDidStart:self];
+ }
- // Update the progress value
- if (totalRows) [self setExportProgressValue:(((i + 1) * 100) / totalRows)];
+ // Mark the process as running
+ [self setExportProcessIsRunning:YES];
- // Retrieve the row from the supplied data
+ if ([self csvDataResult] != nil && [[self csvDataResult] numOfRows]) [[self csvDataResult] dataSeek:0];
+
+ // Detect and restore special characters being used as terminating or line end strings
+ NSMutableString *tempSeparatorString = [NSMutableString stringWithString:[self csvFieldSeparatorString]];
+
+ // Escape tabs, line endings and carriage returns
+ [tempSeparatorString replaceOccurrencesOfString:@"\\t" withString:@"\t"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [tempSeparatorString length])];
+
+ [tempSeparatorString replaceOccurrencesOfString:@"\\n" withString:@"\n"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [tempSeparatorString length])];
+
+ [tempSeparatorString replaceOccurrencesOfString:@"\\r" withString:@"\r"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [tempSeparatorString length])];
+
+ // Set the new field separator string
+ [self setCsvFieldSeparatorString:[NSString stringWithString:tempSeparatorString]];
+
+ NSMutableString *tempLineEndString = [NSMutableString stringWithString:[self csvLineEndingString]];
+
+ // Escape tabs, line endings and carriage returns
+ [tempLineEndString replaceOccurrencesOfString:@"\\t" withString:@"\t"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [tempLineEndString length])];
+
+
+ [tempLineEndString replaceOccurrencesOfString:@"\\n" withString:@"\n"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [tempLineEndString length])];
+
+ [tempLineEndString replaceOccurrencesOfString:@"\\r" withString:@"\r"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [tempLineEndString length])];
+
+ // Set the new line ending string
+ [self setCsvLineEndingString:[NSString stringWithString:tempLineEndString]];
+
+ // Set up escaped versions of strings for substitution within the loop
+ escapedEscapeString = [[self csvEscapeString] stringByAppendingString:[self csvEscapeString]];
+ escapedFieldSeparatorString = [[self csvEscapeString] stringByAppendingString:[self csvFieldSeparatorString]];
+ escapedEnclosingString = [[self csvEscapeString] stringByAppendingString:[self csvEnclosingCharacterString]];
+ escapedLineEndString = [[self csvEscapeString] stringByAppendingString:[self csvLineEndingString]];
+
+ // Determine the total number of rows and starting row depending on supplied data format
if ([self csvDataArray] == nil) {
- // Header row
- [csvRow setArray:(i == -1) ? [[self csvDataResult] fetchFieldNames] : [[self csvDataResult] fetchRowAsArray]];
+ startingRow = [self csvOutputFieldNames] ? 1 : 0;
+ totalRows = [[self csvDataResult] numOfRows];
}
else {
- [csvRow setArray:NSArrayObjectAtIndex([self csvDataArray], i)];
+ startingRow = [self csvOutputFieldNames] ? 0 : 1;
+ totalRows = [[self csvDataArray] count];
}
- [csvString setString:@""];
-
- for (j = 0; j < [csvRow count]; j++)
- {
- // For NULL objects supplied from a queryResult, add an unenclosed null string as per prefs
- if ([[csvRow objectAtIndex:j] isKindOfClass:[NSNull class]]) {
- [csvString appendString:[self csvNULLString]];
-
- if (j < [csvRow count] - 1) [csvString appendString:[self csvFieldSeparatorString]];
+ [csvData setString:@""];
- continue;
+ // Walk through the supplied data constructing the CSV string
+ for (i = startingRow; i < totalRows; i++)
+ {
+ // Check to see if the operation has been cancelled. If so exit the loop.
+ if ([self isCancelled]) {
+ break;
}
- // Retrieve the contents of this cell
- if ([NSArrayObjectAtIndex(csvRow, j) isKindOfClass:[NSData class]]) {
- dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(csvRow, j) encoding:[self exportOutputEncoding]];
-
- if (dataConversionString == nil) {
- dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(csvRow, j) encoding:NSASCIIStringEncoding];
- }
-
- [csvCell setString:[NSString stringWithString:dataConversionString]];
- [dataConversionString release];
+ // Update the progress value
+ if (totalRows) [self setExportProgressValue:(((i + 1) * 100) / totalRows)];
+
+ // Retrieve the row from the supplied data
+ if ([self csvDataArray] == nil) {
+ // Header row
+ [csvRow setArray:(i == -1) ? [[self csvDataResult] fetchFieldNames] : [[self csvDataResult] fetchRowAsArray]];
}
else {
- [csvCell setString:[NSArrayObjectAtIndex(csvRow, j) description]];
+ [csvRow setArray:NSArrayObjectAtIndex([self csvDataArray], i)];
}
- // For NULL values supplied via an array add the unenclosed null string as set in preferences
- if ([csvCell isEqualToString:[self csvNULLString]]) {
- [csvString appendString:[self csvNULLString]];
- }
- // Add empty strings as a pair of enclosing characters.
- else if ([csvCell length] == 0) {
- [csvString appendString:[self csvEnclosingCharacterString]];
- [csvString appendString:[self csvEnclosingCharacterString]];
+ [csvString setString:@""];
+
+ for (j = 0; j < [csvRow count]; j++)
+ {
+ // For NULL objects supplied from a queryResult, add an unenclosed null string as per prefs
+ if ([[csvRow objectAtIndex:j] isKindOfClass:[NSNull class]]) {
+ [csvString appendString:[self csvNULLString]];
+
+ if (j < [csvRow count] - 1) [csvString appendString:[self csvFieldSeparatorString]];
+
+ continue;
+ }
- }
- else {
- // Test whether this cell contains a number
+ // Retrieve the contents of this cell
if ([NSArrayObjectAtIndex(csvRow, j) isKindOfClass:[NSData class]]) {
- csvCellIsNumeric = NO;
+ dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(csvRow, j) encoding:[self exportOutputEncoding]];
+
+ if (dataConversionString == nil) {
+ dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(csvRow, j) encoding:NSASCIIStringEncoding];
+ }
+
+ [csvCell setString:[NSString stringWithString:dataConversionString]];
+ [dataConversionString release];
}
- // If an array of bools supplying information as to whether the column is numeric has been supplied, use it.
- else if ([self csvTableColumnNumericStatus] != nil) {
- csvCellIsNumeric = [NSArrayObjectAtIndex([self csvTableColumnNumericStatus], j) boolValue];
- }
- // Or fall back to testing numeric content via an NSScanner.
else {
- csvNumericTester = [NSScanner scannerWithString:csvCell];
- csvCellIsNumeric = [csvNumericTester scanFloat:nil] &&
- [csvNumericTester isAtEnd] &&
- ([csvCell characterAtIndex:0] != '0' ||
- [csvCell length] == 1 ||
- ([csvCell length] > 1 &&
- [csvCell characterAtIndex:1] == '.'));
+ [csvCell setString:[NSArrayObjectAtIndex(csvRow, j) description]];
}
- // Escape any occurrences of the escaping character
- [csvCell replaceOccurrencesOfString:[self csvEscapeString]
- withString:escapedEscapeString
- options:NSLiteralSearch
- range:NSMakeRange(0, [csvCell length])];
-
- // Escape any occurrences of the enclosure string
- if (![[self csvEscapeString] isEqualToString:[self csvEnclosingCharacterString]]) {
- [csvCell replaceOccurrencesOfString:[self csvEnclosingCharacterString]
- withString:escapedEnclosingString
+ // For NULL values supplied via an array add the unenclosed null string as set in preferences
+ if ([csvCell isEqualToString:[self csvNULLString]]) {
+ [csvString appendString:[self csvNULLString]];
+ }
+ // Add empty strings as a pair of enclosing characters.
+ else if ([csvCell length] == 0) {
+ [csvString appendString:[self csvEnclosingCharacterString]];
+ [csvString appendString:[self csvEnclosingCharacterString]];
+
+ }
+ else {
+ // Test whether this cell contains a number
+ if ([NSArrayObjectAtIndex(csvRow, j) isKindOfClass:[NSData class]]) {
+ csvCellIsNumeric = NO;
+ }
+ // If an array of bools supplying information as to whether the column is numeric has been supplied, use it.
+ else if ([self csvTableColumnNumericStatus] != nil) {
+ csvCellIsNumeric = [NSArrayObjectAtIndex([self csvTableColumnNumericStatus], j) boolValue];
+ }
+ // Or fall back to testing numeric content via an NSScanner.
+ else {
+ csvNumericTester = [NSScanner scannerWithString:csvCell];
+ csvCellIsNumeric = [csvNumericTester scanFloat:nil] &&
+ [csvNumericTester isAtEnd] &&
+ ([csvCell characterAtIndex:0] != '0' ||
+ [csvCell length] == 1 ||
+ ([csvCell length] > 1 &&
+ [csvCell characterAtIndex:1] == '.'));
+ }
+
+ // Escape any occurrences of the escaping character
+ [csvCell replaceOccurrencesOfString:[self csvEscapeString]
+ withString:escapedEscapeString
options:NSLiteralSearch
range:NSMakeRange(0, [csvCell length])];
- }
-
- // Escape occurrences of the line end character
- [csvCell replaceOccurrencesOfString:[self csvLineEndingString]
- withString:escapedLineEndString
- options:NSLiteralSearch
- range:NSMakeRange(0, [csvCell length])];
-
- // If the string isn't quoted or otherwise enclosed, escape occurrences of the field separators
- if (quoteFieldSeparators || csvCellIsNumeric) {
- [csvCell replaceOccurrencesOfString:[self csvFieldSeparatorString]
- withString:escapedFieldSeparatorString
+
+ // Escape any occurrences of the enclosure string
+ if (![[self csvEscapeString] isEqualToString:[self csvEnclosingCharacterString]]) {
+ [csvCell replaceOccurrencesOfString:[self csvEnclosingCharacterString]
+ withString:escapedEnclosingString
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [csvCell length])];
+ }
+
+ // Escape occurrences of the line end character
+ [csvCell replaceOccurrencesOfString:[self csvLineEndingString]
+ withString:escapedLineEndString
options:NSLiteralSearch
range:NSMakeRange(0, [csvCell length])];
+
+ // If the string isn't quoted or otherwise enclosed, escape occurrences of the field separators
+ if (quoteFieldSeparators || csvCellIsNumeric) {
+ [csvCell replaceOccurrencesOfString:[self csvFieldSeparatorString]
+ withString:escapedFieldSeparatorString
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [csvCell length])];
+ }
+
+ // Write out the cell data by appending strings - this is significantly faster than stringWithFormat.
+ if (csvCellIsNumeric) {
+ [csvString appendString:csvCell];
+ }
+ else {
+ [csvString appendString:[self csvEnclosingCharacterString]];
+ [csvString appendString:csvCell];
+ [csvString appendString:[self csvEnclosingCharacterString]];
+ }
}
- // Write out the cell data by appending strings - this is significantly faster than stringWithFormat.
- if (csvCellIsNumeric) {
- [csvString appendString:csvCell];
- }
- else {
- [csvString appendString:[self csvEnclosingCharacterString]];
- [csvString appendString:csvCell];
- [csvString appendString:[self csvEnclosingCharacterString]];
- }
+ if (j < ([csvRow count] - 1)) [csvString appendString:[self csvFieldSeparatorString]];
}
- if (j < ([csvRow count] - 1)) [csvString appendString:[self csvFieldSeparatorString]];
+ // Append the line ending to the string for this row
+ [csvString appendString:[self csvLineEndingString]];
+ [csvData appendString:csvString];
+ }
+
+ // Mark the process as not running
+ [self setExportProcessIsRunning:NO];
+
+ // Tell the delegate that the export process has ended
+ if (delegate && [delegate respondsToSelector:@selector(exportProcessDidEnd:)]) {
+ [delegate exportProcessDidEnd:self];
}
- // Append the line ending to the string for this row
- [csvString appendString:[self csvLineEndingString]];
+ // Pass the resulting CSV data back to the delegate by calling the specified didEndSelector
+ [[self delegate] performSelectorOnMainThread:[self didEndSelector] withObject:csvData waitUntilDone:YES];
- // Write it to the fileHandle
- [csvFileHandle writeData:[csvString dataUsingEncoding:[self exportOutputEncoding]]];
+ [pool release];
}
+ @catch(NSException *e) {
+
+ }
+}
+
+/**
+ * Dealloc
+ */
+- (void)dealloc
+{
+ [csvDataArray release], csvDataArray = nil;
+ [csvDataResult release], csvDataResult = nil;
+ [csvFieldSeparatorString release], csvFieldSeparatorString = nil;
+ [csvEnclosingCharacterString release], csvEnclosingCharacterString = nil;
+ [csvEscapeString release], csvEscapeString = nil;
+ [csvLineEndingString release], csvLineEndingString = nil;
+ [csvNULLString release], csvNULLString = nil;
+ [csvTableColumnNumericStatus release], csvTableColumnNumericStatus = nil;
- [pool release];
+ [super dealloc];
}
@end
diff --git a/Source/SPExportController.h b/Source/SPExportController.h
index 8653c345..ec396db5 100644
--- a/Source/SPExportController.h
+++ b/Source/SPExportController.h
@@ -45,7 +45,7 @@ enum {
typedef NSUInteger SPExportSource;
@interface SPExportController : NSObject
-{
+{
// Table document
IBOutlet id tableDocumentInstance;
IBOutlet id tableWindow;
@@ -107,6 +107,7 @@ typedef NSUInteger SPExportSource;
BOOL exportCancelled;
NSMutableArray *tables;
MCPConnection *connection;
+ NSOperationQueue *operationQueue;
}
@property (readwrite, assign) BOOL exportCancelled;
diff --git a/Source/SPExportController.m b/Source/SPExportController.m
index ba6fab79..91a3a0b7 100644
--- a/Source/SPExportController.m
+++ b/Source/SPExportController.m
@@ -35,7 +35,7 @@
- (void)_loadTables;
- (NSString *)_htmlEscapeString:(NSString *)string;
- (void)_initializeExportUsingSelectedOptions;
-- (BOOL)_exportTablesAsCSV:(NSArray *)exportTables toFileHandle:(NSFileHandle *)fileHandle usingDataExporter:(SPExporter *)exporter;
+- (BOOL)_exportTablesAsCSV:(NSArray *)exportTables usingDataExporter:(SPExporter *)exporter;
@end
@@ -51,7 +51,9 @@
{
if ((self = [super init])) {
[self setExportCancelled:NO];
+
tables = [[NSMutableArray alloc] init];
+ operationQueue = [[NSOperationQueue alloc] init];
}
return self;
@@ -224,6 +226,7 @@
- (void)dealloc
{
[tables release], tables = nil;
+ [operationQueue release], operationQueue = nil;
[super dealloc];
}
@@ -233,6 +236,14 @@
@implementation SPExportController (PrivateAPI)
/**
+ * This method is called by SPCSVExporter objects once they have completed converting their data to CSV data.
+ */
+- (void)_csvDataAvialble:(NSString *)data
+{
+
+}
+
+/**
* Loads all the available database tables in table view.
*/
- (void)_loadTables
@@ -335,9 +346,7 @@
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]];
@@ -363,8 +372,9 @@
break;
}
- // Set the exporter's delegate
+ // Set the exporter's delegate and didEndSelector
[exporter setDelegate:self];
+ [exporter setDidEndSelector:@selector(_csvDataAvialble:)];
switch (exportSource)
{
@@ -375,7 +385,7 @@
break;
case SP_TABLE_EXPORT:
- [self _exportTablesAsCSV:exportTables toFileHandle:[NSFileHandle fileHandleForWritingAtPath:@"/Users/stuart/Desktop/output.csv"] usingDataExporter:exporter];
+ [self _exportTablesAsCSV:exportTables usingDataExporter:exporter];
break;
}
}
@@ -384,7 +394,7 @@
* 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
+- (BOOL)_exportTablesAsCSV:(NSArray *)exportTables usingDataExporter:(SPCSVExporter *)exporter
{
NSUInteger tableCount, i, j;
@@ -428,9 +438,7 @@
[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
@@ -447,9 +455,9 @@
[exportProgressIndicator startAnimation:self];
// For CSV exports of more than one table, output the name of the table
- if (tableCount > 1) {
+ /*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]]];
@@ -478,14 +486,19 @@
}
}
+ [exporter setCsvTableColumnNumericStatus:tableColumnNumericStatus];
+
// 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]]];
}
+ // Assign the data to the exporter
+ [exporter setCsvDataResult:queryResult];
+
// 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];
@@ -496,11 +509,14 @@
[exportProgressIndicator setDoubleValue:0];
[exportProgressIndicator displayIfNeeded];
- // Start the actual export process in a separate thread using the supplied exporter instance
- //[exporter startExportProcess];
+ // Start the actual data conversion process by placing the exporter on the operation queue.
+ // Note that although it is highly likely there is no guarantee that the operation will executed
+ // as soon as it's placed on the queue. There may be a delay if the queue is already executing it's
+ // maximum number of concurrent operations. See the docs for more details.
+ [operationQueue addOperation:exporter];
// Add a spacer to the file
- [fileHandle writeData:[[NSString stringWithFormat:@"%@%@%@", csvLineEnd, csvLineEnd, csvLineEnd] dataUsingEncoding:encoding]];
+ //[fileHandle writeData:[[NSString stringWithFormat:@"%@%@%@", csvLineEnd, csvLineEnd, csvLineEnd] dataUsingEncoding:encoding]];
}
// Close the progress sheet
diff --git a/Source/SPExporter.h b/Source/SPExporter.h
index febbcbc3..9bc2e592 100644
--- a/Source/SPExporter.h
+++ b/Source/SPExporter.h
@@ -55,20 +55,20 @@
@interface SPExporter : NSOperation
{
id delegate;
+ SEL didEndSelector;
double exportProgressValue;
BOOL exportProcessIsRunning;
- BOOL exportProcessShouldExit;
NSStringEncoding exportOutputEncoding;
}
@property (readwrite, assign) id delegate;
+@property (readwrite, assign) SEL didEndSelector;
@property (readwrite, assign) double exportProgressValue;
@property (readwrite, assign) BOOL exportProcessIsRunning;
-@property (readwrite, assign) BOOL exportProcessShouldExit;
@property (readwrite, assign) NSStringEncoding exportOutputEncoding;
diff --git a/Source/SPExporter.m b/Source/SPExporter.m
index 9cc681d8..a5a1f834 100644
--- a/Source/SPExporter.m
+++ b/Source/SPExporter.m
@@ -28,9 +28,9 @@
@implementation SPExporter
@synthesize delegate;
+@synthesize didEndSelector;
@synthesize exportProgressValue;
@synthesize exportProcessIsRunning;
-@synthesize exportProcessShouldExit;
@synthesize exportOutputEncoding;
/**
@@ -41,7 +41,6 @@
if ((self == [super init])) {
[self setExportProgressValue:0];
[self setExportProcessIsRunning:NO];
- [self setExportProcessShouldExit:NO];
// Default the output encoding to UTF-8
[self setExportOutputEncoding:NSUTF8StringEncoding];
diff --git a/Source/SPSQLExporter.h b/Source/SPSQLExporter.h
index 3b5f3be3..7a2e9006 100644
--- a/Source/SPSQLExporter.h
+++ b/Source/SPSQLExporter.h
@@ -28,8 +28,5 @@
#import "SPExporter.h"
@interface SPSQLExporter : SPExporter
-{
-
-}
@end
diff --git a/Source/SPSQLExporter.m b/Source/SPSQLExporter.m
index 39653abc..db9e4532 100644
--- a/Source/SPSQLExporter.m
+++ b/Source/SPSQLExporter.m
@@ -27,4 +27,22 @@
@implementation SPSQLExporter
+/**
+ * Start the SQL data conversion process. This method is automatically called when an instance of this object
+ * is placed on an NSOperationQueue. Do not call it directly as there is no manual multithreading.
+ */
+- (void)main
+{
+ @try {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+
+
+ [pool release];
+ }
+ @catch (NSException *e) {
+
+ }
+}
+
@end
diff --git a/Source/SPExporterAccess.h b/Source/SPXMLExporter.h
index 484a9e69..dba81cba 100644
--- a/Source/SPExporterAccess.h
+++ b/Source/SPXMLExporter.h
@@ -1,10 +1,10 @@
//
// $Id$
//
-// SPExporterAccess.h
+// SPSXMLExporter.h
// sequel-pro
//
-// Created by Stuart Connolly (stuconnolly.com) on August 29, 2009
+// Created by Stuart Connolly (stuconnolly.com) on October 6, 2009
// Copyright (c) 2009 Stuart Connolly. All rights reserved.
//
// This program is free software; you can redistribute it and/or modify
@@ -23,18 +23,10 @@
//
// More info at <http://code.google.com/p/sequel-pro/>
-#import <Foundation/Foundation.h>
+#import <Cocoa/Cocoa.h>
-@protocol SPExporterAccess <NSObject>
+#import "SPExporter.h"
-/**
- * Starts the export process.
- */
-- (BOOL)startExportProcess;
-
-/**
- * Stops the export process and passes control back to SPExportController.
- */
-- (BOOL)stopExportProcess;
+@interface SPXMLExporter : SPExporter
@end
diff --git a/Source/SPXMLExporter.m b/Source/SPXMLExporter.m
new file mode 100644
index 00000000..dabfe263
--- /dev/null
+++ b/Source/SPXMLExporter.m
@@ -0,0 +1,48 @@
+//
+// $Id$
+//
+// SPXMLExporter.h
+// sequel-pro
+//
+// Created by Stuart Connolly (stuconnolly.com) on October 6, 2009
+// Copyright (c) 2009 Stuart Connolly. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "SPXMLExporter.h"
+
+@implementation SPXMLExporter
+
+/**
+ * Start the SQL data conversion process. This method is automatically called when an instance of this object
+ * is placed on an NSOperationQueue. Do not call it directly as there is no manual multithreading.
+ */
+- (void)main
+{
+ @try {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+
+
+ [pool release];
+ }
+ @catch (NSException *e) {
+
+ }
+}
+
+@end
diff --git a/Source/TableDocument.h b/Source/TableDocument.h
index 7ef7616d..b907ab37 100644
--- a/Source/TableDocument.h
+++ b/Source/TableDocument.h
@@ -54,7 +54,7 @@ enum sp_current_query_mode
IBOutlet id extendedTableInfoInstance;
IBOutlet id databaseDataInstance;
IBOutlet id spHistoryControllerInstance;
- IBOutlet id spExportControllerInstance;
+ IBOutlet id exportControllerInstance;
IBOutlet NSSearchField *listFilterField;
diff --git a/Source/TableDocument.m b/Source/TableDocument.m
index b98d7d51..e8290043 100644
--- a/Source/TableDocument.m
+++ b/Source/TableDocument.m
@@ -587,18 +587,16 @@
[tableRelationsInstance setConnection:mySQLConnection];
[customQueryInstance setConnection:mySQLConnection];
[tableDumpInstance setConnection:mySQLConnection];
- [spExportControllerInstance setConnection:mySQLConnection];
+ [exportControllerInstance setConnection:mySQLConnection];
[tableDataInstance setConnection:mySQLConnection];
[extendedTableInfoInstance setConnection:mySQLConnection];
[databaseDataInstance setConnection:mySQLConnection];
- if (userManagerInstance == nil)
- {
+
+ if (!userManagerInstance) {
userManagerInstance = [[SPUserManager alloc] initWithConnection:mySQLConnection];
}
- else
- {
- [userManagerInstance setConnection:mySQLConnection];
- }
+
+ [userManagerInstance setConnection:mySQLConnection];
// Set the cutom query editor's MySQL version
[customQueryInstance setMySQLversion:mySQLVersion];
@@ -2528,11 +2526,10 @@
*/
- (IBAction)export:(id)sender
{
- if ([sender tag] == -1) {
- //[tableDumpInstance export];
-
- [spExportControllerInstance export];
- } else {
+ if ([sender tag] == -1) {
+ [exportControllerInstance export];
+ }
+ else {
[tableDumpInstance exportFile:[sender tag]];
}
}