diff options
author | Bibiko <bibiko@eva.mpg.de> | 2010-03-30 13:29:49 +0000 |
---|---|---|
committer | Bibiko <bibiko@eva.mpg.de> | 2010-03-30 13:29:49 +0000 |
commit | 052959a5d7f92a629445deffd990da315da5c856 (patch) | |
tree | c1080bad74547cd2445eb62a2cb3860473fe33e0 | |
parent | d6403ef10ff74af3d9ce05ce089055ff102a06eb (diff) | |
download | sequelpro-052959a5d7f92a629445deffd990da315da5c856.tar.gz sequelpro-052959a5d7f92a629445deffd990da315da5c856.tar.bz2 sequelpro-052959a5d7f92a629445deffd990da315da5c856.zip |
• next trial to make getAllKeysOfDbStructure thread safe
• some speed improvements for navigator
- pre-calculate display string for type info to avoid doing it all the time while refreshing the outline view
• suppress double-clicking at a not yet queried db structure if the same connection is querying another structure to avoid accessing the same storage objects from different threads (test)
• reload outline view after filtering in navigator runs in its own thread to avoid blocking SP
• fixed memory leaks while returning [obj copy]
-rw-r--r-- | Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m | 34 | ||||
-rw-r--r-- | Source/SPNavigatorController.h | 2 | ||||
-rw-r--r-- | Source/SPNavigatorController.m | 164 |
3 files changed, 135 insertions, 65 deletions
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m index 35d07a39..fd9842aa 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m @@ -33,6 +33,7 @@ #import "MCPStreamingResult.h" #import "MCPConnectionProxy.h" #import "MCPStringAdditions.h" +#import "RegexKitLite.h" #include <unistd.h> #include <mach/mach_time.h> @@ -1897,11 +1898,14 @@ void performThreadedKeepAlive(void *ptr) SPUniqueSchemaDelimiter, [[[self delegate] allDatabaseNames] componentsJoinedByString:SPUniqueSchemaDelimiter]] componentsSeparatedByString:SPUniqueSchemaDelimiter]; + for(id db in dbs) { - if(![[structure valueForKey:connectionID] objectForKey:[NSString stringWithFormat:@"%@%@%@", connectionID, SPUniqueSchemaDelimiter, db]]) { + NSString *dbid = [NSString stringWithFormat:@"%@%@%@", connectionID, SPUniqueSchemaDelimiter, db]; + if(![[structure valueForKey:connectionID] objectForKey:dbid]) { // NSLog(@"added db %@", db); removeAddFlag = YES; - [[structure valueForKey:connectionID] setObject:db forKey:[NSString stringWithFormat:@"%@%@%@", connectionID, SPUniqueSchemaDelimiter, db]]; + [[structure valueForKey:connectionID] setObject:db forKey:dbid]; + [allKeysofDbStructure addObject:dbid]; } } @@ -2078,6 +2082,7 @@ void performThreadedKeepAlive(void *ptr) while(row = mysql_fetch_row(theResult)) { NSString *field = [self stringWithUTF8CString:row[0]]; NSString *type = [self stringWithUTF8CString:row[1]]; + NSString *type_display = [type stringByReplacingOccurrencesOfRegex:@"\\(.*?,.*?\\)" withString:@"(…)"]; NSString *coll = [self stringWithUTF8CString:row[2]]; NSString *isnull = [self stringWithUTF8CString:row[3]]; NSString *key = [self stringWithUTF8CString:row[4]]; @@ -2097,7 +2102,7 @@ void performThreadedKeepAlive(void *ptr) if(![[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id]) [[[structure valueForKey:connectionID] valueForKey:db_id] setObject:[NSMutableDictionary dictionary] forKey:table_id]; - [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject:[NSArray arrayWithObjects:type, def, isnull, charset, coll, key, extra, priv, comment, [NSNumber numberWithUnsignedLongLong:uniqueCounter], nil] forKey:field_id]; + [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject:[NSArray arrayWithObjects:type, def, isnull, charset, coll, key, extra, priv, comment, type_display, [NSNumber numberWithUnsignedLongLong:uniqueCounter], nil] forKey:field_id]; [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject:@"0" forKey:@" struct_type "]; uniqueCounter++; } @@ -2126,6 +2131,7 @@ void performThreadedKeepAlive(void *ptr) while(row = mysql_fetch_row(theResult)) { NSString *field = [self stringWithUTF8CString:row[0]]; NSString *type = [self stringWithUTF8CString:row[1]]; + NSString *type_display = [type stringByReplacingOccurrencesOfRegex:@"\\(.*?,.*?\\)" withString:@"(…)"]; NSString *coll = [self stringWithUTF8CString:row[2]]; NSString *isnull = [self stringWithUTF8CString:row[3]]; NSString *key = [self stringWithUTF8CString:row[4]]; @@ -2145,7 +2151,7 @@ void performThreadedKeepAlive(void *ptr) if(![[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id]) [[[structure valueForKey:connectionID] valueForKey:db_id] setObject:[NSMutableDictionary dictionary] forKey:table_id]; - [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject:[NSArray arrayWithObjects:type, def, isnull, charset, coll, key, extra, priv, comment, [NSNumber numberWithUnsignedLongLong:uniqueCounter], nil] forKey:field_id]; + [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject:[NSArray arrayWithObjects:type, def, isnull, charset, coll, key, extra, priv, comment, type_display, [NSNumber numberWithUnsignedLongLong:uniqueCounter], nil] forKey:field_id]; [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject:@"1" forKey:@" struct_type "]; uniqueCounter++; } @@ -2213,7 +2219,7 @@ void performThreadedKeepAlive(void *ptr) */ - (NSDictionary *)getDbStructure { - return [structure copy]; + return [[structure copy] autorelease]; } /** @@ -2221,7 +2227,23 @@ void performThreadedKeepAlive(void *ptr) */ - (NSArray *)getAllKeysOfDbStructure { - return [allKeysofDbStructure copy]; + NSArray *r = nil; + @try + { + r = [NSArray arrayWithArray:allKeysofDbStructure]; + } + @catch(id ae) + { + @try + { + r = [NSArray arrayWithArray:allKeysofDbStructure]; + } + @catch(id ae) + { + return nil; + } + } + return r; } #pragma mark - diff --git a/Source/SPNavigatorController.h b/Source/SPNavigatorController.h index 061ebd86..6c31b013 100644 --- a/Source/SPNavigatorController.h +++ b/Source/SPNavigatorController.h @@ -56,6 +56,8 @@ BOOL ignoreUpdate; BOOL isFiltered; + BOOL isFiltering; + NSImage *connectionIcon; NSImage *databaseIcon; NSImage *tableIcon; diff --git a/Source/SPNavigatorController.m b/Source/SPNavigatorController.m index 40a7ef7c..439b4d5c 100644 --- a/Source/SPNavigatorController.m +++ b/Source/SPNavigatorController.m @@ -75,6 +75,7 @@ static SPNavigatorController *sharedNavigatorController = nil; selectedKey2 = @""; ignoreUpdate = NO; isFiltered = NO; + isFiltering = NO; [syncButton setState:NSOffState]; NSDictionaryClass = [NSDictionary class]; @@ -222,6 +223,7 @@ static SPNavigatorController *sharedNavigatorController = nil; - (void)selectPath:(NSString*)schemaPath { + if(schemaPath && [schemaPath length]) { // Do not change the selection if a field of schemaPath's table is already selected @@ -358,16 +360,28 @@ static SPNavigatorController *sharedNavigatorController = nil; - (void)selectInActiveDocumentItem:(id)item fromView:(id)outlineView { + // Do nothing for connection root item yet if([outlineView levelForItem:item] == 0) return; + + NSPoint pos = [NSEvent mouseLocation]; + pos.y -= 20; + + // Suppress selecting for not queried database if connection is just querying an other database + if([outlineView levelForItem:item] == 1 + && ![outlineView isExpandable:item] && [updatingConnections count]) { + [SPTooltip showWithObject:NSLocalizedString(@"The connection is busy. Please wait and try again.", @"the connection is busy. please wait and try again tooltip") + atLocation:pos + ofType:@"text"]; + + return; + } + id parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaData; if(!parentObject) return; id parentKeys = [parentObject allKeysForObject:item]; if(parentKeys && [parentKeys count] == 1) { - NSPoint pos = [NSEvent mouseLocation]; - pos.y -= 20; - NSArray *pathArray = [[[parentKeys objectAtIndex:0] description] componentsSeparatedByString:SPUniqueSchemaDelimiter]; if([pathArray count] > 1) { @@ -406,10 +420,10 @@ static SPNavigatorController *sharedNavigatorController = nil; - (void)isUpdatingNavigator:(NSNotification *)aNotification { - id object = [aNotification object]; - - if([object isKindOfClass:[TableDocument class]]) - [updatingConnections addObject:[object connectionID]]; + // id object = [aNotification object]; + // + // if([object isKindOfClass:[TableDocument class]]) + // [updatingConnections addObject:[object connectionID]]; } @@ -439,6 +453,9 @@ static SPNavigatorController *sharedNavigatorController = nil; return; } + [updatingConnections addObject:connectionName]; + + if(![schemaData objectForKey:connectionName]) { [schemaData setObject:[NSMutableDictionary dictionary] forKey:connectionName]; } @@ -463,13 +480,15 @@ static SPNavigatorController *sharedNavigatorController = nil; [schemaData setObject:[NSDictionary dictionary] forKey:[NSString stringWithFormat:@"%@&DEL&no data loaded yet", connectionName]]; [allSchemaKeys setObject:[NSArray array] forKey:connectionName]; } - [updatingConnections removeObject:connectionName]; [outlineSchema1 reloadData]; [outlineSchema2 reloadData]; [self restoreExpandStatus]; [self restoreSelectedItems]; + + [updatingConnections removeObject:connectionName]; + } [self syncButtonAction:self]; @@ -574,6 +593,7 @@ static SPNavigatorController *sharedNavigatorController = nil; [schemaDataFiltered removeAllObjects]; [schemaData removeObjectForKey:connectionID]; [allSchemaKeys removeObjectForKey:connectionID]; + [updatingConnections removeAllObjects]; [infoArray removeAllObjects]; [expandStatus1 removeAllObjects]; [expandStatus2 removeAllObjects]; @@ -598,8 +618,12 @@ static SPNavigatorController *sharedNavigatorController = nil; - (IBAction)filterTree:(id)sender { + NSString *pattern = [[[searchField stringValue] stringByReplacingOccurrencesOfString:@"." withString:SPUniqueSchemaDelimiter] lowercaseString]; + // Suppress search for '.' since this matches everything + if([pattern isEqualToString:SPUniqueSchemaDelimiter]) return; + [self saveSelectedItems]; id currentItem = [outlineSchema2 selectedItem]; @@ -609,67 +633,88 @@ static SPNavigatorController *sharedNavigatorController = nil; else parentObject = [outlineSchema2 parentForItem:currentItem] ? [outlineSchema2 parentForItem:currentItem] : schemaData; - NSString *connectionID = nil; - if(parentObject && [[parentObject allKeys] count]) - connectionID = [[[[parentObject allKeys] objectAtIndex:0] componentsSeparatedByString:SPUniqueSchemaDelimiter] objectAtIndex:0]; + @try{ + + + NSString *connectionID = nil; + if(parentObject && [[parentObject allKeys] count]) + connectionID = [[[[parentObject allKeys] objectAtIndex:0] componentsSeparatedByString:SPUniqueSchemaDelimiter] objectAtIndex:0]; - if((pattern && ![pattern length]) || !parentObject || ![[parentObject allKeys] count] || !connectionID || [connectionID length] < 2 || ![allSchemaKeys objectForKey:connectionID]) { - isFiltered = NO; - [searchField setStringValue:@""]; - [schemaDataFiltered removeAllObjects]; - [outlineSchema2 reloadData]; - [self restoreExpandStatus]; - [self restoreSelectedItems]; - return; - } + if((pattern && ![pattern length]) || !parentObject || ![[parentObject allKeys] count] || !connectionID || [connectionID length] < 2 || ![allSchemaKeys objectForKey:connectionID]) { + isFiltered = NO; + [searchField setStringValue:@""]; + [schemaDataFiltered removeAllObjects]; + [outlineSchema2 reloadData]; + [self restoreExpandStatus]; + [self restoreSelectedItems]; + isFiltering = NO; + return; + } - isFiltered = YES; + if(isFiltering) return; - [syncButton setState:NSOffState]; + isFiltered = YES; - NSMutableDictionary *structure = [NSMutableDictionary dictionary]; - [structure setObject:[NSMutableDictionary dictionary] forKey:connectionID]; + [syncButton setState:NSOffState]; + NSMutableDictionary *structure = [NSMutableDictionary dictionary]; + [structure setObject:[NSMutableDictionary dictionary] forKey:connectionID]; - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@", pattern]; - NSArray *filteredItems = [[allSchemaKeys objectForKey:connectionID] filteredArrayUsingPredicate:predicate]; - for(NSString* item in filteredItems) { - NSArray *a = [item componentsSeparatedByString:SPUniqueSchemaDelimiter]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@", pattern]; + NSArray *filteredItems = [[allSchemaKeys objectForKey:connectionID] filteredArrayUsingPredicate:predicate]; - NSString *db_id = [NSString stringWithFormat:@"%@%@%@", connectionID,SPUniqueSchemaDelimiter,NSArrayObjectAtIndex(a, 1)]; + BOOL searchFailed = NO; - if(!a || [a count] < 2) continue; + for(NSString* item in filteredItems) { + NSArray *a = [item componentsSeparatedByString:SPUniqueSchemaDelimiter]; - if(![[structure valueForKey:connectionID] valueForKey:db_id]) { - [[structure valueForKey:connectionID] setObject:[NSMutableDictionary dictionary] forKey:db_id]; - } - if([a count] > 2) { + NSString *db_id = [NSString stringWithFormat:@"%@%@%@", connectionID,SPUniqueSchemaDelimiter,NSArrayObjectAtIndex(a, 1)]; - NSString *table_id = [NSString stringWithFormat:@"%@%@%@", db_id,SPUniqueSchemaDelimiter,[a objectAtIndex:2]]; + if(!a || [a count] < 2) continue; - if(![[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id]) { - [[[structure valueForKey:connectionID] valueForKey:db_id] setObject:[NSMutableDictionary dictionary] forKey:table_id]; + if(![[structure valueForKey:connectionID] valueForKey:db_id]) { + [[structure valueForKey:connectionID] setObject:[NSMutableDictionary dictionary] forKey:db_id]; } + if([a count] > 2) { + + NSString *table_id = [NSString stringWithFormat:@"%@%@%@", db_id,SPUniqueSchemaDelimiter,[a objectAtIndex:2]]; - if([[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:@" struct_type "]) - [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject: - [[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:@" struct_type "] forKey:@" struct_type "]; - else - [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject: - [NSNumber numberWithInt:0] forKey:@" struct_type "]; + if(![[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id]) { + [[[structure valueForKey:connectionID] valueForKey:db_id] setObject:[NSMutableDictionary dictionary] forKey:table_id]; + } - if([a count] > 3) { - NSString *field_id = [NSString stringWithFormat:@"%@%@%@", table_id,SPUniqueSchemaDelimiter,[a objectAtIndex:3]]; - if([[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:field_id]) + if([[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:@" struct_type "]) [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject: - [[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:field_id] forKey:field_id]; + [[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:@" struct_type "] forKey:@" struct_type "]; + else + [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject: + [NSNumber numberWithInt:0] forKey:@" struct_type "]; + + if([a count] > 3) { + NSString *field_id = [NSString stringWithFormat:@"%@%@%@", table_id,SPUniqueSchemaDelimiter,[a objectAtIndex:3]]; + if([[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:field_id]) + [[[[structure valueForKey:connectionID] valueForKey:db_id] valueForKey:table_id] setObject: + [[[[schemaData objectForKey:connectionID] objectForKey:db_id] objectForKey:table_id] objectForKey:field_id] forKey:field_id]; + } } } + [schemaDataFiltered setDictionary:[structure retain]]; + [NSThread detachNewThreadSelector:@selector(reloadAfterFiltering) toTarget:self withObject:nil]; + + } + @catch(id ae) + { + NSPoint pos = [NSEvent mouseLocation]; + pos.y -= 20; + + [SPTooltip showWithObject:NSLocalizedString(@"Filtering failed. Please try again.", @"filtering failed. please try again. tooltip") + atLocation:pos + ofType:@"text"]; + + isFiltering = NO; } - [schemaDataFiltered setDictionary:[structure retain]]; - [NSThread detachNewThreadSelector:@selector(reloadAfterFiltering) toTarget:self withObject:nil]; } @@ -678,6 +723,7 @@ static SPNavigatorController *sharedNavigatorController = nil; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [outlineSchema2 reloadData]; [outlineSchema2 expandItem:[outlineSchema2 itemAtRow:0] expandChildren:YES]; + isFiltering = NO; [pool release]; } @@ -905,8 +951,7 @@ static SPNavigatorController *sharedNavigatorController = nil; if([outlineView levelForItem:item] == 3 && [item isKindOfClass:[NSArray class]]) { - NSString *typ = [NSString stringWithFormat:@"%@,%@,%@", [NSArrayObjectAtIndex(item, 0) stringByReplacingOccurrencesOfRegex:@"\\(.*?,.*?\\)" withString:@"(…)"], NSArrayObjectAtIndex(item, 3), NSArrayObjectAtIndex(item, 5)]; - NSTokenFieldCell *b = [[[NSTokenFieldCell alloc] initTextCell:typ] autorelease]; + NSTokenFieldCell *b = [[[NSTokenFieldCell alloc] initTextCell:NSArrayObjectAtIndex(item, 9)] autorelease]; [b setEditable:NO]; [b setAlignment:NSRightTextAlignment]; [b setFont:[NSFont systemFontOfSize:11]]; @@ -986,11 +1031,12 @@ static SPNavigatorController *sharedNavigatorController = nil; // selected item is a field if([selectedItem isKindOfClass:[NSArray class]]) { NSInteger i = 0; - for(id item in selectedItem) { - if([item isKindOfClass:[NSString class]] && [(NSString*)item length]) { - [infoArray addObject:[NSString stringWithFormat:@"%@: %@", [self tableInfoLabelForIndex:i ofType:0], [item stringByReplacingOccurrencesOfString:@"," withString:@", "]]]; - } - i++; + for(i=0; i<[selectedItem count]-2; i++) { + NSString *item = NSArrayObjectAtIndex(selectedItem, i); + if(![item length]) continue; + [infoArray addObject:[NSString stringWithFormat:@"%@: %@", + [self tableInfoLabelForIndex:i ofType:0], + [item stringByReplacingOccurrencesOfString:@"," withString:@", "]]]; } } @@ -1002,9 +1048,9 @@ static SPNavigatorController *sharedNavigatorController = nil; NSInteger keyIndex = 0; if(keys && [keys count] == 2) { // there only are two keys, get that key which doesn't begin with " " due to it's the struct_type key - if([[keys objectAtIndex:keyIndex] hasPrefix:@" "]) keyIndex++; - if([keys objectAtIndex:keyIndex] && [[selectedItem objectForKey:[keys objectAtIndex:keyIndex]] isKindOfClass:[NSArray class]]) { - for(id item in [selectedItem objectForKey:[keys objectAtIndex:keyIndex]]) { + if([NSArrayObjectAtIndex(keys, keyIndex) hasPrefix:@" "]) keyIndex++; + if(NSArrayObjectAtIndex(keys, keyIndex) && [[selectedItem objectForKey:NSArrayObjectAtIndex(keys, keyIndex)] isKindOfClass:[NSArray class]]) { + for(id item in [selectedItem objectForKey:NSArrayObjectAtIndex(keys, keyIndex)]) { if([item isKindOfClass:[NSString class]] && [(NSString*)item length]) { [infoArray addObject:[NSString stringWithFormat:@"%@: %@", [self tableInfoLabelForIndex:i ofType:type], item]]; } |