aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorstuconnolly <stuart02@gmail.com>2009-10-09 22:42:24 +0000
committerstuconnolly <stuart02@gmail.com>2009-10-09 22:42:24 +0000
commit20256abbd66b16013af66cbc6e6e08f3f763459c (patch)
tree4b8fb4854c7bdb49138cf90baf0ae46a882c0ea6 /Source
parent9560da0d1e97fd834f05ed10c57a65744a6a3e70 (diff)
downloadsequelpro-20256abbd66b16013af66cbc6e6e08f3f763459c.tar.gz
sequelpro-20256abbd66b16013af66cbc6e6e08f3f763459c.tar.bz2
sequelpro-20256abbd66b16013af66cbc6e6e08f3f763459c.zip
Yet more export redesign work. Export is now currently working for single tables, but produces deadlock errors when attempting to export multiple tables as a result of the initial streaming request for the tables' data all being done from the same thread. To resolve this each of the streaming requests will be made concurrently in separate operations and once the data is available a new concurrent operation (SPExporter subclass instance) will be spawned to perform the data conversion process.
Diffstat (limited to 'Source')
-rw-r--r--Source/SPCSVExporter.h14
-rw-r--r--Source/SPCSVExporter.m183
-rw-r--r--Source/SPExportController.h5
-rw-r--r--Source/SPExportController.m160
4 files changed, 183 insertions, 179 deletions
diff --git a/Source/SPCSVExporter.h b/Source/SPCSVExporter.h
index c0cc75c4..b0edc04e 100644
--- a/Source/SPCSVExporter.h
+++ b/Source/SPCSVExporter.h
@@ -28,21 +28,11 @@
#import "MCPKit.h"
#import "SPExporter.h"
-/**
- *
- */
-@interface SPCSVExporterDelegate
-
-- (void)csvDataAvailable:(NSString *)data;
-
-@end
-
-
@interface SPCSVExporter : SPExporter
{
// CSV data
NSArray *csvDataArray;
- MCPResult *csvDataResult;
+ MCPStreamingResult *csvDataResult;
// CSV options
BOOL csvOutputFieldNames;
@@ -55,7 +45,7 @@
}
@property (readwrite, retain) NSArray *csvDataArray;
-@property (readwrite, retain) MCPResult *csvDataResult;
+@property (readwrite, retain) MCPStreamingResult *csvDataResult;
@property (readwrite, assign) BOOL csvOutputFieldNames;
@property (readwrite, retain) NSString *csvFieldSeparatorString;
diff --git a/Source/SPCSVExporter.m b/Source/SPCSVExporter.m
index 9bbbb4af..4937e7c9 100644
--- a/Source/SPCSVExporter.m
+++ b/Source/SPCSVExporter.m
@@ -48,18 +48,19 @@
@try {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSMutableArray *csvRow = [NSMutableArray array];
- NSMutableString *csvCell = [NSMutableString string];
- NSMutableString *csvString = [NSMutableString string];
- NSMutableString *csvData = [NSMutableString string];
-
+ NSMutableString *csvString = [NSMutableString string];
+ NSMutableString *csvData = [NSMutableString string];
+ NSMutableString *csvCellString = [NSMutableString string];
+
+ NSArray *csvRow;
NSScanner *csvNumericTester;
NSString *escapedEscapeString, *escapedFieldSeparatorString, *escapedEnclosingString, *escapedLineEndString, *dataConversionString;
-
+
+ id csvCell;
BOOL csvCellIsNumeric;
BOOL quoteFieldSeparators = [[self csvEnclosingCharacterString] isEqualToString:@""];
-
- NSUInteger i, j, startingRow, totalRows;
+
+ NSUInteger i, totalRows, csvCellCount = 0;
// Check that we have all the required info before starting the export
if ((![self csvOutputFieldNames]) ||
@@ -82,12 +83,10 @@
// Check that we have at least some data to export
if ((![self csvDataArray]) && (![self csvDataResult])) return;
-
+
// Mark the process as running
[self setExportProcessIsRunning:YES];
- 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]];
@@ -132,143 +131,165 @@
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];
- }
+ // Set up the starting row; for supplied arrays, which include the column
+ // headers as the first row, decide whether to skip the first row.
+ NSUInteger currentRowIndex = 0;
[csvData setString:@""];
-
- // Walk through the supplied data constructing the CSV string
- for (i = startingRow; i < totalRows; i++)
+
+ if (([self csvDataArray]) && (![self csvOutputFieldNames])) currentRowIndex++;
+
+ // Drop into the processing loop
+ NSAutoreleasePool *csvExportPool = [[NSAutoreleasePool alloc] init];
+
+ NSUInteger currentPoolDataLength = 0;
+
+ while (1)
{
- // Check to see if the operation has been cancelled. If so exit the loop.
- if ([self isCancelled]) {
- break;
- }
-
- // 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]];
+ // Retrieve the next row from the supplied data, either directly from the array...
+ if ([self csvDataArray]) {
+ csvRow = NSArrayObjectAtIndex([self csvDataArray], currentRowIndex);
}
+ // Or by reading an appropriate row from the streaming result
else {
- [csvRow setArray:NSArrayObjectAtIndex([self csvDataArray], i)];
+ // If still requested to read the field names, get the field names
+ if ([self csvOutputFieldNames]) {
+ csvRow = [[self csvDataResult] fetchFieldNames];
+ [self setCsvOutputFieldNames:NO];
+ }
+ else {
+ csvRow = [[self csvDataResult] fetchNextRowAsArray];
+
+ if (!csvRow) break;
+ }
}
+ // Get the cell count if we don't already have it stored
+ if (!csvCellCount) csvCellCount = [csvRow count];
+
[csvString setString:@""];
- for (j = 0; j < [csvRow count]; j++)
+ for (i = 0 ; i < csvCellCount; i++)
{
+ csvCell = NSArrayObjectAtIndex(csvRow, i);
+
// For NULL objects supplied from a queryResult, add an unenclosed null string as per prefs
- if ([[csvRow objectAtIndex:j] isKindOfClass:[NSNull class]]) {
+ if ([csvCell isKindOfClass:[NSNull class]]) {
[csvString appendString:[self csvNULLString]];
- if (j < [csvRow count] - 1) [csvString appendString:[self csvFieldSeparatorString]];
+ if (i < (csvCellCount - 1)) [csvString appendString:[self csvFieldSeparatorString]];
continue;
}
// Retrieve the contents of this cell
- if ([NSArrayObjectAtIndex(csvRow, j) isKindOfClass:[NSData class]]) {
- dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(csvRow, j) encoding:[self exportOutputEncoding]];
+ if ([csvCell isKindOfClass:[NSData class]]) {
+ dataConversionString = [[NSString alloc] initWithData:csvCell encoding:[self exportOutputEncoding]];
if (dataConversionString == nil) {
- dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(csvRow, j) encoding:NSASCIIStringEncoding];
+ dataConversionString = [[NSString alloc] initWithData:csvCell encoding:NSASCIIStringEncoding];
}
- [csvCell setString:[NSString stringWithString:dataConversionString]];
+ [csvCellString setString:[NSString stringWithString:dataConversionString]];
[dataConversionString release];
}
else {
- [csvCell setString:[NSArrayObjectAtIndex(csvRow, j) description]];
+ [csvCellString setString:[csvCell description]];
}
// For NULL values supplied via an array add the unenclosed null string as set in preferences
- if ([csvCell isEqualToString:[self csvNULLString]]) {
+ if ([csvCellString isEqualToString:[self csvNULLString]]) {
[csvString appendString:[self csvNULLString]];
}
// Add empty strings as a pair of enclosing characters.
- else if ([csvCell length] == 0) {
+ else if ([csvCellString 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]]) {
+ // If an array of bools supplying information as to whether the column is numeric has been supplied, use it.
+ if ([self csvTableColumnNumericStatus] != nil) {
+ csvCellIsNumeric = [NSArrayObjectAtIndex([self csvTableColumnNumericStatus], i) boolValue];
+ }
+ // Otherwise, first test whether this cell contains data
+ else if ([NSArrayObjectAtIndex(csvRow, i) 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];
+ csvNumericTester = [NSScanner scannerWithString:csvCellString];
+
csvCellIsNumeric = [csvNumericTester scanFloat:nil] &&
[csvNumericTester isAtEnd] &&
- ([csvCell characterAtIndex:0] != '0' ||
- [csvCell length] == 1 ||
- ([csvCell length] > 1 &&
- [csvCell characterAtIndex:1] == '.'));
+ ([csvCellString characterAtIndex:0] != '0' ||
+ [csvCellString length] == 1 ||
+ ([csvCellString length] > 1 &&
+ [csvCellString characterAtIndex:1] == '.'));
}
// Escape any occurrences of the escaping character
- [csvCell replaceOccurrencesOfString:[self csvEscapeString]
- withString:escapedEscapeString
- options:NSLiteralSearch
- range:NSMakeRange(0, [csvCell length])];
+ [csvCellString replaceOccurrencesOfString:[self csvEscapeString]
+ withString:escapedEscapeString
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [csvCellString length])];
// 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])];
+ [csvCellString replaceOccurrencesOfString:[self csvEnclosingCharacterString]
+ withString:escapedEnclosingString
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [csvCellString length])];
}
// Escape occurrences of the line end character
- [csvCell replaceOccurrencesOfString:[self csvLineEndingString]
- withString:escapedLineEndString
- options:NSLiteralSearch
- range:NSMakeRange(0, [csvCell length])];
+ [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 (quoteFieldSeparators || csvCellIsNumeric) {
- [csvCell replaceOccurrencesOfString:[self csvFieldSeparatorString]
- withString:escapedFieldSeparatorString
- options:NSLiteralSearch
- range:NSMakeRange(0, [csvCell length])];
+ [csvCellString replaceOccurrencesOfString:[self csvFieldSeparatorString]
+ withString:escapedFieldSeparatorString
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [csvCellString length])];
}
// Write out the cell data by appending strings - this is significantly faster than stringWithFormat.
if (csvCellIsNumeric) {
- [csvString appendString:csvCell];
+ [csvString appendString:csvCellString];
}
else {
[csvString appendString:[self csvEnclosingCharacterString]];
- [csvString appendString:csvCell];
+ [csvString appendString:csvCellString];
[csvString appendString:[self csvEnclosingCharacterString]];
}
}
- if (j < ([csvRow count] - 1)) [csvString appendString:[self csvFieldSeparatorString]];
+ if (i < ([csvRow count] - 1)) [csvString appendString:[self csvFieldSeparatorString]];
}
- // Append the line ending to the string for this row
+ // Append the line ending to the string for this row, and record the length processed for pool flushing
[csvString appendString:[self csvLineEndingString]];
[csvData appendString:csvString];
+
+ currentPoolDataLength += [csvString length];
+
+ currentRowIndex++;
+
+ // Update the progress value
+ if (totalRows) [self setExportProgressValue:(((i + 1) * 100) / totalRows)];
+
+ // If an array was supplied and we've processed all rows, break
+ if ([self csvDataArray] && (totalRows == currentRowIndex)) break;
+
+ // Drain the autorelease pool as required to keep memory usage low
+ if (currentPoolDataLength > 250000) {
+ [csvExportPool drain];
+ csvExportPool = [[NSAutoreleasePool alloc] init];
+ }
}
-
+
// Assign the resulting CSV data to the expoter's export data
[self setExportData:csvData];
@@ -276,7 +297,7 @@
[self setExportProcessIsRunning:NO];
// Call the delegate's didEndSelector while passing this exporter to it
- [[self delegate] performSelectorOnMainThread:[self didEndSelector] withObject:self waitUntilDone:YES];
+ [[self delegate] performSelectorOnMainThread:[self didEndSelector] withObject:self waitUntilDone:NO];
[pool release];
}
diff --git a/Source/SPExportController.h b/Source/SPExportController.h
index eec8ce63..294f5851 100644
--- a/Source/SPExportController.h
+++ b/Source/SPExportController.h
@@ -27,6 +27,8 @@
#import "SPExporterDataAccess.h"
+#import "SPLogger.h"
+
// Export type constants
enum {
SP_SQL_EXPORT = 1,
@@ -67,6 +69,7 @@ typedef NSUInteger SPExportSource;
IBOutlet id exportInputMatrix;
IBOutlet id exportFilePerTableCheck;
IBOutlet id exportFilePerTableNote;
+ IBOutlet id exportProcessLowMemory;
// Export progress sheet
IBOutlet id exportProgressWindow;
@@ -116,6 +119,8 @@ typedef NSUInteger SPExportSource;
// Concurrent operation queue
NSOperationQueue *operationQueue;
+
+ SPLogger *log;
}
@property (readwrite, assign) BOOL exportCancelled;
diff --git a/Source/SPExportController.m b/Source/SPExportController.m
index b6adc58a..f7b1878f 100644
--- a/Source/SPExportController.m
+++ b/Source/SPExportController.m
@@ -32,9 +32,8 @@
@interface SPExportController (PrivateAPI)
-- (NSString *)_htmlEscapeString:(NSString *)string;
- (void)_initializeExportUsingSelectedOptions;
-- (BOOL)_exportTablesAsCSV:(NSArray *)exportTables usingDataExporter:(SPExporter *)exporter;
+- (BOOL)_exportTables:(NSArray *)exportTables asType:(SPExportType)type;
@end
@@ -53,6 +52,8 @@
tables = [[NSMutableArray alloc] init];
operationQueue = [[NSOperationQueue alloc] init];
+
+ log = [SPLogger logger];
}
return self;
@@ -163,7 +164,12 @@
[panel setCanChooseDirectories:YES];
[panel setCanCreateDirectories:YES];
- [panel beginSheetForDirectory:NSHomeDirectory() file:nil modalForWindow:exportWindow modalDelegate:self didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) contextInfo:nil];
+ [panel beginSheetForDirectory:NSHomeDirectory()
+ file:nil
+ modalForWindow:exportWindow
+ modalDelegate:self
+ didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:)
+ contextInfo:nil];
}
#pragma mark -
@@ -227,6 +233,8 @@
*/
- (void)exporterDataConversionProcessComplete:(SPExporter *)exporter
{
+ // Do something with the data...
+
// If there are no more operations in the queue, close the progress sheet
if ([[operationQueue operations] count] == 0) {
[NSApp endSheet:exportProgressWindow returnCode:0];
@@ -278,32 +286,6 @@
@implementation SPExportController (PrivateAPI)
/**
- * Escapes the supplied HTML string
- */
-- (NSString *)_htmlEscapeString:(NSString *)string
-{
- NSMutableString *mutableString = [NSMutableString stringWithString:string];
-
- [mutableString replaceOccurrencesOfString:@"&" withString:@"&amp;"
- options:NSLiteralSearch
- range:NSMakeRange(0, [mutableString length])];
-
- [mutableString replaceOccurrencesOfString:@"<" withString:@"&lt;"
- options:NSLiteralSearch
- range:NSMakeRange(0, [mutableString length])];
-
- [mutableString replaceOccurrencesOfString:@">" withString:@"&gt;"
- options:NSLiteralSearch
- range:NSMakeRange(0, [mutableString length])];
-
- [mutableString replaceOccurrencesOfString:@"\"" withString:@"&quot;"
- options:NSLiteralSearch
- range:NSMakeRange(0, [mutableString length])];
-
- return [NSString stringWithString:mutableString];
-}
-
-/**
*
*/
- (void)_initializeExportUsingSelectedOptions
@@ -319,7 +301,7 @@
}
}
- // Determine what data to use (filtered result, custom query result or selected tables) for the export operation
+ // Determine what data to use (filtered result, custom query result or selected table(s)) for the export operation
SPExportSource exportSource = ([exportInputMatrix selectedRow] + 1);
NSMutableArray *exportTables = [NSMutableArray array];
@@ -345,43 +327,7 @@
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] initWithDelegate:self];
-
- [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;
- }
-
+ // Begin the export based on the type
switch (exportSource)
{
case SP_FILTERED_EXPORT:
@@ -391,24 +337,23 @@
break;
case SP_TABLE_EXPORT:
- [self _exportTablesAsCSV:exportTables usingDataExporter:exporter];
+ [self _exportTables:exportTables asType:exportType];
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.
+ * Exports the contents' of the supplied array of tables. Note that this method currently only supports
+ * exporting in CSV and XML formats.
*/
-- (BOOL)_exportTablesAsCSV:(NSArray *)exportTables usingDataExporter:(SPCSVExporter *)exporter
+- (BOOL)_exportTables:(NSArray *)exportTables asType:(SPExportType)type
{
- NSUInteger tableCount, i;
+ NSUInteger i;
NSMutableString *errors = [NSMutableString string];
NSMutableString *infoString = [NSMutableString string];
NSDictionary *tableDetails;
- NSMutableArray *tableColumnNumericStatus;
NSStringEncoding encoding = [[self connection] encoding];
// Reset the interface
@@ -440,19 +385,21 @@
options:NSLiteralSearch
range:NSMakeRange(0, [csvLineEnd length])];
- if ([exportTables count] > 1) {
+ /*if ([exportTables count] > 1) {
[infoString setString:[NSString stringWithFormat:@"Host: %@ Database: %@ Generation Time: %@%@%@",
[tableDocumentInstance host], [tableDocumentInstance database], [NSDate date], csvLineEnd, csvLineEnd]];
- }
+ }*/
- tableCount = [exportTables count];
+ NSUInteger tableCount = [exportTables count];
// Loop through the tables
- for (i = 0 ; i < ((tableCount) && (![self exportCancelled])); i++)
+ for (i = 0 ; i < tableCount; i++)
{
+ if ([self exportCancelled]) break;
+
// Update the progress text and reset the progress bar to indeterminate status
NSString *tableName = [exportTables objectAtIndex:i];
-
+
[exportProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Table %d of %d (%@): fetching data...", @"text showing that app is fetching data for table dump"), (i + 1), tableCount, tableName]];
[exportProgressText displayIfNeeded];
@@ -475,7 +422,7 @@
}
// Retrieve the table details via the data class, and use it to build an array containing column numeric status
- tableColumnNumericStatus = [NSMutableArray array];
+ NSMutableArray *tableColumnNumericStatus = [NSMutableArray array];
for (NSDictionary *column in [tableDetails objectForKey:@"columns"])
{
@@ -485,19 +432,60 @@
[tableColumnTypeGrouping isEqualToString:@"integer"] ||
[tableColumnTypeGrouping isEqualToString:@"float"])]];
}
-
- [exporter setCsvTableColumnNumericStatus:tableColumnNumericStatus];
- // Retrieve all the content within this table
- queryResult = [connection queryString:[NSString stringWithFormat:@"SELECT * FROM %@", [tableName backtickQuotedString]]];
-
+ // Use low memory export?
+ BOOL useLowMemoryBlockingStreaming = ([exportProcessLowMemory state] == NSOnState);
+
+ // Make a streaming request for the data
+ MCPStreamingResult *queryResultStreaming = [connection streamingQueryString:[NSString stringWithFormat:@"SELECT * FROM %@", [tableName backtickQuotedString]] useLowMemoryBlockingStreaming:useLowMemoryBlockingStreaming];
+
// 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];
+ 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 (type)
+ {
+ case SP_SQL_EXPORT:
+
+ break;
+ case SP_CSV_EXPORT:
+ csvExporter = [[SPCSVExporter alloc] initWithDelegate:self];
+
+ [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"]];
+
+ [csvExporter setCsvTableColumnNumericStatus:tableColumnNumericStatus];
+
+ // Assign the data to the exporter
+ [csvExporter setCsvDataResult:queryResultStreaming];
+
+ exporter = csvExporter;
+
+ break;
+ case SP_XML_EXPORT:
+
+ break;
+ case SP_PDF_EXPORT:
+
+ break;
+ case SP_HTML_EXPORT:
+
+ break;
+ case SP_EXCEL_EXPORT:
+
+ break;
+ }
// 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]];