From ae0de60e69ffd51cda85ff70417cd354ee781c1c Mon Sep 17 00:00:00 2001 From: Bibiko Date: Mon, 29 Mar 2010 12:10:44 +0000 Subject: =?UTF-8?q?=E2=80=A2=20fixed=20several=20issue=20for=20completion?= =?UTF-8?q?=20lists=20=E2=80=A2=20improved=20gathering=20and=20caching=20o?= =?UTF-8?q?f=20structure=20data=20coming=20from=20connection=20windows=20w?= =?UTF-8?q?ith=20the=20same=20connection=20=E2=80=A2=20made=20the=20struct?= =?UTF-8?q?ure=20querying=20more=20stable=20against=20threading=20issues?= =?UTF-8?q?=20=E2=80=A2=20moved=20getUniqueDbIdentifierFor=20from=20MCPCon?= =?UTF-8?q?nection=20to=20SPNavigatorController=20to=20be=20up-to-date=20i?= =?UTF-8?q?n=20all=20connection=20windows=20=E2=80=A2=20improved=20detecti?= =?UTF-8?q?on=20if=20db=20structure=20querying=20should=20be=20performed?= =?UTF-8?q?=20or=20not=20(not=20yet=20finished)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h | 8 +- Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m | 131 +++++++++------------ 2 files changed, 65 insertions(+), 74 deletions(-) (limited to 'Frameworks/MCPKit/MCPFoundationKit') diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h index 18450551..bf5d4145 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h @@ -113,6 +113,11 @@ */ - (NSArray*)allViewNames; +/** + * + */ +- (NSArray*)allSchemaKeys; + @end @interface MCPConnection : NSObject @@ -276,9 +281,10 @@ void performThreadedKeepAlive(void *ptr); - (MCPResult *)listTablesFromDB:(NSString *)dbName like:(NSString *)tablesName; - (MCPResult *)listFieldsFromTable:(NSString *)tableName; - (MCPResult *)listFieldsFromTable:(NSString *)tableName like:(NSString *)fieldsName; + +// Structure querying - (void)queryDbStructureWithUserInfo:(NSDictionary*)userInfo; - (NSDictionary *)getDbStructure; -- (NSInteger)getUniqueDbIdentifierFor:(NSString*)term; - (NSArray *)getAllKeysOfDbStructure; // Server information diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m index 3c6bb9e7..70249488 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m @@ -1862,7 +1862,11 @@ void performThreadedKeepAlive(void *ptr) if (!isQueryingDbStructure) { -// NSLog(@"queryDbStructureWithUserInfo called"); +// NSLog(@"queryDbStructureWithUserInfo called with %@ and db %@", [userInfo description], [[[self delegate] database] description]); + + isQueryingDbStructure = YES; + + [[NSNotificationCenter defaultCenter] postNotificationName:@"SPDBStructureIsUpdating" object:delegate]; NSString *SPUniqueSchemaDelimiter = @"￸"; @@ -1872,10 +1876,15 @@ void performThreadedKeepAlive(void *ptr) else connectionID = @"_"; - if(![structure valueForKey:connectionID]) - [structure setObject:[NSMutableDictionary dictionary] forKey:connectionID]; + // Re-init with already cached data from navigator controller + [structure removeAllObjects]; + [structure setObject:[NSMutableDictionary dictionaryWithDictionary:[[self delegate] getDbStructure]] forKey:connectionID]; + [allKeysofDbStructure removeAllObjects]; + [allKeysofDbStructure addObjectsFromArray:[[self delegate] allSchemaKeys]]; + + BOOL removeAddFlag = NO; - // Add all known database coming from connection if they aren't parsed yet + // Add all known databases coming from connection if they aren't parsed yet NSArray *dbs = [[NSString stringWithFormat:@"%@%@%@", [[[self delegate] allSystemDatabaseNames] componentsJoinedByString:SPUniqueSchemaDelimiter], SPUniqueSchemaDelimiter, @@ -1883,6 +1892,8 @@ void performThreadedKeepAlive(void *ptr) componentsSeparatedByString:SPUniqueSchemaDelimiter]; for(id db in dbs) { if(![[structure valueForKey:connectionID] objectForKey:[NSString stringWithFormat:@"%@%@%@", connectionID, SPUniqueSchemaDelimiter, db]]) { +// NSLog(@"added db %@", db); + removeAddFlag = YES; [[structure valueForKey:connectionID] setObject:db forKey:[NSString stringWithFormat:@"%@%@%@", connectionID, SPUniqueSchemaDelimiter, db]]; } } @@ -1890,12 +1901,14 @@ void performThreadedKeepAlive(void *ptr) // Remove deleted databases in structure and keys in allKeysofDbStructure // Use a dict to avoid was mutated while being enumerated. while iterating via allKeys NSArray *keys = [[NSDictionary dictionaryWithDictionary:[structure valueForKey:connectionID]] allKeys]; - BOOL removeFlag = NO; for(id key in keys) { NSString *db = [[key componentsSeparatedByString:SPUniqueSchemaDelimiter] objectAtIndex:1]; if(![dbs containsObject:db]) { - removeFlag = YES; - [[structure valueForKey:connectionID] removeObjectForKey:key]; +// NSLog(@"removed db %@", db); + removeAddFlag = YES; + if([[structure valueForKey:connectionID] isKindOfClass:[NSDictionary class]]) { + [[structure valueForKey:connectionID] removeObjectForKey:key]; + } NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT SELF BEGINSWITH %@", [NSString stringWithFormat:@"%@%@", key, SPUniqueSchemaDelimiter]]; [allKeysofDbStructure filterUsingPredicate:predicate]; [allKeysofDbStructure removeObject:key]; @@ -1907,33 +1920,41 @@ void performThreadedKeepAlive(void *ptr) currentDatabase = [[self delegate] database]; if(!currentDatabase || (currentDatabase && ![currentDatabase length])) { +// NSLog(@"no db - return"); isQueryingDbStructure = NO; - if(removeFlag) + if(removeAddFlag) [[NSNotificationCenter defaultCenter] postNotificationName:@"SPDBStructureWasUpdated" object:delegate]; [queryPool release]; return; } - // if([currentDatabase isEqualToString:@"mysql"]) { - // if(![[structure valueForKey:connectionID] objectForKey:currentDatabase] || ![[[structure valueForKey:connectionID] objectForKey:currentDatabase] isKindOfClass:[NSDictionary class]]) { - // if(removeFlag) - // [[NSNotificationCenter defaultCenter] postNotificationName:@"SPDBStructureWasUpdated" object:delegate]; - // [queryPool release]; - // return; - // } - // } - // if([currentDatabase isEqualToString:@"information_schema"]) { - // if(![[structure valueForKey:connectionID] objectForKey:currentDatabase] || ![[[structure valueForKey:connectionID] objectForKey:currentDatabase] isKindOfClass:[NSDictionary class]]) { - // if(removeFlag) - // [[NSNotificationCenter defaultCenter] postNotificationName:@"SPDBStructureWasUpdated" object:delegate]; - // [queryPool release]; - // return; - // } - // } + NSString *db_id = [NSString stringWithFormat:@"%@%@%@", connectionID, SPUniqueSchemaDelimiter, currentDatabase]; + + // mysql and information_schema's schema will never change thus query data only once + if([currentDatabase isEqualToString:@"mysql"]) { + if([[structure valueForKey:connectionID] objectForKey:db_id] && [[[structure valueForKey:connectionID] objectForKey:db_id] isKindOfClass:[NSDictionary class]]) { +// NSLog(@"mysql was parsed - return"); + if(removeAddFlag) + [[NSNotificationCenter defaultCenter] postNotificationName:@"SPDBStructureWasUpdated" object:delegate]; + [queryPool release]; + return; + } + } + if([currentDatabase isEqualToString:@"information_schema"]) { + if([[structure valueForKey:connectionID] objectForKey:db_id] && [[[structure valueForKey:connectionID] objectForKey:db_id] isKindOfClass:[NSDictionary class]]) { +// NSLog(@"information_schema was parsed - return"); + if(removeAddFlag) + [[NSNotificationCenter defaultCenter] postNotificationName:@"SPDBStructureWasUpdated" object:delegate]; + [queryPool release]; + return; + } + } if(userInfo == nil || ![userInfo objectForKey:@"forceUpdate"]) { - if([[self delegate] navigatorSchemaPathExistsForDatabase:currentDatabase]) { - if(removeFlag) + if([[structure valueForKey:connectionID] objectForKey:db_id] && [[[structure valueForKey:connectionID] objectForKey:db_id] isKindOfClass:[NSDictionary class]]) { +// NSLog(@"no forceUpdate - return"); + isQueryingDbStructure = NO; + if(removeAddFlag) [[NSNotificationCenter defaultCenter] postNotificationName:@"SPDBStructureWasUpdated" object:delegate]; [queryPool release]; return; @@ -1943,8 +1964,6 @@ void performThreadedKeepAlive(void *ptr) NSArray *tables = [[[self delegate] valueForKeyPath:@"tablesListInstance"] allTableNames]; NSArray *tableviews = [[[self delegate] valueForKeyPath:@"tablesListInstance"] allViewNames]; - NSString *db_id = [NSString stringWithFormat:@"%@%@%@", connectionID, SPUniqueSchemaDelimiter, currentDatabase]; - NSUInteger numberOfTables = 0; if(tables && [tables count]) numberOfTables += [tables count]; if(tableviews && [tableviews count]) numberOfTables += [tableviews count]; @@ -1961,11 +1980,13 @@ void performThreadedKeepAlive(void *ptr) } // Delete all stored data for to be queried db - [[structure valueForKey:connectionID] removeObjectForKey:db_id]; + if([[structure valueForKey:connectionID] isKindOfClass:[NSDictionary class]]) + [[structure valueForKey:connectionID] removeObjectForKey:db_id]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT SELF BEGINSWITH %@", [NSString stringWithFormat:@"%@%@", db_id, SPUniqueSchemaDelimiter]]; [allKeysofDbStructure filterUsingPredicate:predicate]; [allKeysofDbStructure removeObject:db_id]; - + // Re-add currentDatabase in case that structure querying will fail + [[structure valueForKey:connectionID] setObject:currentDatabase forKey:db_id]; NSString *currentDatabaseEscaped = [currentDatabase stringByReplacingOccurrencesOfString:@"`" withString:@"``"]; @@ -1977,8 +1998,6 @@ void performThreadedKeepAlive(void *ptr) const char *theSocket; void *connectionSetupStatus; - isQueryingDbStructure = YES; - mysql_options(structConnection, MYSQL_OPT_CONNECT_TIMEOUT, (const void *)&connectionTimeout); // Set up the host, socket and password as per the connect method @@ -2165,62 +2184,28 @@ void performThreadedKeepAlive(void *ptr) // Notify that the structure querying has been performed [[NSNotificationCenter defaultCenter] postNotificationName:@"SPDBStructureWasUpdated" object:delegate]; - // NSLog(@"QUERIED INFO"); mysql_close(structConnection); - isQueryingDbStructure = NO; } } + } else { + // Notify that the structure querying has been performed + [[NSNotificationCenter defaultCenter] postNotificationName:@"SPDBStructureWasUpdated" object:delegate]; } + isQueryingDbStructure = NO; [queryPool release]; } /** - * Returns 1 for db and 2 for table name if table name is not a db name and versa visa. - * Otherwise it return 0. Mainly used for completion to know whether a `foo`. can only be - * a db name or a table name. - */ -- (NSInteger)getUniqueDbIdentifierFor:(NSString*)term -{ - - NSString *SPUniqueSchemaDelimiter = @"￸"; - - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF ENDSWITH[c] %@", [NSString stringWithFormat:@"%@%@", SPUniqueSchemaDelimiter, [term lowercaseString]]]; - NSArray *result = [[allKeysofDbStructure allObjects] filteredArrayUsingPredicate:predicate]; - - if([result count] < 1 ) return 0; - if([result count] == 1) { - NSArray *split = [[result objectAtIndex:0] componentsSeparatedByString:SPUniqueSchemaDelimiter]; - if([split count] == 2 ) return 1; - if([split count] == 3 ) return 2; - return 0; - } - // case if field is equal to a table or db name - NSMutableArray *arr = [NSMutableArray array]; - for(NSString *item in result) { - if([[item componentsSeparatedByString:SPUniqueSchemaDelimiter] count] < 4) - [arr addObject:item]; - } - if([arr count] < 1 ) return 0; - if([arr count] == 1) { - NSArray *split = [[arr objectAtIndex:0] componentsSeparatedByString:SPUniqueSchemaDelimiter]; - if([split count] == 2 ) return 1; - if([split count] == 3 ) return 2; - return 0; - } - return 0; -} - -/** - * Returns a dict containing the structure of all available databases (mainly for completion). + * Returns a dict containing the structure of all available databases */ - (NSDictionary *)getDbStructure { - return [NSDictionary dictionaryWithDictionary:structure];; + return [NSDictionary dictionaryWithDictionary:structure]; } /** - * Returns all keys of the db structure. + * Returns all keys of the db structure */ - (NSArray *)getAllKeysOfDbStructure { -- cgit v1.2.3