aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBibiko <bibiko@eva.mpg.de>2010-02-16 11:23:45 +0000
committerBibiko <bibiko@eva.mpg.de>2010-02-16 11:23:45 +0000
commit22ae0fa8c302d22071116abca27d2add3a0af991 (patch)
tree0110aebd405f15296badd823157eaac500e6a18d /Source
parentc64877be105019508234b9ee867d710de3b8160c (diff)
downloadsequelpro-22ae0fa8c302d22071116abca27d2add3a0af991.tar.gz
sequelpro-22ae0fa8c302d22071116abca27d2add3a0af991.tar.bz2
sequelpro-22ae0fa8c302d22071116abca27d2add3a0af991.zip
• re-factored and outsourced the entire CSV import field mapper sheet
- changed the way to choose whether a source field should be imported or not by introducing a new table column 'operators' - clicking at the 'operator's header toggles all operators to 'Import' or 'Do not import' - added tooltips for each table cell; if file's first line are the headers show them in the tooltips as well - added checkbox "First line contains fields names" since it'll be clear in this pane whether a file has a header line or not (will be sync with prefs) - added the possibility to choose the import method: INSERT INTO or REPLACE INTO • deleted all old field mapper stuff from TableDump and DBView.xib Notes: - tests are needed to be sure that this change does not cause mismatches while importing - symbols for Do (not) import are tendative - maybe use images - a further import method UPDATE plus an operator '=' will be added soon - chance to add a new global source variable will come soon - displaying of source field types will come soon - semi-automatically matching of source field names and header names will come soon - the GUI needs some improvements afterwards
Diffstat (limited to 'Source')
-rw-r--r--Source/SPFieldMapperController.h36
-rw-r--r--Source/SPFieldMapperController.m285
-rw-r--r--Source/TableDump.h116
-rw-r--r--Source/TableDump.m220
4 files changed, 376 insertions, 281 deletions
diff --git a/Source/SPFieldMapperController.h b/Source/SPFieldMapperController.h
index d48585e0..19cf316a 100644
--- a/Source/SPFieldMapperController.h
+++ b/Source/SPFieldMapperController.h
@@ -1,7 +1,7 @@
//
// $Id$
//
-// SPQueryFavoriteManager.h
+// SPFieldMapperController.h
// sequel-pro
//
// Created by Hans-Jörg Bibiko on February 01, 2010
@@ -25,8 +25,6 @@
#import <Cocoa/Cocoa.h>
#import <MCPKit/MCPKit.h>
-
-
@interface SPFieldMapperController : NSWindowController {
IBOutlet id fieldMapperTableView;
@@ -36,19 +34,33 @@
IBOutlet id rowUpButton;
IBOutlet id rowDownButton;
IBOutlet id recordCountLabel;
+ IBOutlet id importFieldNamesHeaderSwitch;
id theDelegate;
+ id fieldMappingImportArray;
NSInteger fieldMappingCurrentRow;
- NSArray *fieldMappingImportArray;
- NSArray *fieldMappingArray;
+ NSMutableArray *fieldMappingArray;
NSMutableArray *fieldMappingTableColumnNames;
+ NSMutableArray *fieldMappingButtonOptions;
+ NSMutableArray *fieldMappingOperatorOptions;
+ NSMutableArray *fieldMappingOperatorArray;
+
+ NSNumber *doImport;
+ NSNumber *doNotImport;
+ NSNumber *isEqual;
+ NSString *doImportString;
+ NSString *doNotImportString;
+ NSString *isEqualString;
BOOL fieldMappingImportArrayIsPreview;
+ BOOL importFieldNamesHeader;
MCPConnection *mySQLConnection;
NSString *sourcePath;
+
+ NSUserDefaults *prefs;
}
@property(retain) NSString* sourcePath;
@@ -56,6 +68,15 @@
- (id)initWithDelegate:(id)managerDelegate;
- (void)setConnection:(MCPConnection *)theConnection;
+- (void)setImportDataArray:(id)theFieldMappingImportArray hasHeader:(BOOL)hasHeader;
+
+// Getter methods
+- (NSString*)selectedTableTarget;
+- (NSArray*)fieldMapperOperator;
+- (NSString*)selectedImportMethod;
+- (NSArray*)fieldMappingArray;
+- (NSArray*)fieldMappingTableColumnNames;
+- (BOOL)importFieldNamesHeader;
// IBAction methods
- (IBAction)changeTableTarget:(id)sender;
@@ -63,4 +84,9 @@
- (IBAction)stepRow:(id)sender;
- (IBAction)closeSheet:(id)sender;
+// Others
+- (void)setupFieldMappingArray;
+- (void)updateFieldMappingButtonCell;
+- (void)updateFieldMappingOperatorOptions;
+
@end
diff --git a/Source/SPFieldMapperController.m b/Source/SPFieldMapperController.m
index 3ed30270..8dc06d87 100644
--- a/Source/SPFieldMapperController.m
+++ b/Source/SPFieldMapperController.m
@@ -1,7 +1,7 @@
//
// $Id$
//
-// SPQueryFavoriteManager.m
+// SPFieldMapperController.m
// sequel-pro
//
// Created by Hans-Jörg Bibiko on February 01, 2010
@@ -26,6 +26,8 @@
#import "SPFieldMapperController.h"
#import "SPTableData.h"
#import "TablesList.h"
+#import "SPArrayAdditions.h"
+#import "SPConstants.h"
@implementation SPFieldMapperController
@@ -34,7 +36,6 @@
#pragma mark -
#pragma mark Initialization
-
/**
* Initialize the field mapper
*/
@@ -49,7 +50,20 @@
return nil;
}
theDelegate = managerDelegate;
- fieldMappingTableColumnNames = [[NSMutableArray alloc] initWithCapacity:1];
+ fieldMappingTableColumnNames = [[NSMutableArray alloc] init];
+ fieldMappingButtonOptions = [[NSMutableArray alloc] init];
+ fieldMappingOperatorOptions = [[NSMutableArray alloc] init];
+ fieldMappingOperatorArray = [[NSMutableArray alloc] init];
+ fieldMappingArray = nil;
+
+ doImport = [NSNumber numberWithInteger:0];
+ doNotImport = [NSNumber numberWithInteger:1];
+ isEqual = [NSNumber numberWithInteger:2];
+ doImportString = @"→";
+ doNotImportString = @"×";
+ isEqualString = @"=";
+
+ prefs = [NSUserDefaults standardUserDefaults];
}
return self;
@@ -57,27 +71,31 @@
- (void)awakeFromNib
{
+
+ // Set source path
[fileSourcePath setURL:[NSURL URLWithString:sourcePath]];
+
+ // Init table target popup menu
[tableTargetPopup removeAllItems];
- [tableTargetPopup addItemsWithTitles:[[theDelegate valueForKeyPath:@"tablesListInstance"] allTableNames]];
+ if([[theDelegate valueForKeyPath:@"tablesListInstance"] allTableNames]) {
+ [tableTargetPopup addItemsWithTitles:[[theDelegate valueForKeyPath:@"tablesListInstance"] allTableNames]];
+
+ // Select either the currently selected table, or the first item in the list
+ if ([[theDelegate valueForKeyPath:@"tableDocumentInstance"] table] != nil && ![[[theDelegate valueForKeyPath:@"tablesListInstance"] tableName] isEqualToString:@""]) {
+ [tableTargetPopup selectItemWithTitle:[[theDelegate valueForKeyPath:@"tablesListInstance"] tableName]];
+ } else {
+ [tableTargetPopup selectItemAtIndex:0];
+ }
- // Select either the currently selected table, or the first item in the list
- if ([[theDelegate valueForKeyPath:@"tableDocumentInstance"] table] != nil && ![[[theDelegate valueForKeyPath:@"tablesListInstance"] tableName] isEqualToString:@""]) {
- [tableTargetPopup selectItemWithTitle:[[theDelegate valueForKeyPath:@"tablesListInstance"] tableName]];
- } else {
- [tableTargetPopup selectItemAtIndex:0];
}
+ [importFieldNamesHeaderSwitch setState:importFieldNamesHeader];
+
[self changeTableTarget:self];
-}
-/*
- * Set the connection for use.
- * Called by the connect sheet methods.
- */
-- (void)setConnection:(MCPConnection *)theConnection
-{
- mySQLConnection = theConnection;
- [mySQLConnection retain];
+ [[self window] makeFirstResponder:fieldMapperTableView];
+ if([fieldMappingTableColumnNames count])
+ [fieldMapperTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
+
}
- (void)dealloc
@@ -85,10 +103,62 @@
if (mySQLConnection) [mySQLConnection release];
if (sourcePath) [sourcePath release];
if (fieldMappingTableColumnNames) [fieldMappingTableColumnNames release];
+ if (fieldMappingArray) [fieldMappingArray release];
+ if (fieldMappingButtonOptions) [fieldMappingButtonOptions release];
+ if (fieldMappingOperatorOptions) [fieldMappingOperatorOptions release];
+ if (fieldMappingOperatorArray) [fieldMappingOperatorArray release];
[super dealloc];
}
#pragma mark -
+#pragma mark Setter methods
+
+- (void)setConnection:(MCPConnection *)theConnection
+{
+ mySQLConnection = theConnection;
+ [mySQLConnection retain];
+}
+
+- (void)setImportDataArray:(id)theFieldMappingImportArray hasHeader:(BOOL)hasHeader
+{
+ fieldMappingImportArray = theFieldMappingImportArray;
+ importFieldNamesHeader = hasHeader;
+}
+
+#pragma mark -
+#pragma mark Getter methods
+
+- (NSString*)selectedTableTarget
+{
+ return [tableTargetPopup titleOfSelectedItem];
+}
+
+- (NSArray*)fieldMapperOperator
+{
+ return [NSArray arrayWithArray:fieldMappingOperatorArray];
+}
+
+- (NSString*)selectedImportMethod
+{
+ return [importMethodPopup titleOfSelectedItem];
+}
+
+- (NSArray*)fieldMappingArray
+{
+ return fieldMappingArray;
+}
+
+- (NSArray*)fieldMappingTableColumnNames
+{
+ return fieldMappingTableColumnNames;
+}
+
+- (BOOL)importFieldNamesHeader
+{
+ return importFieldNamesHeader;
+}
+
+#pragma mark -
#pragma mark IBAction methods
- (IBAction)closeSheet:(id)sender
@@ -98,7 +168,9 @@
- (IBAction)changeTableTarget:(id)sender
{
-
+
+ NSInteger i;
+
// Remove all the current columns
[fieldMappingTableColumnNames removeAllObjects];
@@ -111,24 +183,49 @@
[fieldMappingTableColumnNames addObject:[NSString stringWithString:[column objectForKey:@"name"]]];
}
}
- NSLog(@"f %@", [fieldMappingTableColumnNames description]);
+
[selectedTableData release];
// Update the table view
fieldMappingCurrentRow = 0;
if (fieldMappingArray) [fieldMappingArray release], fieldMappingArray = nil;
- // [self setupFieldMappingArray];
+ [self setupFieldMappingArray];
[rowDownButton setEnabled:NO];
[rowUpButton setEnabled:([fieldMappingImportArray count] > 1)];
[recordCountLabel setStringValue:[NSString stringWithFormat:@"%ld of %@%lu records", (long)(fieldMappingCurrentRow+1), fieldMappingImportArrayIsPreview?@"first ":@"", (unsigned long)[fieldMappingImportArray count]]];
- // [self updateFieldMappingButtonCell];
+ [self updateFieldMappingButtonCell];
+ [self updateFieldMappingOperatorOptions];
+
+ // Set all operators to doNotImport
+ [fieldMappingOperatorArray removeAllObjects];
+ for(i=0; i < [fieldMappingTableColumnNames count]; i++)
+ [fieldMappingOperatorArray addObject:doNotImport];
+
+ // Set the first n operators to doImport
+ if([fieldMappingImportArray count]) {
+ NSInteger possibleImports = ([NSArrayObjectAtIndex(fieldMappingImportArray, 0) count] > [fieldMappingTableColumnNames count]) ? [fieldMappingTableColumnNames count] : [NSArrayObjectAtIndex(fieldMappingImportArray, 0) count];
+ for(i=0; i < possibleImports; i++)
+ [fieldMappingOperatorArray replaceObjectAtIndex:i withObject:doImport];
+ }
+
[fieldMapperTableView reloadData];
+
}
- (IBAction)changeImportMethod:(id)sender
{
-
+ NSInteger i;
+ // If operator is set to = for UPDATE method replace it by doNotImport
+ if(![[importMethodPopup titleOfSelectedItem] isEqualToString:@"UPDATE"]) {
+ for(i=0; i<[fieldMappingTableColumnNames count]; i++) {
+ if([fieldMappingOperatorArray objectAtIndex:i] == isEqual)
+ [fieldMappingOperatorArray replaceObjectAtIndex:i withObject:doNotImport];
+ }
+ }
+
+ [self updateFieldMappingOperatorOptions];
+ [fieldMapperTableView reloadData];
}
/*
@@ -141,7 +238,7 @@
} else {
fieldMappingCurrentRow++;
}
- // [self updateFieldMappingButtonCell];
+ [self updateFieldMappingButtonCell];
[fieldMapperTableView reloadData];
@@ -152,6 +249,61 @@
[rowUpButton setEnabled:(fieldMappingCurrentRow != ([fieldMappingImportArray count]-1))];
}
+/*
+ * Sets up the fieldMapping array to be shown in the tableView
+ */
+- (void)setupFieldMappingArray
+{
+ NSInteger i, value;
+
+ if (!fieldMappingArray) {
+ fieldMappingArray = [[NSMutableArray alloc] init];
+
+ for (i = 0; i < [fieldMappingTableColumnNames count]; i++) {
+ if (i < [NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow) count]
+ && ![NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), i) isKindOfClass:[NSNull class]]) {
+ value = i;
+ } else {
+ value = 0;
+ }
+
+ [fieldMappingArray addObject:[NSNumber numberWithInteger:value]];
+ }
+ }
+
+ [fieldMapperTableView reloadData];
+}
+
+/*
+ * Update the NSButtonCell items for use in the import_value mapping display
+ */
+- (void)updateFieldMappingButtonCell
+{
+ NSInteger i;
+
+ [fieldMappingButtonOptions setArray:[fieldMappingImportArray objectAtIndex:fieldMappingCurrentRow]];
+ for (i = 0; i < [fieldMappingButtonOptions count]; i++) {
+ if ([[fieldMappingButtonOptions objectAtIndex:i] isNSNull]) {
+ [fieldMappingButtonOptions replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%i. %@", i+1, [prefs objectForKey:SPNullValue]]];
+ } else {
+ [fieldMappingButtonOptions replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%i. %@", i+1, NSArrayObjectAtIndex(fieldMappingButtonOptions, i)]];
+ }
+ }
+}
+
+/*
+ * Update the NSButtonCell items for use in the operator mapping display
+ */
+- (void)updateFieldMappingOperatorOptions
+{
+ if(![[importMethodPopup titleOfSelectedItem] isEqualToString:@"UPDATE"]) {
+ [fieldMappingOperatorOptions setArray:[NSArray arrayWithObjects:doImportString, doNotImportString, nil]];
+ } else {
+ [fieldMappingOperatorOptions setArray:[NSArray arrayWithObjects:doImportString, doNotImportString, isEqualString, nil]];
+ }
+}
+
+
#pragma mark -
#pragma mark Table view datasource methods
@@ -162,30 +314,93 @@
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
+ [aCell setFont:([prefs boolForKey:SPUseMonospacedFonts]) ? [NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]] : [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
+}
+
+- (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)aTableColumn
+{
+
+ // A click at the operator column's header toggles all operators
+ if ([[aTableColumn identifier] isEqualToString:@"operator"]
+ && [self numberOfRowsInTableView:tableView]
+ && [fieldMappingOperatorArray count]
+ && [fieldMappingTableColumnNames count]) {
+ NSInteger i;
+ NSNumber *globalValue = doImport;
+ if([fieldMappingOperatorArray objectAtIndex:0] == doImport)
+ globalValue = doNotImport;
+ [fieldMappingOperatorArray removeAllObjects];
+ for(i=0; i < [fieldMappingTableColumnNames count]; i++)
+ [fieldMappingOperatorArray addObject:globalValue];
+ [fieldMapperTableView reloadData];
+ }
}
+- (NSString *)tableView:(NSTableView *)aTableView toolTipForCell:(NSCell *)aCell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex mouseLocation:(NSPoint)mouseLocation
+{
+ if([[aTableColumn identifier] isEqualToString:@"import_value"] && [importFieldNamesHeaderSwitch state] == NSOnState)
+ if(fieldMappingCurrentRow)
+ return [NSString stringWithFormat:@"%@: %@",
+ [NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, 0), [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]) description],
+ [NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]) description]];
+ else
+ return [NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, 0), [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]) description];
+ else if([[aTableColumn identifier] isEqualToString:@"import_value"] && [importFieldNamesHeaderSwitch state] == NSOffState)
+ return [NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), [NSArrayObjectAtIndex(fieldMappingArray, rowIndex) integerValue]) description];
+ else if([[aTableColumn identifier] isEqualToString:@"operator"]) {
+ if([aCell objectValue] == doImport)
+ return NSLocalizedString(@"Do import", @"import operator");
+ else if([aCell objectValue] == doNotImport)
+ return NSLocalizedString(@"Do not import", @"do not import operator");
+ else if([aCell objectValue] == isEqual)
+ return NSLocalizedString(@"Do UPDATE where field contents match", @"do update operator");
+ else
+ return @"";
+ }
+ else if([[aTableColumn identifier] isEqualToString:@"target_field"])
+ return [fieldMappingTableColumnNames objectAtIndex:rowIndex];
+
+
+ return @"";
+}
+
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
if ([[aTableColumn identifier] isEqualToString:@"target_field"]) {
+ if ([[aTableColumn dataCell] isKindOfClass:[NSPopUpButtonCell class]]) {
+ [(NSPopUpButton *)[aTableColumn dataCell] removeAllItems];
+ [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemWithTitle:[fieldMappingTableColumnNames objectAtIndex:rowIndex]];
+ }
return [fieldMappingTableColumnNames objectAtIndex:rowIndex];
-
}
- // else if ([[aTableColumn identifier] isEqualToString:@"value"]) {
- // if ([[[aTableColumn dataCell] class] isEqualTo:[NSPopUpButtonCell class]]) {
- // [(NSPopUpButtonCell *)[aTableColumn dataCell] removeAllItems];
- // [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemWithTitle:NSLocalizedString(@"Do not import", @"text for csv import drop downs")];
- // [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemsWithTitles:fieldMappingButtonOptions];
- // }
- //
- // returnObject = [fieldMappingArray objectAtIndex:rowIndex];
- // }
+ else if ([[aTableColumn identifier] isEqualToString:@"import_value"]) {
+ if ([[aTableColumn dataCell] isKindOfClass:[NSPopUpButtonCell class]]) {
+ [(NSPopUpButtonCell *)[aTableColumn dataCell] removeAllItems];
+ [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemsWithTitles:fieldMappingButtonOptions];
+ }
+
+ return [fieldMappingArray objectAtIndex:rowIndex];
+ }
+ else if ([[aTableColumn identifier] isEqualToString:@"operator"]) {
+ if ([[aTableColumn dataCell] isKindOfClass:[NSPopUpButtonCell class]]) {
+ [(NSPopUpButtonCell *)[aTableColumn dataCell] removeAllItems];
+ [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemsWithTitles:fieldMappingOperatorOptions];
+ }
+
+ return [fieldMappingOperatorArray objectAtIndex:rowIndex];
+ }
return nil;
}
- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
+ if ([[aTableColumn identifier] isEqualToString:@"import_value"]) {
+ [fieldMappingArray replaceObjectAtIndex:rowIndex withObject:anObject];
+ }
+ else if ([[aTableColumn identifier] isEqualToString:@"operator"]) {
+ [fieldMappingOperatorArray replaceObjectAtIndex:rowIndex withObject:anObject];
+ }
}
-
@end
diff --git a/Source/TableDump.h b/Source/TableDump.h
index 644057b6..001b1778 100644
--- a/Source/TableDump.h
+++ b/Source/TableDump.h
@@ -44,87 +44,82 @@ typedef enum _SPExportModes {
IBOutlet id tableDataInstance;
IBOutlet id customQueryInstance;
- IBOutlet id tableWindow;
-
- IBOutlet id exportDumpView;
- IBOutlet id exportCSVView;
- IBOutlet id exportMultipleCSVView;
- IBOutlet id exportMultipleXMLView;
- IBOutlet id exportDumpTableView;
- IBOutlet id exportMultipleCSVTableView;
- IBOutlet id exportMultipleXMLTableView;
- IBOutlet id exportFieldNamesSwitch;
- IBOutlet id exportFieldsTerminatedField;
- IBOutlet id exportFieldsEnclosedField;
- IBOutlet id exportFieldsEscapedField;
- IBOutlet id exportLinesTerminatedField;
- IBOutlet id exportMultipleFieldNamesSwitch;
- IBOutlet id exportMultipleFieldsTerminatedField;
- IBOutlet id exportMultipleFieldsEnclosedField;
- IBOutlet id exportMultipleFieldsEscapedField;
- IBOutlet id exportMultipleLinesTerminatedField;
-
+ IBOutlet id tableWindow;
+
+ IBOutlet id exportDumpView;
+ IBOutlet id exportCSVView;
+ IBOutlet id exportMultipleCSVView;
+ IBOutlet id exportMultipleXMLView;
+ IBOutlet id exportDumpTableView;
+ IBOutlet id exportMultipleCSVTableView;
+ IBOutlet id exportMultipleXMLTableView;
+ IBOutlet id exportFieldNamesSwitch;
+ IBOutlet id exportFieldsTerminatedField;
+ IBOutlet id exportFieldsEnclosedField;
+ IBOutlet id exportFieldsEscapedField;
+ IBOutlet id exportLinesTerminatedField;
+ IBOutlet id exportMultipleFieldNamesSwitch;
+ IBOutlet id exportMultipleFieldsTerminatedField;
+ IBOutlet id exportMultipleFieldsEnclosedField;
+ IBOutlet id exportMultipleFieldsEscapedField;
+ IBOutlet id exportMultipleLinesTerminatedField;
+
// New Export Window
IBOutlet id exportWindow;
IBOutlet id exportTabBar;
IBOutlet id exportToolbar;
IBOutlet id exportTableList;
-
+
IBOutlet id importCSVView;
IBOutlet NSPopUpButton *importFormatPopup;
IBOutlet id importCSVBox;
- IBOutlet id importFieldNamesSwitch;
- IBOutlet id importFieldsTerminatedField;
- IBOutlet id importFieldsEnclosedField;
- IBOutlet id importFieldsEscapedField;
- IBOutlet id importLinesTerminatedField;
-
- IBOutlet id addDropTableSwitch;
- IBOutlet id addCreateTableSwitch;
- IBOutlet id addTableContentSwitch;
- IBOutlet id addErrorsSwitch;
- IBOutlet id sqlFullStreamingSwitch;
- IBOutlet id csvFullStreamingSwitch;
- IBOutlet id multiCSVFullStreamingSwitch;
- IBOutlet id multiXMLFullStreamingSwitch;
- IBOutlet id errorsSheet;
- IBOutlet id errorsView;
- IBOutlet id singleProgressSheet;
- IBOutlet id singleProgressBar;
- IBOutlet id singleProgressTitle;
- IBOutlet id singleProgressText;
-
- IBOutlet id fieldMappingSheet;
- IBOutlet id fieldMappingPopup;
- IBOutlet id fieldMappingTableView;
-
- IBOutlet id rowUpButton;
- IBOutlet id rowDownButton;
- IBOutlet id recordCountLabel;
+ IBOutlet id importFieldNamesSwitch;
+ IBOutlet id importFieldsTerminatedField;
+ IBOutlet id importFieldsEnclosedField;
+ IBOutlet id importFieldsEscapedField;
+ IBOutlet id importLinesTerminatedField;
+ IBOutlet id importFieldMapperSheetWindow;
+
+ IBOutlet id addDropTableSwitch;
+ IBOutlet id addCreateTableSwitch;
+ IBOutlet id addTableContentSwitch;
+ IBOutlet id addErrorsSwitch;
+ IBOutlet id sqlFullStreamingSwitch;
+ IBOutlet id csvFullStreamingSwitch;
+ IBOutlet id multiCSVFullStreamingSwitch;
+ IBOutlet id multiXMLFullStreamingSwitch;
+ IBOutlet id errorsSheet;
+ IBOutlet id errorsView;
+ IBOutlet id singleProgressSheet;
+ IBOutlet id singleProgressBar;
+ IBOutlet id singleProgressTitle;
+ IBOutlet id singleProgressText;
MCPConnection *mySQLConnection;
NSMutableArray *tables;
+
+ // Field Mapper Controller
+ SPFieldMapperController *fieldMapperController;
NSArray *fieldMappingImportArray;
BOOL fieldMappingImportArrayIsPreview;
- NSMutableArray *fieldMappingTableColumnNames;
- NSMutableArray *fieldMappingArray;
- NSMutableArray *fieldMappingButtonOptions;
- NSInteger fieldMappingCurrentRow;
+ NSArray *fieldMappingTableColumnNames;
+ NSArray *fieldMappingArray;
+ NSArray *fieldMapperOperator;
+ NSString *selectedTableTarget;
+ NSString *selectedImportMethod;
+ NSInteger fieldMapperSheetStatus;
+
NSUInteger exportMode;
NSUserDefaults *prefs;
BOOL progressCancelled;
-
- NSInteger fieldMapperSheetStatus;
- SPFieldMapperController *fieldMapperController;
+
}
// IBAction methods
- (IBAction)reloadTables:(id)sender;
- (IBAction)selectTables:(id)sender;
- (IBAction)closeSheet:(id)sender;
-- (IBAction)closeFieldMapperSheet:(id)sender;
-- (IBAction)stepRow:(id)sender;
- (IBAction)cancelProgressBar:(id)sender;
// Export methods
@@ -139,11 +134,8 @@ typedef enum _SPExportModes {
- (void)startSQLImportProcessWithFile:(NSString *)filename;
- (void)importCSVFile:(NSString *)filename;
- (IBAction)changeFormat:(id)sender;
-- (IBAction)changeTable:(id)sender;
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo;
-- (BOOL) buildFieldMappingArrayWithData:(NSArray *)importData isPreview:(BOOL)dataIsPreviewData;
-- (void)setupFieldMappingArray;
-- (void)updateFieldMappingButtonCell;
+- (BOOL) buildFieldMappingArrayWithData:(NSArray *)importData isPreview:(BOOL)dataIsPreviewData ofSoureFile:(NSString*)filename;
- (NSString *) mappedValueStringForRowArray:(NSArray *)csvRowArray;
// Export methods
diff --git a/Source/TableDump.m b/Source/TableDump.m
index 2e055f94..33118738 100644
--- a/Source/TableDump.m
+++ b/Source/TableDump.m
@@ -108,11 +108,6 @@
[exportMultipleXMLTableView reloadData];
}
-- (IBAction)closeFieldMapperSheet:(id)sender
-{
- [NSApp endSheet:fieldMappingSheet returnCode:[sender tag]];
-}
-
/**
* Common method for ending modal sessions
*/
@@ -513,39 +508,6 @@
[importCSVBox setHidden:![[[importFormatPopup selectedItem] title] isEqualToString:@"CSV"]];
}
-/**
- * When the table in the CSV field mapping sheet is changed, retrieve
- * the columns from the new table and reset the field mapping array.
- */
-- (IBAction)changeTable:(id)sender
-{
-
- // Remove all the current columns
- [fieldMappingTableColumnNames removeAllObjects];
-
- // Retrieve the information for the newly selected table using a SPTableData instance
- SPTableData *selectedTableData = [[SPTableData alloc] init];
- [selectedTableData setConnection:mySQLConnection];
- NSDictionary *tableDetails = [selectedTableData informationForTable:[fieldMappingPopup titleOfSelectedItem]];
- if (tableDetails) {
- for (NSDictionary *column in [tableDetails objectForKey:@"columns"]) {
- [fieldMappingTableColumnNames addObject:[NSString stringWithString:[column objectForKey:@"name"]]];
- }
- }
- [selectedTableData release];
-
- // Update the table view
- fieldMappingCurrentRow = 0;
- if (fieldMappingArray) [fieldMappingArray release], fieldMappingArray = nil;
- [self setupFieldMappingArray];
- [rowDownButton setEnabled:NO];
- [rowUpButton setEnabled:([fieldMappingImportArray count] > 1)];
- [recordCountLabel setStringValue:[NSString stringWithFormat:@"%ld of %@%lu records", (long)(fieldMappingCurrentRow+1), fieldMappingImportArrayIsPreview?@"first ":@"", (unsigned long)[fieldMappingImportArray count]]];
-
- [self updateFieldMappingButtonCell];
- [fieldMappingTableView reloadData];
-}
-
- (void)importBackgroundProcess:(NSString*)filename
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -822,7 +784,7 @@
BOOL allDataRead = NO;
BOOL insertBaseStringHasEntries;
NSStringEncoding csvEncoding = [MCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]];
- if (fieldMappingArray) [fieldMappingArray release], fieldMappingArray = nil;
+ fieldMappingArray = nil;
// Start the notification timer to allow notifications to be shown even if frontmost for long queries
[[SPGrowlController sharedGrowlController] setVisibilityForNotificationName:@"Import Finished"];
@@ -975,7 +937,7 @@
&& ([parsedRows count] >= 100 || (!csvRowArray && allDataRead)))
{
[self closeAndStopProgressSheet];
- if (![self buildFieldMappingArrayWithData:parsedRows isPreview:!allDataRead]) {
+ if (![self buildFieldMappingArrayWithData:parsedRows isPreview:!allDataRead ofSoureFile:filename]) {
[csvParser release];
[csvDataBuffer release];
[parsedRows release];
@@ -992,13 +954,13 @@
[NSApp beginSheet:singleProgressSheet modalForWindow:tableWindow modalDelegate:self didEndSelector:nil contextInfo:nil];
[singleProgressSheet makeKeyWindow];
- // Set up the field names import string
- [insertBaseString appendString:@"INSERT INTO "];
- [insertBaseString appendString:[[fieldMappingPopup titleOfSelectedItem] backtickQuotedString]];
+ // Set up the field names import string for INSERT or REPLACE INTO
+ [insertBaseString appendFormat:@"%@ INTO ", selectedImportMethod];
+ [insertBaseString appendString:[selectedTableTarget backtickQuotedString]];
[insertBaseString appendString:@" ("];
insertBaseStringHasEntries = NO;
for (i = 0; i < [fieldMappingArray count]; i++) {
- if ([NSArrayObjectAtIndex(fieldMappingArray, i) integerValue] > 0) {
+ if ([NSArrayObjectAtIndex(fieldMapperOperator, i) integerValue] == 0) {
if (insertBaseStringHasEntries) [insertBaseString appendString:@","];
else insertBaseStringHasEntries = YES;
[insertBaseString appendString:[NSArrayObjectAtIndex(fieldMappingTableColumnNames, i) backtickQuotedString]];
@@ -1079,7 +1041,7 @@
[csvDataBuffer release];
[parsedRows release];
[parsePositions release];
- if (fieldMappingArray) [fieldMappingArray release], fieldMappingArray = nil;
+ fieldMappingArray = nil;
[importPool drain];
[tableDocumentInstance setQueryMode:SPInterfaceQueryMode];
@@ -1103,7 +1065,7 @@
// If the table selected for import is also selected in the content view,
// update the content view - on the main thread to avoid crashes.
- if ([tablesListInstance tableName] && [[fieldMappingPopup titleOfSelectedItem] isEqualToString:[tablesListInstance tableName]]) {
+ if ([tablesListInstance tableName] && [selectedTableTarget isEqualToString:[tablesListInstance tableName]]) {
if ([[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableContent]) {
[tableContentInstance performSelectorOnMainThread:@selector(reloadTable:) withObject:nil waitUntilDone:YES];
} else {
@@ -1142,7 +1104,7 @@
* Takes an array of data to show when selecting the field mapping, and an indicator of whether
* that dataset is complete or a preview of the full data set.
*/
-- (BOOL) buildFieldMappingArrayWithData:(NSArray *)importData isPreview:(BOOL)dataIsPreviewData
+- (BOOL) buildFieldMappingArrayWithData:(NSArray *)importData isPreview:(BOOL)dataIsPreviewData ofSoureFile:(NSString*)filename
{
// Ensure data was provided, or alert than an import error occurred and return false.
@@ -1172,12 +1134,8 @@
}
fieldMappingImportArrayIsPreview = dataIsPreviewData;
- // Get the list of tables (not views) to display in the field mapping interface
- [fieldMappingPopup removeAllItems];
- [fieldMappingPopup addItemsWithTitles:[tablesListInstance allTableNames]];
-
// If there's no tables to select, error
- if (![[fieldMappingPopup itemArray] count]) {
+ if (![[tablesListInstance allTableNames] count]) {
[self closeAndStopProgressSheet];
SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"),
NSLocalizedString(@"OK", @"OK button"),
@@ -1189,46 +1147,41 @@
return FALSE;
}
- // Set up tableView buttons
- NSPopUpButtonCell *buttonCell = [[NSPopUpButtonCell alloc] init];
- [buttonCell setControlSize:NSSmallControlSize];
- [buttonCell setFont:[NSFont labelFontOfSize:[NSFont smallSystemFontSize]]];
- [buttonCell setBordered:NO];
- [[fieldMappingTableView tableColumnWithIdentifier:@"value"] setDataCell:buttonCell];
- [buttonCell release];
-
- // Select either the currently selected table, or the first item in the list
- if ([tableDocumentInstance table] != nil && ![[tablesListInstance tableName] isEqualToString:@""]) {
- [fieldMappingPopup selectItemWithTitle:[tablesListInstance tableName]];
- } else {
- [fieldMappingPopup selectItemAtIndex:0];
- }
-
// Set the import array
if (fieldMappingImportArray) [fieldMappingImportArray release];
fieldMappingImportArray = [[NSArray alloc] initWithArray:importData];
-
- // Trigger a table selection and setup
- [self changeTable:self];
fieldMapperSheetStatus = 1;
- // if(fieldMapperController) [fieldMapperController release];
- // fieldMapperController = [[SPFieldMapperController alloc] initWithDelegate:self];
+ // Init the field mapper controller
+ fieldMapperController = [[SPFieldMapperController alloc] initWithDelegate:self];
+ [fieldMapperController setConnection:mySQLConnection];
+ [fieldMapperController setSourcePath:filename];
+ [fieldMapperController setImportDataArray:fieldMappingImportArray hasHeader:[importFieldNamesSwitch state]];
- // Show fieldMapping sheet
- // [NSApp beginSheet:[fieldMapperController window]
- [NSApp beginSheet:fieldMappingSheet
+ // Show field mapper sheet and set the focus to it
+ [NSApp beginSheet:[fieldMapperController window]
modalForWindow:tableWindow
modalDelegate:self
didEndSelector:@selector(fieldMapperDidEndSheet:returnCode:contextInfo:)
contextInfo:nil];
- // Wait for fieldMappingSheet
+ [[fieldMapperController window] makeKeyWindow];
+
+ // Wait for field mapper sheet
while (fieldMapperSheetStatus == 1)
usleep(100000);
- // if(fieldMapperController) [fieldMapperController release];
+ // Get mapping settings
+ fieldMapperOperator = [NSArray arrayWithArray:[fieldMapperController fieldMapperOperator]];
+ fieldMappingArray = [NSArray arrayWithArray:[fieldMapperController fieldMappingArray]];
+ selectedTableTarget = [NSString stringWithString:[fieldMapperController selectedTableTarget]];
+ selectedImportMethod = [NSString stringWithString:[fieldMapperController selectedImportMethod]];
+ fieldMappingTableColumnNames = [NSArray arrayWithArray:[fieldMapperController fieldMappingTableColumnNames]];
+ [importFieldNamesSwitch setState:[fieldMapperController importFieldNamesHeader]];
+ [prefs setBool:[importFieldNamesSwitch state] forKey:SPCSVImportFirstLineIsHeader];
+
+ if(fieldMapperController) [fieldMapperController release];
if(fieldMapperSheetStatus == 2)
return YES;
@@ -1243,69 +1196,6 @@
}
/*
- * Sets up the fieldMapping array to be shown in the tableView
- */
-- (void)setupFieldMappingArray
-{
- NSInteger i, value;
-
- if (!fieldMappingArray) {
- fieldMappingArray = [[NSMutableArray alloc] init];
-
- for (i = 0; i < [fieldMappingTableColumnNames count]; i++) {
- if (i < [NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow) count] && ![NSArrayObjectAtIndex(NSArrayObjectAtIndex(fieldMappingImportArray, fieldMappingCurrentRow), i) isKindOfClass:[NSNull class]]) {
- value = i + 1;
- } else {
- value = 0;
- }
-
- [fieldMappingArray addObject:[NSNumber numberWithInteger:value]];
- }
- }
-
- [fieldMappingTableView reloadData];
-}
-
-/*
- * Update the NSButtonCell items for use in the field mapping display
- */
-- (void)updateFieldMappingButtonCell
-{
- int i;
-
- [fieldMappingButtonOptions setArray:[fieldMappingImportArray objectAtIndex:fieldMappingCurrentRow]];
- for (i = 0; i < [fieldMappingButtonOptions count]; i++) {
- if ([[fieldMappingButtonOptions objectAtIndex:i] isNSNull]) {
- [fieldMappingButtonOptions replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%i. %@", i+1, [prefs objectForKey:SPNullValue]]];
- } else {
- [fieldMappingButtonOptions replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%i. %@", i+1, NSArrayObjectAtIndex(fieldMappingButtonOptions, i)]];
- }
- }
-}
-
-- (IBAction)stepRow:(id)sender
-/*
- displays next/previous row in fieldMapping tableView
- */
-{
- if ( [sender tag] == 0 ) {
- fieldMappingCurrentRow--;
- } else {
- fieldMappingCurrentRow++;
- }
- [self updateFieldMappingButtonCell];
-
- //-----------[self setupFieldMappingArray];
- [fieldMappingTableView reloadData];
-
- [recordCountLabel setStringValue:[NSString stringWithFormat:@"%ld of %@%lu records", (long)(fieldMappingCurrentRow+1), fieldMappingImportArrayIsPreview?@"first ":@"", (unsigned long)[fieldMappingImportArray count]]];
-
- // enable/disable buttons
- [rowDownButton setEnabled:(fieldMappingCurrentRow != 0)];
- [rowUpButton setEnabled:(fieldMappingCurrentRow != ([fieldMappingImportArray count]-1))];
-}
-
-/*
* Construct the VALUES string for a CSV row, based on the field mapping array - including
* surrounding brackets but not including the VALUES keyword.
*/
@@ -1318,15 +1208,16 @@
NSInteger mappingArrayCount = [fieldMappingArray count];
for (i = 0; i < mappingArrayCount; i++) {
- mapColumn = [NSArrayObjectAtIndex(fieldMappingArray, i) integerValue];
// Skip unmapped columns
- if (!mapColumn) continue;
+ if ([NSArrayObjectAtIndex(fieldMapperOperator, i) integerValue] > 0) continue;
+
+ mapColumn = [NSArrayObjectAtIndex(fieldMappingArray, i) integerValue];
if ([valueString length] > 1) [valueString appendString:@","];
// Append the data
- cellData = NSArrayObjectAtIndex(csvRowArray, mapColumn - 1);
+ cellData = NSArrayObjectAtIndex(csvRowArray, mapColumn);
if (cellData == [NSNull null]) {
[valueString appendString:@"NULL"];
@@ -2794,8 +2685,6 @@
setFont:[NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]]];
[[[exportMultipleXMLTableView tableColumnWithIdentifier:@"tables"] dataCell]
setFont:[NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]]];
- [[[fieldMappingTableView tableColumnWithIdentifier:@"0"] dataCell]
- setFont:[NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]]];
[errorsView setFont:[NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]]];
} else {
[[[exportDumpTableView tableColumnWithIdentifier:@"tables"] dataCell]
@@ -2804,8 +2693,6 @@
setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
[[[exportMultipleXMLTableView tableColumnWithIdentifier:@"tables"] dataCell]
setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
- [[[fieldMappingTableView tableColumnWithIdentifier:@"0"] dataCell]
- setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
[errorsView setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
}
}
@@ -2815,7 +2702,7 @@
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView;
{
- return (aTableView == fieldMappingTableView) ? [fieldMappingTableColumnNames count] : [tables count];
+ return [tables count];
}
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
@@ -2826,39 +2713,19 @@
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
id returnObject = nil;
-
- if ( aTableView == fieldMappingTableView ) {
- if ([[aTableColumn identifier] isEqualToString:@"field"]) {
- returnObject = [fieldMappingTableColumnNames objectAtIndex:rowIndex];
-
- } else if ([[aTableColumn identifier] isEqualToString:@"value"]) {
- if ([[[aTableColumn dataCell] class] isEqualTo:[NSPopUpButtonCell class]]) {
- [(NSPopUpButtonCell *)[aTableColumn dataCell] removeAllItems];
- [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemWithTitle:NSLocalizedString(@"Do not import", @"text for csv import drop downs")];
- [(NSPopUpButtonCell *)[aTableColumn dataCell] addItemsWithTitles:fieldMappingButtonOptions];
- }
-
- returnObject = [fieldMappingArray objectAtIndex:rowIndex];
- }
+
+ if ( [[aTableColumn identifier] isEqualToString:@"switch"] ) {
+ returnObject = [[tables objectAtIndex:rowIndex] objectAtIndex:0];
} else {
- if ( [[aTableColumn identifier] isEqualToString:@"switch"] ) {
- returnObject = [[tables objectAtIndex:rowIndex] objectAtIndex:0];
- } else {
- returnObject = [[tables objectAtIndex:rowIndex] objectAtIndex:1];
- }
+ returnObject = [[tables objectAtIndex:rowIndex] objectAtIndex:1];
}
-
+
return returnObject;
}
- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
- if ( aTableView == fieldMappingTableView ) {
- [fieldMappingArray replaceObjectAtIndex:rowIndex withObject:anObject];
- }
- else {
- [[tables objectAtIndex:rowIndex] replaceObjectAtIndex:0 withObject:anObject];
- }
+ [[tables objectAtIndex:rowIndex] replaceObjectAtIndex:0 withObject:anObject];
}
@@ -2925,8 +2792,6 @@
self = [super init];
tables = [[NSMutableArray alloc] init];
- fieldMappingTableColumnNames = [[NSMutableArray alloc] init];
- fieldMappingButtonOptions = [[NSMutableArray alloc] init];
fieldMappingArray = nil;
fieldMappingImportArray = nil;
fieldMappingImportArrayIsPreview = NO;
@@ -2938,10 +2803,7 @@
- (void)dealloc
{
[tables release];
- [fieldMappingTableColumnNames release];
- [fieldMappingButtonOptions release];
if (fieldMappingImportArray) [fieldMappingImportArray release];
- if (fieldMappingArray) [fieldMappingArray release];
if (prefs) [prefs release];
[super dealloc];