From b414bddc98508b09d37ece8f4394194f3a0234b8 Mon Sep 17 00:00:00 2001 From: stuconnolly Date: Wed, 4 Jul 2012 09:41:57 +0000 Subject: Move the table structure's loading logic into it's own category. --- Source/SPIndexesController.m | 4 +- Source/SPTableStructure.h | 5 - Source/SPTableStructure.m | 308 +-------------------------------- Source/SPTableStructureDelegate.m | 2 + Source/SPTableStructureLoading.h | 46 +++++ Source/SPTableStructureLoading.m | 354 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 407 insertions(+), 312 deletions(-) create mode 100644 Source/SPTableStructureLoading.h create mode 100644 Source/SPTableStructureLoading.m (limited to 'Source') diff --git a/Source/SPIndexesController.m b/Source/SPIndexesController.m index 840ef33f..d7617d39 100644 --- a/Source/SPIndexesController.m +++ b/Source/SPIndexesController.m @@ -28,12 +28,14 @@ #import "SPServerSupport.h" #import "SPTableContent.h" #import "SPTableData.h" -#import #import "SPDatabaseDocument.h" #import "SPTablesList.h" #import "SPTableView.h" #import "SPDatabaseViewController.h" #import "SPTableStructure.h" +#import "SPTableStructureLoading.h" + +#import // Constants static const NSString *SPNewIndexIndexName = @"IndexName"; diff --git a/Source/SPTableStructure.h b/Source/SPTableStructure.h index a97f70b2..881cdd09 100644 --- a/Source/SPTableStructure.h +++ b/Source/SPTableStructure.h @@ -96,11 +96,6 @@ @property (assign) id reloadFieldsButton; #endif -// Table loading -- (void)loadTable:(NSString *)aTable; -- (IBAction)reloadTable:(id)sender; -- (void)setTableDetails:(NSDictionary *)tableDetails; - #ifdef SP_REFACTOR /* method decls */ - (void)setDatabaseDocument:(SPDatabaseDocument*)doc; - (void)setTableListInstance:(SPTablesList*)list; diff --git a/Source/SPTableStructure.m b/Source/SPTableStructure.m index ba8c5eb9..671f7202 100644 --- a/Source/SPTableStructure.m +++ b/Source/SPTableStructure.m @@ -36,6 +36,8 @@ #import "SPIndexesController.h" #import "RegexKitLite.h" #import "SPTableFieldValidation.h" +#import "SPTableStructureLoading.h" + #import @interface SPTableStructure (PrivateAPI) @@ -223,312 +225,6 @@ [tableSourceView reloadData]; } -#pragma mark - -#pragma mark Table loading - -/** - * Loads aTable, put it in an array, update the tableViewColumns and reload the tableView - */ -- (void)loadTable:(NSString *)aTable -{ - NSMutableDictionary *theTableEnumLists = [NSMutableDictionary dictionary]; - - // Check whether a save of the current row is required. - if (![[self onMainThread] saveRowOnDeselect]) return; - - // If no table is selected, reset the interface and return - if (!aTable || ![aTable length]) { - [[self onMainThread] setTableDetails:nil]; - return; - } - - NSMutableArray *theTableFields = [[NSMutableArray alloc] init]; - - // 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] autorelease]]; - } - - // Retrieve the indexes for the table - SPMySQLResult *indexResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW INDEX FROM %@", [aTable backtickQuotedString]]]; - - // 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 lastErrorMessage]]); - } - - return; - } - - // Process the indexes into a local array of dictionaries - NSArray *theTableIndexes = [self convertIndexResultToArray:indexResult]; - - // 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 { - if ([[field objectForKey:@"typegrouping"] isEqualToString:@"geometry"]) { - [field setObject:@"SPA" forKey:@"Key"]; - } - else { - [field setObject:(([[theIndex objectForKey:@"Non_unique"] isEqualToString:@"1"]) ? @"MUL" : @"UNI") forKey:@"Key"]; - } - } - - break; - } - } - } - - // Set up the encoding PopUpButtonCell - NSArray *encodings = [databaseDataInstance getDatabaseCharacterSetEncodings]; - - if ([encodings count]) { - - // Populate encoding popup button - NSMutableArray *encodingTitles = [[NSMutableArray alloc] initWithCapacity:[encodings count]+1]; - - [encodingTitles addObject:@""]; - - for (NSDictionary *encoding in encodings) - { - [encodingTitles addObject:(![encoding objectForKey:@"DESCRIPTION"]) ? [encoding objectForKey:@"CHARACTER_SET_NAME"] : [NSString stringWithFormat:@"%@ (%@)", [encoding objectForKey:@"DESCRIPTION"], [encoding objectForKey:@"CHARACTER_SET_NAME"]]]; - } - - [[encodingPopupCell onMainThread] removeAllItems]; - [[encodingPopupCell onMainThread] addItemsWithTitles:encodingTitles]; - [encodingTitles release]; - } - else { - [[encodingPopupCell onMainThread] removeAllItems]; - [[encodingPopupCell onMainThread] addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")]; - } - - // Process all the fields to normalise keys and add additional information - for (id theField in theTableFields) - { - // Select and re-map encoding and collation since [self dataSource] stores the choice as NSNumbers - NSString *fieldEncoding = @""; - NSInteger selectedIndex = 0; - - NSString *type = [[[theField objectForKey:@"type"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; - - NSString *collation = nil; - NSString *encoding = nil; - - if ([fieldValidation isFieldTypeString:type] || ![type hasSuffix:@"BINARY"] || ![type hasSuffix:@"BLOB"]) { - - collation = [theField objectForKey:@"collation"] ? [theField objectForKey:@"collation"] : [[tableDataInstance statusValues] objectForKey:@"collation"]; - encoding = [theField objectForKey:@"encoding"] ? [theField objectForKey:@"encoding"] : [tableDataInstance tableEncoding]; - - // If we still don't have a collation then fallback on the database default (not available on MySQL < 4.1.1). - if (!collation) { - collation = [databaseDataInstance getDatabaseDefaultCollation]; - } - } - - if (encoding) { - for (id enc in encodings) - { - if ([[enc objectForKey:@"CHARACTER_SET_NAME"] isEqualToString:encoding]) { - fieldEncoding = encoding; - break; - } - - selectedIndex++; - } - - // Due to leading @"" in popup list - selectedIndex++; - } - - [theField setObject:[NSNumber numberWithInteger:selectedIndex] forKey:@"encoding"]; - - selectedIndex = 0; - - if (encoding && collation) { - - NSArray *theCollations = [databaseDataInstance getDatabaseCollationsForEncoding:fieldEncoding]; - - for (id col in theCollations) - { - if ([[col objectForKey:@"COLLATION_NAME"] isEqualToString:collation]) { - - // Set BINARY if collation ends with _bin for convenience - if ([[col objectForKey:@"COLLATION_NAME"] hasSuffix:@"_bin"]) { - [theField setObject:[NSNumber numberWithInt:1] forKey:@"binary"]; - } - - break; - } - - selectedIndex++; - } - - // Due to leading @"" in popup list - selectedIndex++; - } - - [theField setObject:[NSNumber numberWithInteger:selectedIndex] forKey:@"collation"]; - - // 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"]; - } - - // 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"] isNSNull]) - [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 - NSDictionary *tableDetails = [NSDictionary dictionaryWithObjectsAndKeys: - aTable, @"name", - theTableFields, @"tableFields", - theTableIndexes, @"tableIndexes", - theTableEnumLists, @"enumLists", - nil]; - - [[self onMainThread] setTableDetails:tableDetails]; - - isCurrentExtraAutoIncrement = [tableDataInstance tableHasAutoIncrementField]; - autoIncrementIndex = nil; - - // Send the query finished/work complete notification - [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance]; - - [theTableFields release]; -} - -/** - * Reloads the table (performing a new mysql-query) - */ -- (IBAction)reloadTable:(id)sender -{ - - // Check whether a save of the current row is required - if ( ![[self onMainThread] saveRowOnDeselect] ) return; - - [tableDataInstance resetAllData]; - [tableDocumentInstance setStatusRequiresReload:YES]; - - // Query the structure of all databases in the background (mainly for completion) - [NSThread detachNewThreadSelector:@selector(queryDbStructureWithUserInfo:) toTarget:[tableDocumentInstance databaseStructureRetrieval] withObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], @"forceUpdate", nil]]; - - [self loadTable:selectedTable]; -} - -/** - * Update stored table details and update the interface to match the supplied - * table details. - * Should be called on the main thread. - */ -- (void) setTableDetails:(NSDictionary *)tableDetails -{ - NSString *newTableName = [tableDetails objectForKey:@"name"]; - NSMutableDictionary *newDefaultValues; - - BOOL enableInteraction = -#ifndef SP_REFACTOR /* patch */ - ![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableStructure] || -#endif - ![tableDocumentInstance isWorking]; - - // 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 - [tableSourceView deselectAll:self]; - [tableFields removeAllObjects]; - [enumFields removeAllObjects]; - [indexesTableView deselectAll:self]; - [addFieldButton setEnabled:NO]; - [duplicateFieldButton setEnabled:NO]; - [removeFieldButton setEnabled:NO]; -#ifndef SP_REFACTOR - [addIndexButton setEnabled:NO]; - [removeIndexButton setEnabled:NO]; - [editTableButton setEnabled:NO]; -#endif - - // If no table is selected, refresh the table/index display to blank and return - if (!selectedTable) { - [tableSourceView reloadData]; - // Empty indexesController's fields and indices explicitly before reloading - [indexesController setFields:[NSArray array]]; - [indexesController setIndexes:[NSArray array]]; - [indexesTableView reloadData]; - return; - } - - // 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:@"name"]]; - - defaultValues = [[NSDictionary dictionaryWithDictionary:newDefaultValues] retain]; - -#ifndef SP_REFACTOR - // Enable the edit table button - [editTableButton setEnabled:enableInteraction]; -#endif - - // If a view is selected, disable the buttons; otherwise enable. - BOOL editingEnabled = ([tablesListInstance tableType] == SPTableTypeTable) && enableInteraction; - - [addFieldButton setEnabled:editingEnabled]; -#ifndef SP_REFACTOR - [addIndexButton setEnabled:editingEnabled]; -#endif - - // Reload the views - [indexesTableView reloadData]; - [tableSourceView reloadData]; -} - #pragma mark - #pragma mark Edit methods diff --git a/Source/SPTableStructureDelegate.m b/Source/SPTableStructureDelegate.m index 4ca02803..084fb4d0 100644 --- a/Source/SPTableStructureDelegate.m +++ b/Source/SPTableStructureDelegate.m @@ -30,6 +30,8 @@ #import "SPTableData.h" #import "SPTableView.h" #import "SPTableFieldValidation.h" +#import "SPTableStructureLoading.h" + #import @implementation SPTableStructure (SPTableStructureDelegate) diff --git a/Source/SPTableStructureLoading.h b/Source/SPTableStructureLoading.h new file mode 100644 index 00000000..8db66680 --- /dev/null +++ b/Source/SPTableStructureLoading.h @@ -0,0 +1,46 @@ +// +// $Id$ +// +// SPTableStructureLoading.h +// Sequel Pro +// +// Created by Stuart Connolly (stuconnolly.com) on July 4, 2012 +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#import "SPTableStructure.h" + +/** + * @category SPTableStructureLoading SPTableStructureLoading.h + * + * @author Stuart Connolly http://stuconnolly.com/ + * + * Contains all functionality related to loading a table's structure. + */ +@interface SPTableStructure (SPTableStructureLoading) + +- (void)loadTable:(NSString *)aTable; +- (IBAction)reloadTable:(id)sender; +- (void)setTableDetails:(NSDictionary *)tableDetails; + +@end diff --git a/Source/SPTableStructureLoading.m b/Source/SPTableStructureLoading.m new file mode 100644 index 00000000..40b731a5 --- /dev/null +++ b/Source/SPTableStructureLoading.m @@ -0,0 +1,354 @@ +// +// $Id$ +// +// SPTableStructureLoading.m +// Sequel Pro +// +// Created by Stuart Connolly (stuconnolly.com) on July 4, 2012 +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#import "SPTableStructureLoading.h" +#import "SPTableData.h" +#import "SPAlertSheets.h" +#import "SPDatabaseData.h" +#import "SPTableFieldValidation.h" +#import "SPDatabaseViewController.h" +#import "SPIndexesController.h" +#import "SPTablesList.h" + +#import + +@implementation SPTableStructure (SPTableStructureLoading) + +#pragma mark - +#pragma mark Table loading + +/** + * Loads aTable, puts it in an array, updates the tableViewColumns and reloads the tableView. + */ +- (void)loadTable:(NSString *)aTable +{ + NSMutableDictionary *theTableEnumLists = [NSMutableDictionary dictionary]; + + // Check whether a save of the current row is required. + if (![[self onMainThread] saveRowOnDeselect]) return; + + // If no table is selected, reset the interface and return + if (!aTable || ![aTable length]) { + [[self onMainThread] setTableDetails:nil]; + return; + } + + NSMutableArray *theTableFields = [[NSMutableArray alloc] init]; + + // 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] autorelease]]; + } + + // Retrieve the indexes for the table + SPMySQLResult *indexResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW INDEX FROM %@", [aTable backtickQuotedString]]]; + + // 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 lastErrorMessage]]); + } + + return; + } + + // Process the indexes into a local array of dictionaries + NSArray *theTableIndexes = [self convertIndexResultToArray:indexResult]; + + // 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 { + if ([[field objectForKey:@"typegrouping"] isEqualToString:@"geometry"]) { + [field setObject:@"SPA" forKey:@"Key"]; + } + else { + [field setObject:(([[theIndex objectForKey:@"Non_unique"] isEqualToString:@"1"]) ? @"MUL" : @"UNI") forKey:@"Key"]; + } + } + + break; + } + } + } + + // Set up the encoding PopUpButtonCell + NSArray *encodings = [databaseDataInstance getDatabaseCharacterSetEncodings]; + + if ([encodings count]) { + + // Populate encoding popup button + NSMutableArray *encodingTitles = [[NSMutableArray alloc] initWithCapacity:[encodings count]+1]; + + [encodingTitles addObject:@""]; + + for (NSDictionary *encoding in encodings) + { + [encodingTitles addObject:(![encoding objectForKey:@"DESCRIPTION"]) ? [encoding objectForKey:@"CHARACTER_SET_NAME"] : [NSString stringWithFormat:@"%@ (%@)", [encoding objectForKey:@"DESCRIPTION"], [encoding objectForKey:@"CHARACTER_SET_NAME"]]]; + } + + [[encodingPopupCell onMainThread] removeAllItems]; + [[encodingPopupCell onMainThread] addItemsWithTitles:encodingTitles]; + [encodingTitles release]; + } + else { + [[encodingPopupCell onMainThread] removeAllItems]; + [[encodingPopupCell onMainThread] addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")]; + } + + // Process all the fields to normalise keys and add additional information + for (id theField in theTableFields) + { + // Select and re-map encoding and collation since [self dataSource] stores the choice as NSNumbers + NSString *fieldEncoding = @""; + NSInteger selectedIndex = 0; + + NSString *type = [[[theField objectForKey:@"type"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; + + NSString *collation = nil; + NSString *encoding = nil; + + if ([fieldValidation isFieldTypeString:type] || ![type hasSuffix:@"BINARY"] || ![type hasSuffix:@"BLOB"]) { + + collation = [theField objectForKey:@"collation"] ? [theField objectForKey:@"collation"] : [[tableDataInstance statusValues] objectForKey:@"collation"]; + encoding = [theField objectForKey:@"encoding"] ? [theField objectForKey:@"encoding"] : [tableDataInstance tableEncoding]; + + // If we still don't have a collation then fallback on the database default (not available on MySQL < 4.1.1). + if (!collation) { + collation = [databaseDataInstance getDatabaseDefaultCollation]; + } + } + + if (encoding) { + for (id enc in encodings) + { + if ([[enc objectForKey:@"CHARACTER_SET_NAME"] isEqualToString:encoding]) { + fieldEncoding = encoding; + break; + } + + selectedIndex++; + } + + // Due to leading @"" in popup list + selectedIndex++; + } + + [theField setObject:[NSNumber numberWithInteger:selectedIndex] forKey:@"encoding"]; + + selectedIndex = 0; + + if (encoding && collation) { + + NSArray *theCollations = [databaseDataInstance getDatabaseCollationsForEncoding:fieldEncoding]; + + for (id col in theCollations) + { + if ([[col objectForKey:@"COLLATION_NAME"] isEqualToString:collation]) { + + // Set BINARY if collation ends with _bin for convenience + if ([[col objectForKey:@"COLLATION_NAME"] hasSuffix:@"_bin"]) { + [theField setObject:[NSNumber numberWithInt:1] forKey:@"binary"]; + } + + break; + } + + selectedIndex++; + } + + // Due to leading @"" in popup list + selectedIndex++; + } + + [theField setObject:[NSNumber numberWithInteger:selectedIndex] forKey:@"collation"]; + + // 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"]; + } + + // 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"] isNSNull]) + [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 + NSDictionary *tableDetails = [NSDictionary dictionaryWithObjectsAndKeys: + aTable, @"name", + theTableFields, @"tableFields", + theTableIndexes, @"tableIndexes", + theTableEnumLists, @"enumLists", + nil]; + + [[self onMainThread] setTableDetails:tableDetails]; + + isCurrentExtraAutoIncrement = [tableDataInstance tableHasAutoIncrementField]; + autoIncrementIndex = nil; + + // Send the query finished/work complete notification + [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance]; + + [theTableFields release]; +} + +/** + * Reloads the table (performing a new query). + */ +- (IBAction)reloadTable:(id)sender +{ + // Check whether a save of the current row is required + if (![[self onMainThread] saveRowOnDeselect]) return; + + [tableDataInstance resetAllData]; + [tableDocumentInstance setStatusRequiresReload:YES]; + + // Query the structure of all databases in the background (mainly for completion) + [NSThread detachNewThreadSelector:@selector(queryDbStructureWithUserInfo:) + toTarget:[tableDocumentInstance databaseStructureRetrieval] + withObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], @"forceUpdate", nil]]; + + [self loadTable:selectedTable]; +} + +/** + * Updates the stored table details and updates the interface to match. + * + * Should be called on the main thread. + */ +- (void) setTableDetails:(NSDictionary *)tableDetails +{ + NSString *newTableName = [tableDetails objectForKey:@"name"]; + NSMutableDictionary *newDefaultValues; + + BOOL enableInteraction = +#ifndef SP_REFACTOR /* patch */ + ![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableStructure] || +#endif + ![tableDocumentInstance isWorking]; + + // 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 + [tableSourceView deselectAll:self]; + [tableFields removeAllObjects]; + [enumFields removeAllObjects]; + [indexesTableView deselectAll:self]; + [addFieldButton setEnabled:NO]; + [duplicateFieldButton setEnabled:NO]; + [removeFieldButton setEnabled:NO]; +#ifndef SP_REFACTOR + [addIndexButton setEnabled:NO]; + [removeIndexButton setEnabled:NO]; + [editTableButton setEnabled:NO]; +#endif + + // If no table is selected, refresh the table/index display to blank and return + if (!selectedTable) { + [tableSourceView reloadData]; + // Empty indexesController's fields and indices explicitly before reloading + [indexesController setFields:[NSArray array]]; + [indexesController setIndexes:[NSArray array]]; + [indexesTableView reloadData]; + + return; + } + + // 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:@"name"]]; + } + + defaultValues = [[NSDictionary dictionaryWithDictionary:newDefaultValues] retain]; + +#ifndef SP_REFACTOR + // Enable the edit table button + [editTableButton setEnabled:enableInteraction]; +#endif + + // If a view is selected, disable the buttons; otherwise enable. + BOOL editingEnabled = ([tablesListInstance tableType] == SPTableTypeTable) && enableInteraction; + + [addFieldButton setEnabled:editingEnabled]; +#ifndef SP_REFACTOR + [addIndexButton setEnabled:editingEnabled]; +#endif + + // Reload the views + [indexesTableView reloadData]; + [tableSourceView reloadData]; +} + +@end -- cgit v1.2.3