diff options
author | Bibiko <bibiko@eva.mpg.de> | 2010-10-23 22:18:53 +0000 |
---|---|---|
committer | Bibiko <bibiko@eva.mpg.de> | 2010-10-23 22:18:53 +0000 |
commit | c965b60b6ec45f56aa406296b5c35f48360f175a (patch) | |
tree | 68570c4682d74094247970ff6b1513bd07cefd95 /Source | |
parent | a24ef7bf96e86d8e9ad7ee3ac9147dfca5cb810d (diff) | |
download | sequelpro-c965b60b6ec45f56aa406296b5c35f48360f175a.tar.gz sequelpro-c965b60b6ec45f56aa406296b5c35f48360f175a.tar.bz2 sequelpro-c965b60b6ec45f56aa406296b5c35f48360f175a.zip |
• CSV Import Field Mapper Sheet
- added the possibility to apply any sql function while importing set via "Add value or expression" sheet eg concat('$2', '$1', length('$3')) whereby $1 $2 $3 are the placeholder for the csv file columns 1 2 3 [first column starts with 1]
• fixed ' escaping issue in MCPConnection
Diffstat (limited to 'Source')
-rw-r--r-- | Source/SPConstants.h | 1 | ||||
-rw-r--r-- | Source/SPConstants.m | 1 | ||||
-rw-r--r-- | Source/SPDataImport.m | 92 | ||||
-rw-r--r-- | Source/SPFieldMapperController.h | 4 | ||||
-rw-r--r-- | Source/SPFieldMapperController.m | 84 |
5 files changed, 169 insertions, 13 deletions
diff --git a/Source/SPConstants.h b/Source/SPConstants.h index 0992cc1b..fd8c3af6 100644 --- a/Source/SPConstants.h +++ b/Source/SPConstants.h @@ -352,6 +352,7 @@ extern NSString *SPBlobTextEditorSpellCheckingEnabled; extern NSString *SPUniqueSchemaDelimiter; extern NSString *SPLastImportIntoNewTableEncoding; extern NSString *SPLastImportIntoNewTableType; +extern NSString *SPGlobalValueHistory; // URLs diff --git a/Source/SPConstants.m b/Source/SPConstants.m index b84c174f..3dadf8c4 100644 --- a/Source/SPConstants.m +++ b/Source/SPConstants.m @@ -179,6 +179,7 @@ NSString *SPBlobTextEditorSpellCheckingEnabled = @"BlobTextEditorSpellChecking NSString *SPUniqueSchemaDelimiter = @""; // U+FFF8 NSString *SPLastImportIntoNewTableEncoding = @"LastImportIntoNewTableEncoding"; NSString *SPLastImportIntoNewTableType = @"LastImportIntoNewTableType"; +NSString *SPGlobalValueHistory = @"GlobalValueHistory"; // URLs NSString *SPDonationsURL = @"http://www.sequelpro.com/donate.html"; diff --git a/Source/SPDataImport.m b/Source/SPDataImport.m index a1051c8c..61698b46 100644 --- a/Source/SPDataImport.m +++ b/Source/SPDataImport.m @@ -1259,6 +1259,7 @@ NSInteger mapColumn; id cellData; NSInteger mappingArrayCount = [fieldMappingArray count]; + NSString *re = @"(?<!\\\\)\\$(\\d+)"; for (i = 0; i < mappingArrayCount; i++) { @@ -1275,8 +1276,34 @@ // Append the data // - check for global values if(fieldMappingArrayHasGlobalVariables && mapColumn >= numberOfImportDataColumns) { - // Global variables are coming wrapped in ' ' if there're not marked as SQL - [setString appendString:NSArrayObjectAtIndex(fieldMappingGlobalValueArray, mapColumn)]; + NSMutableString *globalVar = [NSMutableString string]; + if([NSArrayObjectAtIndex(fieldMappingGlobalValueArray, mapColumn) isKindOfClass:[NSNull class]]) { + [globalVar setString:@"NULL"]; + } else { + [globalVar setString:NSArrayObjectAtIndex(fieldMappingGlobalValueArray, mapColumn)]; + // Global variables are coming wrapped in ' ' if there're not marked as SQL. + // If global variable contains column placeholders $1 etc. replace them. + if([globalVar rangeOfString:@"$"].length && [globalVar isMatchedByRegex:re]) { + while([globalVar isMatchedByRegex:re]) { + [globalVar flushCachedRegexData]; + NSRange aRange = [globalVar rangeOfRegex:re capture:0L]; + NSInteger colIndex = [[globalVar substringWithRange:[globalVar rangeOfRegex:re capture:1L]] integerValue]; + if(colIndex > 0 && colIndex <= [csvRowArray count]) { + NSString *colStr = NSArrayObjectAtIndex(csvRowArray, colIndex-1); + // escape column string for ' or " if the char just before $… is a " or ' + if(aRange.location && [globalVar characterAtIndex:aRange.location-1] == '\'') + [globalVar replaceCharactersInRange:aRange withString:[colStr stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]]; + else if(aRange.location && [globalVar characterAtIndex:aRange.location-1] == '"') + [globalVar replaceCharactersInRange:aRange withString:[colStr stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]; + else + [globalVar replaceCharactersInRange:aRange withString:colStr]; + } else { + [globalVar replaceCharactersInRange:aRange withString:@""]; + } + } + } + } + [setString appendString:globalVar]; } else { cellData = NSArrayObjectAtIndex(csvRowArray, mapColumn); @@ -1299,8 +1326,34 @@ // Append the data // - check for global values if(fieldMappingArrayHasGlobalVariables && mapColumn >= numberOfImportDataColumns) { - // Global variables are coming wrapped in ' ' if there're not marked as SQL - [whereString appendFormat:@"=%@", NSArrayObjectAtIndex(fieldMappingGlobalValueArray, mapColumn)]; + NSMutableString *globalVar = [NSMutableString string]; + if([NSArrayObjectAtIndex(fieldMappingGlobalValueArray, mapColumn) isKindOfClass:[NSNull class]]) { + [globalVar setString:@"NULL"]; + } else { + [globalVar setString:NSArrayObjectAtIndex(fieldMappingGlobalValueArray, mapColumn)]; + // Global variables are coming wrapped in ' ' if there're not marked as SQL. + // If global variable contains column placeholders $1 etc. replace them. + if([globalVar rangeOfString:@"$"].length && [globalVar isMatchedByRegex:re]) { + while([globalVar isMatchedByRegex:re]) { + [globalVar flushCachedRegexData]; + NSRange aRange = [globalVar rangeOfRegex:re capture:0L]; + NSInteger colIndex = [[globalVar substringWithRange:[globalVar rangeOfRegex:re capture:1L]] integerValue]; + if(colIndex > 0 && colIndex <= [csvRowArray count]) { + NSString *colStr = NSArrayObjectAtIndex(csvRowArray, colIndex-1); + // escape column string for ' or " if the char just before $… is a " or ' + if(aRange.location && [globalVar characterAtIndex:aRange.location-1] == '\'') + [globalVar replaceCharactersInRange:aRange withString:[colStr stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]]; + else if(aRange.location && [globalVar characterAtIndex:aRange.location-1] == '"') + [globalVar replaceCharactersInRange:aRange withString:[colStr stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]; + else + [globalVar replaceCharactersInRange:aRange withString:colStr]; + } else { + [globalVar replaceCharactersInRange:aRange withString:@""]; + } + } + } + } + [whereString appendFormat:@"=%@", globalVar]; } else { cellData = NSArrayObjectAtIndex(csvRowArray, mapColumn); @@ -1331,6 +1384,7 @@ NSInteger mapColumn; id cellData; NSInteger mappingArrayCount = [fieldMappingArray count]; + NSString *re = @"(?<!\\\\)\\$(\\d+)"; for (i = 0; i < mappingArrayCount; i++) { @@ -1344,8 +1398,34 @@ // Append the data // - check for global values if(fieldMappingArrayHasGlobalVariables && mapColumn >= numberOfImportDataColumns) { - // Global variables are coming wrapped in ' ' if there're not marked as SQL - [valueString appendString:NSArrayObjectAtIndex(fieldMappingGlobalValueArray, mapColumn)]; + NSMutableString *globalVar = [NSMutableString string]; + if([NSArrayObjectAtIndex(fieldMappingGlobalValueArray, mapColumn) isKindOfClass:[NSNull class]]) { + [globalVar setString:@"NULL"]; + } else { + [globalVar setString:NSArrayObjectAtIndex(fieldMappingGlobalValueArray, mapColumn)]; + // Global variables are coming wrapped in ' ' if there're not marked as SQL. + // If global variable contains column placeholders $1 etc. replace them. + if([globalVar rangeOfString:@"$"].length && [globalVar isMatchedByRegex:re]) { + while([globalVar isMatchedByRegex:re]) { + [globalVar flushCachedRegexData]; + NSRange aRange = [globalVar rangeOfRegex:re capture:0L]; + NSInteger colIndex = [[globalVar substringWithRange:[globalVar rangeOfRegex:re capture:1L]] integerValue]; + if(colIndex > 0 && colIndex <= [csvRowArray count]) { + NSString *colStr = NSArrayObjectAtIndex(csvRowArray, colIndex-1); + // escape column string for ' or " if the char just before $… is a " or ' + if(aRange.location && [globalVar characterAtIndex:aRange.location-1] == '\'') + [globalVar replaceCharactersInRange:aRange withString:[colStr stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]]; + else if(aRange.location && [globalVar characterAtIndex:aRange.location-1] == '"') + [globalVar replaceCharactersInRange:aRange withString:[colStr stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]; + else + [globalVar replaceCharactersInRange:aRange withString:colStr]; + } else { + [globalVar replaceCharactersInRange:aRange withString:@""]; + } + } + } + } + [valueString appendString:globalVar]; } else { cellData = NSArrayObjectAtIndex(csvRowArray, mapColumn); diff --git a/Source/SPFieldMapperController.h b/Source/SPFieldMapperController.h index 33b4a400..8a70df90 100644 --- a/Source/SPFieldMapperController.h +++ b/Source/SPFieldMapperController.h @@ -62,6 +62,8 @@ IBOutlet NSButton *removeGlobalValueButton; IBOutlet NSButton *insertNULLValueButton; IBOutlet id replaceAfterSavingCheckBox; + IBOutlet NSPopUpButton *insertPullDownButton; + IBOutlet NSMenu *recentGlobalValueMenu; IBOutlet id ignoreCheckBox; IBOutlet id ignoreUpdateCheckBox; @@ -175,6 +177,8 @@ - (IBAction)insertNULLValue:(id)sender; - (IBAction)closeGlobalValuesSheet:(id)sender; - (IBAction)advancedCheckboxValidation:(id)sender; +- (IBAction)insertPulldownValue:(id)sender; +- (IBAction)insertRecentGlobalValue:(id)sender; - (IBAction)newTable:(id)sender; - (IBAction)newTableInfo:(id)sender; diff --git a/Source/SPFieldMapperController.m b/Source/SPFieldMapperController.m index 1787c6f2..10afade0 100644 --- a/Source/SPFieldMapperController.m +++ b/Source/SPFieldMapperController.m @@ -280,10 +280,8 @@ { NSMutableArray *globals = [NSMutableArray array]; for(NSInteger i=0; i < [fieldMappingGlobalValues count]; i++) - if([[fieldMappingGlobalValuesSQLMarked objectAtIndex:i] boolValue]) + if([[fieldMappingGlobalValuesSQLMarked objectAtIndex:i] boolValue] || [[fieldMappingGlobalValues objectAtIndex:i] isKindOfClass:[NSNull class]]) [globals addObject:[fieldMappingGlobalValues objectAtIndex:i]]; - else if([[fieldMappingGlobalValues objectAtIndex:i] isKindOfClass:[NSNull class]]) - [globals addObject:[NSString stringWithFormat:@"'%@'", [fieldMappingGlobalValues objectAtIndex:i]]]; else [globals addObject:[NSString stringWithFormat:@"'%@'", [[fieldMappingGlobalValues objectAtIndex:i] stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]]]; @@ -1053,6 +1051,35 @@ { addGlobalSheetIsOpen = YES; + // Init insert pulldown menu + + // Remove all dynamic menu items + while([insertPullDownButton numberOfItems] > 5) + [insertPullDownButton removeItemAtIndex:[insertPullDownButton numberOfItems]-1]; + + // Add recent global value menu + if([prefs objectForKey:SPGlobalValueHistory] && [[prefs objectForKey:SPGlobalValueHistory] isKindOfClass:[NSArray class]] && [[prefs objectForKey:SPGlobalValueHistory] count]) + for(id item in [prefs objectForKey:SPGlobalValueHistory]) + [recentGlobalValueMenu addItemWithTitle:item action:@selector(insertRecentGlobalValue:) keyEquivalent:@""]; + + // Add column placeholder + NSInteger i = 0; + if([fieldMappingImportArray count] && [[fieldMappingImportArray objectAtIndex:0] count]) { + for(id item in [fieldMappingImportArray objectAtIndex:0]) { + i++; + if ([item isNSNull]) { + [insertPullDownButton addItemWithTitle:[NSString stringWithFormat:@"%i. <%@>", i, [prefs objectForKey:SPNullValue]]]; + } else if ([item isSPNotLoaded]) { + [insertPullDownButton addItemWithTitle:[NSString stringWithFormat:@"%i. <%@>", i, @"DEFAULT"]]; + } else { + if([item length] > 20) + [insertPullDownButton addItemWithTitle:[NSString stringWithFormat:@"%i. %@…", i, [item substringToIndex:20]]]; + else + [insertPullDownButton addItemWithTitle:[NSString stringWithFormat:@"%i. %@", i, item]]; + } + } + } + [NSApp beginSheet:globalValuesSheet modalForWindow:[self window] modalDelegate:self @@ -1221,6 +1248,27 @@ } } +- (IBAction)insertPulldownValue:(id)sender +{ + + if([globalValuesTableView numberOfSelectedRows] != 1 || [globalValuesTableView editedRow] < 0) return; + + NSInteger index = [sender indexOfItem:[sender selectedItem]] - 4; + if([[[NSApp keyWindow] firstResponder] respondsToSelector:@selector(insertText:)]) + [[[NSApp keyWindow] firstResponder] insertText:[NSString stringWithFormat:@"$%ld", index]]; + +} + +- (IBAction)insertRecentGlobalValue:(id)sender +{ + + if([globalValuesTableView numberOfSelectedRows] != 1 || [globalValuesTableView editedRow] < 0) return; + + if([[[NSApp keyWindow] firstResponder] respondsToSelector:@selector(insertText:)]) + [[[NSApp keyWindow] firstResponder] insertText:[sender title]]; + +} + #pragma mark - #pragma mark Others @@ -1782,14 +1830,36 @@ } [self validateImportButton]; } - // Refresh table - // [aTableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.01]; } else if(aTableView == globalValuesTableView) { - if ([[aTableColumn identifier] isEqualToString:@"global_value"]) + if ([[aTableColumn identifier] isEqualToString:@"global_value"]) { + [fieldMappingGlobalValues replaceObjectAtIndex:(numberOfImportColumns + rowIndex) withObject:anObject]; - else if ([[aTableColumn identifier] isEqualToString:@"sql"]) + + // If anObject contains $1 etc. enable SQL checkbox + if([anObject isMatchedByRegex:@"(?<!\\\\)\\$\\d+"]) + [fieldMappingGlobalValuesSQLMarked replaceObjectAtIndex:(numberOfImportColumns + rowIndex) withObject:[NSNumber numberWithInteger:1]]; + + // Store anObject as recent global value if it's new + NSMutableArray *recents = [NSMutableArray array]; + if([prefs objectForKey:SPGlobalValueHistory] && [[prefs objectForKey:SPGlobalValueHistory] isKindOfClass:[NSArray class]] && [[prefs objectForKey:SPGlobalValueHistory] count]) + [recents setArray:[prefs objectForKey:SPGlobalValueHistory]]; + if([recents containsObject:anObject]) + [recents removeObject:anObject]; + [recents insertObject:anObject atIndex:0]; + while([recents count] > 20) + [recents removeObjectAtIndex:[recents count]-1]; + if([recents count]) + [prefs setObject:recents forKey:SPGlobalValueHistory]; + + // Re-init recent menu + [recentGlobalValueMenu removeAllItems]; + for(id item in recents) + [recentGlobalValueMenu addItemWithTitle:item action:@selector(insertRecentGlobalValue:) keyEquivalent:@""]; + + } else if ([[aTableColumn identifier] isEqualToString:@"sql"]) { [fieldMappingGlobalValuesSQLMarked replaceObjectAtIndex:(numberOfImportColumns + rowIndex) withObject:anObject]; + } } } |