diff options
Diffstat (limited to 'Source/SPDataImport.m')
-rw-r--r-- | Source/SPDataImport.m | 71 |
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]; |