aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPCSVExporter.m573
-rw-r--r--Source/SPDotExporter.m239
-rw-r--r--Source/SPHTMLExporter.m10
-rw-r--r--Source/SPPDFExporter.m9
-rw-r--r--Source/SPXMLExporter.m291
5 files changed, 553 insertions, 569 deletions
diff --git a/Source/SPCSVExporter.m b/Source/SPCSVExporter.m
index fe6ebdac..b465b4e2 100644
--- a/Source/SPCSVExporter.m
+++ b/Source/SPCSVExporter.m
@@ -65,345 +65,342 @@
*/
- (void)main
{
- @try {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSMutableString *csvString = [NSMutableString string];
- NSMutableString *csvCellString = [NSMutableString string];
-
- NSMutableArray *tableColumnNumericStatus = [NSMutableArray array];
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSMutableString *csvString = [NSMutableString string];
+ NSMutableString *csvCellString = [NSMutableString string];
+
+ NSMutableArray *tableColumnNumericStatus = [NSMutableArray array];
+
+ NSArray *csvRow = nil;
+ NSScanner *csvNumericTester = nil;
+ MCPStreamingResult *streamingResult = nil;
+ NSString *escapedEscapeString, *escapedFieldSeparatorString, *escapedEnclosingString, *escapedLineEndString, *dataConversionString;
- NSArray *csvRow = nil;
- NSScanner *csvNumericTester = nil;
- MCPStreamingResult *streamingResult = nil;
- NSString *escapedEscapeString, *escapedFieldSeparatorString, *escapedEnclosingString, *escapedLineEndString, *dataConversionString;
+ id csvCell;
+ BOOL csvCellIsNumeric;
+ BOOL quoteFieldSeparators = [[self csvEnclosingCharacterString] isEqualToString:@""];
- id csvCell;
- BOOL csvCellIsNumeric;
- BOOL quoteFieldSeparators = [[self csvEnclosingCharacterString] isEqualToString:@""];
+ NSUInteger i, totalRows, lastProgressValue, csvCellCount = 0;
- NSUInteger i, totalRows, lastProgressValue, csvCellCount = 0;
-
- // Check to see if we have at least a table name or data array
- if ((![self csvTableName]) && (![self csvDataArray]) ||
- ([[self csvTableName] isEqualToString:@""]) && ([[self csvDataArray] count] == 0))
- {
- [pool release];
- return;
- }
-
- // Check that we have all the required info before starting the export
- if ((![self csvOutputFieldNames]) ||
- (![self csvFieldSeparatorString]) ||
- (![self csvEscapeString]) ||
- (![self csvLineEndingString]))
- {
- [pool release];
- return;
- }
-
- // Check that the CSV output options are not just empty strings
- if (([[self csvFieldSeparatorString] isEqualToString:@""]) ||
- ([[self csvEscapeString] isEqualToString:@""]) ||
- ([[self csvLineEndingString] isEqualToString:@""]))
- {
- [pool release];
- return;
- }
-
- // Inform the delegate that the export process is about to begin
- [delegate performSelectorOnMainThread:@selector(csvExportProcessWillBegin:) withObject:self waitUntilDone:NO];
+ // Check to see if we have at least a table name or data array
+ if ((![self csvTableName]) && (![self csvDataArray]) ||
+ ([[self csvTableName] isEqualToString:@""]) && ([[self csvDataArray] count] == 0))
+ {
+ [pool release];
+ return;
+ }
+
+ // Check that we have all the required info before starting the export
+ if ((![self csvOutputFieldNames]) ||
+ (![self csvFieldSeparatorString]) ||
+ (![self csvEscapeString]) ||
+ (![self csvLineEndingString]))
+ {
+ [pool release];
+ return;
+ }
+
+ // Check that the CSV output options are not just empty strings
+ if (([[self csvFieldSeparatorString] isEqualToString:@""]) ||
+ ([[self csvEscapeString] isEqualToString:@""]) ||
+ ([[self csvLineEndingString] isEqualToString:@""]))
+ {
+ [pool release];
+ return;
+ }
- // Mark the process as running
- [self setExportProcessIsRunning:YES];
-
- lastProgressValue = 0;
-
- // Make a streaming request for the data if the data array isn't set
- if ((![self csvDataArray]) && [self csvTableName]) {
- streamingResult = [connection streamingQueryString:[NSString stringWithFormat:@"SELECT * FROM %@", [[self csvTableName] backtickQuotedString]] useLowMemoryBlockingStreaming:[self exportUsingLowMemoryBlockingStreaming]];
- }
-
- // 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]];
+ // Inform the delegate that the export process is about to begin
+ [delegate performSelectorOnMainThread:@selector(csvExportProcessWillBegin:) withObject:self waitUntilDone:NO];
+
+ // Mark the process as running
+ [self setExportProcessIsRunning:YES];
+
+ lastProgressValue = 0;
+
+ // Make a streaming request for the data if the data array isn't set
+ if ((![self csvDataArray]) && [self csvTableName]) {
+ streamingResult = [connection streamingQueryString:[NSString stringWithFormat:@"SELECT * FROM %@", [[self csvTableName] backtickQuotedString]] useLowMemoryBlockingStreaming:[self exportUsingLowMemoryBlockingStreaming]];
+ }
+
+ // 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]];
+
+ // 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;
+
+ [csvString setString:@""];
+
+ if ([self csvDataArray]) totalRows = [[self csvDataArray] count];
+ if (([self csvDataArray]) && (![self csvOutputFieldNames])) currentRowIndex++;
+
+ if ([self csvTableName] && (![self csvDataArray])) {
- // 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;
+ NSDictionary *tableDetails;
- [csvString setString:@""];
+ // Determine whether the supplied table is actually a table or a view via the CREATE TABLE command, and get the table details
+ MCPResult *queryResult = [connection queryString:[NSString stringWithFormat:@"SHOW CREATE TABLE %@", [[self csvTableName] backtickQuotedString]]];
- if ([self csvDataArray]) totalRows = [[self csvDataArray] count];
- if (([self csvDataArray]) && (![self csvOutputFieldNames])) currentRowIndex++;
+ [queryResult setReturnDataAsStrings:YES];
- if ([self csvTableName] && (![self csvDataArray])) {
+ if ([queryResult numOfRows]) {
+ tableDetails = [[NSDictionary alloc] initWithDictionary:[queryResult fetchRowAsDictionary]];
- NSDictionary *tableDetails;
-
- // Determine whether the supplied table is actually a table or a view via the CREATE TABLE command, and get the table details
- MCPResult *queryResult = [connection queryString:[NSString stringWithFormat:@"SHOW CREATE TABLE %@", [[self csvTableName] backtickQuotedString]]];
-
- [queryResult setReturnDataAsStrings:YES];
+ tableDetails = [[NSDictionary alloc] initWithDictionary:([tableDetails objectForKey:@"Create View"]) ? [[self csvTableData] informationForView:[self csvTableName]] : [[self csvTableData] informationForTable:[self csvTableName]]];
+ }
+
+ // Retrieve the table details via the data class, and use it to build an array containing column numeric status
+ for (NSDictionary *column in [tableDetails objectForKey:@"columns"])
+ {
+ NSString *tableColumnTypeGrouping = [column objectForKey:@"typegrouping"];
- if ([queryResult numOfRows]) {
- tableDetails = [[NSDictionary alloc] initWithDictionary:[queryResult fetchRowAsDictionary]];
-
- tableDetails = [[NSDictionary alloc] initWithDictionary:([tableDetails objectForKey:@"Create View"]) ? [[self csvTableData] informationForView:[self csvTableName]] : [[self csvTableData] informationForTable:[self csvTableName]]];
+ [tableColumnNumericStatus addObject:[NSNumber numberWithBool:([tableColumnTypeGrouping isEqualToString:@"bit"] ||
+ [tableColumnTypeGrouping isEqualToString:@"integer"] ||
+ [tableColumnTypeGrouping isEqualToString:@"float"])]];
+ }
+
+ [tableDetails release];
+ }
+
+ // Drop into the processing loop
+ NSAutoreleasePool *csvExportPool = [[NSAutoreleasePool alloc] init];
+
+ NSUInteger currentPoolDataLength = 0;
+
+ // Inform the delegate that we are about to start writing the data to disk
+ [delegate performSelectorOnMainThread:@selector(csvExportProcessWillBeginWritingData:) withObject:self waitUntilDone:NO];
+
+ while (1)
+ {
+ // Check for cancellation flag
+ if ([self isCancelled]) {
+ if (streamingResult) {
+ [connection cancelCurrentQuery];
+ [streamingResult cancelResultLoad];
}
- // Retrieve the table details via the data class, and use it to build an array containing column numeric status
- for (NSDictionary *column in [tableDetails objectForKey:@"columns"])
- {
- NSString *tableColumnTypeGrouping = [column objectForKey:@"typegrouping"];
-
- [tableColumnNumericStatus addObject:[NSNumber numberWithBool:([tableColumnTypeGrouping isEqualToString:@"bit"] ||
- [tableColumnTypeGrouping isEqualToString:@"integer"] ||
- [tableColumnTypeGrouping isEqualToString:@"float"])]];
- }
+ [csvExportPool release];
+ [pool release];
- [tableDetails release];
+ return;
}
- // Drop into the processing loop
- NSAutoreleasePool *csvExportPool = [[NSAutoreleasePool alloc] init];
-
- NSUInteger currentPoolDataLength = 0;
+ // 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 {
+ // If still requested to read the field names, get the field names
+ if ([self csvOutputFieldNames]) {
+ csvRow = [streamingResult fetchFieldNames];
+ [self setCsvOutputFieldNames:NO];
+ }
+ else {
+ csvRow = [streamingResult fetchNextRowAsArray];
+
+ if (!csvRow) break;
+ }
+ }
- // Inform the delegate that we are about to start writing the data to disk
- [delegate performSelectorOnMainThread:@selector(csvExportProcessWillBeginWritingData:) withObject:self waitUntilDone:NO];
+ // Get the cell count if we don't already have it stored
+ if (!csvCellCount) csvCellCount = [csvRow count];
+
+ [csvString setString:@""];
- while (1)
+ for (i = 0 ; i < csvCellCount; i++)
{
// Check for cancellation flag
if ([self isCancelled]) {
- if (streamingResult) {
- [connection cancelCurrentQuery];
- [streamingResult cancelResultLoad];
- }
-
[csvExportPool release];
[pool release];
return;
}
- // 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 {
- // If still requested to read the field names, get the field names
- if ([self csvOutputFieldNames]) {
- csvRow = [streamingResult fetchFieldNames];
- [self setCsvOutputFieldNames:NO];
- }
- else {
- csvRow = [streamingResult fetchNextRowAsArray];
-
- if (!csvRow) break;
- }
+ csvCell = NSArrayObjectAtIndex(csvRow, i);
+
+ // For NULL objects supplied from a queryResult, add an unenclosed null string as per prefs
+ if ([csvCell isKindOfClass:[NSNull class]]) {
+ [csvString appendString:[self csvNULLString]];
+
+ if (i < (csvCellCount - 1)) [csvString appendString:[self csvFieldSeparatorString]];
+
+ continue;
}
- // Get the cell count if we don't already have it stored
- if (!csvCellCount) csvCellCount = [csvRow count];
-
- [csvString setString:@""];
-
- for (i = 0 ; i < csvCellCount; i++)
- {
- // Check for cancellation flag
- if ([self isCancelled]) {
- [csvExportPool release];
- [pool release];
-
- return;
- }
+ // Retrieve the contents of this cell
+ if ([csvCell isKindOfClass:[NSData class]]) {
+ dataConversionString = [[NSString alloc] initWithData:csvCell encoding:[self exportOutputEncoding]];
- csvCell = NSArrayObjectAtIndex(csvRow, i);
-
- // For NULL objects supplied from a queryResult, add an unenclosed null string as per prefs
- if ([csvCell isKindOfClass:[NSNull class]]) {
- [csvString appendString:[self csvNULLString]];
-
- if (i < (csvCellCount - 1)) [csvString appendString:[self csvFieldSeparatorString]];
-
- continue;
+ if (dataConversionString == nil) {
+ dataConversionString = [[NSString alloc] initWithData:csvCell encoding:NSASCIIStringEncoding];
}
- // Retrieve the contents of this cell
- if ([csvCell isKindOfClass:[NSData class]]) {
- dataConversionString = [[NSString alloc] initWithData:csvCell encoding:[self exportOutputEncoding]];
-
- if (dataConversionString == nil) {
- dataConversionString = [[NSString alloc] initWithData:csvCell encoding:NSASCIIStringEncoding];
- }
-
- [csvCellString setString:[NSString stringWithString:dataConversionString]];
- [dataConversionString release];
+ [csvCellString setString:[NSString stringWithString:dataConversionString]];
+ [dataConversionString release];
+ }
+ else {
+ [csvCellString setString:[csvCell description]];
+ }
+
+ // For NULL values supplied via an array add the unenclosed null string as set in preferences
+ if ([csvCellString isEqualToString:[self csvNULLString]]) {
+ [csvString appendString:[self csvNULLString]];
+ }
+ // Add empty strings as a pair of enclosing characters.
+ else if ([csvCellString length] == 0) {
+ [csvString appendString:[self csvEnclosingCharacterString]];
+ [csvString appendString:[self csvEnclosingCharacterString]];
+ }
+ else {
+ // If an array of bools supplying information as to whether the column is numeric has been supplied, use it.
+ if ([tableColumnNumericStatus count] > 0) {
+ csvCellIsNumeric = [NSArrayObjectAtIndex(tableColumnNumericStatus, i) boolValue];
+ }
+ // Otherwise, first test whether this cell contains data
+ else if ([NSArrayObjectAtIndex(csvRow, i) isKindOfClass:[NSData class]]) {
+ csvCellIsNumeric = NO;
}
+ // Or fall back to testing numeric content via an NSScanner.
else {
- [csvCellString setString:[csvCell description]];
+ csvNumericTester = [NSScanner scannerWithString:csvCellString];
+
+ csvCellIsNumeric = [csvNumericTester scanFloat:nil] &&
+ [csvNumericTester isAtEnd] &&
+ ([csvCellString characterAtIndex:0] != '0' ||
+ [csvCellString length] == 1 ||
+ ([csvCellString length] > 1 &&
+ [csvCellString characterAtIndex:1] == '.'));
}
+
+ // Escape any occurrences of the escaping character
+ [csvCellString replaceOccurrencesOfString:[self csvEscapeString]
+ withString:escapedEscapeString
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [csvCellString length])];
- // For NULL values supplied via an array add the unenclosed null string as set in preferences
- if ([csvCellString isEqualToString:[self csvNULLString]]) {
- [csvString appendString:[self csvNULLString]];
- }
- // Add empty strings as a pair of enclosing characters.
- else if ([csvCellString length] == 0) {
- [csvString appendString:[self csvEnclosingCharacterString]];
- [csvString appendString:[self csvEnclosingCharacterString]];
- }
- else {
- // If an array of bools supplying information as to whether the column is numeric has been supplied, use it.
- if ([tableColumnNumericStatus count] > 0) {
- csvCellIsNumeric = [NSArrayObjectAtIndex(tableColumnNumericStatus, i) boolValue];
- }
- // Otherwise, first test whether this cell contains data
- else if ([NSArrayObjectAtIndex(csvRow, i) isKindOfClass:[NSData class]]) {
- csvCellIsNumeric = NO;
- }
- // Or fall back to testing numeric content via an NSScanner.
- else {
- csvNumericTester = [NSScanner scannerWithString:csvCellString];
-
- csvCellIsNumeric = [csvNumericTester scanFloat:nil] &&
- [csvNumericTester isAtEnd] &&
- ([csvCellString characterAtIndex:0] != '0' ||
- [csvCellString length] == 1 ||
- ([csvCellString length] > 1 &&
- [csvCellString characterAtIndex:1] == '.'));
- }
-
- // Escape any occurrences of the escaping character
- [csvCellString replaceOccurrencesOfString:[self csvEscapeString]
- withString:escapedEscapeString
+ // Escape any occurrences of the enclosure string
+ if (![[self csvEscapeString] isEqualToString:[self csvEnclosingCharacterString]]) {
+ [csvCellString replaceOccurrencesOfString:[self csvEnclosingCharacterString]
+ withString:escapedEnclosingString
options:NSLiteralSearch
range:NSMakeRange(0, [csvCellString length])];
-
- // Escape any occurrences of the enclosure string
- if (![[self csvEscapeString] isEqualToString:[self csvEnclosingCharacterString]]) {
- [csvCellString replaceOccurrencesOfString:[self csvEnclosingCharacterString]
- withString:escapedEnclosingString
- options:NSLiteralSearch
- range:NSMakeRange(0, [csvCellString length])];
- }
-
- // Escape occurrences of the line end character
- [csvCellString replaceOccurrencesOfString:[self csvLineEndingString]
- withString:escapedLineEndString
+ }
+
+ // 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 (quoteFieldSeparators || csvCellIsNumeric) {
+ [csvCellString replaceOccurrencesOfString:[self csvFieldSeparatorString]
+ withString:escapedFieldSeparatorString
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) {
- [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:csvCellString];
- }
- else {
- [csvString appendString:[self csvEnclosingCharacterString]];
- [csvString appendString:csvCellString];
- [csvString appendString:[self csvEnclosingCharacterString]];
- }
}
- if (i < ([csvRow count] - 1)) [csvString appendString:[self csvFieldSeparatorString]];
+ // Write out the cell data by appending strings - this is significantly faster than stringWithFormat.
+ if (csvCellIsNumeric) {
+ [csvString appendString:csvCellString];
+ }
+ else {
+ [csvString appendString:[self csvEnclosingCharacterString]];
+ [csvString appendString:csvCellString];
+ [csvString appendString:[self csvEnclosingCharacterString]];
+ }
}
- // Append the line ending to the string for this row, and record the length processed for pool flushing
- [csvString appendString:[self csvLineEndingString]];
- currentPoolDataLength += [csvString length];
-
- // Write it to the fileHandle
- [[self exportOutputFileHandle] writeData:[csvString dataUsingEncoding:[self exportOutputEncoding]]];
-
- currentRowIndex++;
-
- // Update the progress
- if (totalRows && (currentRowIndex * ([self exportMaxProgress] / totalRows)) > lastProgressValue) {
-
- NSInteger progress = (currentRowIndex * ([self exportMaxProgress] / totalRows));
-
- [self setExportProgressValue:progress];
-
- lastProgressValue = progress;
- }
+ if (i < ([csvRow count] - 1)) [csvString appendString:[self csvFieldSeparatorString]];
+ }
+
+ // Append the line ending to the string for this row, and record the length processed for pool flushing
+ [csvString appendString:[self csvLineEndingString]];
+ currentPoolDataLength += [csvString length];
+
+ // Write it to the fileHandle
+ [[self exportOutputFileHandle] writeData:[csvString dataUsingEncoding:[self exportOutputEncoding]]];
+
+ currentRowIndex++;
+
+ // Update the progress
+ if (totalRows && (currentRowIndex * ([self exportMaxProgress] / totalRows)) > lastProgressValue) {
- // Inform the delegate that the export's progress has been updated
- [delegate performSelectorOnMainThread:@selector(csvExportProcessProgressUpdated:) withObject:self waitUntilDone:NO];
+ NSInteger progress = (currentRowIndex * ([self exportMaxProgress] / totalRows));
- // Drain the autorelease pool as required to keep memory usage low
- if (currentPoolDataLength > 250000) {
- [csvExportPool release];
- csvExportPool = [[NSAutoreleasePool alloc] init];
- }
+ [self setExportProgressValue:progress];
- // If an array was supplied and we've processed all rows, break
- if ([self csvDataArray] && (totalRows == currentRowIndex)) break;
+ lastProgressValue = progress;
}
- // Write data to disk
- [[self exportOutputFileHandle] synchronizeFile];
-
- // Mark the process as not running
- [self setExportProcessIsRunning:NO];
+ // Inform the delegate that the export's progress has been updated
+ [delegate performSelectorOnMainThread:@selector(csvExportProcessProgressUpdated:) withObject:self waitUntilDone:NO];
- // Inform the delegate that the export process is complete
- [delegate performSelectorOnMainThread:@selector(csvExportProcessComplete:) withObject:self waitUntilDone:NO];
+ // Drain the autorelease pool as required to keep memory usage low
+ if (currentPoolDataLength > 250000) {
+ [csvExportPool release];
+ csvExportPool = [[NSAutoreleasePool alloc] init];
+ }
- [csvExportPool release];
- [pool release];
+ // If an array was supplied and we've processed all rows, break
+ if ([self csvDataArray] && (totalRows == currentRowIndex)) break;
}
- @catch(NSException *e) {}
+
+ // Write data to disk
+ [[self exportOutputFileHandle] synchronizeFile];
+
+ // Mark the process as not running
+ [self setExportProcessIsRunning:NO];
+
+ // Inform the delegate that the export process is complete
+ [delegate performSelectorOnMainThread:@selector(csvExportProcessComplete:) withObject:self waitUntilDone:NO];
+
+ [csvExportPool release];
+ [pool release];
}
/**
diff --git a/Source/SPDotExporter.m b/Source/SPDotExporter.m
index cbb132d9..044065e5 100644
--- a/Source/SPDotExporter.m
+++ b/Source/SPDotExporter.m
@@ -61,150 +61,147 @@
*/
- (void)main
{
- @try {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSMutableString *metaString = [NSMutableString string];
-
- // Check that we have all the required info before starting the export
- if ((![self dotExportTables]) || (![self dotTableData]) || ([[self dotExportTables] count] == 0)) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSMutableString *metaString = [NSMutableString string];
+
+ // Check that we have all the required info before starting the export
+ if ((![self dotExportTables]) || (![self dotTableData]) || ([[self dotExportTables] count] == 0)) {
+ [pool release];
+ return;
+ }
+
+ // Inform the delegate that the export process is about to begin
+ [delegate performSelectorOnMainThread:@selector(dotExportProcessWillBegin:) withObject:self waitUntilDone:NO];
+
+ // Mark the process as running
+ [self setExportProcessIsRunning:YES];
+
+ [metaString setString:@"// ************************************************************\n"];
+ [metaString appendString:@"// Generated by: Sequel Pro\n"];
+ [metaString appendString:[NSString stringWithFormat:@"// Version %@\n//\n", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]]];
+ [metaString appendString:[NSString stringWithFormat:@"// %@\n// %@\n//\n", SPHomePageURL, SPDevURL]];
+ [metaString appendString:[NSString stringWithFormat:@"// Host: %@ (MySQL %@)\n", [self dotDatabaseHost], [self dotDatabaseVersion]]];
+ [metaString appendString:[NSString stringWithFormat:@"// Database: %@\n", [self dotDatabaseName]]];
+ [metaString appendString:[NSString stringWithFormat:@"// Generation Time: %@\n", [NSDate date]]];
+ [metaString appendString:@"// ************************************************************\n\n"];
+
+ [metaString appendString:@"digraph \"Database Structure\" {\n"];
+ [metaString appendString:[NSString stringWithFormat:@"\tlabel = \"ER Diagram: %@\";\n", [self dotDatabaseName]]];
+ [metaString appendString:@"\tlabelloc = t;\n"];
+ [metaString appendString:@"\tcompound = true;\n"];
+ [metaString appendString:@"\tnode [ shape = record ];\n"];
+ [metaString appendString:@"\tfontname = \"Helvetica\";\n"];
+ [metaString appendString:@"\tranksep = 1.25;\n"];
+ [metaString appendString:@"\tratio = 0.7;\n"];
+ [metaString appendString:@"\trankdir = LR;\n"];
+
+ // Write information to the file
+ [[self exportOutputFileHandle] writeData:[metaString dataUsingEncoding:NSUTF8StringEncoding]];
+
+ NSMutableArray *fkInfo = [[NSMutableArray alloc] init];
+
+ // Process the tables
+ for (NSInteger i = 0; i < [[self dotExportTables] count]; i++)
+ {
+ // Check for cancellation flag
+ if ([self isCancelled]) {
[pool release];
return;
}
+
+ NSString *tableName = NSArrayObjectAtIndex([self dotExportTables], i);
+ NSDictionary *tableInfo = [[self dotTableData] informationForTable:tableName];
+
+ // Set the current table
+ [self setDotExportCurrentTable:tableName];
+
+ // Inform the delegate that we are about to start fetcihing data for the current table
+ [delegate performSelectorOnMainThread:@selector(dotExportProcessWillBeginFetchingData:) withObject:self waitUntilDone:NO];
+
+ NSString *hdrColor = @"#DDDDDD";
+
+ if ([[tableInfo objectForKey:@"type"] isEqualToString:@"View"]) {
+ hdrColor = @"#DDDDFF";
+ }
- // Inform the delegate that the export process is about to begin
- [delegate performSelectorOnMainThread:@selector(dotExportProcessWillBegin:) withObject:self waitUntilDone:NO];
+ [metaString setString:[NSString stringWithFormat:@"\tsubgraph \"table_%@\" {\n", tableName]];
+ [metaString appendString:@"\t\tnode [ shape = \"plaintext\" ];\n"];
+ [metaString appendString:[NSString stringWithFormat:@"\t\t\"%@\" [ label=<\n", tableName]];
+ [metaString appendString:@"\t\t\t<TABLE BORDER=\"0\" CELLSPACING=\"0\" CELLBORDER=\"1\">\n"];
+ [metaString appendString:[NSString stringWithFormat:@"\t\t\t<TR><TD COLSPAN=\"3\" BGCOLOR=\"%@\">%@</TD></TR>\n", hdrColor, tableName]];
- // Mark the process as running
- [self setExportProcessIsRunning:YES];
+ // Get the column info
+ NSArray *columnInfo = [tableInfo objectForKey:@"columns"];
- [metaString setString:@"// ************************************************************\n"];
- [metaString appendString:@"// Generated by: Sequel Pro\n"];
- [metaString appendString:[NSString stringWithFormat:@"// Version %@\n//\n", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]]];
- [metaString appendString:[NSString stringWithFormat:@"// %@\n// %@\n//\n", SPHomePageURL, SPDevURL]];
- [metaString appendString:[NSString stringWithFormat:@"// Host: %@ (MySQL %@)\n", [self dotDatabaseHost], [self dotDatabaseVersion]]];
- [metaString appendString:[NSString stringWithFormat:@"// Database: %@\n", [self dotDatabaseName]]];
- [metaString appendString:[NSString stringWithFormat:@"// Generation Time: %@\n", [NSDate date]]];
- [metaString appendString:@"// ************************************************************\n\n"];
+ for (NSInteger j = 0; j < [columnInfo count]; j++ )
+ {
+ [metaString appendString:[NSString stringWithFormat:@"\t\t\t<TR><TD COLSPAN=\"3\" PORT=\"%@\">%@:<FONT FACE=\"Helvetica-Oblique\" POINT-SIZE=\"10\">%@</FONT></TD></TR>\n", [[columnInfo objectAtIndex:j] objectForKey:@"name"], [[columnInfo objectAtIndex:j] objectForKey:@"name"], [[columnInfo objectAtIndex:j] objectForKey:@"type"]]];
+ }
- [metaString appendString:@"digraph \"Database Structure\" {\n"];
- [metaString appendString:[NSString stringWithFormat:@"\tlabel = \"ER Diagram: %@\";\n", [self dotDatabaseName]]];
- [metaString appendString:@"\tlabelloc = t;\n"];
- [metaString appendString:@"\tcompound = true;\n"];
- [metaString appendString:@"\tnode [ shape = record ];\n"];
- [metaString appendString:@"\tfontname = \"Helvetica\";\n"];
- [metaString appendString:@"\tranksep = 1.25;\n"];
- [metaString appendString:@"\tratio = 0.7;\n"];
- [metaString appendString:@"\trankdir = LR;\n"];
+ [metaString appendString:@"\t\t\t</TABLE>>\n"];
+ [metaString appendString:@"\t\t];\n"];
+ [metaString appendString:@"\t}\n"];
- // Write information to the file
[[self exportOutputFileHandle] writeData:[metaString dataUsingEncoding:NSUTF8StringEncoding]];
-
- NSMutableArray *fkInfo = [[NSMutableArray alloc] init];
- // Process the tables
- for (NSInteger i = 0; i < [[self dotExportTables] count]; i++)
+ // see about relations
+ columnInfo = [tableInfo objectForKey:@"constraints"];
+
+ for (NSInteger j = 0; j < [columnInfo count]; j++)
{
// Check for cancellation flag
if ([self isCancelled]) {
[pool release];
return;
}
-
- NSString *tableName = NSArrayObjectAtIndex([self dotExportTables], i);
- NSDictionary *tableInfo = [[self dotTableData] informationForTable:tableName];
-
- // Set the current table
- [self setDotExportCurrentTable:tableName];
-
- // Inform the delegate that we are about to start fetcihing data for the current table
- [delegate performSelectorOnMainThread:@selector(dotExportProcessWillBeginFetchingData:) withObject:self waitUntilDone:NO];
-
- NSString *hdrColor = @"#DDDDDD";
-
- if ([[tableInfo objectForKey:@"type"] isEqualToString:@"View"]) {
- hdrColor = @"#DDDDFF";
- }
- [metaString setString:[NSString stringWithFormat:@"\tsubgraph \"table_%@\" {\n", tableName]];
- [metaString appendString:@"\t\tnode [ shape = \"plaintext\" ];\n"];
- [metaString appendString:[NSString stringWithFormat:@"\t\t\"%@\" [ label=<\n", tableName]];
- [metaString appendString:@"\t\t\t<TABLE BORDER=\"0\" CELLSPACING=\"0\" CELLBORDER=\"1\">\n"];
- [metaString appendString:[NSString stringWithFormat:@"\t\t\t<TR><TD COLSPAN=\"3\" BGCOLOR=\"%@\">%@</TD></TR>\n", hdrColor, tableName]];
+ // Get the column references. Currently the columns themselves are an array,
+ // while reference columns and tables are comma separated if there are more than
+ // one. Only use the first of each for the time being.
+ NSArray *ccols = [NSArrayObjectAtIndex(columnInfo, j) objectForKey:@"columns"];
+ NSString *ccol = NSArrayObjectAtIndex(columnInfo, 0);
+ NSString *rcol = [NSArrayObjectAtIndex(columnInfo, j) objectForKey:@"ref_columns"];
- // Get the column info
- NSArray *columnInfo = [tableInfo objectForKey:@"columns"];
+ NSString *extra = @"";
- for (NSInteger j = 0; j < [columnInfo count]; j++ )
- {
- [metaString appendString:[NSString stringWithFormat:@"\t\t\t<TR><TD COLSPAN=\"3\" PORT=\"%@\">%@:<FONT FACE=\"Helvetica-Oblique\" POINT-SIZE=\"10\">%@</FONT></TD></TR>\n", [[columnInfo objectAtIndex:j] objectForKey:@"name"], [[columnInfo objectAtIndex:j] objectForKey:@"name"], [[columnInfo objectAtIndex:j] objectForKey:@"type"]]];
+ if ([ccols count] > 1) {
+ extra = @" [ arrowhead=crow, arrowtail=odiamond ]";
+ rcol = NSArrayObjectAtIndex([rcol componentsSeparatedByString:@","], 0);
}
- [metaString appendString:@"\t\t\t</TABLE>>\n"];
- [metaString appendString:@"\t\t];\n"];
- [metaString appendString:@"\t}\n"];
-
- [[self exportOutputFileHandle] writeData:[metaString dataUsingEncoding:NSUTF8StringEncoding]];
-
- // see about relations
- columnInfo = [tableInfo objectForKey:@"constraints"];
-
- for (NSInteger j = 0; j < [columnInfo count]; j++)
- {
- // Check for cancellation flag
- if ([self isCancelled]) {
- [pool release];
- return;
- }
-
- // Get the column references. Currently the columns themselves are an array,
- // while reference columns and tables are comma separated if there are more than
- // one. Only use the first of each for the time being.
- NSArray *ccols = [NSArrayObjectAtIndex(columnInfo, j) objectForKey:@"columns"];
- NSString *ccol = NSArrayObjectAtIndex(columnInfo, 0);
- NSString *rcol = [NSArrayObjectAtIndex(columnInfo, j) objectForKey:@"ref_columns"];
-
- NSString *extra = @"";
-
- if ([ccols count] > 1) {
- extra = @" [ arrowhead=crow, arrowtail=odiamond ]";
- rcol = NSArrayObjectAtIndex([rcol componentsSeparatedByString:@","], 0);
- }
-
- [fkInfo addObject:[NSString stringWithFormat:@"%@:%@ -> %@:%@ %@", tableName, ccol, [NSArrayObjectAtIndex(columnInfo, j) objectForKey:@"ref_table"], rcol, extra]];
- }
+ [fkInfo addObject:[NSString stringWithFormat:@"%@:%@ -> %@:%@ %@", tableName, ccol, [NSArrayObjectAtIndex(columnInfo, j) objectForKey:@"ref_table"], rcol, extra]];
}
-
- // Inform the delegate that we are about to start fetching relations data for the current table
- [delegate performSelectorOnMainThread:@selector(dotExportProcessWillBeginFetchingRelationsData:) withObject:self waitUntilDone:NO];
-
- [metaString setString:@"edge [ arrowhead=inv, arrowtail=normal, style=dashed, color=\"#444444\" ];\n"];
-
- // Get the relations
- for (NSInteger i = 0; i < [fkInfo count]; i++)
- {
- [metaString appendString:[NSString stringWithFormat:@"%@;\n", [fkInfo objectAtIndex:i]]];
- }
-
- [fkInfo release];
-
- [metaString appendString:@"}\n"];
-
- // Write information to the file
- [[self exportOutputFileHandle] writeData:[metaString dataUsingEncoding:NSUTF8StringEncoding]];
-
- // Write data to disk
- [[self exportOutputFileHandle] closeFile];
-
- // Mark the process as not running
- [self setExportProcessIsRunning:NO];
-
- // Inform the delegate that the export process is complete
- [delegate performSelectorOnMainThread:@selector(dotExportProcessComplete:) withObject:self waitUntilDone:NO];
-
- [pool release];
}
- @catch (NSException *e) { }
+
+ // Inform the delegate that we are about to start fetching relations data for the current table
+ [delegate performSelectorOnMainThread:@selector(dotExportProcessWillBeginFetchingRelationsData:) withObject:self waitUntilDone:NO];
+
+ [metaString setString:@"edge [ arrowhead=inv, arrowtail=normal, style=dashed, color=\"#444444\" ];\n"];
+
+ // Get the relations
+ for (NSInteger i = 0; i < [fkInfo count]; i++)
+ {
+ [metaString appendString:[NSString stringWithFormat:@"%@;\n", [fkInfo objectAtIndex:i]]];
+ }
+
+ [fkInfo release];
+
+ [metaString appendString:@"}\n"];
+
+ // Write information to the file
+ [[self exportOutputFileHandle] writeData:[metaString dataUsingEncoding:NSUTF8StringEncoding]];
+
+ // Write data to disk
+ [[self exportOutputFileHandle] closeFile];
+
+ // Mark the process as not running
+ [self setExportProcessIsRunning:NO];
+
+ // Inform the delegate that the export process is complete
+ [delegate performSelectorOnMainThread:@selector(dotExportProcessComplete:) withObject:self waitUntilDone:NO];
+
+ [pool release];
}
/**
diff --git a/Source/SPHTMLExporter.m b/Source/SPHTMLExporter.m
index 45f41c54..dbf649dc 100644
--- a/Source/SPHTMLExporter.m
+++ b/Source/SPHTMLExporter.m
@@ -50,13 +50,9 @@
*/
- (void)main
{
- @try {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [pool release];
-
- }
- @catch (NSException *e) { }
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [pool release];
}
@end
diff --git a/Source/SPPDFExporter.m b/Source/SPPDFExporter.m
index a850e2bf..725b4173 100644
--- a/Source/SPPDFExporter.m
+++ b/Source/SPPDFExporter.m
@@ -50,12 +50,9 @@
*/
- (void)main
{
- @try {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [pool release];
- }
- @catch (NSException *e) { }
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [pool release];
}
@end
diff --git a/Source/SPXMLExporter.m b/Source/SPXMLExporter.m
index de43560e..0c060a55 100644
--- a/Source/SPXMLExporter.m
+++ b/Source/SPXMLExporter.m
@@ -58,73 +58,104 @@
*/
- (void)main
{
- @try {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSArray *xmlRow = nil;
- NSString *dataConversionString = nil;
- MCPStreamingResult *streamingResult = nil;
-
- NSMutableArray *xmlTags = [NSMutableArray array];
- NSMutableString *xmlString = [NSMutableString string];
- NSMutableString *xmlItem = [NSMutableString string];
-
- NSUInteger xmlRowCount = 0;
- NSUInteger i, totalRows, currentRowIndex, lastProgressValue, currentPoolDataLength;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSArray *xmlRow = nil;
+ NSString *dataConversionString = nil;
+ MCPStreamingResult *streamingResult = nil;
+
+ NSMutableArray *xmlTags = [NSMutableArray array];
+ NSMutableString *xmlString = [NSMutableString string];
+ NSMutableString *xmlItem = [NSMutableString string];
+
+ NSUInteger xmlRowCount = 0;
+ NSUInteger i, totalRows, currentRowIndex, lastProgressValue, currentPoolDataLength;
+
+ // Check to see if we have at least a table name or data array
+ if ((![self xmlTableName]) && (![self xmlDataArray]) ||
+ ([[self xmlTableName] isEqualToString:@""]) && ([[self xmlDataArray] count] == 0))
+ {
+ [pool release];
+ return;
+ }
+
+ // Inform the delegate that the export process is about to begin
+ [delegate performSelectorOnMainThread:@selector(xmlExportProcessWillBegin:) withObject:self waitUntilDone:NO];
+
+ // Mark the process as running
+ [self setExportProcessIsRunning:YES];
+
+ lastProgressValue = 0;
+
+ // Make a streaming request for the data if the data array isn't set
+ if ((![self xmlDataArray]) && [self xmlTableName]) {
+ totalRows = [[[[connection queryString:[NSString stringWithFormat:@"SELECT COUNT(1) FROM %@", [[self xmlTableName] backtickQuotedString]]] fetchRowAsArray] objectAtIndex:0] integerValue];
+ streamingResult = [connection streamingQueryString:[NSString stringWithFormat:@"SELECT * FROM %@", [[self xmlTableName] backtickQuotedString]] useLowMemoryBlockingStreaming:[self exportUsingLowMemoryBlockingStreaming]];
+ }
+ else {
+ totalRows = [[self xmlDataArray] count];
+ }
+
+ // Set up an array of encoded field names as opening and closing tags
+ xmlRow = ([self xmlDataArray]) ? [[self xmlDataArray] objectAtIndex:0] : [streamingResult fetchFieldNames];
+
+ for (i = 0; i < [xmlRow count]; i++)
+ {
+ [xmlTags addObject:[NSMutableArray array]];
- // Check to see if we have at least a table name or data array
- if ((![self xmlTableName]) && (![self xmlDataArray]) ||
- ([[self xmlTableName] isEqualToString:@""]) && ([[self xmlDataArray] count] == 0))
- {
+ [[xmlTags objectAtIndex:i] addObject:[NSString stringWithFormat:@"\t\t<%@>", [[[xmlRow objectAtIndex:i] description] HTMLEscapeString]]];
+ [[xmlTags objectAtIndex:i] addObject:[NSString stringWithFormat:@"</%@>\n", [[[xmlRow objectAtIndex:i] description] HTMLEscapeString]]];
+ }
+
+ [[self exportOutputFileHandle] writeData:[xmlString dataUsingEncoding:[self exportOutputEncoding]]];
+
+ // Write an opening tag in the form of the table name
+ [[self exportOutputFileHandle] writeData:[[NSString stringWithFormat:@"\t<%@>\n", ([self xmlTableName]) ? [[self xmlTableName] HTMLEscapeString] : @"custom"] dataUsingEncoding:[self exportOutputEncoding]]];
+
+ // Set up the starting row, which is 0 for streaming result sets and
+ // 1 for supplied arrays which include the column headers as the first row.
+ currentRowIndex = 0;
+
+ if ([self xmlDataArray]) currentRowIndex++;
+
+ // Drop into the processing loop
+ NSAutoreleasePool *xmlExportPool = [[NSAutoreleasePool alloc] init];
+
+ currentPoolDataLength = 0;
+
+ while (1)
+ {
+ // Check for cancellation flag
+ if ([self isCancelled]) {
+ if (streamingResult) {
+ [connection cancelCurrentQuery];
+ [streamingResult cancelResultLoad];
+ }
+
+ [xmlExportPool release];
[pool release];
+
return;
}
-
- // Inform the delegate that the export process is about to begin
- [delegate performSelectorOnMainThread:@selector(xmlExportProcessWillBegin:) withObject:self waitUntilDone:NO];
- // Mark the process as running
- [self setExportProcessIsRunning:YES];
-
- lastProgressValue = 0;
-
- // Make a streaming request for the data if the data array isn't set
- if ((![self xmlDataArray]) && [self xmlTableName]) {
- totalRows = [[[[connection queryString:[NSString stringWithFormat:@"SELECT COUNT(1) FROM %@", [[self xmlTableName] backtickQuotedString]]] fetchRowAsArray] objectAtIndex:0] integerValue];
- streamingResult = [connection streamingQueryString:[NSString stringWithFormat:@"SELECT * FROM %@", [[self xmlTableName] backtickQuotedString]] useLowMemoryBlockingStreaming:[self exportUsingLowMemoryBlockingStreaming]];
- }
+ // Retrieve the next row from the supplied data, either directly from the array...
+ if ([self xmlDataArray]) {
+ xmlRow = NSArrayObjectAtIndex([self xmlDataArray], currentRowIndex);
+ }
+ // Or by reading an appropriate row from the streaming result
else {
- totalRows = [[self xmlDataArray] count];
- }
-
- // Set up an array of encoded field names as opening and closing tags
- xmlRow = ([self xmlDataArray]) ? [[self xmlDataArray] objectAtIndex:0] : [streamingResult fetchFieldNames];
-
- for (i = 0; i < [xmlRow count]; i++)
- {
- [xmlTags addObject:[NSMutableArray array]];
+ xmlRow = [streamingResult fetchNextRowAsArray];
- [[xmlTags objectAtIndex:i] addObject:[NSString stringWithFormat:@"\t\t<%@>", [[[xmlRow objectAtIndex:i] description] HTMLEscapeString]]];
- [[xmlTags objectAtIndex:i] addObject:[NSString stringWithFormat:@"</%@>\n", [[[xmlRow objectAtIndex:i] description] HTMLEscapeString]]];
+ if (!xmlRow) break;
}
- [[self exportOutputFileHandle] writeData:[xmlString dataUsingEncoding:[self exportOutputEncoding]]];
-
- // Write an opening tag in the form of the table name
- [[self exportOutputFileHandle] writeData:[[NSString stringWithFormat:@"\t<%@>\n", ([self xmlTableName]) ? [[self xmlTableName] HTMLEscapeString] : @"custom"] dataUsingEncoding:[self exportOutputEncoding]]];
+ // Get the cell count if we don't already have it stored
+ if (!xmlRowCount) xmlRowCount = [xmlRow count];
- // Set up the starting row, which is 0 for streaming result sets and
- // 1 for supplied arrays which include the column headers as the first row.
- currentRowIndex = 0;
+ // Construct the row
+ [xmlString setString:@"\t<row>\n"];
- if ([self xmlDataArray]) currentRowIndex++;
-
- // Drop into the processing loop
- NSAutoreleasePool *xmlExportPool = [[NSAutoreleasePool alloc] init];
-
- currentPoolDataLength = 0;
-
- while (1)
+ for (i = 0; i < xmlRowCount; i++)
{
// Check for cancellation flag
if ([self isCancelled]) {
@@ -139,109 +170,75 @@
return;
}
- // Retrieve the next row from the supplied data, either directly from the array...
- if ([self xmlDataArray]) {
- xmlRow = NSArrayObjectAtIndex([self xmlDataArray], currentRowIndex);
- }
- // Or by reading an appropriate row from the streaming result
- else {
- xmlRow = [streamingResult fetchNextRowAsArray];
-
- if (!xmlRow) break;
- }
-
- // Get the cell count if we don't already have it stored
- if (!xmlRowCount) xmlRowCount = [xmlRow count];
-
- // Construct the row
- [xmlString setString:@"\t<row>\n"];
-
- for (i = 0; i < xmlRowCount; i++)
- {
- // Check for cancellation flag
- if ([self isCancelled]) {
- if (streamingResult) {
- [connection cancelCurrentQuery];
- [streamingResult cancelResultLoad];
- }
-
- [xmlExportPool release];
- [pool release];
-
- return;
- }
+ // Retrieve the contents of this tag
+ if ([NSArrayObjectAtIndex(xmlRow, i) isKindOfClass:[NSData class]]) {
+ dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(xmlRow, i) encoding:[self exportOutputEncoding]];
- // Retrieve the contents of this tag
- if ([NSArrayObjectAtIndex(xmlRow, i) isKindOfClass:[NSData class]]) {
- dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(xmlRow, i) encoding:[self exportOutputEncoding]];
-
- if (dataConversionString == nil) {
- dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(xmlRow, i) encoding:NSASCIIStringEncoding];
- }
-
- [xmlItem setString:[NSString stringWithString:dataConversionString]];
- [dataConversionString release];
- }
- else {
- [xmlItem setString:[NSArrayObjectAtIndex(xmlRow, i) description]];
+ if (dataConversionString == nil) {
+ dataConversionString = [[NSString alloc] initWithData:NSArrayObjectAtIndex(xmlRow, i) encoding:NSASCIIStringEncoding];
}
- // Add the opening and closing tag and the contents to the XML string
- [xmlString appendString:NSArrayObjectAtIndex(NSArrayObjectAtIndex(xmlTags, i), 0)];
- [xmlString appendString:[xmlItem HTMLEscapeString]];
- [xmlString appendString:NSArrayObjectAtIndex(NSArrayObjectAtIndex(xmlTags, i), 1)];
- }
-
- [xmlString appendString:@"\t</row>\n"];
-
- // Record the total length for use with pool flushing
- currentPoolDataLength += [xmlString length];
-
- // Write the row to the filehandle
- [[self exportOutputFileHandle] writeData:[xmlString dataUsingEncoding:[self exportOutputEncoding]]];
-
- // Update the progress counter and progress bar
- currentRowIndex++;
-
- // Update the progress
- if (totalRows && (currentRowIndex * ([self exportMaxProgress] / totalRows)) > lastProgressValue) {
-
- NSInteger progress = (currentRowIndex * ([self exportMaxProgress] / totalRows));
-
- [self setExportProgressValue:progress];
-
- lastProgressValue = progress;
- }
-
- // Inform the delegate that the export's progress has been updated
- [delegate performSelectorOnMainThread:@selector(xmlExportProcessProgressUpdated:) withObject:self waitUntilDone:NO];
-
- // Drain the autorelease pool as required to keep memory usage low
- if (currentPoolDataLength > 250000) {
- [xmlExportPool release];
- xmlExportPool = [[NSAutoreleasePool alloc] init];
+ [xmlItem setString:[NSString stringWithString:dataConversionString]];
+ [dataConversionString release];
+ }
+ else {
+ [xmlItem setString:[NSArrayObjectAtIndex(xmlRow, i) description]];
}
- // If an array was supplied and we've processed all rows, break
- if ([self xmlDataArray] && totalRows == currentRowIndex) break;
+ // Add the opening and closing tag and the contents to the XML string
+ [xmlString appendString:NSArrayObjectAtIndex(NSArrayObjectAtIndex(xmlTags, i), 0)];
+ [xmlString appendString:[xmlItem HTMLEscapeString]];
+ [xmlString appendString:NSArrayObjectAtIndex(NSArrayObjectAtIndex(xmlTags, i), 1)];
}
- // Write the closing tag for the table
- [[self exportOutputFileHandle] writeData:[[NSString stringWithFormat:@"\t</%@>\n\n", ([self xmlTableName]) ? [[self xmlTableName] HTMLEscapeString] : @"custom"] dataUsingEncoding:[self exportOutputEncoding]]];
+ [xmlString appendString:@"\t</row>\n"];
- // Write data to disk
- [[self exportOutputFileHandle] synchronizeFile];
+ // Record the total length for use with pool flushing
+ currentPoolDataLength += [xmlString length];
- // Mark the process as not running
- [self setExportProcessIsRunning:NO];
+ // Write the row to the filehandle
+ [[self exportOutputFileHandle] writeData:[xmlString dataUsingEncoding:[self exportOutputEncoding]]];
- // Inform the delegate that the export process is complete
- [delegate performSelectorOnMainThread:@selector(xmlExportProcessComplete:) withObject:self waitUntilDone:NO];
+ // Update the progress counter and progress bar
+ currentRowIndex++;
- [xmlExportPool release];
- [pool release];
+ // Update the progress
+ if (totalRows && (currentRowIndex * ([self exportMaxProgress] / totalRows)) > lastProgressValue) {
+
+ NSInteger progress = (currentRowIndex * ([self exportMaxProgress] / totalRows));
+
+ [self setExportProgressValue:progress];
+
+ lastProgressValue = progress;
+ }
+
+ // Inform the delegate that the export's progress has been updated
+ [delegate performSelectorOnMainThread:@selector(xmlExportProcessProgressUpdated:) withObject:self waitUntilDone:NO];
+
+ // Drain the autorelease pool as required to keep memory usage low
+ if (currentPoolDataLength > 250000) {
+ [xmlExportPool release];
+ xmlExportPool = [[NSAutoreleasePool alloc] init];
+ }
+
+ // If an array was supplied and we've processed all rows, break
+ if ([self xmlDataArray] && totalRows == currentRowIndex) break;
}
- @catch (NSException *e) { }
+
+ // Write the closing tag for the table
+ [[self exportOutputFileHandle] writeData:[[NSString stringWithFormat:@"\t</%@>\n\n", ([self xmlTableName]) ? [[self xmlTableName] HTMLEscapeString] : @"custom"] dataUsingEncoding:[self exportOutputEncoding]]];
+
+ // Write data to disk
+ [[self exportOutputFileHandle] synchronizeFile];
+
+ // Mark the process as not running
+ [self setExportProcessIsRunning:NO];
+
+ // Inform the delegate that the export process is complete
+ [delegate performSelectorOnMainThread:@selector(xmlExportProcessComplete:) withObject:self waitUntilDone:NO];
+
+ [xmlExportPool release];
+ [pool release];
}
/**