aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPTableStructure.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPTableStructure.m')
-rw-r--r--Source/SPTableStructure.m719
1 files changed, 377 insertions, 342 deletions
diff --git a/Source/SPTableStructure.m b/Source/SPTableStructure.m
index ac490b82..2ec324a7 100644
--- a/Source/SPTableStructure.m
+++ b/Source/SPTableStructure.m
@@ -55,14 +55,14 @@
tableFields = [[NSMutableArray alloc] init];
oldRow = [[NSMutableDictionary alloc] init];
enumFields = [[NSMutableDictionary alloc] init];
-
+
currentlyEditingRow = -1;
defaultValues = nil;
selectedTable = nil;
-
+
prefs = [NSUserDefaults standardUserDefaults];
}
-
+
return self;
}
@@ -73,15 +73,17 @@
{
// Set the structure and index view's vertical gridlines if required
[tableSourceView setGridStyleMask:([prefs boolForKey:SPDisplayTableViewVerticalGridlines]) ? NSTableViewSolidVerticalGridLineMask : NSTableViewGridNone];
-
+
// Set the strutcture and index view's font
BOOL useMonospacedFont = [prefs boolForKey:SPUseMonospacedFonts];
-
+
for (NSTableColumn *fieldColumn in [tableSourceView tableColumns])
{
[[fieldColumn dataCell] setFont:(useMonospacedFont) ? [NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]] : [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
}
-
+
+ databaseDataInstance = [tableDocumentInstance valueForKeyPath:@"databaseDataInstance"];
+
// Add observers for document task activity
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(startDocumentTaskForTab:)
@@ -100,12 +102,10 @@
*/
- (void)loadTable:(NSString *)aTable
{
- NSArray *theTableFields, *theTableIndexes;
+ NSMutableArray *theTableFields = [NSMutableArray array];
+ NSArray *theTableIndexes;
NSMutableDictionary *theTableEnumLists = [NSMutableDictionary dictionary];
- NSArray *extrasArray;
- NSMutableDictionary *tempDefaultValues;
NSInteger i;
- SPSQLParser *fieldParser;
// Check whether a save of the current row is required.
if ( ![[self onMainThread] saveRowOnDeselect] ) return;
@@ -115,32 +115,10 @@
[[self onMainThread] setTableDetails:nil];
return;
}
-
- // Send the query started/working notification
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryWillBePerformed" object:tableDocumentInstance];
-
- // Retrieve the column information for this table.
- // TODO: update this and indexes to use TableData at some point - tiny bit more parsing required...
- tableSourceResult = [[mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@", [aTable backtickQuotedString]]] retain];
-
- // If an error occurred, reset the interface and abort
- if ([mySQLConnection queryErrored]) {
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
- [[self onMainThread] setTableDetails:nil];
-
- if ([mySQLConnection isConnected]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
- nil, nil, [NSApp mainWindow], self, nil, nil,
- [NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving information.\nMySQL said: %@", @"message of panel when retrieving information failed"),
- [mySQLConnection getLastErrorMessage]]);
- }
- if (tableSourceResult) [tableSourceResult release];
- return;
- }
- // Process the field names into a local array of dictionaries
- theTableFields = [self fetchResultAsArray:tableSourceResult];
- [tableSourceResult release];
+ // Make a mutable copy out of the cached [tableDataInstance columns] since we're adding infos
+ for(id col in [tableDataInstance columns])
+ [theTableFields addObject:[col mutableCopy]];
// Retrieve the indexes for the table
indexResult = [[mySQLConnection queryString:[NSString stringWithFormat:@"SHOW INDEX FROM %@", [aTable backtickQuotedString]]] retain];
@@ -151,7 +129,7 @@
[[self onMainThread] setTableDetails:nil];
if ([mySQLConnection isConnected]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
nil, nil, [NSApp mainWindow], self, nil, nil,
[NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving information.\nMySQL said: %@", @"message of panel when retrieving information failed"),
[mySQLConnection getLastErrorMessage]]);
@@ -164,72 +142,95 @@
theTableIndexes = [self fetchResultAsArray:indexResult];
[indexResult release];
- // Process all the fields to normalise keys and add additional information
- for (id theField in theTableFields) {
- NSString *type;
- NSString *length;
- NSString *extras;
-
- // Set up the field parser with the type definition
- fieldParser = [[SPSQLParser alloc] initWithString:[theField objectForKey:@"Type"]];
-
- // Pull out the field type; if no brackets are found, this returns nil - in which case simple values can be used.
- type = [fieldParser trimAndReturnStringToCharacter:'(' trimmingInclusively:YES returningInclusively:NO];
- if (!type) {
- type = [NSString stringWithString:fieldParser];
- length = @"";
- extras = @"";
- } else {
-
- // Pull out the length, which may include enum/set values
- length = [fieldParser trimAndReturnStringToCharacter:')' trimmingInclusively:YES returningInclusively:NO];
- if (!length) length = @"";
+ // Set the Key column
+ for(NSDictionary* theIndex in theTableIndexes) {
+ for(id field in theTableFields) {
+ if([[field objectForKey:@"name"] isEqualToString:[theIndex objectForKey:@"Column_name"]]) {
+ if([[theIndex objectForKey:@"Key_name"] isEqualToString:@"PRIMARY"])
+ [field setObject:@"PRI" forKey:@"Key"];
+ else
+ [field setObject:(([[theIndex objectForKey:@"Non_unique"] isEqualToString:@"1"]) ? @"MUL" : @"UNI") forKey:@"Key"];
+ break;
+ }
+ }
+ }
- // Separate any remaining extras
- extras = [NSString stringWithString:fieldParser];
- if (!extras) extras = @"";
+ // Set up the encoding PopUpButtonCell
+ NSArray *encodings = [databaseDataInstance getDatabaseCharacterSetEncodings];
+ if (([encodings count] > 0) && ([tableDataInstance tableEncoding])) {
+ NSString *selectedTitle = @"";
+ [[[[tableSourceView tableColumns] objectAtIndex:10] dataCell] removeAllItems];
+ [[[[tableSourceView tableColumns] objectAtIndex:10] dataCell] addItemWithTitle:@""];
+ // Populate encoding popup button
+ for (NSDictionary *encoding in encodings)
+ {
+ NSString *menuItemTitle = (![encoding objectForKey:@"DESCRIPTION"]) ? [encoding objectForKey:@"CHARACTER_SET_NAME"] : [NSString stringWithFormat:@"%@ (%@)", [encoding objectForKey:@"DESCRIPTION"], [encoding objectForKey:@"CHARACTER_SET_NAME"]];
+ [[[[tableSourceView tableColumns] objectAtIndex:10] dataCell] addItemWithTitle:menuItemTitle];
}
+ }
+ else {
+ [[[[tableSourceView tableColumns] objectAtIndex:10] dataCell] addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")];
+ }
- [fieldParser release];
+ // Process all the fields to normalise keys and add additional information
+ for (id theField in theTableFields) {
- // Get possible values if the field is an enum or a set
- if ([type isEqualToString:@"enum"] || [type isEqualToString:@"set"]) {
- SPSQLParser *valueParser = [[SPSQLParser alloc] initWithString:length];
- NSMutableArray *possibleValues = [[NSMutableArray alloc] initWithArray:[valueParser splitStringByCharacter:',']];
- for (i = 0; i < [possibleValues count]; i++) {
- [valueParser setString:[possibleValues objectAtIndex:i]];
- [possibleValues replaceObjectAtIndex:i withObject:[valueParser unquotedString]];
+ // Select and re-map encoding and collation since [self dataSource] stores the choice as NSNumbers
+ NSString *fieldEncoding = @"";
+ NSInteger selectedIndex = 0;
+ if([theField objectForKey:@"encoding"]) {
+ for(id enc in encodings) {
+ if([[enc objectForKey:@"CHARACTER_SET_NAME"] isEqualToString:[theField objectForKey:@"encoding"]]) {
+ fieldEncoding = [theField objectForKey:@"encoding"];
+ break;
+ }
+ selectedIndex++;
}
- [theTableEnumLists setObject:[NSArray arrayWithArray:possibleValues] forKey:[theField objectForKey:@"Field"]];
- [possibleValues release];
- [valueParser release];
+ selectedIndex++; // due to leading @"" in popup list
}
-
- // For timestamps check to see whether "on update CURRENT_TIMESTAMP" - not returned
- // by SHOW COLUMNS - should be set from the table data store
- if ([type isEqualToString:@"timestamp"]
- && [[[tableDataInstance columnWithName:[theField objectForKey:@"Field"]] objectForKey:@"onupdatetimestamp"] integerValue])
- {
- [theField setObject:@"on update CURRENT_TIMESTAMP" forKey:@"Extra"];
+ [theField setObject:[NSNumber numberWithInt:selectedIndex] forKey:@"encoding"];
+ selectedIndex = 0;
+ if([fieldEncoding length] && [theField objectForKey:@"collation"]) {
+ NSArray *theCollations = [databaseDataInstance getDatabaseCollationsForEncoding:fieldEncoding];
+ for(id col in theCollations) {
+ if([[col objectForKey:@"COLLATION_NAME"] isEqualToString:[theField objectForKey:@"collation"]]) {
+ break;
+ }
+ selectedIndex++;
+ }
+ selectedIndex++; // due to leading @"" in popup list
}
+ [theField setObject:[NSNumber numberWithInt:selectedIndex] forKey:@"collation"];
- // Scan extras for values like unsigned, zerofill, binary
- extrasArray = [extras componentsSeparatedByString:@" "];
- for (id extra in extrasArray) {
- if ([extra isEqualToString:@"unsigned"]) {
- [theField setObject:@"1" forKey:@"unsigned"];
- } else if ([extra isEqualToString:@"zerofill"]) {
- [theField setObject:@"1" forKey:@"zerofill"];
- } else if ([extra isEqualToString:@"binary"]) {
- [theField setObject:@"1" forKey:@"binary"];
- } else {
- if (![extra isEqualToString:@""])
- NSLog(@"ERROR: unknown option in field definition: %@", extra);
- }
+ NSString *type = [[theField objectForKey:@"type"] uppercaseString];
+
+ // Get possible values if the field is an enum or a set
+ if (([type isEqualToString:@"ENUM"] || [type isEqualToString:@"SET"]) && [theField objectForKey:@"values"]) {
+ [theTableEnumLists setObject:[NSArray arrayWithArray:[theField objectForKey:@"values"]] forKey:[theField objectForKey:@"name"]];
+ [theField setObject:[NSString stringWithFormat:@"'%@'", [[theField objectForKey:@"values"] componentsJoinedByString:@"','"]] forKey:@"length"];
}
- [theField setObject:type forKey:@"Type"];
- [theField setObject:length forKey:@"Length"];
+ // Join length and decimals if any
+ if ([theField objectForKey:@"decimals"])
+ [theField setObject:[NSString stringWithFormat:@"%@,%@", [theField objectForKey:@"length"], [theField objectForKey:@"decimals"]] forKey:@"length"];
+
+ // Normalize default
+ if(![theField objectForKey:@"default"])
+ [theField setObject:@"" forKey:@"default"];
+ else if([[theField objectForKey:@"default"] isKindOfClass:[NSNull class]])
+ [theField setObject:[prefs stringForKey:SPNullValue] forKey:@"default"];
+
+ // Init Extra field
+ [theField setObject:@"None" forKey:@"Extra"];
+
+ // Check for auto_increment and set Extra accordingly
+ if([[theField objectForKey:@"autoincrement"] integerValue])
+ [theField setObject:@"auto_increment" forKey:@"Extra"];
+
+ // For timestamps check to see whether "on update CURRENT_TIMESTAMP" and set Extra accordingly
+ else if ([type isEqualToString:@"TIMESTAMP"] && [[theField objectForKey:@"onupdatetimestamp"] integerValue])
+ [theField setObject:@"on update CURRENT_TIMESTAMP" forKey:@"Extra"];
+
}
// Set up the table details for the new table, and request an data/interface update
@@ -243,7 +244,7 @@
// Send the query finished/work complete notification
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
-
+
}
/**
@@ -274,7 +275,7 @@
// Update the selected table name
if (selectedTable) [selectedTable release], selectedTable = nil;
if (newTableName) selectedTable = [[NSString alloc] initWithString:newTableName];
-
+
[indexesController setTable:selectedTable];
// Reset the table store and display
@@ -301,27 +302,25 @@
// Update the fields and indexes stores
[tableFields setArray:[tableDetails objectForKey:@"tableFields"]];
-
+
[indexesController setFields:tableFields];
[indexesController setIndexes:[tableDetails objectForKey:@"tableIndexes"]];
-
+
if (defaultValues) [defaultValues release], defaultValues = nil;
-
+
newDefaultValues = [NSMutableDictionary dictionaryWithCapacity:[tableFields count]];
-
- for (id theField in tableFields)
- {
- [newDefaultValues setObject:[theField objectForKey:@"Default"] forKey:[theField objectForKey:@"Field"]];
- }
-
+
+ for (id theField in tableFields)
+ [newDefaultValues setObject:[theField objectForKey:@"default"] forKey:[theField objectForKey:@"name"]];
+
defaultValues = [[NSDictionary dictionaryWithDictionary:newDefaultValues] retain];
-
+
// Enable the edit table button
[editTableButton setEnabled:enableInteraction];
// If a view is selected, disable the buttons; otherwise enable.
BOOL editingEnabled = ([tablesListInstance tableType] == SPTableTypeTable) && enableInteraction;
-
+
[addFieldButton setEnabled:editingEnabled];
[addIndexButton setEnabled:editingEnabled];
@@ -342,10 +341,10 @@
if ( ![self saveRowOnDeselect] ) return;
NSInteger insertIndex = ([tableSourceView numberOfSelectedRows] == 0 ? [tableSourceView numberOfRows] : [tableSourceView selectedRow] + 1);
-
- [tableFields insertObject:[NSMutableDictionary
- dictionaryWithObjects:[NSArray arrayWithObjects:@"", @"int", @"", @"0", @"0", @"0", ([prefs boolForKey:SPNewFieldsAllowNulls]) ? @"1" : @"0", @"", [prefs stringForKey:SPNullValue], @"None", nil]
- forKeys:[NSArray arrayWithObjects:@"Field", @"Type", @"Length", @"unsigned", @"zerofill", @"binary", @"Null", @"Key", @"Default", @"Extra", nil]]
+
+ [tableFields insertObject:[NSMutableDictionary
+ dictionaryWithObjects:[NSArray arrayWithObjects:@"", @"INT", @"", @"0", @"0", @"0", ([prefs boolForKey:SPNewFieldsAllowNulls]) ? @"1" : @"0", @"", [prefs stringForKey:SPNullValue], @"None", @"", @"", @"", nil]
+ forKeys:[NSArray arrayWithObjects:@"name", @"type", @"length", @"unsigned", @"zerofill", @"binary", @"null", @"Key", @"default", @"Extra", @"comment", @"encoding", @"collation", nil]]
atIndex:insertIndex];
[tableSourceView reloadData];
@@ -373,10 +372,10 @@
// Check whether a save of the current row is required.
if ( ![self saveRowOnDeselect] ) return;
-
+
//add copy of selected row and go in edit mode
tempRow = [NSMutableDictionary dictionaryWithDictionary:[tableFields objectAtIndex:rowToCopy]];
- [tempRow setObject:[[tempRow objectForKey:@"Field"] stringByAppendingString:@"Copy"] forKey:@"Field"];
+ [tempRow setObject:[[tempRow objectForKey:@"name"] stringByAppendingString:@"Copy"] forKey:@"name"];
[tempRow setObject:@"" forKey:@"Key"];
[tempRow setObject:@"None" forKey:@"Extra"];
[tableFields addObject:tempRow];
@@ -397,31 +396,31 @@
// Check whether a save of the current row is required.
if (![self saveRowOnDeselect]) return;
-
+
NSInteger index = [tableSourceView selectedRow];
-
+
if ((index == -1) || (index > ([tableFields count] - 1))) return;
// Check if the user tries to delete the last defined field in table
// Note that because of better menu item validation, this check will now never evaluate to true.
if ([tableSourceView numberOfRows] < 2) {
NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Error while deleting field", @"Error while deleting field")
- defaultButton:NSLocalizedString(@"OK", @"OK button")
- alternateButton:nil
- otherButton:nil
+ defaultButton:NSLocalizedString(@"OK", @"OK button")
+ alternateButton:nil
+ otherButton:nil
informativeTextWithFormat:NSLocalizedString(@"You cannot delete the last field in a table. Delete the table instead.", @"You cannot delete the last field in a table. Delete the table instead.")];
[alert setAlertStyle:NSCriticalAlertStyle];
[alert beginSheetModalForWindow:[tableDocumentInstance parentWindow] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"cannotremovefield"];
-
+
}
-
- NSString *field = [[tableFields objectAtIndex:index] objectForKey:@"Field"];
-
+
+ NSString *field = [[tableFields objectAtIndex:index] objectForKey:@"name"];
+
BOOL hasForeignKey = NO;
NSString *referencedTable = @"";
-
+
// Check to see whether the user is attempting to remove a field that has foreign key constraints and thus
// would result in an error if not dropped before removing the field.
for (NSDictionary *constraint in [tableDataInstance getConstraints])
@@ -435,22 +434,22 @@
}
}
}
-
+
NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Delete field '%@'?", @"delete field message"), field]
defaultButton:NSLocalizedString(@"Delete", @"delete button")
- alternateButton:NSLocalizedString(@"Cancel", @"cancel button")
- otherButton:nil
+ alternateButton:NSLocalizedString(@"Cancel", @"cancel button")
+ otherButton:nil
informativeTextWithFormat:(hasForeignKey) ? [NSString stringWithFormat:NSLocalizedString(@"This field is part of a foreign key relationship with the table '%@'. This relationship must be removed before the field can be deleted.\n\nAre you sure you want to continue to delete the relationship and the field? This action cannot be undone.", @"delete field and foreign key informative message"), referencedTable] : [NSString stringWithFormat:NSLocalizedString(@"Are you sure you want to delete the field '%@'? This action cannot be undone.", @"delete field informative message"), field]];
-
+
[alert setAlertStyle:NSCriticalAlertStyle];
-
+
NSArray *buttons = [alert buttons];
-
+
// Change the alert's cancel button to have the key equivalent of return
[[buttons objectAtIndex:0] setKeyEquivalent:@"d"];
[[buttons objectAtIndex:0] setKeyEquivalentModifierMask:NSCommandKeyMask];
[[buttons objectAtIndex:1] setKeyEquivalent:@"\r"];
-
+
[alert beginSheetModalForWindow:[tableDocumentInstance parentWindow] modalDelegate:self didEndSelector:@selector(removeFieldSheetDidEnd:returnCode:contextInfo:) contextInfo:(hasForeignKey) ? @"removeFieldAndForeignKey" : @"removeField"];
}
@@ -460,19 +459,19 @@
- (IBAction)resetAutoIncrement:(id)sender
{
if ([sender tag] == 1) {
-
+
[resetAutoIncrementLine setHidden:YES];
-
+
if ([[tableDocumentInstance valueForKeyPath:@"tableTabView"] indexOfTabViewItem:[[tableDocumentInstance valueForKeyPath:@"tableTabView"] selectedTabViewItem]] == 0)
[resetAutoIncrementLine setHidden:NO];
-
+
// Begin the sheet
[NSApp beginSheet:resetAutoIncrementSheet
- modalForWindow:[tableDocumentInstance parentWindow]
+ modalForWindow:[tableDocumentInstance parentWindow]
modalDelegate:self
- didEndSelector:@selector(resetAutoincrementSheetDidEnd:returnCode:contextInfo:)
+ didEndSelector:@selector(resetAutoincrementSheetDidEnd:returnCode:contextInfo:)
contextInfo:nil];
-
+
[resetAutoIncrementValue setStringValue:@"1"];
}
else if ([sender tag] == 2) {
@@ -487,7 +486,7 @@
{
// Order out current sheet to suppress overlapping of sheets
[theSheet orderOut:nil];
-
+
if (returnCode == NSAlertDefaultReturn) {
[self setAutoIncrementTo:[[resetAutoIncrementValue stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
@@ -504,14 +503,14 @@
if (returnCode == NSAlertDefaultReturn) {
[tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Removing field...", @"removing field task status message")];
-
+
NSNumber *removeKey = [NSNumber numberWithBool:[contextInfo hasSuffix:@"AndForeignKey"]];
-
+
if ([NSThread isMainThread]) {
[NSThread detachNewThreadSelector:@selector(_removeFieldAndForeignKey:) toTarget:self withObject:removeKey];
-
- [tableDocumentInstance enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:NULL];
- }
+
+ [tableDocumentInstance enableTaskCancellationWithTitle:NSLocalizedString(@"Cancel", @"cancel button") callbackObject:self callbackFunction:NULL];
+ }
else {
[self _removeFieldAndForeignKey:removeKey];
}
@@ -543,12 +542,12 @@ closes the keySheet
#pragma mark Additional methods
/**
- * Sets the connection (received from SPDatabaseDocument) and makes things that have to be done only once
+ * Sets the connection (received from SPDatabaseDocument) and makes things that have to be done only once
*/
- (void)setConnection:(MCPConnection *)theConnection
{
mySQLConnection = theConnection;
-
+
// Set the indexes controller connection
[indexesController setConnection:mySQLConnection];
@@ -586,10 +585,10 @@ closes the keySheet
[mySQLConnection queryString:[NSString stringWithFormat:@"ALTER TABLE %@ AUTO_INCREMENT = %@", [selTable backtickQuotedString], [autoIncValue stringValue]]];
if ([mySQLConnection queryErrored]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"),
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"),
NSLocalizedString(@"OK", @"OK button"),
- nil, nil, [NSApp mainWindow], nil, nil, nil,
- [NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to reset AUTO_INCREMENT of table '%@'.\n\nMySQL said: %@", @"error resetting auto_increment informative message"),
+ nil, nil, [NSApp mainWindow], nil, nil, nil,
+ [NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to reset AUTO_INCREMENT of table '%@'.\n\nMySQL said: %@", @"error resetting auto_increment informative message"),
selTable, [mySQLConnection getLastErrorMessage]]);
}
@@ -685,181 +684,196 @@ closes the keySheet
if (!isEditingRow || currentlyEditingRow == -1)
return YES;
-
+
if (alertSheetOpened)
return NO;
theRow = [tableFields objectAtIndex:currentlyEditingRow];
-
+
if (isEditingNewRow) {
// ADD syntax
- if ([[theRow objectForKey:@"Length"] isEqualToString:@""] || ![theRow objectForKey:@"Length"]) {
-
+ if ([[theRow objectForKey:@"length"] isEqualToString:@""] || ![theRow objectForKey:@"length"]) {
+
queryString = [NSMutableString stringWithFormat:@"ALTER TABLE %@ ADD %@ %@",
- [selectedTable backtickQuotedString],
- [[theRow objectForKey:@"Field"] backtickQuotedString],
- [theRow objectForKey:@"Type"]];
- }
+ [selectedTable backtickQuotedString],
+ [[theRow objectForKey:@"name"] backtickQuotedString],
+ [[theRow objectForKey:@"type"] uppercaseString]];
+ }
else {
queryString = [NSMutableString stringWithFormat:@"ALTER TABLE %@ ADD %@ %@(%@)",
- [selectedTable backtickQuotedString],
- [[theRow objectForKey:@"Field"] backtickQuotedString],
- [theRow objectForKey:@"Type"],
- [theRow objectForKey:@"Length"]];
+ [selectedTable backtickQuotedString],
+ [[theRow objectForKey:@"name"] backtickQuotedString],
+ [[theRow objectForKey:@"type"] uppercaseString],
+ [theRow objectForKey:@"length"]];
}
- }
+ }
else {
// CHANGE syntax
- if (([[theRow objectForKey:@"Length"] isEqualToString:@""]) ||
- (![theRow objectForKey:@"Length"]) ||
- ([[theRow objectForKey:@"Type"] isEqualToString:@"datetime"]))
+ if (([[theRow objectForKey:@"length"] isEqualToString:@""]) ||
+ (![theRow objectForKey:@"length"]) ||
+ ([[[theRow objectForKey:@"type"] lowercaseString] isEqualToString:@"datetime"]))
{
- // If the old row and new row dictionaries are equal then the user didn't actually change anything so don't continue
+ // If the old row and new row dictionaries are equal then the user didn't actually change anything so don't continue
if ([oldRow isEqualToDictionary:theRow]) {
isEditingRow = NO;
currentlyEditingRow = -1;
return YES;
}
-
+
queryString = [NSMutableString stringWithFormat:@"ALTER TABLE %@ CHANGE %@ %@ %@",
- [selectedTable backtickQuotedString],
- [[oldRow objectForKey:@"Field"] backtickQuotedString],
- [[theRow objectForKey:@"Field"] backtickQuotedString],
- [theRow objectForKey:@"Type"]];
- }
+ [selectedTable backtickQuotedString],
+ [[oldRow objectForKey:@"name"] backtickQuotedString],
+ [[theRow objectForKey:@"name"] backtickQuotedString],
+ [[theRow objectForKey:@"type"] uppercaseString]];
+ }
else {
- // If the old row and new row dictionaries are equal then the user didn't actually change anything so don't continue
+ // If the old row and new row dictionaries are equal then the user didn't actually change anything so don't continue
if ([oldRow isEqualToDictionary:theRow]) {
isEditingRow = NO;
currentlyEditingRow = -1;
return YES;
}
-
+
queryString = [NSMutableString stringWithFormat:@"ALTER TABLE %@ CHANGE %@ %@ %@(%@)",
- [selectedTable backtickQuotedString],
- [[oldRow objectForKey:@"Field"] backtickQuotedString],
- [[theRow objectForKey:@"Field"] backtickQuotedString],
- [theRow objectForKey:@"Type"],
- [theRow objectForKey:@"Length"]];
+ [selectedTable backtickQuotedString],
+ [[oldRow objectForKey:@"name"] backtickQuotedString],
+ [[theRow objectForKey:@"name"] backtickQuotedString],
+ [[theRow objectForKey:@"type"] uppercaseString],
+ [theRow objectForKey:@"length"]];
}
}
-
+
+ NSString *fieldEncoding = @"";
+ if([[theRow objectForKey:@"encoding"] integerValue] > 0) {
+ NSString *enc = [[[[[tableSourceView tableColumns] objectAtIndex:10] dataCell] itemAtIndex:[[theRow objectForKey:@"encoding"] integerValue]] title];
+ NSInteger start = [enc rangeOfString:@"("].location+1;
+ NSInteger end = [enc length] - start - 1;
+ fieldEncoding = [enc substringWithRange:NSMakeRange(start, end)];
+ [queryString appendFormat:@" CHARACTER SET %@", fieldEncoding];
+ }
+ if(![fieldEncoding length] && [tableDataInstance tableEncoding]) {
+ fieldEncoding = [tableDataInstance tableEncoding];
+ }
+ if([fieldEncoding length] && [[theRow objectForKey:@"collation"] integerValue] > 0) {
+ NSArray *theCollations = [databaseDataInstance getDatabaseCollationsForEncoding:fieldEncoding];
+ NSString *col = [[theCollations objectAtIndex:[[theRow objectForKey:@"collation"] integerValue]-1] objectForKey:@"COLLATION_NAME"];
+ [queryString appendFormat:@" COLLATE %@", col];
+ }
+
+
// Field specification
if ([[theRow objectForKey:@"unsigned"] integerValue] == 1) {
[queryString appendString:@" UNSIGNED"];
}
-
+
if ( [[theRow objectForKey:@"zerofill"] integerValue] == 1) {
[queryString appendString:@" ZEROFILL"];
}
-
+
if ( [[theRow objectForKey:@"binary"] integerValue] == 1) {
[queryString appendString:@" BINARY"];
}
- if ([[theRow objectForKey:@"Null"] integerValue] == 0) {
+ if ([[theRow objectForKey:@"null"] integerValue] == 0) {
[queryString appendString:@" NOT NULL"];
} else {
[queryString appendString:@" NULL"];
}
-
+
// Don't provide any defaults for auto-increment fields
if ([[theRow objectForKey:@"Extra"] isEqualToString:@"auto_increment"]) {
[queryString appendString:@" "];
- }
+ }
else {
// If a NULL value has been specified, and NULL is allowed, specify DEFAULT NULL
- if ([[theRow objectForKey:@"Default"] isEqualToString:[prefs objectForKey:SPNullValue]]) {
- if ([[theRow objectForKey:@"Null"] integerValue] == 1) {
+ if ([[theRow objectForKey:@"default"] isEqualToString:[prefs objectForKey:SPNullValue]]) {
+ if ([[theRow objectForKey:@"null"] integerValue] == 1) {
[queryString appendString:@" DEFAULT NULL "];
}
- }
+ }
// Otherwise, if CURRENT_TIMESTAMP was specified for timestamps, use that
- else if ([[theRow objectForKey:@"Type"] isEqualToString:@"timestamp"] &&
- [[[theRow objectForKey:@"Default"] uppercaseString] isEqualToString:@"CURRENT_TIMESTAMP"])
+ else if ([[theRow objectForKey:@"type"] isEqualToString:@"timestamp"] &&
+ [[[theRow objectForKey:@"default"] uppercaseString] isEqualToString:@"CURRENT_TIMESTAMP"])
{
[queryString appendString:@" DEFAULT CURRENT_TIMESTAMP "];
}
// If the field is of type BIT, permit the use of single qoutes and also don't quote the default value.
// For example, use DEFAULT b'1' as opposed to DEFAULT 'b\'1\'' which results in an error.
- else if ([[theRow objectForKey:@"Type"] isEqualToString:@"bit"]) {
- [queryString appendFormat:@" DEFAULT %@ ", [theRow objectForKey:@"Default"]];
+ else if ([[[theRow objectForKey:@"type"] lowercaseString] isEqualToString:@"bit"]) {
+ [queryString appendFormat:@" DEFAULT %@ ", [theRow objectForKey:@"default"]];
}
// Otherwise, use the provided default
else {
- [queryString appendFormat:@" DEFAULT '%@' ", [mySQLConnection prepareString:[theRow objectForKey:@"Default"]]];
+ [queryString appendFormat:@" DEFAULT '%@' ", [mySQLConnection prepareString:[theRow objectForKey:@"default"]]];
}
}
-
+
if (!(
- [[theRow objectForKey:@"Extra"] isEqualToString:@""] ||
+ [[theRow objectForKey:@"Extra"] isEqualToString:@""] ||
[[theRow objectForKey:@"Extra"] isEqualToString:@"None"]
- ) &&
- [theRow objectForKey:@"Extra"] )
+ ) &&
+ [theRow objectForKey:@"Extra"] )
{
[queryString appendString:@" "];
[queryString appendString:[theRow objectForKey:@"Extra"]];
}
-
- if (!isEditingNewRow) {
- // Add details not provided via the SHOW COLUMNS query from the table data cache so column details aren't lost
- NSDictionary *originalColumnDetails = [[tableDataInstance columns] objectAtIndex:currentlyEditingRow];
+ if (!isEditingNewRow) {
// Any column comments
- if ([originalColumnDetails objectForKey:@"comment"] && [(NSString *)[originalColumnDetails objectForKey:@"comment"] length]) {
- [queryString appendFormat:@" COMMENT '%@'", [mySQLConnection prepareString:[originalColumnDetails objectForKey:@"comment"]]];
+ if ([[theRow objectForKey:@"comment"] length]) {
+ [queryString appendFormat:@" COMMENT '%@'", [mySQLConnection prepareString:[theRow objectForKey:@"comment"]]];
}
// Unparsed details - column formats, storage, reference definitions
- if ([originalColumnDetails objectForKey:@"unparsed"]) {
- [queryString appendString:[originalColumnDetails objectForKey:@"unparsed"]];
+ if ([[theRow objectForKey:@"unparsed"] length]) {
+ [queryString appendString:[theRow objectForKey:@"unparsed"]];
}
}
-
+
// Asks the user to add an index to query if auto_increment is set and field isn't indexed
- if ([[theRow objectForKey:@"Extra"] isEqualToString:@"auto_increment"] &&
- ([[theRow objectForKey:@"Key"] isEqualToString:@""] ||
- ![theRow objectForKey:@"Key"]))
+ if ([[theRow objectForKey:@"Extra"] isEqualToString:@"auto_increment"] &&
+ ([[theRow objectForKey:@"Key"] isEqualToString:@""] ||
+ ![theRow objectForKey:@"Key"]))
{
[chooseKeyButton selectItemAtIndex:0];
-
- [NSApp beginSheet:keySheet
- modalForWindow:[tableDocumentInstance parentWindow] modalDelegate:self
- didEndSelector:nil
+
+ [NSApp beginSheet:keySheet
+ modalForWindow:[tableDocumentInstance parentWindow] modalDelegate:self
+ didEndSelector:nil
contextInfo:nil];
-
+
code = [NSApp runModalForWindow:keySheet];
-
+
[NSApp endSheet:keySheet];
[keySheet orderOut:nil];
-
+
if (code) {
// User wants to add PRIMARY KEY
- if ([chooseKeyButton indexOfSelectedItem] == 0 ) {
+ if ([chooseKeyButton indexOfSelectedItem] == 0 ) {
[queryString appendString:@" PRIMARY KEY"];
-
+
// Add AFTER ... only if the user added a new field
if (isEditingNewRow) {
- [queryString appendFormat:@" AFTER %@", [[[tableFields objectAtIndex:(currentlyEditingRow -1)] objectForKey:@"Field"] backtickQuotedString]];
+ [queryString appendFormat:@" AFTER %@", [[[tableFields objectAtIndex:(currentlyEditingRow -1)] objectForKey:@"name"] backtickQuotedString]];
}
- }
+ }
else {
// Add AFTER ... only if the user added a new field
if (isEditingNewRow) {
- [queryString appendFormat:@" AFTER %@", [[[tableFields objectAtIndex:(currentlyEditingRow -1)] objectForKey:@"Field"] backtickQuotedString]];
- }
-
- [queryString appendFormat:@", ADD %@ (%@)", [chooseKeyButton titleOfSelectedItem], [[theRow objectForKey:@"Field"] backtickQuotedString]];
+ [queryString appendFormat:@" AFTER %@", [[[tableFields objectAtIndex:(currentlyEditingRow -1)] objectForKey:@"name"] backtickQuotedString]];
+ }
+
+ [queryString appendFormat:@", ADD %@ (%@)", [chooseKeyButton titleOfSelectedItem], [[theRow objectForKey:@"name"] backtickQuotedString]];
}
}
- }
+ }
// Add AFTER ... only if the user added a new field
else if (isEditingNewRow) {
- [queryString appendFormat:@" AFTER %@", [[[tableFields objectAtIndex:(currentlyEditingRow -1)] objectForKey:@"Field"] backtickQuotedString]];
+ [queryString appendFormat:@" AFTER %@", [[[tableFields objectAtIndex:(currentlyEditingRow -1)] objectForKey:@"name"] backtickQuotedString]];
}
-
+
// Execute query
[mySQLConnection queryString:queryString];
@@ -867,7 +881,7 @@ closes the keySheet
isEditingRow = NO;
isEditingNewRow = NO;
currentlyEditingRow = -1;
-
+
[tableDataInstance resetAllData];
[tablesListInstance setStatusRequiresReload:YES];
[self loadTable:selectedTable];
@@ -879,14 +893,14 @@ closes the keySheet
[NSThread detachNewThreadSelector:@selector(queryDbStructureWithUserInfo:) toTarget:mySQLConnection withObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], @"forceUpdate", selectedTable, @"affectedItem", [NSNumber numberWithInt:[tablesListInstance tableType]], @"affectedItemType", nil]];
return YES;
- }
+ }
else {
alertSheetOpened = YES;
if([mySQLConnection getLastErrorID] == 1146) { // If the current table doesn't exist anymore
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"),
- NSLocalizedString(@"OK", @"OK button"),
- nil, nil, [tableDocumentInstance parentWindow], self, nil, nil,
- [NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to alter table '%@'.\n\nMySQL said: %@", @"error while trying to alter table message"),
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"),
+ NSLocalizedString(@"OK", @"OK button"),
+ nil, nil, [tableDocumentInstance parentWindow], self, nil, nil,
+ [NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to alter table '%@'.\n\nMySQL said: %@", @"error while trying to alter table message"),
selectedTable, [mySQLConnection getLastErrorMessage]]);
isEditingRow = NO;
@@ -907,20 +921,20 @@ closes the keySheet
}
// Problem: alert sheet doesn't respond to first click
if (isEditingNewRow) {
- SPBeginAlertSheet(NSLocalizedString(@"Error adding field", @"error adding field message"),
- NSLocalizedString(@"Edit row", @"Edit row button"),
- NSLocalizedString(@"Discard changes", @"discard changes button"), nil, [tableDocumentInstance parentWindow], self, @selector(addRowErrorSheetDidEnd:returnCode:contextInfo:), nil,
- [NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to add the field '%@'.\n\nMySQL said: %@", @"error adding field informative message"),
- [theRow objectForKey:@"Field"], [mySQLConnection getLastErrorMessage]]);
- }
+ SPBeginAlertSheet(NSLocalizedString(@"Error adding field", @"error adding field message"),
+ NSLocalizedString(@"Edit row", @"Edit row button"),
+ NSLocalizedString(@"Discard changes", @"discard changes button"), nil, [tableDocumentInstance parentWindow], self, @selector(addRowErrorSheetDidEnd:returnCode:contextInfo:), nil,
+ [NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to add the field '%@'.\n\nMySQL said: %@", @"error adding field informative message"),
+ [theRow objectForKey:@"name"], [mySQLConnection getLastErrorMessage]]);
+ }
else {
- SPBeginAlertSheet(NSLocalizedString(@"Error changing field", @"error changing field message"),
- NSLocalizedString(@"Edit row", @"Edit row button"),
- NSLocalizedString(@"Discard changes", @"discard changes button"), nil, [tableDocumentInstance parentWindow], self, @selector(addRowErrorSheetDidEnd:returnCode:contextInfo:), nil,
- [NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to change the field '%@'.\n\nMySQL said: %@", @"error changing field informative message"),
- [theRow objectForKey:@"Field"], [mySQLConnection getLastErrorMessage]]);
+ SPBeginAlertSheet(NSLocalizedString(@"Error changing field", @"error changing field message"),
+ NSLocalizedString(@"Edit row", @"Edit row button"),
+ NSLocalizedString(@"Discard changes", @"discard changes button"), nil, [tableDocumentInstance parentWindow], self, @selector(addRowErrorSheetDidEnd:returnCode:contextInfo:), nil,
+ [NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to change the field '%@'.\n\nMySQL said: %@", @"error changing field informative message"),
+ [theRow objectForKey:@"name"], [mySQLConnection getLastErrorMessage]]);
}
-
+
return NO;
}
}
@@ -950,7 +964,7 @@ closes the keySheet
[tableFields replaceObjectAtIndex:currentlyEditingRow
withObject:[NSMutableDictionary dictionaryWithDictionary:oldRow]];
isEditingRow = NO;
- }
+ }
else {
[tableFields removeObjectAtIndex:currentlyEditingRow];
isEditingRow = NO;
@@ -965,7 +979,7 @@ closes the keySheet
/**
* A method to show an error sheet after a short delay, so that it can
- * be called from within an endSheet selector. This should be called on
+ * be called from within an endSheet selector. This should be called on
* the main thread.
*/
-(void)showErrorSheetWith:(NSDictionary *)errorDictionary
@@ -979,9 +993,9 @@ closes the keySheet
[self performSelector:@selector(showErrorSheetWith:) withObject:delayedErrorDictionary afterDelay:0.3];
return;
}
-
+
// Display the error sheet
- SPBeginAlertSheet([errorDictionary objectForKey:@"title"], NSLocalizedString(@"OK", @"OK button"),
+ SPBeginAlertSheet([errorDictionary objectForKey:@"title"], NSLocalizedString(@"OK", @"OK button"),
nil, nil, [tableDocumentInstance parentWindow], self, nil, nil,
[errorDictionary objectForKey:@"message"]);
}
@@ -990,21 +1004,21 @@ closes the keySheet
* This method is called as part of Key Value Observing which is used to watch for preference changes which effect the interface.
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
-{
+{
// Display table veiew vertical gridlines preference changed
if ([keyPath isEqualToString:SPDisplayTableViewVerticalGridlines]) {
[tableSourceView setGridStyleMask:([[change objectForKey:NSKeyValueChangeNewKey] boolValue]) ? NSTableViewSolidVerticalGridLineMask : NSTableViewGridNone];
}
// Use monospaced fonts preference changed
else if ([keyPath isEqualToString:SPUseMonospacedFonts]) {
-
+
BOOL useMonospacedFont = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
-
+
for (NSTableColumn *fieldColumn in [tableSourceView tableColumns])
{
[[fieldColumn dataCell] setFont:(useMonospacedFont) ? [NSFont fontWithName:SPDefaultMonospacedFontName size:[NSFont smallSystemFontSize]] : [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
}
-
+
[tableSourceView reloadData];
}
}
@@ -1018,17 +1032,17 @@ closes the keySheet
if ([menuItem action] == @selector(removeField:)) {
return (([tableSourceView numberOfSelectedRows] == 1) && ([tableSourceView numberOfRows] > 1));
}
-
+
// Duplicate field
if ([menuItem action] == @selector(copyField:)) {
return ([tableSourceView numberOfSelectedRows] == 1);
}
-
+
// Reset AUTO_INCREMENT
if ([menuItem action] == @selector(resetAutoIncrement:)) {
return [indexesController validateMenuItem:menuItem];
}
-
+
return YES;
}
@@ -1059,7 +1073,7 @@ get the default value for a specified field
- (NSString *)defaultValueForField:(NSString *)field
{
if ( ![defaultValues objectForKey:field] ) {
- return [prefs objectForKey:SPNullValue];
+ return [prefs objectForKey:SPNullValue];
} else if ( [[defaultValues objectForKey:field] isMemberOfClass:[NSNull class]] ) {
return [prefs objectForKey:SPNullValue];
} else {
@@ -1075,18 +1089,18 @@ returns an array containing the field names of the selected table
NSMutableArray *tempArray = [NSMutableArray array];
NSEnumerator *enumerator;
id field;
-
+
//load table if not already done
if ( ![tablesListInstance structureLoaded] ) {
[self loadTable:[tablesListInstance tableName]];
}
-
+
//get field names
enumerator = [tableFields objectEnumerator];
while ( (field = [enumerator nextObject]) ) {
- [tempArray addObject:[field objectForKey:@"Field"]];
+ [tempArray addObject:[field objectForKey:@"name"]];
}
-
+
return [NSArray arrayWithArray:tempArray];
}
@@ -1100,42 +1114,42 @@ returns a dictionary containing enum/set field names as key and possible values
/**
* Returns a dictionary describing the source of the table to be used for printing purposes. The object accessible
- * via the key 'structure' is an array of the tables fields, where the first element is always the field names
+ * via the key 'structure' is an array of the tables fields, where the first element is always the field names
* and each subsequent element is the field data. This is also true for the table's indexes, which are accessible
* via the key 'indexes'.
*/
- (NSDictionary *)tableSourceForPrinting
-{
+{
NSInteger i, j;
NSMutableArray *tempResult = [NSMutableArray array];
NSMutableArray *tempResult2 = [NSMutableArray array];
-
+
NSString *nullValue = [prefs stringForKey:SPNullValue];
CFStringRef escapedNullValue = CFXMLCreateStringByEscapingEntities(NULL, ((CFStringRef)nullValue), NULL);
-
+
MCPResult *structureQueryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@", [selectedTable backtickQuotedString]]];
MCPResult *indexesQueryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW INDEXES FROM %@", [selectedTable backtickQuotedString]]];
-
+
[structureQueryResult setReturnDataAsStrings:YES];
[indexesQueryResult setReturnDataAsStrings:YES];
-
+
if ([structureQueryResult numOfRows]) [structureQueryResult dataSeek:0];
if ([indexesQueryResult numOfRows]) [indexesQueryResult dataSeek:0];
-
+
[tempResult addObject:[structureQueryResult fetchFieldNames]];
-
+
NSMutableArray *temp = [[indexesQueryResult fetchFieldNames] mutableCopy];
-
+
// Remove the 'table' column
[temp removeObjectAtIndex:0];
-
+
[tempResult2 addObject:temp];
-
+
[temp release];
-
+
for (i = 0; i < [structureQueryResult numOfRows]; i++) {
NSMutableArray *row = [[structureQueryResult fetchRowAsArray] mutableCopy];
-
+
// For every NULL value replace it with the user's NULL value placeholder so we can actually print it
for (j = 0; j < [row count]; j++)
{
@@ -1143,18 +1157,18 @@ returns a dictionary containing enum/set field names as key and possible values
[row replaceObjectAtIndex:j withObject:(NSString *)escapedNullValue];
}
}
-
+
[tempResult addObject:row];
-
+
[row release];
}
for (i = 0; i < [indexesQueryResult numOfRows]; i++) {
NSMutableArray *index = [[indexesQueryResult fetchRowAsArray] mutableCopy];
-
+
// Remove the 'table' column values
[index removeObjectAtIndex:0];
-
+
// For every NULL value replace it with the user's NULL value placeholder so we can actually print it
for (j = 0; j < [index count]; j++)
{
@@ -1162,9 +1176,9 @@ returns a dictionary containing enum/set field names as key and possible values
[index replaceObjectAtIndex:j withObject:(NSString *)escapedNullValue];
}
}
-
+
[tempResult2 addObject:index];
-
+
[index release];
}
@@ -1189,7 +1203,7 @@ returns a dictionary containing enum/set field names as key and possible values
[copyFieldButton setEnabled:NO];
[reloadFieldsButton setEnabled:NO];
[editTableButton setEnabled:NO];
-
+
[indexesTableView setEnabled:NO];
[addIndexButton setEnabled:NO];
[removeIndexButton setEnabled:NO];
@@ -1205,22 +1219,22 @@ returns a dictionary containing enum/set field names as key and possible values
if (![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableStructure]) return;
BOOL editingEnabled = ([tablesListInstance tableType] == SPTableTypeTable);
-
+
[tableSourceView setEnabled:YES];
[tableSourceView displayIfNeeded];
[addFieldButton setEnabled:editingEnabled];
-
+
if (editingEnabled && [tableSourceView numberOfSelectedRows] > 0) {
[removeFieldButton setEnabled:YES];
[copyFieldButton setEnabled:YES];
}
-
+
[reloadFieldsButton setEnabled:YES];
[editTableButton setEnabled:YES];
-
+
[indexesTableView setEnabled:YES];
[indexesTableView displayIfNeeded];
-
+
[addIndexButton setEnabled:editingEnabled];
[removeIndexButton setEnabled:(editingEnabled && ([indexesTableView numberOfSelectedRows] > 0))];
[refreshIndexesButton setEnabled:YES];
@@ -1235,10 +1249,34 @@ returns a dictionary containing enum/set field names as key and possible values
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex
-{
+{
// Return a placeholder if the table is reloading
if (rowIndex >= [tableFields count]) return @"...";
+ if([[tableColumn identifier] isEqualToString:@"collation"]) {
+ if([[[tableFields objectAtIndex:rowIndex] objectForKey:@"encoding"] integerValue] > 0) {
+ NSString *enc = [[[[[tableSourceView tableColumns] objectAtIndex:10] dataCell] itemAtIndex:[[[tableFields objectAtIndex:rowIndex] objectForKey:@"encoding"] integerValue]] title];
+ NSInteger start = [enc rangeOfString:@"("].location+1;
+ NSInteger end = [enc length] - start - 1;
+ collations = [databaseDataInstance getDatabaseCollationsForEncoding:[enc substringWithRange:NSMakeRange(start, end)]];
+ } else {
+ if([tableDataInstance tableEncoding]) {
+ collations = [databaseDataInstance getDatabaseCollationsForEncoding:[tableDataInstance tableEncoding]];
+ } else {
+ collations = [NSArray array];
+ }
+ }
+
+ [[tableColumn dataCell] removeAllItems];
+
+ if ([collations count] > 0) {
+ [[tableColumn dataCell] addItemWithTitle:@""];
+ // Populate collation popup button
+ for (NSDictionary *collation in collations)
+ [[tableColumn dataCell] addItemWithTitle:[collation objectForKey:@"COLLATION_NAME"]];
+ }
+ }
+
return [[tableFields objectAtIndex:rowIndex] objectForKey:[tableColumn identifier]];
}
@@ -1252,7 +1290,7 @@ returns a dictionary containing enum/set field names as key and possible values
isEditingRow = YES;
currentlyEditingRow = rowIndex;
}
-
+
[[tableFields objectAtIndex:rowIndex] setObject:(anObject) ? anObject : @"" forKey:[aTableColumn identifier]];
}
@@ -1305,11 +1343,11 @@ would result in a position change.
// Ensure the drop is of the correct type
if (operation == NSTableViewDropAbove && row != -1 && [pboardTypes containsObject:@"SequelProPasteboard"]) {
-
+
// Ensure the drag originated within this table
if ([info draggingSource] == tableView) {
originalRow = [[[info draggingPasteboard] stringForType:@"SequelProPasteboard"] integerValue];
-
+
if (row != originalRow && row != (originalRow+1)) {
return NSDragOperationMove;
}
@@ -1339,58 +1377,55 @@ would result in a position change.
// Begin construction of the reordering query
queryString = [NSMutableString stringWithFormat:@"ALTER TABLE %@ MODIFY COLUMN %@ %@", [selectedTable backtickQuotedString],
- [[originalRow objectForKey:@"Field"] backtickQuotedString],
- [originalRow objectForKey:@"Type"]];
+ [[originalRow objectForKey:@"name"] backtickQuotedString],
+ [[originalRow objectForKey:@"type"] uppercaseString]];
// Add the length parameter if necessary
- if ( [originalRow objectForKey:@"Length"] && ![[originalRow objectForKey:@"Length"] isEqualToString:@""]) {
- [queryString appendFormat:@"(%@)", [originalRow objectForKey:@"Length"]];
+ if ( [originalRow objectForKey:@"length"] && ![[originalRow objectForKey:@"length"] isEqualToString:@""]) {
+ [queryString appendFormat:@"(%@)", [originalRow objectForKey:@"length"]];
}
// Add unsigned, zerofill, binary, not null if necessary
- if ([[originalRow objectForKey:@"unsigned"] isEqualToString:@"1"]) {
+ if ([[originalRow objectForKey:@"unsigned"] integerValue]) {
[queryString appendString:@" UNSIGNED"];
}
- if ([[originalRow objectForKey:@"zerofill"] isEqualToString:@"1"]) {
+ if ([[originalRow objectForKey:@"zerofill"] integerValue]) {
[queryString appendString:@" ZEROFILL"];
}
- if ([[originalRow objectForKey:@"binary"] isEqualToString:@"1"]) {
+ if ([[originalRow objectForKey:@"binary"] integerValue]) {
[queryString appendString:@" BINARY"];
}
- if ([[originalRow objectForKey:@"Null"] isEqualToString:@"0"] ) {
+ if (![[originalRow objectForKey:@"null"] integerValue]) {
[queryString appendString:@" NOT NULL"];
}
if (![[originalRow objectForKey:@"Extra"] isEqualToString:@"None"] ) {
[queryString appendString:@" "];
[queryString appendString:[[originalRow objectForKey:@"Extra"] uppercaseString]];
}
-
- BOOL isTimestampType = [[originalRow objectForKey:@"Type"] isEqualToString:@"timestamp"];
+
+ BOOL isTimestampType = [[[originalRow objectForKey:@"type"] lowercaseString] isEqualToString:@"timestamp"];
// Add the default value
- if ([[originalRow objectForKey:@"Default"] isEqualToString:[prefs objectForKey:SPNullValue]]) {
- if ([[originalRow objectForKey:@"Null"] integerValue] == 1) {
+ if ([[originalRow objectForKey:@"default"] isEqualToString:[prefs objectForKey:SPNullValue]]) {
+ if ([[originalRow objectForKey:@"null"] integerValue] == 1) {
[queryString appendString:(isTimestampType) ? @" NULL DEFAULT NULL" : @" DEFAULT NULL"];
}
- }
- else if (isTimestampType && ([[[originalRow objectForKey:@"Default"] uppercaseString] isEqualToString:@"CURRENT_TIMESTAMP"]) ) {
+ }
+ else if (isTimestampType && ([[[originalRow objectForKey:@"default"] uppercaseString] isEqualToString:@"CURRENT_TIMESTAMP"]) ) {
[queryString appendString:@" DEFAULT CURRENT_TIMESTAMP"];
- }
+ }
else {
- [queryString appendFormat:@" DEFAULT '%@'", [mySQLConnection prepareString:[originalRow objectForKey:@"Default"]]];
+ [queryString appendFormat:@" DEFAULT '%@'", [mySQLConnection prepareString:[originalRow objectForKey:@"default"]]];
}
- // Add details not provided via the SHOW COLUMNS query from the table data cache so column details aren't lost
- NSDictionary *originalColumnDetails = [[tableDataInstance columns] objectAtIndex:originalRowIndex];
-
// Any column comments
- if ([originalColumnDetails objectForKey:@"comment"] && [(NSString *)[originalColumnDetails objectForKey:@"comment"] length]) {
- [queryString appendFormat:@" COMMENT '%@'", [mySQLConnection prepareString:[originalColumnDetails objectForKey:@"comment"]]];
+ if ([[originalRow objectForKey:@"comment"] length]) {
+ [queryString appendFormat:@" COMMENT '%@'", [mySQLConnection prepareString:[originalRow objectForKey:@"comment"]]];
}
// Unparsed details - column formats, storage, reference definitions
- if ([originalColumnDetails objectForKey:@"unparsed"]) {
- [queryString appendString:[originalColumnDetails objectForKey:@"unparsed"]];
+ if ([originalRow objectForKey:@"unparsed"]) {
+ [queryString appendString:[originalRow objectForKey:@"unparsed"]];
}
// Add the new location
@@ -1398,12 +1433,12 @@ would result in a position change.
[queryString appendString:@" FIRST"];
} else {
[queryString appendFormat:@" AFTER %@",
- [[[tableFields objectAtIndex:destinationRowIndex-1] objectForKey:@"Field"] backtickQuotedString]];
+ [[[tableFields objectAtIndex:destinationRowIndex-1] objectForKey:@"name"] backtickQuotedString]];
}
// Run the query; report any errors, or reload the table on success
[mySQLConnection queryString:queryString];
-
+
if ([mySQLConnection queryErrored]) {
SPBeginAlertSheet(NSLocalizedString(@"Error moving field", @"error moving field message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [tableDocumentInstance parentWindow], self, nil, nil,
[NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to move the field.\n\nMySQL said: %@", @"error moving field informative message"), [mySQLConnection getLastErrorMessage]]);
@@ -1423,7 +1458,7 @@ would result in a position change.
}
[[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
-
+
[originalRow release];
return YES;
}
@@ -1437,13 +1472,13 @@ would result in a position change.
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
id object = [aNotification object];
-
+
// Check for which table view the selection changed
if (object == tableSourceView) {
-
+
// If we are editing a row, attempt to save that row - if saving failed, reselect the edit row.
if (isEditingRow && [tableSourceView selectedRow] != currentlyEditingRow && ![self saveRowOnDeselect]) return;
-
+
[copyFieldButton setEnabled:YES];
// Check if there is currently a field selected and change button state accordingly
@@ -1453,7 +1488,7 @@ would result in a position change.
[removeFieldButton setEnabled:NO];
[copyFieldButton setEnabled:NO];
}
-
+
// If the table only has one field, disable the remove button. This removes the need to check that the user
// is attempting to remove the last field in a table in removeField: above, but leave it in just in case.
if ([tableSourceView numberOfRows] == 1) {
@@ -1495,7 +1530,7 @@ would result in a position change.
}
}
return TRUE;
-
+
// Trap the enter key, triggering a save
}
else if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertNewline:)] )
@@ -1503,7 +1538,7 @@ would result in a position change.
[[control window] makeFirstResponder:control];
[self addRowToDB];
return TRUE;
-
+
// Trap escape, aborting the edit and reverting the row
}
else if ( [[control window] methodForSelector:command] == [[control window] methodForSelector:@selector(_cancelKey:)] ||
@@ -1532,7 +1567,7 @@ would result in a position change.
* is uneditable.
*/
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex {
-
+
//make sure that the message is from the right table view
if (tableView!=tableSourceView) return;
@@ -1558,7 +1593,7 @@ would result in a position change.
}
- (NSRect)splitView:(NSSplitView *)splitView additionalEffectiveRectOfDividerAtIndex:(NSInteger)dividerIndex
-{
+{
return [structureGrabber convertRect:[structureGrabber bounds] toView:splitView];
}
@@ -1569,7 +1604,7 @@ would result in a position change.
if ([tablesIndexesSplitView isSubviewCollapsed:indexesView]) {
[indexesShowButton setHidden:NO];
} else {
- [indexesShowButton setHidden:YES];
+ [indexesShowButton setHidden:YES];
}
}
}
@@ -1583,18 +1618,18 @@ would result in a position change.
#pragma mark Private API methods
/**
- * Removes a field from the current table and the dependent foreign key if specified.
+ * Removes a field from the current table and the dependent foreign key if specified.
*/
- (void)_removeFieldAndForeignKey:(NSNumber *)removeForeignKey
-{
+{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
+
// Remove the foreign key before the field if required
if ([removeForeignKey boolValue]) {
-
+
NSString *relationName = @"";
- NSString *field = [[tableFields objectAtIndex:[tableSourceView selectedRow]] objectForKey:@"Field"];
-
+ NSString *field = [[tableFields objectAtIndex:[tableSourceView selectedRow]] objectForKey:@"name"];
+
// Get the foreign key name
for (NSDictionary *constraint in [tableDataInstance getConstraints])
{
@@ -1606,42 +1641,42 @@ would result in a position change.
}
}
}
-
+
[mySQLConnection queryString:[NSString stringWithFormat:@"ALTER TABLE %@ DROP FOREIGN KEY %@", [selectedTable backtickQuotedString], [relationName backtickQuotedString]]];
-
+
// Check for errors, but only if the query wasn't cancelled
if ([mySQLConnection queryErrored] && ![mySQLConnection queryCancelled]) {
NSMutableDictionary *errorDictionary = [NSMutableDictionary dictionary];
[errorDictionary setObject:NSLocalizedString(@"Unable to delete relation", @"error deleting relation message") forKey:@"title"];
[errorDictionary setObject:[NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to delete the relation '%@'.\n\nMySQL said: %@", @"error deleting relation informative message"), relationName, [mySQLConnection getLastErrorMessage]] forKey:@"message"];
[[self onMainThread] showErrorSheetWith:errorDictionary];
- }
+ }
}
-
+
// Remove field
[mySQLConnection queryString:[NSString stringWithFormat:@"ALTER TABLE %@ DROP %@",
- [selectedTable backtickQuotedString], [[[tableFields objectAtIndex:[tableSourceView selectedRow]] objectForKey:@"Field"] backtickQuotedString]]];
-
+ [selectedTable backtickQuotedString], [[[tableFields objectAtIndex:[tableSourceView selectedRow]] objectForKey:@"name"] backtickQuotedString]]];
+
// Check for errors, but only if the query wasn't cancelled
if ([mySQLConnection queryErrored] && ![mySQLConnection queryCancelled]) {
NSMutableDictionary *errorDictionary = [NSMutableDictionary dictionary];
[errorDictionary setObject:NSLocalizedString(@"Error", @"error") forKey:@"title"];
[errorDictionary setObject:[NSString stringWithFormat:NSLocalizedString(@"Couldn't delete field %@.\nMySQL said: %@", @"message of panel when field cannot be deleted"),
- [[tableFields objectAtIndex:[tableSourceView selectedRow]] objectForKey:@"Field"],
+ [[tableFields objectAtIndex:[tableSourceView selectedRow]] objectForKey:@"name"],
[mySQLConnection getLastErrorMessage]] forKey:@"message"];
[[self onMainThread] showErrorSheetWith:errorDictionary];
- }
+ }
else {
[tableDataInstance resetAllData];
[tablesListInstance setStatusRequiresReload:YES];
[self loadTable:selectedTable];
-
+
// Mark the content table cache for refresh
[tablesListInstance setContentRequiresReload:YES];
}
-
+
[tableDocumentInstance endTask];
-
+
[pool drain];
}
@@ -1651,16 +1686,16 @@ would result in a position change.
* Dealloc.
*/
- (void)dealloc
-{
+{
[[NSNotificationCenter defaultCenter] removeObserver:self];
-
+
[tableFields release];
[oldRow release];
[enumFields release];
-
+
if (defaultValues) [defaultValues release];
if (selectedTable) [selectedTable release];
-
+
[super dealloc];
}