From bd1c8a535691781746f1a1ff4ea9d215744061c5 Mon Sep 17 00:00:00 2001 From: Bibiko Date: Sun, 10 Jan 2010 19:23:42 +0000 Subject: =?UTF-8?q?=E2=80=A2=20first=20preparations=20to=20improve=20the?= =?UTF-8?q?=20Custom=20Query=20database=20names/table=20names/field=20name?= =?UTF-8?q?s=20+=20type=20and=20encoding=20completion=20-=20after=20connec?= =?UTF-8?q?ting=20and=20updating=20the=20table=20list=20a=20background=20t?= =?UTF-8?q?ask=20executed=20on=20a=20different=20connection=20will=20be=20?= =?UTF-8?q?performed=20to=20query=20the=20information=5Fschema=20db=20(MyS?= =?UTF-8?q?QL=20>=3D=205=20only=20so=20far)=20-=20the=20MCPConnection=20ob?= =?UTF-8?q?ject=20holds=20a=20NSDictionary=20with=20all=20structural=20dat?= =?UTF-8?q?a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: not yet active --- Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m | 145 +++++++++++++++++++++ 1 file changed, 145 insertions(+) (limited to 'Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m') diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m index 9f87c0d1..11f9cfec 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m @@ -109,6 +109,9 @@ static BOOL sTruncateLongFieldInLogs = YES; useKeepAlive = YES; keepAliveInterval = 60; + theDbStructure = nil; + isQueryingDbStructure = NO; + connectionThreadId = 0; maxAllowedPacketSize = -1; lastQueryExecutionTime = 0; @@ -378,6 +381,11 @@ static BOOL sTruncateLongFieldInLogs = YES; serverVersionString = nil; } + if (theDbStructure != nil) { + [theDbStructure release]; + theDbStructure = nil; + } + [self stopKeepAliveTimer]; } @@ -1797,6 +1805,123 @@ void performThreadedKeepAlive(void *ptr) return theResult; } +/** + * Updates the dict containing the structure of all available databases (mainly for completion) + * executed on a new connection. + */ +- (void)queryDbStructure +{ + + return; + + if (!isQueryingDbStructure && [self serverMajorVersion] >= 5) { + + MYSQL *structConnection = mysql_init(NULL); + if (structConnection) { + const char *theLogin = [self cStringFromString:connectionLogin]; + const char *theHost; + const char *thePass; + 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 + if (!connectionHost || ![connectionHost length]) { + theHost = NULL; + } else { + theHost = [self cStringFromString:connectionHost]; + } + if (connectionSocket == nil || ![connectionSocket length]) { + theSocket = kMCPConnectionDefaultSocket; + } else { + theSocket = [self cStringFromString:connectionSocket]; + } + if (!connectionPassword) { + if (delegate && [delegate respondsToSelector:@selector(keychainPasswordForConnection:)]) { + thePass = [self cStringFromString:[delegate keychainPasswordForConnection:self]]; + } + } else { + thePass = [self cStringFromString:connectionPassword]; + } + + // Connect + connectionSetupStatus = mysql_real_connect(structConnection, theHost, theLogin, thePass, NULL, connectionPort, theSocket, mConnectionFlags); + thePass = NULL; + if (connectionSetupStatus) { + MYSQL_RES *theResult; + MYSQL_ROW row; + + NSStringEncoding theConnectionEncoding = [MCPConnection encodingForMySQLEncoding:mysql_character_set_name(structConnection)]; + + // Set connection to UTF-8 since the information_schema is encoded in UTF-8 + NSString *setNameString = @"SET NAMES 'utf8'"; + NSData *encodedSetNameData = NSStringDataUsingLossyEncoding(setNameString, theConnectionEncoding, 1); + const char *setNameCString = [encodedSetNameData bytes]; + unsigned long setNameCStringLength = [encodedSetNameData length]; + if (mysql_real_query(structConnection, setNameCString, setNameCStringLength) != 0) { + isQueryingDbStructure = NO; + return; + } + + // Query the desired data + NSString *queryDbString = @"SELECT TABLE_SCHEMA AS `databases`, TABLE_NAME AS `tables`, COLUMN_NAME AS `fields`, COLUMN_TYPE AS `type`, CHARACTER_SET_NAME AS `charset` FROM `information_schema`.`COLUMNS`"; + NSData *encodedQueryData = NSStringDataUsingLossyEncoding(queryDbString, theConnectionEncoding, 1); + const char *queryCString = [encodedQueryData bytes]; + unsigned long queryCStringLength = [encodedQueryData length]; + + if (mysql_real_query(structConnection, queryCString, queryCStringLength) == 0) { + theResult = mysql_use_result(structConnection); + NSMutableDictionary *structure = [NSMutableDictionary dictionary]; + + while(row = mysql_fetch_row(theResult)) { + NSString *db = [self stringWithUTF8CString:row[0]]; + NSString *table = [self stringWithUTF8CString:row[1]]; + NSString *field = [self stringWithUTF8CString:row[2]]; + NSString *type = [self stringWithUTF8CString:row[3]]; + NSString *charset = (row[4]) ? [self stringWithUTF8CString:row[4]] : @""; + + if(![structure valueForKey:db]) + [structure setObject:[NSMutableDictionary dictionary] forKey:db]; + + if(![[structure valueForKey:db] valueForKey:table]) + [[structure valueForKey:db] setObject:[NSMutableDictionary dictionary] forKey:table]; + + [[[structure valueForKey:db] valueForKey:table] setObject:[NSArray arrayWithObjects:type,charset,nil] forKey:field]; + + } + + mysql_free_result(theResult); + mysql_close(structConnection); + if(theDbStructure != nil) { + [theDbStructure release]; + theDbStructure = nil; + } + + theDbStructure = [[NSDictionary dictionaryWithDictionary:structure] retain]; + isQueryingDbStructure = NO; + return; + + } + mysql_close(structConnection); + isQueryingDbStructure = NO; + } + } + } + +} + + +/** + * Returns a dict containing the structure of all available databases (mainly for completion). + */ +- (NSDictionary *)getDbStructure +{ + return [theDbStructure retain]; +} + #pragma mark - #pragma mark Server information @@ -2153,6 +2278,26 @@ void performThreadedKeepAlive(void *ptr) return theString; } +/** + * Returns a NSString from a C style string encoded with the character set of theMCPConnection. + */ +- (NSString *)stringWithUTF8CString:(const char *)theCString +{ + NSData *theData; + NSString *theString; + + if (theCString == NULL) return @""; + + theData = [NSData dataWithBytes:theCString length:(strlen(theCString))]; + theString = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding]; + + if (theString) { + [theString autorelease]; + } + + return theString; +} + /** * Use the string encoding to convert the returned NSData to a string (for a Text field). */ -- cgit v1.2.3