aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks
diff options
context:
space:
mode:
Diffstat (limited to 'Frameworks')
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h5
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m145
2 files changed, 150 insertions, 0 deletions
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h
index f9e0fa82..8398f4ca 100644
--- a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h
@@ -105,6 +105,7 @@ static inline NSData* NSStringDataUsingLossyEncoding(NSString* self, NSInteger e
BOOL isMaxAllowedPacketEditable;
NSString *serverVersionString;
+ NSDictionary *theDbStructure;
NSTimer *keepAliveTimer;
pthread_t keepAliveThread;
@@ -115,6 +116,7 @@ static inline NSData* NSStringDataUsingLossyEncoding(NSString* self, NSInteger e
BOOL queryCancelUsedReconnect;
BOOL delegateQueryLogging;
BOOL delegateResponseToWillQueryString;
+ BOOL isQueryingDbStructure;
// Pointers
IMP cStringPtr;
@@ -225,6 +227,8 @@ void performThreadedKeepAlive(void *ptr);
- (MCPResult *)listTablesFromDB:(NSString *)dbName like:(NSString *)tablesName;
- (MCPResult *)listFieldsFromTable:(NSString *)tableName;
- (MCPResult *)listFieldsFromTable:(NSString *)tableName like:(NSString *)fieldsName;
+- (void)queryDbStructure;
+- (NSDictionary *)getDbStructure;
// Server information
- (NSString *)clientInfo;
@@ -254,5 +258,6 @@ void performThreadedKeepAlive(void *ptr);
- (const char *)cStringFromString:(NSString *)theString usingEncoding:(NSStringEncoding)encoding;
- (NSString *)stringWithCString:(const char *)theCString;
- (NSString *)stringWithText:(NSData *)theTextData;
+- (NSString *)stringWithUTF8CString:(const char *)theCString;
@end
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
@@ -2154,6 +2279,26 @@ void performThreadedKeepAlive(void *ptr)
}
/**
+ * 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).
*/
- (NSString *)stringWithText:(NSData *)theTextData