aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2012-03-22 01:18:18 +0000
committerrowanbeentje <rowan@beent.je>2012-03-22 01:18:18 +0000
commit24f89a873caf37947f0447ff870ca4c8d55c453e (patch)
tree22162a0e1eead7190e316c384ff8c6c1b98661b3
parent3916b4227d1e02942504e13a2d36b3e6f57670bb (diff)
downloadsequelpro-24f89a873caf37947f0447ff870ca4c8d55c453e.tar.gz
sequelpro-24f89a873caf37947f0447ff870ca4c8d55c453e.tar.bz2
sequelpro-24f89a873caf37947f0447ff870ca4c8d55c453e.zip
- Rework SPTableData PRIMARY KEY and UNIQUE KEY parsing to use SPSQLParser instead of regexes
- Support multiple primary keys in the SPTableData parse - If possible, use primary keys to preserve table content selection instead of row indexes - Improve SPTableData primary keys method to use cached value instead of using another query - Preserve selection when filtering tables if appropriate
-rw-r--r--Source/SPConstants.h2
-rw-r--r--Source/SPConstants.m2
-rw-r--r--Source/SPDatabaseDocument.m23
-rw-r--r--Source/SPHistoryController.m12
-rw-r--r--Source/SPIndexesController.m17
-rw-r--r--Source/SPTableContent.h6
-rw-r--r--Source/SPTableContent.m160
-rw-r--r--Source/SPTableData.h1
-rw-r--r--Source/SPTableData.m99
9 files changed, 199 insertions, 123 deletions
diff --git a/Source/SPConstants.h b/Source/SPConstants.h
index 4b2d87a3..ce53ceb3 100644
--- a/Source/SPConstants.h
+++ b/Source/SPConstants.h
@@ -400,6 +400,8 @@ extern NSString *SPLastImportIntoNewTableType;
extern NSString *SPGlobalValueHistory;
extern NSString *SPBundleDeletedDefaultBundlesKey;
extern NSString *SPHiddenKeyFileVisibilityKey;
+extern NSString *SPSelectionDetailTypeIndexed;
+extern NSString *SPSelectionDetailTypePrimaryKeyed;
// URLs
extern NSString *SPDonationsURL;
diff --git a/Source/SPConstants.m b/Source/SPConstants.m
index 7fa35505..ae9845fa 100644
--- a/Source/SPConstants.m
+++ b/Source/SPConstants.m
@@ -211,6 +211,8 @@ NSString *SPLastImportIntoNewTableType = @"LastImportIntoNewTableType"
NSString *SPGlobalValueHistory = @"GlobalValueHistory";
NSString *SPBundleDeletedDefaultBundlesKey = @"deletedDefaultBundles";
NSString *SPHiddenKeyFileVisibilityKey = @"KeySelectionHiddenFilesVisibility";
+NSString *SPSelectionDetailTypeIndexed = @"SelectionDetailTypeNSIndexSet";
+NSString *SPSelectionDetailTypePrimaryKeyed = @"SelectionDetailTypePrimaryKeyedDetails";
// URLs
NSString *SPDonationsURL = @"http://www.sequelpro.com/donate/";
diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m
index 7fd93c1b..529b05f5 100644
--- a/Source/SPDatabaseDocument.m
+++ b/Source/SPDatabaseDocument.m
@@ -4297,16 +4297,9 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax";
if ([tableContentInstance filterSettings])
[sessionState setObject:[tableContentInstance filterSettings] forKey:@"contentFilter"];
- NSIndexSet *contentSelectedIndexSet = [tableContentInstance selectedRowIndexes];
- if (contentSelectedIndexSet && [contentSelectedIndexSet count]) {
- NSMutableArray *indices = [NSMutableArray array];
- NSUInteger indexBuffer[[contentSelectedIndexSet count]];
- NSUInteger limit = [contentSelectedIndexSet getIndexes:indexBuffer maxCount:[contentSelectedIndexSet count] inIndexRange:NULL];
- NSUInteger idx;
- for (idx = 0; idx < limit; idx++) {
- [indices addObject:[NSNumber numberWithInteger:indexBuffer[idx]]];
- }
- [sessionState setObject:indices forKey:@"contentSelectedIndexSet"];
+ NSDictionary *contentSelectedRows = [tableContentInstance selectionDetailsAllowingIndexSelection:YES];
+ if (contentSelectedRows) {
+ [sessionState setObject:contentSelectedRows forKey:@"contentSelection"];
}
}
@@ -4734,14 +4727,8 @@ static NSString *SPCreateSyntx = @"SPCreateSyntax";
[tablesListInstance selectTableAtIndex:[NSNumber numberWithInteger:[tables indexOfObject:[spfSession objectForKey:@"table"]]]];
// Restore table selection indexes
- if([spfSession objectForKey:@"contentSelectedIndexSet"]) {
- NSMutableIndexSet *anIndexSet = [NSMutableIndexSet indexSet];
- NSArray *items = [spfSession objectForKey:@"contentSelectedIndexSet"];
- NSUInteger i;
- for(i=0; i<[items count]; i++)
- [anIndexSet addIndex:[NSArrayObjectAtIndex(items, i) integerValue]];
-
- [tableContentInstance setSelectedRowIndexesToRestore:anIndexSet];
+ if([spfSession objectForKey:@"contentSelection"]) {
+ [tableContentInstance setSelectionToRestore:[spfSession objectForKey:@"contentSelection"]];
}
[[tablesListInstance valueForKeyPath:@"tablesListView"] scrollRowToVisible:[tables indexOfObject:[spfSession objectForKey:@"selectedTable"]]];
diff --git a/Source/SPHistoryController.m b/Source/SPHistoryController.m
index 3bd3b0b3..2729397c 100644
--- a/Source/SPHistoryController.m
+++ b/Source/SPHistoryController.m
@@ -267,7 +267,7 @@
NSString *contentSortCol = [tableContentInstance sortColumnName];
BOOL contentSortColIsAsc = [tableContentInstance sortColumnIsAscending];
NSUInteger contentPageNumber = [tableContentInstance pageNumber];
- NSIndexSet *contentSelectedIndexSet = [tableContentInstance selectedRowIndexes];
+ NSDictionary *contentSelectedRows = [tableContentInstance selectionDetailsAllowingIndexSelection:YES];
NSRect contentViewport = [tableContentInstance viewport];
NSDictionary *contentFilter = [tableContentInstance filterSettings];
NSData *filterTableData = [tableContentInstance filterTableData];
@@ -283,7 +283,7 @@
[NSNumber numberWithBool:contentSortColIsAsc], @"sortIsAsc",
nil];
if (contentSortCol) [contentState setObject:contentSortCol forKey:@"sortCol"];
- if (contentSelectedIndexSet) [contentState setObject:contentSelectedIndexSet forKey:@"selection"];
+ if (contentSelectedRows) [contentState setObject:contentSelectedRows forKey:@"selection"];
if (contentFilter) [contentState setObject:contentFilter forKey:@"filter"];
if (filterTableData) [contentState setObject:filterTableData forKey:@"filterTable"];
@@ -322,7 +322,7 @@
|| ![[currentHistoryEntry objectForKey:@"contentFilter"] isEqualToDictionary:contentFilter])))
{
[currentHistoryEntry setObject:[NSValue valueWithRect:contentViewport] forKey:@"contentViewport"];
- if (contentSelectedIndexSet) [currentHistoryEntry setObject:contentSelectedIndexSet forKey:@"contentSelectedIndexSet"];
+ if (contentSelectedRows) [currentHistoryEntry setObject:contentSelectedRows forKey:@"contentSelection"];
// Special case: if the last history item is currently active, and has no table,
// but the new selection does - delete the last entry, in order to replace it.
@@ -344,7 +344,7 @@
[NSValue valueWithRect:contentViewport], @"contentViewport",
nil];
if (contentSortCol) [newEntry setObject:contentSortCol forKey:@"contentSortCol"];
- if (contentSelectedIndexSet) [newEntry setObject:contentSelectedIndexSet forKey:@"contentSelectedIndexSet"];
+ if (contentSelectedRows) [newEntry setObject:contentSelectedRows forKey:@"contentSelection"];
if (contentFilter) [newEntry setObject:contentFilter forKey:@"contentFilter"];
[history addObject:newEntry];
@@ -397,7 +397,7 @@
// Set table content details for restore
[tableContentInstance setSortColumnNameToRestore:[historyEntry objectForKey:@"contentSortCol"] isAscending:[[historyEntry objectForKey:@"contentSortColIsAsc"] boolValue]];
[tableContentInstance setPageToRestore:[[historyEntry objectForKey:@"contentPageNumber"] integerValue]];
- [tableContentInstance setSelectedRowIndexesToRestore:[historyEntry objectForKey:@"contentSelectedIndexSet"]];
+ [tableContentInstance setSelectionToRestore:[historyEntry objectForKey:@"contentSelection"]];
[tableContentInstance setViewportToRestore:[[historyEntry objectForKey:@"contentViewport"] rectValue]];
[tableContentInstance setFiltersToRestore:[historyEntry objectForKey:@"contentFilter"]];
@@ -514,7 +514,7 @@
// Restore the content view state
[tableContentInstance setSortColumnNameToRestore:[contentState objectForKey:@"sortCol"] isAscending:[[contentState objectForKey:@"sortIsAsc"] boolValue]];
[tableContentInstance setPageToRestore:[[contentState objectForKey:@"page"] unsignedIntegerValue]];
- [tableContentInstance setSelectedRowIndexesToRestore:[contentState objectForKey:@"selection"]];
+ [tableContentInstance setSelectionToRestore:[contentState objectForKey:@"selection"]];
[tableContentInstance setViewportToRestore:[[contentState objectForKey:@"viewport"] rectValue]];
[tableContentInstance setFiltersToRestore:[contentState objectForKey:@"filter"]];
}
diff --git a/Source/SPIndexesController.m b/Source/SPIndexesController.m
index 99d359f7..f4f03d28 100644
--- a/Source/SPIndexesController.m
+++ b/Source/SPIndexesController.m
@@ -187,22 +187,7 @@ static const NSString *SPNewIndexKeyBlockSize = @"IndexKeyBlockSize";
// Check to see whether a primary key already exists for the table, and if so select INDEX instead
for (NSDictionary *field in fields)
{
- BOOL hasCompositePrimaryKey = NO;
- BOOL isPrimaryKey = [[field objectForKey:@"isprimarykey"] boolValue];
-
- // The 'isprimarykey' key of a field is only present for single column primary keys, not composite keys,
- // so we need to check the indexes manually.
- if (!isPrimaryKey) {
- for (NSDictionary *index in indexes)
- {
- if ([[index objectForKey:@"Key_name"] isEqualToString:@"PRIMARY"]) {
- hasCompositePrimaryKey = YES;
- break;
- }
- }
- }
-
- if (isPrimaryKey || hasCompositePrimaryKey) {
+ if ([[field objectForKey:@"isprimarykey"] boolValue]) {
// Hide primary key option
[[[indexTypePopUpButton menu] itemWithTag:SPPrimaryKeyMenuTag] setHidden:YES];
diff --git a/Source/SPTableContent.h b/Source/SPTableContent.h
index d8feee7e..7e77c749 100644
--- a/Source/SPTableContent.h
+++ b/Source/SPTableContent.h
@@ -143,7 +143,7 @@
BOOL tableRowsSelectable;
NSString *sortColumnToRestore;
NSUInteger pageToRestore;
- NSIndexSet *selectionIndexToRestore;
+ NSDictionary *selectionToRestore;
NSRect selectionViewportToRestore;
NSString *filterFieldToRestore, *filterComparisonToRestore, *filterValueToRestore, *firstBetweenValueToRestore, *secondBetweenValueToRestore;
@@ -272,14 +272,14 @@
- (NSString *)sortColumnName;
- (BOOL)sortColumnIsAscending;
- (NSUInteger)pageNumber;
-- (NSIndexSet *)selectedRowIndexes;
+- (NSDictionary *)selectionDetailsAllowingIndexSelection:(BOOL)allowIndexFallback;
- (NSRect)viewport;
- (CGFloat)tablesListWidth;
- (NSDictionary *)filterSettings;
- (NSArray *)dataColumnDefinitions;
- (void)setSortColumnNameToRestore:(NSString *)theSortColumnName isAscending:(BOOL)isAscending;
- (void)setPageToRestore:(NSUInteger)thePage;
-- (void)setSelectedRowIndexesToRestore:(NSIndexSet *)theIndexSet;
+- (void)setSelectionToRestore:(NSDictionary *)theSelection;
- (void)setViewportToRestore:(NSRect)theViewport;
- (void)setFiltersToRestore:(NSDictionary *)filterSettings;
- (void)storeCurrentDetailsForRestoration;
diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m
index 3e81c2ad..948c4eb3 100644
--- a/Source/SPTableContent.m
+++ b/Source/SPTableContent.m
@@ -129,7 +129,7 @@
sortColumnToRestore = nil;
sortColumnToRestoreIsAsc = YES;
pageToRestore = 1;
- selectionIndexToRestore = nil;
+ selectionToRestore = nil;
selectionViewportToRestore = NSZeroRect;
filterFieldToRestore = nil;
filterComparisonToRestore = nil;
@@ -303,14 +303,6 @@
[(SPCopyTable*)[tableContentView onMainThread] scrollRectToVisible:selectionViewportToRestore];
}
- // Restore selection indexes if appropriate
- if (selectionIndexToRestore) {
- BOOL previousTableRowsSelectable = tableRowsSelectable;
- tableRowsSelectable = YES;
- [[tableContentView onMainThread] selectRowIndexes:selectionIndexToRestore byExtendingSelection:NO];
- tableRowsSelectable = previousTableRowsSelectable;
- }
-
// Update display if necessary
if (!NSEqualRects(selectionViewportToRestore, NSZeroRect))
[[tableContentView onMainThread] setNeedsDisplayInRect:selectionViewportToRestore];
@@ -854,6 +846,65 @@
// End cancellation ability
[tableDocumentInstance disableTaskCancellation];
+ // Restore selection indexes if appropriate
+ if (selectionToRestore) {
+ BOOL previousTableRowsSelectable = tableRowsSelectable;
+ tableRowsSelectable = YES;
+ NSMutableIndexSet *selectionSet = [NSMutableIndexSet indexSet];
+
+ // Currently two types of stored selection are supported: primary keys and direct index sets.
+ if ([[selectionToRestore objectForKey:@"type"] isEqualToString:SPSelectionDetailTypePrimaryKeyed]) {
+
+ // Check whether the keys are still present and get their positions
+ BOOL columnsFound = YES;
+ NSArray *primaryKeyFieldNames = [selectionToRestore objectForKey:@"keys"];
+ NSUInteger primaryKeyFieldCount = [primaryKeyFieldNames count];
+ NSUInteger primaryKeyFieldIndexes[primaryKeyFieldCount];
+ for (NSUInteger i = 0; i < primaryKeyFieldCount; i++) {
+ primaryKeyFieldIndexes[i] = [[tableDataInstance columnNames] indexOfObject:[primaryKeyFieldNames objectAtIndex:i]];
+ if (primaryKeyFieldIndexes[i] == NSNotFound) {
+ columnsFound = NO;
+ }
+ }
+
+ // Only proceed with reselection if all columns were found
+ if (columnsFound) {
+ NSDictionary *selectionKeysToRestore = [selectionToRestore objectForKey:@"rows"];
+ NSUInteger rowsToSelect = [selectionKeysToRestore count];
+ BOOL rowMatches = NO;
+
+ for (NSUInteger i = 0; i < tableRowsCount; i++) {
+ if (primaryKeyFieldCount == 1) {
+ if ([selectionKeysToRestore objectForKey:SPDataStorageObjectAtRowAndColumn(tableValues, i, primaryKeyFieldIndexes[0])]) {
+ rowMatches = YES;
+ }
+ } else {
+ NSMutableString *lookupString = [[NSMutableString alloc] initWithString:[SPDataStorageObjectAtRowAndColumn(tableValues, i, primaryKeyFieldIndexes[0]) description]];
+ for (NSUInteger j = 1; j < primaryKeyFieldCount; j++) {
+ [lookupString appendString:SPUniqueSchemaDelimiter];
+ [lookupString appendString:[SPDataStorageObjectAtRowAndColumn(tableValues, i, primaryKeyFieldIndexes[j]) description]];
+ }
+ if ([selectionKeysToRestore objectForKey:lookupString]) rowMatches = YES;
+ [lookupString release];
+ }
+
+ if (rowMatches) {
+ [selectionSet addIndex:i];
+ rowsToSelect--;
+ if (rowsToSelect <= 0) break;
+ rowMatches = NO;
+ }
+ }
+ }
+
+ } else if ([[selectionToRestore objectForKey:@"type"] isEqualToString:SPSelectionDetailTypeIndexed]) {
+ selectionSet = [selectionToRestore objectForKey:@"rows"];
+ }
+
+ [[tableContentView onMainThread] selectRowIndexes:selectionSet byExtendingSelection:NO];
+ tableRowsSelectable = previousTableRowsSelectable;
+ }
+
if ([prefs boolForKey:SPLimitResults] && (contentPage > 1 || (NSInteger)tableRowsCount == [prefs integerForKey:SPLimitResultsValue]))
{
isLimited = YES;
@@ -1465,6 +1516,7 @@
#endif
// Reset and reload data using the new filter settings
+ [self setSelectionToRestore:[self selectionDetailsAllowingIndexSelection:NO]];
previousTableRowsCount = 0;
[self clearTableValues];
[self loadTableValues];
@@ -1596,7 +1648,7 @@
// Update data using the new sort order
previousTableRowsCount = tableRowsCount;
-
+ [self setSelectionToRestore:[self selectionDetailsAllowingIndexSelection:NO]];
[self loadTableValues];
if ([mySQLConnection queryErrored] && ![mySQLConnection lastQueryWasCancelled]) {
@@ -3626,11 +3678,81 @@
}
/**
- * Provide a getter for the table's selected rows index set
+ * Provide a getter for the table's selected rows. If a primary key is available,
+ * the returned dictionary will contain details of the primary key used, and an
+ * identifier for each selected row. If no primary key is available, the returned
+ * dictionary will contain details and a list of the selected row *indexes* if the
+ * supplied argument is set to true, which may not always be appropriate.
*/
-- (NSIndexSet *) selectedRowIndexes
+- (NSDictionary *)selectionDetailsAllowingIndexSelection:(BOOL)allowIndexFallback
{
- return [tableContentView selectedRowIndexes];
+
+ // If a primary key is available, store the selection details for rows using the primary key.
+ NSArray *primaryKeyFieldNames = [tableDataInstance primaryKeyColumnNames];
+ if (primaryKeyFieldNames) {
+
+ // Set up an array of the column indexes to store
+ NSUInteger primaryKeyFieldCount = [primaryKeyFieldNames count];
+ NSUInteger primaryKeyFieldIndexes[primaryKeyFieldCount];
+ BOOL problemColumns = NO;
+ for (NSUInteger i = 0; i < primaryKeyFieldCount; i++) {
+ primaryKeyFieldIndexes[i] = [[tableDataInstance columnNames] indexOfObject:[primaryKeyFieldNames objectAtIndex:i]];
+ if (primaryKeyFieldIndexes[i] == NSNotFound) {
+ problemColumns = YES;
+#ifndef SP_REFACTOR
+ } else {
+ if ([prefs boolForKey:SPLoadBlobsAsNeeded]) {
+ if ([tableDataInstance columnIsBlobOrText:[primaryKeyFieldNames objectAtIndex:i]]) {
+ problemColumns = YES;
+ }
+ }
+#endif
+ }
+ }
+
+ // Only proceed with key-based selection if there were no problem columns
+ if (!problemColumns) {
+ NSIndexSet *selectedRowIndexes = [tableContentView selectedRowIndexes];
+ NSUInteger *indexBuffer = malloc(sizeof(NSUInteger) * [selectedRowIndexes count]);
+ NSUInteger indexCount = [selectedRowIndexes getIndexes:indexBuffer maxCount:[selectedRowIndexes count] inIndexRange:NULL];
+
+ NSMutableDictionary *selectedRowLookupTable = [NSMutableDictionary dictionaryWithCapacity:indexCount];
+ NSNumber *trueNumber = [NSNumber numberWithBool:YES];
+ for (NSUInteger i = 0; i < indexCount; i++) {
+ if (primaryKeyFieldCount == 1) {
+ [selectedRowLookupTable setObject:trueNumber forKey:[SPDataStorageObjectAtRowAndColumn(tableValues, indexBuffer[i], primaryKeyFieldIndexes[0]) description]];
+ } else {
+ NSMutableString *lookupString = [NSMutableString stringWithString:SPDataStorageObjectAtRowAndColumn(tableValues, indexBuffer[i], primaryKeyFieldIndexes[0])];
+ for (NSUInteger j = 1; j < primaryKeyFieldCount; j++) {
+ [lookupString appendString:SPUniqueSchemaDelimiter];
+ [lookupString appendString:[SPDataStorageObjectAtRowAndColumn(tableValues, indexBuffer[i], primaryKeyFieldIndexes[j]) description]];
+ }
+ [selectedRowLookupTable setObject:trueNumber forKey:lookupString];
+ }
+ }
+ free(indexBuffer);
+
+ return [NSDictionary dictionaryWithObjectsAndKeys:
+ SPSelectionDetailTypePrimaryKeyed, @"type",
+ selectedRowLookupTable, @"rows",
+ primaryKeyFieldNames, @"keys",
+ nil];
+ }
+ }
+
+ // If no primary key was available, fall back to using just the selected row indexes if permitted
+ if (allowIndexFallback) {
+ return [NSDictionary dictionaryWithObjectsAndKeys:
+ SPSelectionDetailTypeIndexed, @"type",
+ [tableContentView selectedRowIndexes], @"rows",
+ nil];
+ }
+
+ // Otherwise return a blank selection
+ return [NSDictionary dictionaryWithObjectsAndKeys:
+ SPSelectionDetailTypeIndexed, @"type",
+ [NSIndexSet indexSet], @"rows",
+ nil];
}
/**
@@ -3711,11 +3833,11 @@
/**
* Set the selected row indexes to restore on next table load
*/
-- (void) setSelectedRowIndexesToRestore:(NSIndexSet *)theIndexSet
+- (void) setSelectionToRestore:(NSDictionary *)theSelection
{
- if (selectionIndexToRestore) [selectionIndexToRestore release], selectionIndexToRestore = nil;
+ if (selectionToRestore) [selectionToRestore release], selectionToRestore = nil;
- if (theIndexSet) selectionIndexToRestore = [[NSIndexSet alloc] initWithIndexSet:theIndexSet];
+ if (theSelection) selectionToRestore = [theSelection copy];
}
/**
@@ -3777,7 +3899,7 @@
{
[self setSortColumnNameToRestore:[self sortColumnName] isAscending:[self sortColumnIsAscending]];
[self setPageToRestore:[self pageNumber]];
- [self setSelectedRowIndexesToRestore:[self selectedRowIndexes]];
+ [self setSelectionToRestore:[self selectionDetailsAllowingIndexSelection:YES]];
[self setViewportToRestore:[self viewport]];
[self setFiltersToRestore:[self filterSettings]];
}
@@ -3789,7 +3911,7 @@
{
[self setSortColumnNameToRestore:nil isAscending:YES];
[self setPageToRestore:1];
- [self setSelectedRowIndexesToRestore:nil];
+ [self setSelectionToRestore:nil];
[self setViewportToRestore:NSZeroRect];
[self setFiltersToRestore:nil];
}
@@ -4291,7 +4413,7 @@
if (sortCol) [sortCol release];
[usedQuery release];
if (sortColumnToRestore) [sortColumnToRestore release];
- if (selectionIndexToRestore) [selectionIndexToRestore release];
+ if (selectionToRestore) [selectionToRestore release];
if (filterFieldToRestore) filterFieldToRestore = nil;
if (filterComparisonToRestore) filterComparisonToRestore = nil;
if (filterValueToRestore) filterValueToRestore = nil;
diff --git a/Source/SPTableData.h b/Source/SPTableData.h
index 94c95da4..e292fe7a 100644
--- a/Source/SPTableData.h
+++ b/Source/SPTableData.h
@@ -35,6 +35,7 @@
NSMutableArray *constraints;
NSArray *triggers;
NSMutableDictionary *status;
+ NSMutableArray *primaryKeyColumns;
NSString *tableEncoding;
NSString *tableCreateSyntax;
diff --git a/Source/SPTableData.m b/Source/SPTableData.m
index 0c0814d6..b2626057 100644
--- a/Source/SPTableData.m
+++ b/Source/SPTableData.m
@@ -53,6 +53,7 @@
columnNames = [[NSMutableArray alloc] init];
constraints = [[NSMutableArray alloc] init];
status = [[NSMutableDictionary alloc] init];
+ primaryKeyColumns = [[NSMutableArray alloc] init];
triggers = nil;
tableEncoding = nil;
@@ -375,6 +376,7 @@
[columnNames removeAllObjects];
[constraints removeAllObjects];
tableHasAutoIncrementField = NO;
+ [primaryKeyColumns removeAllObjects];
if( [tableListInstance tableType] == SPTableTypeTable || [tableListInstance tableType] == SPTableTypeView ) {
tableData = [self informationForTable:[tableListInstance tableName]];
@@ -400,6 +402,7 @@
[tableEncoding release];
}
tableEncoding = [[NSString alloc] initWithString:[tableData objectForKey:@"encoding"]];
+ [primaryKeyColumns addObjectsFromArray:[tableData objectForKey:@"primarykeyfield"]];
pthread_mutex_unlock(&dataProcessingLock);
@@ -419,6 +422,7 @@
NSEnumerator *enumerator;
tableHasAutoIncrementField = NO;
+ [primaryKeyColumns removeAllObjects];
if (viewData == nil) {
[columns removeAllObjects];
@@ -707,33 +711,38 @@
// add "isprimarykey" to the corresponding tableColumn
// add dict root "primarykeyfield" = <field> for faster accessing
else if( [NSArrayObjectAtIndex(parts, 0) hasPrefix:@"PRIMARY"] && [parts count] == 3) {
- NSString *parsedString = [(NSString*)NSArrayObjectAtIndex(parts, 2) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
- if([parsedString length]>4) {
- NSString *priFieldName = [[parsedString substringWithRange:NSMakeRange(2,[parsedString length]-4)] stringByReplacingOccurrencesOfString:@"``" withString:@"`"];
- [tableData setObject:priFieldName forKey:@"primarykeyfield"];
- for(id theTableColumn in tableColumns)
- if([[theTableColumn objectForKey:@"name"] isEqualToString:priFieldName]) {
- [theTableColumn setObject:[NSNumber numberWithInteger:1] forKey:@"isprimarykey"];
- break;
+ SPSQLParser *keyParser = [SPSQLParser stringWithString:NSArrayObjectAtIndex(parts, 2)];
+ keyParser = [SPSQLParser stringWithString:[keyParser stringFromCharacter:'(' toCharacter:')' inclusively:NO]];
+ NSArray *primaryKeyQuotedNames = [keyParser splitStringByCharacter:','];
+ if ([keyParser length]) {
+ NSMutableArray *primaryKeyFields = [NSMutableArray array];
+ for (NSString *quotedKeyName in primaryKeyQuotedNames) {
+ NSString *primaryFieldName = [[SPSQLParser stringWithString:quotedKeyName] unquotedString];
+ [primaryKeyFields addObject:primaryFieldName];
+ for (NSMutableDictionary *theTableColumn in tableColumns) {
+ if ([[theTableColumn objectForKey:@"name"] isEqualToString:primaryFieldName]) {
+ [theTableColumn setObject:[NSNumber numberWithInteger:1] forKey:@"isprimarykey"];
+ break;
+ }
}
+ }
+ [tableData setObject:primaryKeyFields forKey:@"primarykeyfield"];
}
}
// unique keys
// add to each corresponding tableColumn the tag "unique" if given
else if( [NSArrayObjectAtIndex(parts, 0) hasPrefix:@"UNIQUE"] && [parts count] == 4) {
- NSString *parsedString = [(NSString*)NSArrayObjectAtIndex(parts, 3) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
- if([parsedString length]>4) {
- NSArray *uniqueFieldNames = [parsedString componentsSeparatedByString:@"`,`"];
- for(NSString* uniq in uniqueFieldNames) {
- NSString *uniqField = [[uniq stringByReplacingOccurrencesOfRegex:@"^\\(`|`\\)" withString:@""] stringByReplacingOccurrencesOfString:@"``" withString:@"`"];
- for(id theTableColumn in tableColumns)
- if([[theTableColumn objectForKey:@"name"] isEqualToString:uniqField]) {
- [theTableColumn setObject:[NSNumber numberWithInteger:1] forKey:@"unique"];
- break;
- }
+ SPSQLParser *keyParser = [SPSQLParser stringWithString:NSArrayObjectAtIndex(parts, 3)];
+ keyParser = [SPSQLParser stringWithString:[keyParser stringFromCharacter:'(' toCharacter:')' inclusively:NO]];
+ for (NSString *quotedUniqueKey in [keyParser splitStringByCharacter:',']) {
+ NSString *uniqueFieldName = [[SPSQLParser stringWithString:quotedUniqueKey] unquotedString];
+ for (NSMutableDictionary *theTableColumn in tableColumns) {
+ if ([[theTableColumn objectForKey:@"name"] isEqualToString:uniqueFieldName]) {
+ [theTableColumn setObject:[NSNumber numberWithInteger:1] forKey:@"unique"];
+ break;
+ }
}
-
}
}
// who knows
@@ -1284,52 +1293,19 @@
- (NSArray *)primaryKeyColumnNames
{
- // Ensure that identifier queries occur over UTF8
- BOOL changeEncoding = ![[mySQLConnection encoding] isEqualToString:@"utf8"];
- if (changeEncoding) {
- [mySQLConnection storeEncodingForRestoration];
- [mySQLConnection setEncoding:@"utf8"];
- }
-
- NSString *selectedTable = [tableListInstance tableName];
- if(![selectedTable length]) return nil;
-
- SPMySQLResult *r;
- NSMutableArray *keyColumns = [NSMutableArray array];
-
- // select all columns that are primary keys
- // MySQL before 5.0.3 does not support the WHERE syntax
- r = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@ /*!50003 WHERE `key` = 'PRI'*/", [selectedTable backtickQuotedString]]];
- [r setReturnDataAsStrings:YES];
- [r setDefaultRowReturnType:SPMySQLResultRowAsArray];
-
- if ([r numberOfRows] < 1) {
- if (changeEncoding && [mySQLConnection isConnected]) [mySQLConnection restoreStoredEncoding];
- return nil;
- }
-
- if ([mySQLConnection queryErrored]) {
- if ([mySQLConnection isConnected]) {
- NSRunAlertPanel(@"Error", [NSString stringWithFormat:NSLocalizedString(@"An error occured while retrieving the PRIMARY KEY data:\n\n%@",@"message when the query that fetches the primary keys fails"), [mySQLConnection lastErrorMessage]], @"OK", nil, nil);
- if (changeEncoding) [mySQLConnection restoreStoredEncoding];
- }
- return nil;
- }
-
-
- for (NSArray *resultRow in r) {
+ // If processing is already in action, wait for it to complete
+ [self _loopWhileWorking];
- // check if the row is indeed a key (for MySQL servers before 5.0.3)
- if ([[NSArrayObjectAtIndex(resultRow ,3) description] isEqualToString:@"PRI"]) {
- [keyColumns addObject:[NSArrayObjectAtIndex(resultRow ,0) description]];
+ if ([columns count] == 0) {
+ if ([tableListInstance tableType] == SPTableTypeView) {
+ [self updateInformationForCurrentView];
+ } else {
+ [self updateInformationForCurrentTable];
}
}
- if (changeEncoding) [mySQLConnection restoreStoredEncoding];
-
- if([keyColumns count]) return keyColumns;
-
- return nil;
+ if (![primaryKeyColumns count]) return nil;
+ return primaryKeyColumns;
}
#pragma mark -
@@ -1343,6 +1319,7 @@
[columnNames release];
[constraints release];
[status release];
+ [primaryKeyColumns release];
if (triggers) [triggers release];
if (tableEncoding) [tableEncoding release];