aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPDataImport.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPDataImport.m')
-rw-r--r--Source/SPDataImport.m71
1 files changed, 58 insertions, 13 deletions
diff --git a/Source/SPDataImport.m b/Source/SPDataImport.m
index 03a1afb7..d1b2b67a 100644
--- a/Source/SPDataImport.m
+++ b/Source/SPDataImport.m
@@ -69,6 +69,8 @@
geometryFieldsMapIndex = [[NSMutableIndexSet alloc] init];
bitFields = [[NSMutableArray alloc] init];
bitFieldsMapIndex = [[NSMutableIndexSet alloc] init];
+ nullableNumericFields = [[NSMutableArray alloc] init];
+ nullableNumericFieldsMapIndex = [[NSMutableIndexSet alloc] init];
fieldMappingArray = nil;
fieldMappingGlobalValueArray = nil;
fieldMappingTableColumnNames = nil;
@@ -712,6 +714,7 @@
NSUInteger csvRowsPerQuery = 50;
NSUInteger csvRowsThisQuery;
NSUInteger fileTotalLength = 0;
+ BOOL fileIsCompressed;
NSInteger rowsImported = 0;
NSInteger dataBufferLength = 0;
NSInteger dataBufferPosition = 0;
@@ -729,6 +732,8 @@
[geometryFieldsMapIndex removeAllIndexes];
[bitFields removeAllObjects];
[bitFieldsMapIndex removeAllIndexes];
+ [nullableNumericFields removeAllObjects];
+ [nullableNumericFieldsMapIndex removeAllIndexes];
// Start the notification timer to allow notifications to be shown even if frontmost for long queries
[[SPGrowlController sharedGrowlController] setVisibilityForNotificationName:@"Import Finished"];
@@ -746,9 +751,14 @@
return;
}
- // Grab the file length
+ // Grab the file length and status
fileTotalLength = (NSUInteger)[[[[NSFileManager defaultManager] attributesOfItemAtPath:filename error:NULL] objectForKey:NSFileSize] longLongValue];
if (!fileTotalLength) fileTotalLength = 1;
+ fileIsCompressed = [csvFileHandle isCompressed];
+
+ // If importing a bzipped file, use indeterminate progress bars as no progress is available
+ BOOL useIndeterminate = NO;
+ if ([csvFileHandle compressionFormat] == SPBzip2Compression) useIndeterminate = YES;
// Reset progress interface
[errorsView setString:@""];
@@ -926,12 +936,22 @@
}
// Reset progress interface and open the progress sheet
- [[singleProgressBar onMainThread] setIndeterminate:NO];
+ [[singleProgressBar onMainThread] setIndeterminate:useIndeterminate];
[[singleProgressBar onMainThread] setMaxValue:fileTotalLength];
[[singleProgressBar onMainThread] startAnimation:self];
[[NSApp onMainThread] beginSheet:singleProgressSheet modalForWindow:[tableDocumentInstance parentWindow] modalDelegate:self didEndSelector:nil contextInfo:nil];
[[singleProgressSheet onMainThread] makeKeyWindow];
+ // Set up index sets for use during row enumeration
+ for (i = 0; i < [fieldMappingArray count]; i++) {
+ if ([NSArrayObjectAtIndex(fieldMapperOperator, i) integerValue] == 0) {
+ NSString *fieldName = NSArrayObjectAtIndex(fieldMappingTableColumnNames, i);
+ if ([nullableNumericFields containsObject:fieldName]) {
+ [nullableNumericFieldsMapIndex addIndex:i];
+ }
+ }
+ }
+
// Set up the field names import string for INSERT or REPLACE INTO
[insertBaseString appendString:csvImportHeaderString];
if(!importMethodIsUpdate) {
@@ -1062,9 +1082,15 @@
rowsImported++;
csvRowsThisQuery++;
- [singleProgressBar setDoubleValue:[[parsePositions objectAtIndex:i] doubleValue]];
- [singleProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Imported %@ of %@", @"SQL import progress text"),
- [NSString stringForByteSize:[[parsePositions objectAtIndex:i] longValue]], [NSString stringForByteSize:fileTotalLength]]];
+ if (fileIsCompressed) {
+ [singleProgressBar setDoubleValue:[csvFileHandle realDataReadLength]];
+ [singleProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Imported %@ of CSV data", @"CSV import progress text where total size is unknown"),
+ [NSString stringForByteSize:[[parsePositions objectAtIndex:i] longValue]]]];
+ } else {
+ [singleProgressBar setDoubleValue:[[parsePositions objectAtIndex:i] doubleValue]];
+ [singleProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Imported %@ of %@", @"SQL import progress text"),
+ [NSString stringForByteSize:[[parsePositions objectAtIndex:i] longValue]], [NSString stringForByteSize:fileTotalLength]]];
+ }
}
}
@@ -1089,15 +1115,27 @@
(long)(rowsImported+1),[mySQLConnection getLastErrorMessage]];
}
rowsImported++;
- [singleProgressBar setDoubleValue:[[parsePositions objectAtIndex:i] doubleValue]];
- [singleProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Imported %@ of %@", @"SQL import progress text"),
- [NSString stringForByteSize:[[parsePositions objectAtIndex:i] longValue]], [NSString stringForByteSize:fileTotalLength]]];
+ if (fileIsCompressed) {
+ [singleProgressBar setDoubleValue:[csvFileHandle realDataReadLength]];
+ [singleProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Imported %@ of CSV data", @"CSV import progress text where total size is unknown"),
+ [NSString stringForByteSize:[[parsePositions objectAtIndex:i] longValue]]]];
+ } else {
+ [singleProgressBar setDoubleValue:[[parsePositions objectAtIndex:i] doubleValue]];
+ [singleProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Imported %@ of %@", @"SQL import progress text"),
+ [NSString stringForByteSize:[[parsePositions objectAtIndex:i] longValue]], [NSString stringForByteSize:fileTotalLength]]];
+ }
}
} else {
rowsImported += csvRowsThisQuery;
- [singleProgressBar setDoubleValue:[[parsePositions objectAtIndex:csvRowsThisQuery-1] doubleValue]];
- [singleProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Imported %@ of %@", @"SQL import progress text"),
- [NSString stringForByteSize:[[parsePositions objectAtIndex:csvRowsThisQuery-1] longValue]], [NSString stringForByteSize:fileTotalLength]]];
+ if (fileIsCompressed) {
+ [singleProgressBar setDoubleValue:[csvFileHandle realDataReadLength]];
+ [singleProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Imported %@ of CSV data", @"CSV import progress text where total size is unknown"),
+ [NSString stringForByteSize:[[parsePositions objectAtIndex:csvRowsThisQuery-1] longValue]]]];
+ } else {
+ [singleProgressBar setDoubleValue:[[parsePositions objectAtIndex:csvRowsThisQuery-1] doubleValue]];
+ [singleProgressText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Imported %@ of %@", @"SQL import progress text"),
+ [NSString stringForByteSize:[[parsePositions objectAtIndex:csvRowsThisQuery-1] longValue]], [NSString stringForByteSize:fileTotalLength]]];
+ }
}
// Update the arrays
@@ -1263,12 +1301,15 @@
targetTableDetails = [selectedTableData informationForTable:selectedTableTarget];
[selectedTableData release];
- // Store all field names which are of typegrouping 'geometry' and 'bit'
+ // Store all field names which are of typegrouping 'geometry' and 'bit', and check if
+ // numeric columns can hold NULL values to map empty strings to.
for(NSDictionary *field in [targetTableDetails objectForKey:@"columns"]) {
if([[field objectForKey:@"typegrouping"] isEqualToString:@"geometry"])
[geometryFields addObject:[field objectForKey:@"name"]];
if([[field objectForKey:@"typegrouping"] isEqualToString:@"bit"])
[bitFields addObject:[field objectForKey:@"name"]];
+ if(([[field objectForKey:@"typegrouping"] isEqualToString:@"float"] || [[field objectForKey:@"typegrouping"] isEqualToString:@"integer"]) && [[field objectForKey:@"null"] boolValue])
+ [nullableNumericFields addObject:[field objectForKey:@"name"]];
}
[importFieldNamesSwitch setState:[fieldMapperController importFieldNamesHeader]];
@@ -1485,8 +1526,10 @@
if ([cellData isSPNotLoaded])
cellData = NSArrayObjectAtIndex(fieldMappingTableDefaultValues, i);
- if (cellData == [NSNull null]) {
+ // Insert a NULL if the cell is an NSNull, or is a nullable numeric field and empty
+ if (cellData == [NSNull null] || ([nullableNumericFieldsMapIndex containsIndex:i] && [[cellData description] isEqualToString:@""])) {
[valueString appendString:@"NULL"];
+
} else {
// Apply GeomFromText() for each geometry field
if([geometryFields count] && [geometryFieldsMapIndex containsIndex:i]) {
@@ -1650,7 +1693,9 @@
if (geometryFields) [geometryFields release];
if (geometryFieldsMapIndex) [geometryFieldsMapIndex release];
if (bitFields) [bitFields release];
+ if (nullableNumericFields) [nullableNumericFields release];
if (bitFieldsMapIndex) [bitFieldsMapIndex release];
+ if (nullableNumericFieldsMapIndex) [nullableNumericFieldsMapIndex release];
if (lastFilename) [lastFilename release];
if (prefs) [prefs release];