[Mysql-cocoa-commits] CVS: SMySQL/MCPFoundationKit MCPConnection.h,NONE,1.1 MCPConnection.m,NONE,1.1
Brought to you by:
sergecohen
From: Serge C. <ser...@us...> - 2003-10-11 18:48:15
|
Update of /cvsroot/mysql-cocoa/SMySQL/MCPFoundationKit In directory sc8-pr-cvs1:/tmp/cvs-serv18746/MCPFoundationKit Added Files: MCPConnection.h MCPConnection.m MCPFastQueries.h MCPFastQueries.m MCPNull.h MCPNull.m MCPResult.h MCPResult.m MCPResultPlus.h MCPResultPlus.m SMySQL.h SMySQLConstants.h SMySQL_bundled.h SMySQL_static.h Log Message: Moved the foundation type classes to the MCPFoundationKit sub-directory of the project. 2003-10-10; Serge Cohen. --- NEW FILE: MCPConnection.h --- // // MCPConnection.h // SMySQL // // Created by serge cohen (ser...@m4...) on Sat Dec 08 2001. // Copyright (c) 2001 Serge Cohen. // // This code is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or any later version. // // This code is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // For a copy of the GNU General Public License, visit <http://www.gnu.org/> or // write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330, // Boston, MA 02111-1307, USA. // // More info at <http://mysql-cocoa.sourceforge.net/> // // $Id: MCPConnection.h,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ // $Author: sergecohen $ #import <Foundation/Foundation.h> #import "mysql.h" #import "SMySQLConstants.h" @class MCPResult; // Deafult connection option extern const unsigned int kMCPConnectionDefaultOption; // Default socket (from the mysql.h used at compile time) extern const char *kMCPConnectionDefaultSocket; // Added to mysql error code extern const unsigned int kMCPConnectionNotInited; @interface MCPConnection : NSObject { MYSQL *mConnection; /*"The inited MySQL connection"*/ BOOL mConnected; /*"Reflect the fact that the connection is already in place or not"*/ NSStringEncoding mEncoding; /*"The encoding used by MySQL server, to ISO-1 default"*/ } /*" Getting default of MySQL "*/ + (NSDictionary *) getMySQLLocales; + (NSStringEncoding) encodingForMySQLEncoding:(const char *) mysqlEncoding; + (NSStringEncoding) defaultMySQLEncoding; /*" Class maintenance "*/ + (void) initialize; /*" Initialisation "*/ - (id) init; // Port to 0 to use the default port - (id) initToHost:(NSString *) host withLogin:(NSString *) login password:(NSString *) pass usingPort:(int) port; - (id) initToSocket:(NSString *) socket withLogin:(NSString *) login password:(NSString *) pass; - (BOOL) setConnectionOption:(int) option withArgument:(id) arg; // Port to 0 to use the default port - (BOOL) connectWithLogin:(NSString *) login password:(NSString *) pass host:(NSString *) host port:(int) port socket:(NSString *) socket; - (BOOL) selectDB:(NSString *) dbName; /*" Errors information "*/ - (NSString *) getLastErrorMessage; - (unsigned int) getLastErrorID; - (BOOL) isConnected; - (BOOL) checkConnection; /*" Queries "*/ - (NSString *) prepareBinaryData:(NSData *) theData; - (NSString *) prepareString:(NSString *) theString; - (MCPResult *) queryString:(NSString *) query; - (my_ulonglong) affectedRows; - (my_ulonglong) insertId; /*" Getting description of the database structure "*/ - (MCPResult *) listDBs; - (MCPResult *) listDBsLike:(NSString *) dbsName; - (MCPResult *) listTables; - (MCPResult *) listTablesLike:(NSString *) tablesName; // Next method uses SHOW TABLES FROM db to be sure that the db is not changed during this call. - (MCPResult *) listTablesFromDB:(NSString *) dbName like:(NSString *) tablesName; - (MCPResult *) listFieldsFromTable:(NSString *) tableName; - (MCPResult *) listFieldsFromTable:(NSString *) tableName like:(NSString *) fieldsName; /*" Server information and control "*/ - (NSString *) clientInfo; - (NSString *) hostInfo; - (NSString *) serverInfo; - (NSNumber *) protoInfo; - (MCPResult *) listProcesses; - (BOOL) killProcess:(unsigned long) pid; //- (BOOL)createDBWithName:(NSString *)dbName; //- (BOOL)dropDBWithName:(NSString *)dbName; /*" Disconnection "*/ - (void) disconnect; - (void) dealloc; /*" String encoding concerns (c string type to NSString). It's unlikely that users of the framework needs to use these methods which are used internally "*/ - (void) setEncoding:(NSStringEncoding) theEncoding; - (NSStringEncoding) encoding; - (const char *) cStringFromString:(NSString *) theString; - (NSString *) stringWithCString:(const char *) theCString; /*" Text data convertion to string "*/ - (NSString *) stringWithText:(NSData *) theTextData; @end --- NEW FILE: MCPConnection.m --- // // MCPConnection.m // SMySQL // // Created by serge cohen (ser...@m4...) on Sat Dec 08 2001. // Copyright (c) 2001 Serge Cohen. // // This code is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or any later version. // // This code is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // For a copy of the GNU General Public License, visit <http://www.gnu.org/> or // write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330, // Boston, MA 02111-1307, USA. // // More info at <http://mysql-cocoa.sourceforge.net/> // // $Id: MCPConnection.m,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ // $Author: sergecohen $ #import "MCPConnection.h" #import "MCPResult.h" const unsigned int kMCPConnectionDefaultOption = CLIENT_COMPRESS; const char *kMCPConnectionDefaultSocket = MYSQL_UNIX_ADDR; const unsigned int kMCPConnection_Not_Inited = 1000; // For debugging: //static FILE *MCPConnectionLogFile; @implementation MCPConnection /*" !{ $Id: MCPConnection.m,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ } !{ $Name: $ } This class is used to keep a connection with a MySQL server, it correspond to the MYSQL structure of the C API, or the database handle of the PERL DBI/DBD interface. You have to start any work on a MySQL server by getting a working MCPConnection object. Most likely you will use this kind of code: !{ MCPConnection *theConnec = [MCPConnection alloc]; MCPResult *theRes; theConnec = [theConnec initToHost::albert.com withLogin:@"toto" password:@"albert" port:0]; [theConnec selectDB:@"db1"]; theRes = [theConnec queryString:@"select * from table1"]; ... } "*/ + (NSDictionary *) getMySQLLocales /*" Gets a proper Locale dictionary to use formater to parse strings from MySQL. For example strings representing dates should give a proper Locales for use with methods such as NSDate::dateWithNaturalLanguageString: locales: "*/ { NSMutableDictionary *theLocalDict = [NSMutableDictionary dictionaryWithCapacity:12]; [theLocalDict setObject:@"." forKey:@"NSDecimalSeparator"]; return [NSDictionary dictionaryWithDictionary:theLocalDict]; } + (NSStringEncoding) encodingForMySQLEncoding:(const char *) mysqlEncoding /*" Gets a proper NSStringEncoding according to the given MySQL charset. MySQL 4.0 offers this charsets: big5 cp1251 cp1257 croat czech danish dec8 dos estonia euc_kr gb2312 gbk german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr latin1 latin1_de latin2 latin5 sjis swe7 tis620 ujis usa7 win1250 win1251ukr WARNING : incomplete implementation. Please, send your fixes. "*/ { if (!strcmp(mysqlEncoding, "latin1")) { return NSISOLatin1StringEncoding; } if (!strcmp(mysqlEncoding, "latin2")) { return NSISOLatin2StringEncoding; } if (!strcmp(mysqlEncoding, "win1250")) { return NSWindowsCP1250StringEncoding; } if (!strcmp(mysqlEncoding, "cp1251")) { return NSWindowsCP1251StringEncoding; } if (!strcmp(mysqlEncoding, "euc_kr")) { return NSJapaneseEUCStringEncoding; } if (!strcmp(mysqlEncoding, "sjis")) { return NSShiftJISStringEncoding; } // default to iso latin 1, even if it is not exact (throw an exception?) return NSISOLatin1StringEncoding; } + (NSStringEncoding) defaultMySQLEncoding /*" Returns the default charset of the library mysqlclient used. "*/ { return [MCPConnection encodingForMySQLEncoding:MYSQL_CHARSET]; } + (void) initialize /*" Initialize the class version to 2.0.0 "*/ { if (self = [MCPConnection class]) { [self setVersion:020000]; // Ma.Mi.Re -> MaMiRe } // For debugging: /* MCPConnectionLogFile = fopen("MCPConnection_debug.txt","a"); NSLog(@"MCPConnectionLogFile = %p\n", MCPConnectionLogFile); */ return; } - (id) init /*" Initialise a MySQLConnection without making a connection, most likely useless, except with !{setConnectionOption:withArgument:}. "*/ { self = [super init]; mConnection = mysql_init(NULL); mConnected = NO; if (mConnection == NULL) { [self autorelease]; return nil; } // mEncoding = NSISOLatin1StringEncoding; mEncoding = [MCPConnection encodingForMySQLEncoding:mysql_character_set_name(mConnection)]; return self; } - (id) initToHost:(NSString *) host withLogin:(NSString *) login password:(NSString *) pass usingPort:(int) port /*" Initialise a connection using a #{TCP/IP connection} with the given parameters (except if host is set to !{localhost}, in which case uses the default) - host is the hostname or IP adress - login is the user name - pass is the password corresponding to the user name - port is the TCP port to use to connect. If port = 0, uses the default port from mysql.h "*/ { #warning What happens when inited twice the NSObject? self = [super init]; mEncoding = NSISOLatin1StringEncoding; if (mConnected) { // If a the connection is on, disconnect and reset it to default mysql_close(mConnection); mConnection = NULL; } else { } mConnection = mysql_init(mConnection); mConnected = NO; if (mConnection == NULL) { [self autorelease]; return nil; } [self connectWithLogin:login password:pass host:host port:port socket:nil]; return self; } - (id) initToSocket:(NSString *) socket withLogin:(NSString *) login password:(NSString *) pass /*" Initialise a connection using a #{unix socket} with the given parameters - socket is the path to the socket - login is the user name - pass is the password corresponding to the user name "*/ { #warning What happens when inited twice the NSObject? self = [super init]; mEncoding = NSISOLatin1StringEncoding; if (mConnected) { // If a the connection is on, disconnect and reset it to default mysql_close(mConnection); mConnection = NULL; } else { } mConnection = mysql_init(mConnection); mConnected = NO; if (mConnection == NULL) { [self autorelease]; return nil; } [self connectWithLogin:login password:pass host:NULL port:0 socket:socket]; return self; } - (BOOL) setConnectionOption:(int) option withArgument:(id) arg /*" #{NOT YET IMPLEMENTED} This method is to be used for getting special option for a connection, in which case the MCPConnection has to be inited with the init method, then option are selected, finally connection is done using one of the connect methods: !{ MCPConnection *theConnect = [[MCPConnection alloc] init]; [theConnect setConnectionOption: option withArgument: arg]; [theConnect connectToHost:albert.com withLogin:@"toto" password:@"albert" port:0]; .... } "*/ { // So far do nothing except for testing if it's proper time for setting option // What about if some option where setted and a connection is made again with connectTo... if ((mConnected) || (! mConnection)) { return FALSE; } return YES; } - (BOOL) connectWithLogin:(NSString *) login password:(NSString *) pass host:(NSString *) host port:(int) port socket:(NSString *) socket /*" The method used by !{initToHost:withLogin:password:usingPort:} and !{initToSocket:withLogin:password:}. Same information and use of the parameters: - login is the user name - pass is the password corresponding to the user name - host is the hostname or IP adress - port is the TCP port to use to connect. If port = 0, uses the default port from mysql.h - socket is the path to the socket (for the localhost) The socket is used if the host is set to !{@"localhost"}, to an empty or a !{nil} string For the moment the implementation might not be safe if you have a nil pointer to one of the NSString* variables (underestand: I don't know what the result will be). "*/ { #warning What to do if one of the string is a nil pointer? const char *theLogin = [self cStringFromString:login]; const char *theHost = [self cStringFromString:host]; const char *thePass = [self cStringFromString:pass]; const char *theSocket = [self cStringFromString:socket]; void *theRet; if (mConnected) { // Disconnect if it was already connected mysql_close(mConnection); mConnection = NULL; mConnected = NO; [self init]; } if ([host isEqualToString:@""]) { theHost = NULL; } if (theSocket == NULL) { theSocket = kMCPConnectionDefaultSocket; } theRet = mysql_real_connect(mConnection, theHost, theLogin, thePass, NULL, port, theSocket, kMCPConnectionDefaultOption); if (theRet != mConnection) { return mConnected = NO; } mEncoding = [MCPConnection encodingForMySQLEncoding:mysql_character_set_name(mConnection)]; /* NSLog (@"Default encoding is %@\n", [NSString localizedNameOfStringEncoding:[NSString defaultCStringEncoding]]); NSLog (@"MySQL encoding is %@\n", [NSString localizedNameOfStringEncoding:mEncoding]); fprintf(MCPConnectionLogFile,"MySQLEncoding : %s\n", (const char *)[[NSString localizedNameOfStringEncoding:mEncoding] cString]); */ return mConnected = YES; } - (BOOL) selectDB:(NSString *) dbName /*" Selects a database to work with. The MCPConnection object needs to be properly inited and connected to a server. If a connection is not yet set or the selection of the database didn't work, returns NO. Returns YES in normal cases where the database is properly selected. So far, if dbName is a nil pointer it will return NO (as if it cannot connect), most likely this will throw an exception in the future. "*/ { if (dbName == nil) { #warning Should throw an exception, illegal string pointer (nil) // Here we should throw an exception, impossible to select a databse if the string is indeed a nil pointer return NO; } if (mConnected) { const char *theDBName = [self cStringFromString:dbName]; if (mysql_select_db(mConnection, theDBName) == NULL) { return YES; } } return NO; } - (NSString *) getLastErrorMessage /*" Returns a string with the last MySQL error message on the connection. "*/ { if (mConnection) { return [self stringWithCString:mysql_error(mConnection)]; } else { return [NSString stringWithString:@"No connection initailized yet (MYSQL* still NULL)\n"]; } } - (unsigned int) getLastErrorID /*" Returns the ErrorID of the last MySQL error on the connection. "*/ { if (mConnection) { return mysql_errno(mConnection); } return kMCPConnection_Not_Inited; } - (BOOL) isConnected /*" Returns YES if the MCPConnection is connected to a DB, NO otherwise. "*/ { return mConnected; } - (BOOL)checkConnection /*" Checks if the connection to the server is still on. If not, tries to reconnect (changing no parameters from the MYSQL pointer). This method just uses mysql_ping(). "*/ { return (BOOL)(! mysql_ping(mConnection)); } - (NSString *) prepareBinaryData:(NSData *) theData /*" Takes a NSData object and transform it in a proper string for sending to the server in between quotes. "*/ { const char *theCDataBuffer = [theData bytes]; unsigned int theLength = [theData length]; char *theCEscBuffer = (char *)calloc(sizeof(char),(theLength*2) + 1); NSString *theReturn; mysql_real_escape_string(mConnection, theCEscBuffer, theCDataBuffer, theLength); theReturn = [self stringWithCString:theCEscBuffer]; free (theCEscBuffer); return theReturn; } - (NSString *) prepareString:(NSString *) theString /*" Takes a string and escape any special character (like single quote : ') so that the string can be used directly in a query. "*/ { const char *theCStringBuffer = [self cStringFromString:theString]; unsigned int theLength; char *theCEscBuffer; NSString *theReturn; if (theString == nil) { #pragma warning This is not the best solution, here we loose difference between NULL and empty string. // In the mean time, no one should call this method on a nil string, the test should be done before by the user of this method. return @""; } theLength = strlen(theCStringBuffer); theCEscBuffer = (char *)calloc(sizeof(char),(theLength * 2) + 1); mysql_real_escape_string(mConnection, theCEscBuffer, theCStringBuffer, theLength); theReturn = [self stringWithCString:theCEscBuffer]; free (theCEscBuffer); return theReturn; } - (MCPResult *) queryString:(NSString *) query /*" Takes a query string and return an MCPResult object holding the result of the query. The returned MCPResult is not retained, the client is responsible for that (it's autoreleased before being returned). If no field are present in the result (like in an insert query), will return nil (#{difference from previous version implementation}). Though, if their is at least one field the result will be non nil (even if no row are selected). Note that if you want to use this method with binary data (in the query), you should use !{prepareBinaryData:} to include the binary data in the query string. Also if you want to include in your query a string containing any special character (\, ', " ...) then you should use !{prepareString}. "*/ { MCPResult *theResult = [MCPResult alloc]; const char *theCQuery = [self cStringFromString:query]; int theQueryCode; // Temp for debugging: /* NSMutableData *theDefCQuery = [NSMutableData dataWithData:[query dataUsingEncoding:[NSString defaultCStringEncoding] allowLossyConversion:YES]]; NSMutableData *theIso1CQuery = [NSMutableData dataWithData:[query dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:YES]]; const char *theDCQuery, *theICQuery; [theDefCQuery increaseLengthBy:1]; [theIso1CQuery increaseLengthBy:1]; theDCQuery = [theDefCQuery bytes]; theICQuery = [theIso1CQuery bytes]; */ // NSLog (@"In queryString, query is : %s -in ObjC : %@-\n", theCQuery, query); /* fprintf(MCPConnectionLogFile,"C string (MySQL enco.) : "); fwrite((const void *)theCQuery, strlen(theCQuery), 1, MCPConnectionLogFile); fprintf(MCPConnectionLogFile,"\nC string (default enco.) : "); fwrite((const void *)theDCQuery, strlen(theDCQuery), 1, MCPConnectionLogFile); fprintf(MCPConnectionLogFile,"\nC string (iso1 enco.) : "); fwrite((const void *)theICQuery, strlen(theICQuery), 1, MCPConnectionLogFile); fprintf(MCPConnectionLogFile,"\n"); */ if ((theQueryCode = mysql_query(mConnection, theCQuery)) == NULL) { if (mysql_field_count(mConnection) != 0) { theResult = [theResult initWithMySQLPtr:mConnection encoding:mEncoding]; } else { // NSLog (@"Query worked but gives no output\n"); // [theResult init]; return nil; } } else { NSLog (@"Problem in queryString error code is : %d, query is : %s -in ObjC : %@-\n", theQueryCode, theCQuery, query); theResult = [theResult init]; } if (theResult) { [theResult autorelease]; } return theResult; } - (my_ulonglong) affectedRows /*" Returns the number of affected rows by the last query. "*/ { if (mConnected) { return mysql_affected_rows(mConnection); } return 0; } - (my_ulonglong) insertId /*" If the last query was an insert in a table having a autoindex column, returns the id (autoindexed field) of the last row inserted. "*/ { if (mConnected) { return mysql_insert_id(mConnection); } return 0; } - (MCPResult *) listDBs /*" Just a fast wrapper for the more complex !{listDBsWithPattern:} method. "*/ { return [self listDBsLike:nil]; } - (MCPResult *) listDBsLike:(NSString *) dbsName /*" Returns a list of database which name correspond to the SQL regular expression in 'pattern'. The comparison is done with wild card extension : % and _. The result should correspond to the queryString:@"SHOW databases [LIKE wild]"; but implemented with mysql_list_dbs. If an empty string or nil is passed as pattern, all databases will be shown. "*/ { MCPResult *theResult = [MCPResult alloc]; MYSQL_RES *theResPtr; if ((dbsName == nil) || ([dbsName isEqualToString:@""])) { if (theResPtr = mysql_list_dbs(mConnection, NULL)) { [theResult initWithResPtr: theResPtr encoding: mEncoding]; } else { [theResult init]; } } else { const char *theCDBsName = (const char *)[[dbsName dataUsingEncoding: mEncoding allowLossyConversion: YES] bytes]; if (theResPtr = mysql_list_dbs(mConnection, theCDBsName)) { [theResult initWithResPtr: theResPtr encoding: mEncoding]; } else { [theResult init]; } } if (theResult) { [theResult autorelease]; } return theResult; } - (MCPResult *) listTables /*" Make sure a DB is selected (with !{selectDB:} method) first. "*/ { return [self listTablesLike:nil]; } - (MCPResult *) listTablesLike:(NSString *) tablesName /*" From within a database, give back the list of table which name correspond to tablesName (with wild card %, _ extension). Correspond to queryString:@"SHOW tables [LIKE wild]"; uses mysql_list_tables function. If an empty string or nil is passed as tablesName, all tables will be shown. WARNING: #{produce an error if no databases are selected} (with !{selectDB:} for example). "*/ { MCPResult *theResult = [MCPResult alloc]; MYSQL_RES *theResPtr; if ((tablesName == nil) || ([tablesName isEqualToString:@""])) { if (theResPtr = mysql_list_tables(mConnection, NULL)) { [theResult initWithResPtr: theResPtr encoding: mEncoding]; } else { [theResult init]; } } else { const char *theCTablesName = (const char *)[[tablesName dataUsingEncoding: mEncoding allowLossyConversion: YES] bytes]; if (theResPtr = mysql_list_tables(mConnection, theCTablesName)) { [theResult initWithResPtr: theResPtr encoding: mEncoding]; } else { [theResult init]; } } if (theResult) { [theResult autorelease]; } return theResult; } - (MCPResult *) listTablesFromDB:(NSString *) dbName like:(NSString *) tablesName /*" List tables in DB specified by dbName and corresponding to pattern. This method indeed issues a !{SHOW TABLES FROM dbName LIKE ...} query to the server. This is done this way to make sure the selected DB is not changed by this method. "*/ { MCPResult *theResult; if ((tablesName == nil) || ([tablesName isEqualToString:@""])) { NSString *theQuery = [NSString stringWithFormat:@"SHOW TABLES FROM %@", dbName]; theResult = [self queryString:theQuery]; } else { NSString *theQuery = [NSString stringWithFormat:@"SHOW COLUMNS FROM %@ LIKE '%@'", dbName, tablesName]; theResult = [self queryString:theQuery]; } return theResult; } - (MCPResult *)listFieldsFromTable:(NSString *)tableName /*" Just a fast wrapper for the more complex list !{listFieldsWithPattern:forTable:} method. "*/ { return [self listFieldsFromTable:tableName like:nil]; } - (MCPResult *) listFieldsFromTable:(NSString *) tableName like:(NSString *) fieldsName /*" Show all the fields of the table tableName which name correspond to pattern (with wild card expansion : %,_). Indeed, and as recommanded from mysql reference, this method is NOT using mysql_list_fields but the !{queryString:} method. If an empty string or nil is passed as fieldsName, all fields (of tableName) will be returned. "*/ { MCPResult *theResult; if ((fieldsName == nil) || ([fieldsName isEqualToString:@""])) { NSString *theQuery = [NSString stringWithFormat:@"SHOW COLUMNS FROM %@", tableName]; theResult = [self queryString:theQuery]; } else { NSString *theQuery = [NSString stringWithFormat:@"SHOW COLUMNS FROM %@ LIKE '%@'", tableName, fieldsName]; theResult = [self queryString:theQuery]; } return theResult; } - (NSString *) clientInfo /*" Returns a string giving the client library version. "*/ { return [self stringWithCString:mysql_get_client_info()]; } - (NSString *) hostInfo /*" Returns a string giving information on the host of the DB server. "*/ { return [self stringWithCString:mysql_get_host_info(mConnection)]; } - (NSString *) serverInfo /*" Returns a string giving the server version. "*/ { if (mConnected) { return [self stringWithCString: mysql_get_server_info(mConnection)]; } return @""; } - (NSNumber *) protoInfo /*" Returns the number of the protocole used to transfer info from server to client "*/ { return [NSNumber numberWithUnsignedInt:mysql_get_proto_info(mConnection)]; } - (MCPResult *) listProcesses /*" Lists active process "*/ { MCPResult *theResult = [MCPResult alloc]; MYSQL_RES *theResPtr; if (theResPtr = mysql_list_processes(mConnection)) { [theResult initWithResPtr:theResPtr encoding:mEncoding]; } else { [theResult init]; } if (theResult) { [theResult autorelease]; } return theResult; } /* - (BOOL)createDBWithName:(NSString *)dbName { const char *theDBName = [dbName UTF8String]; if ((mConnected) && (! mysql_create_db(mConnection, theDBName))) { return YES; } return NO; } - (BOOL)dropDBWithName:(NSString *)dbName { const char *theDBName = [dbName UTF8String]; if ((mConnected) && (! mysql_drop_db(mConnection, theDBName))) { return YES; } return NO; } */ - (BOOL) killProcess:(unsigned long) pid /*" Kills the process with the given pid. The users needs the !{Process_priv} privilege. "*/ { int theErrorCode; theErrorCode = mysql_kill(mConnection, pid); return (theErrorCode) ? NO : YES; } - (void) disconnect /*" Disconnects a connected MCPConnection object; used by !{dealloc:} method. "*/ { if (mConnected) { mysql_close(mConnection); mConnection = NULL; } mConnected = NO; return; } - (void)dealloc /*" The standard deallocation method for MCPConnection objects. "*/ { [self disconnect]; [super dealloc]; return; } - (void) setEncoding:(NSStringEncoding) theEncoding /*" Sets the encoding used by the server for data transfert. Used to make sure the output of the query result is ok even for non-ascii characters The character set (encoding) used by the db is passed to the MCPConnection object upon connection, so most likely the encoding (from -encoding) method is already the proper one. That is to say : It's unlikely you will need to call this method directly, and #{if ever you use it, do it at your own risks}. "*/ { mEncoding = theEncoding; } - (NSStringEncoding) encoding /*" Gets the encoding for the connection "*/ { return mEncoding; } - (const char *) cStringFromString:(NSString *) theString /*" For internal use only. Transforms a NSString to a C type string (ending with \0) using the character set from the MCPConnection. Lossy conversions are enabled. "*/ { NSMutableData *theData; if (! theString) { return (const char *)NULL; } theData = [NSMutableData dataWithData:[theString dataUsingEncoding:mEncoding allowLossyConversion:YES]]; [theData increaseLengthBy:1]; return (const char *)[theData bytes]; } - (NSString *) stringWithCString:(const char *) theCString /*" Returns a NSString from a C style string encoded with the character set of theMCPConnection. "*/ { NSData * theData; NSString * theString; if (theCString == NULL) { return @""; } theData = [NSData dataWithBytes:theCString length:(strlen(theCString))]; theString = [[NSString alloc] initWithData:theData encoding:mEncoding]; if (theString) { [theString autorelease]; } return theString; } - (NSString *) stringWithText:(NSData *) theTextData /*" Use the string encoding to convert the returned NSData to a string (for a Text field) "*/ { NSString * theString; if (theTextData == nil) { return nil; } theString = [[NSString alloc] initWithData:theTextData encoding:mEncoding]; if (theString) { [theString autorelease]; } return theString; } @end --- NEW FILE: MCPFastQueries.h --- // // MCPFastQueries.h // SMySQL // // Created by Serge Cohen (ser...@m4...) on Mon Jun 03 2002. // Copyright (c) 2001 Serge Cohen. // // This code is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or any later version. // // This code is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // For a copy of the GNU General Public License, visit <http://www.gnu.org/> or // write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330, // Boston, MA 02111-1307, USA. // // More info at <http://mysql-cocoa.sourceforge.net/> // // $Id: MCPFastQueries.h,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ // $Author: sergecohen $ #import <Foundation/Foundation.h> #import "MCPConnection.h" @interface MCPConnection (MCPFastQueries) /*" For insert queries, get directly the Id of the newly inserted row "*/ - (my_ulonglong) insertQuery:(NSString *) aQuery; - (my_ulonglong) updateQuery:(NSString *) aQuery; /*" Returns directly a proper NS object, or a collection (NSArray, NSDictionary...). "*/ - (id) getFirstFieldFromQuery:(NSString *) aQuery; - (id) getFirstRowFromQuery:(NSString *) aQuery asType:(MCPReturnType) aType; - (id) getAllRowsFromQuery:(NSString *) aQuery asType:(MCPReturnType) aType; - (NSArray *) getQuery:(NSString *) aQuery colWithIndex:(unsigned int) aCol; - (NSArray *) getQuery:(NSString *) aQuery colWithName:(NSString *) aColName; @end --- NEW FILE: MCPFastQueries.m --- // // MCPFastQueries.m // SMySQL // // Created by Serge Cohen (ser...@m4...) on Mon Jun 03 2002. // Copyright (c) 2001 Serge Cohen. // // This code is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or any later version. // // This code is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // For a copy of the GNU General Public License, visit <http://www.gnu.org/> or // write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330, // Boston, MA 02111-1307, USA. // // More info at <http://mysql-cocoa.sourceforge.net/> // // $Id: MCPFastQueries.m,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ // $Author: sergecohen $ #import "MCPResultPlus.h" #import "MCPFastQueries.h" @implementation MCPConnection (MCPFastQueries) /*" !{ $Id: MCPFastQueries.m,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ } This actegory is made up to keep the extra methods out or the core of the framework. Basicly this is the place to add methods which are useful, but are just wrappers to the methods of the core (MCPConnection, MCPResult). The purpous being to have a single line call available for current tasks which otherwise would need a couple of lines and object defined. "*/ - (my_ulonglong) insertQuery:(NSString *) aQuery /*" Send the query aQuery to the server and retrieve the row id if the table have a autoincrement column. Returns 0 if no have been inserted "*/ { [self queryString:aQuery]; return [self insertId]; } - (my_ulonglong) updateQuery:(NSString *) aQuery /*" Send the query aQuery to the server and retrieve the number of affected rows (should work with !{update}, !{delete}, !{insert} and !{select} type of queries). NB: This can also be used with a !{select} query if you are only interested in the number of row complying with the query; you'll get no chance to get the result from the query, except by sending the query again (with !{queryString:}) "*/ { [self queryString:aQuery]; return [self affectedRows]; } - (id) getFirstFieldFromQuery:(NSString *) aQuery /*" Get the first field of the first row of the result from the query (aQuery). Should return nil if no object at all are selected. "*/ { MCPResult *theResult = [self queryString:aQuery]; return [[theResult fetchRowAsType:MCPTypeArray] objectAtIndex:0]; } - (id) getFirstRowFromQuery:(NSString *) aQuery asType:(MCPReturnType) aType /*" Get the firdst row of the result from the query aQuery, in a collection of type determined by aType (MCPTypeArray or MCPTypeDictionary) "*/ { MCPResult *theResult = [self queryString:aQuery]; return [theResult fetchRowAsType:aType]; } - (id) getAllRowsFromQuery:(NSString *) aQuery asType:(MCPReturnType) aType /*" Get a bidimensional table of the whole rows of the result from the query aQuery. The type of the result is choosen by aType, it can be (MCPTypeArray, MCPTypeDictionary, MCPTypeFlippedArray & MCPTypeFlippedDictionary). Description of the types can be found in method !{fetch2DResultAsType:}. "*/ { MCPResult *theResult = [self queryString:aQuery]; return [theResult fetch2DResultAsType:aType]; } - (NSArray *) getQuery:(NSString *) aQuery colWithIndex:(unsigned int) aCol /*" Get a column (as an NSArray) of the result from the query aQuery. The column is choosen from it's index, starting from 0. "*/ { MCPResult *theResult = [self queryString:aQuery]; return [theResult fetchColAtIndex:aCol]; } - (NSArray *) getQuery:(NSString *) aQuery colWithName:(NSString *) aColName /*" Get a column (as an NSArray) of the result from the query aQuery. The column is choosen from it's name. "*/ { MCPResult *theResult = [self queryString:aQuery]; return [theResult fetchColWithName:aColName]; } @end --- NEW FILE: MCPNull.h --- // // MCPNull.h // SMySQL // // Created by Serge Cohen (ser...@m4...) on Sun Jun 02 2002. // Copyright (c) 2001 Serge Cohen. // // This code is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or any later version. // // This code is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // For a copy of the GNU General Public License, visit <http://www.gnu.org/> or // write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330, // Boston, MA 02111-1307, USA. // // More info at <http://mysql-cocoa.sourceforge.net/> // // $Id: MCPNull.h,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ // $Author: sergecohen $ #import <Foundation/Foundation.h> @interface NSObject (MCPNSNullTest) /*" Addin to NSObject. "*/ - (BOOL) isNSNull; @end --- NEW FILE: MCPNull.m --- // // MCPNull.m // SMySQL // // Created by Serge Cohen (ser...@m4...) on Sun Jun 02 2002. // Copyright (c) 2001 Serge Cohen. // // This code is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or any later version. // // This code is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // For a copy of the GNU General Public License, visit <http://www.gnu.org/> or // write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330, // Boston, MA 02111-1307, USA. // // More info at <http://mysql-cocoa.sourceforge.net/> // // $Id: MCPNull.m,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ // $Author: sergecohen $ #import "MCPNull.h" @implementation NSObject (MCPNSNullTest) /*" !{ $Id: MCPNull.m,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ } This Category is meant to make any kind of object the possible target to the test (isNSNull) "*/ - (BOOL) isNSNull { return [self isMemberOfClass:[NSNull class]]; } @end --- NEW FILE: MCPResult.h --- // // MCPResult.h // SMySQL // // Created by serge cohen (ser...@m4...) on Sat Dec 08 2001. // Copyright (c) 2001 Serge Cohen. // // This code is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or any later version. // // This code is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // For a copy of the GNU General Public License, visit <http://www.gnu.org/> or // write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330, // Boston, MA 02111-1307, USA. // // More info at <http://mysql-cocoa.sourceforge.net/> // // $Id: MCPResult.h,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ // $Author: sergecohen $ #import <Foundation/Foundation.h> #import "mysql.h" #import "SMySQLConstants.h" @interface MCPResult : NSObject { MYSQL_RES *mResult; /*"The MYSQL_RES structure of the C API"*/ NSArray *mNames; /*"An NSArray holding the name of the columns"*/ NSDictionary *mMySQLLocales; /*"A Locales dictionary to define the locales of MySQL"*/ NSStringEncoding mEncoding; /*"The encoding used by MySQL server, to ISO-1 default"*/ unsigned int mNumOfFields; /*"The number of fields in the result"*/ } /*" Class maintenance "*/ + (void) initialize; /*" Init used #{only} by #{MCPConnection} "*/ - (id) initWithMySQLPtr:(MYSQL *) mySQLPtr encoding:(NSStringEncoding) theEncoding; - (id) initWithResPtr:(MYSQL_RES *) mySQLResPtr encoding:(NSStringEncoding) theEncoding; - (id) init; /*" General info on the result "*/ - (my_ulonglong) numOfRows; - (unsigned int) numOfFields; /*" Getting the rows "*/ - (void) dataSeek:(my_ulonglong) row; - (id) fetchRowAsType:(MCPReturnType) aType; - (NSArray *) fetchRowAsArray; - (NSDictionary *) fetchRowAsDictionary; /*" Getting information on columns "*/ - (NSArray *) fetchFieldsName; - (id) fetchTypesAsType:(MCPReturnType) aType; - (NSArray *) fetchTypesAsArray; - (NSDictionary *) fetchTypesAsDictionary; - (BOOL) isBlobAtIndex:(unsigned int) index; - (BOOL) isBlobForKey:(NSString *) key; /*" Text data convertion to string "*/ - (NSString *) stringWithText:(NSData *) theTextData; /*" Utility method "*/ - (NSString *) description; /*" End of the scope... "*/ - (void) dealloc; /*" Private methods, internal use only "*/ - (const char *) cStringFromString:(NSString *) theString; - (NSString *) stringWithCString:(const char *) theCString; @end --- NEW FILE: MCPResult.m --- // // MCPResult.m // SMySQL // // Created by serge cohen (ser...@m4...) on Sat Dec 08 2001. // Copyright (c) 2001 Serge Cohen. // // This code is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or any later version. // // This code is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // For a copy of the GNU General Public License, visit <http://www.gnu.org/> or // write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330, // Boston, MA 02111-1307, USA. // // More info at <http://mysql-cocoa.sourceforge.net/> // // $Id: MCPResult.m,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ // $Author: sergecohen $ #import "MCPConnection.h" #import "MCPNull.h" #import "MCPResult.h" NSCalendarDate *MCPYear0000; @implementation MCPResult /*" !{ $Id: MCPResult.m,v 1.1 2003/10/11 18:48:07 sergecohen Exp $ } Hold the results of a query to a MySQL database server. It correspond to the MYSQL_RES structure of the C API, and to the statement handle of the PERL DBI/DBD. Uses the !{mysql_store_result()} function from the C API. This object is generated only by a MCPConnection object, in this way (see #{MCPConnection} documentation): !{ MCPConnection *theConnec = [MCPConnection alloc]; MCPResult *theRes; NSDictionnary *theDict; NSArray *theColNames; int i, j; theConnec = [theConnec initToHost::albert.com withLogin:@"toto" password:@"albert" port:0]; [theConnec selectDB:@"db1"]; theRes = [theConnec queryString:@"select * from table1"]; theColNames = [theRes fetchFiedlsName]; i = 0; while (theDict = [theRes fetchRowAsDictionary]){ NSLog(@"Row : %d\n", i); for (j=0; j<[theColNames count]; j++) { NSLog(@" Field : %@, contain : %@\n", [theColNames objectAtInex:j], [theDict objectForKey:[theColNames objectAtIndex:j]]); } i++; } } "*/ + (void) initialize /*" Initialize the class version to 2.0.0 "*/ { if (self = [MCPResult class]) { [self setVersion:020000]; // Ma.Mi.Re -> MaMiRe MCPYear0000 = [[NSCalendarDate dateWithTimeIntervalSinceReferenceDate:-63146822400.0] retain]; [MCPYear0000 setCalendarFormat:@"%Y"]; } return; } - (id) initWithMySQLPtr:(MYSQL *) mySQLPtr encoding:(NSStringEncoding) theEncoding /*" initialise a MCPResult, it is used internally by MCPConnection !{queryString:} method: the only proper way to get a running MCPResult object. "*/ { self = [super init]; mEncoding = theEncoding; if (mResult) { mysql_free_result(mResult); mResult = NULL; } if (mNames) { [mNames release]; mNames = NULL; } mResult = mysql_store_result(mySQLPtr); if (mResult) { mNumOfFields = mysql_num_fields(mResult); } else { mNumOfFields = 0; } /* if (mResult == NULL) { [self autorelease]; return nil; } */ if (mMySQLLocales == NULL) { mMySQLLocales = [[MCPConnection getMySQLLocales] retain]; } return self; } - (id) initWithResPtr:(MYSQL_RES *) mySQLResPtr encoding:(NSStringEncoding) theEncoding /*" This metod it is used internally by MCPConnection object when it have already a MYSQL_RES object to initialise MCPResult object. Initialise a MCPResult with the MYSQL_RES pointer (returned by such a function as mysql_list_dbs). NB: MCPResult should be made by using one of the method of MCPConnection. "*/ { self = [super init]; mEncoding = theEncoding; if (mResult) { mysql_free_result(mResult); mResult = NULL; } if (mNames) { [mNames release]; mNames = NULL; } mResult = mySQLResPtr; if (mResult) { mNumOfFields = mysql_num_fields(mResult); } else { mNumOfFields = 0; } /* if (mResult == NULL) { [self autorelease]; return nil; } */ if (mMySQLLocales == NULL) { mMySQLLocales = [[MCPConnection getMySQLLocales] retain]; } return self; } - (id) init /*" Empty init, normaly of NO use to the user, again, MCPResult should be made through calls to MCPConnection "*/ { self = [super init]; mEncoding = [MCPConnection defaultMySQLEncoding]; if (mResult) { mysql_free_result(mResult); mResult = NULL; } if (mNames) { [mNames release]; mNames = NULL; } if (mMySQLLocales == NULL) { mMySQLLocales = [[MCPConnection getMySQLLocales] retain]; } mNumOfFields = 0; return self; } - (my_ulonglong) numOfRows /*" Return the number of rows selected by the query. "*/ { if (mResult) { return mysql_num_rows(mResult); } return 0; } - (unsigned int) numOfFields /*" Return the number of fields selected by the query. As a side effect it forces an update of the number of fields. "*/ { if (mResult) { return mNumOfFields = mysql_num_fields(mResult); } return mNumOfFields = 0; } - (void) dataSeek:(my_ulonglong) row /*" Go to a precise row in the selected result. 0 is the very first row "*/ { my_ulonglong theRow = (row < 0)? 0 : row; theRow = (theRow < [self numOfRows])? theRow : ([self numOfRows]-1); mysql_data_seek(mResult,theRow); return; } - (id) fetchRowAsType:(MCPReturnType) aType /*" Return the next row of the result as a collection of type defined by aType (namely MCPTypeArray or MCPTypeDictionary). Each field of the row is made into a proper object to hold the info (NSNumber, NSString...). This method returned directly the #{mutable} object generated while going through all the columns "*/ { MYSQL_ROW theRow; unsigned long *theLengths; MYSQL_FIELD *theField; int i; id theReturn; if (mResult == NULL) { // If there is no results, returns nil, as after the last row... return nil; } theRow = mysql_fetch_row(mResult); if (theRow == NULL) { return nil; } switch (aType) { case MCPTypeArray: theReturn = [NSMutableArray arrayWithCapacity:mNumOfFields]; break; case MCPTypeDictionary: if (mNames == nil) { [self fetchFieldsName]; } theReturn = [NSMutableDictionary dictionaryWithCapacity:mNumOfFields]; break; default : NSLog (@"Unknown type : %d, will return an Array!\n", aType); theReturn = [NSMutableArray arrayWithCapacity:mNumOfFields]; break; } theLengths = mysql_fetch_lengths(mResult); theField = mysql_fetch_fields(mResult); for (i=0; i<mNumOfFields; i++) { id theCurrentObj; if (theRow[i] == NULL) { theCurrentObj = [NSNull null]; } else { char *theData = calloc(sizeof(char),theLengths[i]+1); char *theUselLess; memcpy(theData, theRow[i],theLengths[i]); theData[theLengths[i]] = '\0'; switch (theField[i].type) { case FIELD_TYPE_TINY: case FIELD_TYPE_SHORT: case FIELD_TYPE_INT24: case FIELD_TYPE_LONG: theCurrentObj = [NSNumber numberWithLong:atol(theData)]; break; case FIELD_TYPE_LONGLONG: theCurrentObj = [NSNumber numberWithLongLong:strtoq(theData, &theUselLess, 0)]; break; case FIELD_TYPE_DECIMAL: case FIELD_TYPE_FLOAT: case FIELD_TYPE_DOUBLE: theCurrentObj = [NSNumber numberWithDouble:atof(theData)]; break; case FIELD_TYPE_TIMESTAMP: // Indeed one should check which format it is (14,12...2) and get the corresponding format string // a switch on theLength[i] would do that... // Here it will crash if it's not default presentation : TIMESTAMP(14) theCurrentObj = [NSCalendarDate dateWithString:[NSString stringWithUTF8String:theData] calendarFormat:@"%Y%m%d%H%M%S"]; [theCurrentObj setCalendarFormat:@"%Y-%m-%d %H:%M:%S"]; break; case FIELD_TYPE_DATE: theCurrentObj = [NSCalendarDate dateWithString:[NSString stringWithUTF8String:theData] calendarFormat:@"%Y-%m-%d"]; [theCurrentObj setCalendarFormat:@"%Y-%m-%d"]; break; case FIELD_TYPE_TIME: // Pass them back as string for the moment... not TIME object in Cocoa (so far) theCurrentObj = [NSString stringWithUTF8String:theData]; break; case FIELD_TYPE_DATETIME: theCurrentObj = [NSCalendarDate dateWithString:[NSString stringWithCString:theData] calendarFormat:@"%Y-%m-%d %H:%M:%S"]; [theCurrentObj setCalendarFormat:@"%Y-%m-%d %H:%M:%S"]; break; case FIELD_TYPE_YEAR: theCurrentObj = [NSCalendarDate dateWithString:[NSString stringWithCString:theData] calendarFormat:@"%Y"]; [theCurrentObj setCalendarFormat:@"%Y"]; // MySQL is not able to save years before 1900, and then gives a column of 0000, unfortunately, NSCalendarDate // doesn't accept the string @"0000" in the method datewithString: calendarFormat:@"%Y"... if (! theCurrentObj) { theCurrentObj = MCPYear0000; } // Debugging // NSLog(@"The Yeear is : %@, the field is %s\n", theCurrentObj, theData); // End break; case FIELD_TYPE_VAR_STRING: case FIELD_TYPE_STRING: theCurrentObj = [self stringWithCString:theData]; break; case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: theCurrentObj = [NSData dataWithBytes:theData length:theLengths[i]]; break; case FIELD_TYPE_SET: theCurrentObj = [self stringWithCString:theData]; break; case FIELD_TYPE_ENUM: theCurrentObj = [self stringWithCString:theData]; break; case FIELD_TYPE_NULL: theCurrentObj = [NSNull null]; break; case FIELD_TYPE_NEWDATE: // Don't know what the format for this type is... theCurrentObj = [self stringWithCString:theData]; break; default: NSLog (@"in fetchRowAsDictionary : Unknown type : %d for column %d, send back a NSData object", (int)theField[i].type, (int)i); theCurrentObj = [NSData dataWithBytes:theData length:theLengths[i]]; break; } free(theData); // Some of the creators return nil object... if (theCurrentObj == nil) { theCurrentObj = [NSNull null]; } } switch (aType) { case MCPTypeArray : [theReturn addObject:theCurrentObj]; break; case MCPTypeDictionary : [theReturn setObject:theCurrentObj forKey:[mNames objectAtIndex:i]]; break; default : [theReturn addObject:theCurrentObj]; break; } } return theReturn; } - (NSArray *) fetchRowAsArray /*" Return the next row of the result as an array, the index in select field order, the object a proper object for handling the information in the field (NSString, NSNumber ...). Just a #{typed} wrapper for method !{fetchRosAsType:} (with arg MCPTypeArray). NB: Returned object is immutable. "*/ { NSMutableArray *theArray = [self fetchRowAsType:MCPTypeArray]; if (theArray) { return [NSArray arrayWithArray:theArray]; } else { return nil; } } - (NSDictionary *) fetchRowAsDictionary /*" Return the next row of the result as a dictionary, the key being the field name, the object a proper object for handling the information in the field (NSString, NSNumber ...). Just a #{typed} wrapper for method !{fetchRosAsType:} (with arg MCPTypeDictionary). NB: Returned object is immutable. "*/ { NSMutableDictionary *theDict = [self fetchRowAsType:MCPTypeDictionary]; if (theDict) { return [NSDictionary dictionaryWithDictionary:theDict]; } else { return nil; } } - (NSArray *) fetchFieldsName /*" Generate the mNames if not already generated, and return it. mNames is a NSArray holding the names of the fields(columns) of the results "*/ { unsigned int theNumFields; int i; NSMutableArray *theNamesArray; MYSQL_FIELD *theField; if (mNames) { return mNames; } if (mResult == NULL) { // If no results, give an empty array. Maybe it's better to give a nil pointer? return (mNames = [[NSArray array] retain]); } theNumFields = [self numOfFields]; theNamesArray = [NSMutableArray arrayWithCapacity: theNumFields]; theField = mysql_fetch_fields(mResult); for (i=0; i<theNumFields; i++) { NSString *theName = [self stringWithCString:theField[i].name]; if ((theName) && (![theName isEqualToString:@""])) { [theNamesArray addObject:theName]; } else { [theNamesArray addObject:[NSString stringWithFormat:@"Column %d", i]]; } } return (mNames = [[NSArray arrayWithArray:theNamesArray] retain]); } - (id) fetchTypesAsType:(MCPReturnType) aType /*" Return a collection of the fields's type. The type of collection is choosen by the aType variable (MCPTypeArray or MCPTypeDictionary). This method returned directly the #{mutable} object generated while going through all the columns "*/ { int i; id theTypes; MYSQL_FIELD *theField; if (mResult == NULL) { // If no results, give an empty array. Maybe it's better to give a nil pointer? return nil; } switch (aType) { case MCPTypeArray: theTypes = [NSMutableArray arrayWithCapacity:mNumOfFields]; break; case MCPTypeDictionary: if (mNames == nil) { [self fetchFieldsName]; } theTypes = [NSMutableDictionary dictionaryWithCapacity:mNumOfFields]; break; default : NSLog (@"Unknown type : %d, will return an Array!\n", aType); theTypes = [NSMutableArray arrayWithCapacity:mNumOfFields]; break; } theField = mysql_fetch_fields(mResult); for (i=0; i<mNumOfFields; i++) { NSString *theType; switch (theField[i].type) { case FIELD_TYPE_TINY: theType = @"tiny"; break; case FIELD_TYPE_SHORT: theType = @"short"; break; case FIELD_TYPE_LONG: theType = @"long"; break; case FIELD_TYPE_INT24: theType = @"int24"; break; case FIELD_TYPE_LONGLONG: theType = @"longlong"; break; case FIELD_TYPE_DECIMAL: theType = @"decimal"; break; case FIELD_TYPE_FLOAT: theType = @"float"; break; case FIELD_TYPE_DOUBLE: theType = @"double"; break; case FIELD_TYPE_TIMESTAMP: theType = @"timestamp"; break; case FIELD_TYPE_DATE: theType = @"date"; break; case FIELD_TYPE_TIME: theType = @"time"; break; case FIELD_TYPE_DATETIME: theType = @"datetime"; break; case FIELD_TYPE_YEAR: theType = @"year"; break; case FIELD_TYPE_VAR_STRING: theType = @"varstring"; break; case FIELD_TYPE_STRING: theType = @"string"; break; case FIELD_TYPE_TINY_BLOB: theType = @"tinyblob"; break; case FIELD_TYPE_BLOB: theType = @"blob"; break; case FIELD_TYPE_MEDIUM_BLOB: theType = @"mediumblob"; break; case FIELD_TYPE_LONG_BLOB: theType = @"longblob"; break; case FIELD_TYPE_SET: theType = @"set"; break; case FIELD_TYPE_ENUM: theType = @"enum"; break; case FIELD_TYPE_NULL: theType = @"null"; break; case FIELD_TYPE_NEWDATE: theType = @"newdate"; break; default: theType = @"unknown"; NSLog (@"in fetchTypesAsArray : Unknown type for column %d of the MCPResult, type = %d", (int)i, (int)theField[i].type); break; } switch (aType) { case MCPTypeArray : [theTypes addObject:theType]; break; case MCPTypeDictionary : [theTypes setObject:theType forKey:[mNames objectAtIndex:i]]; break; default : [theTypes addObject:theType]; break; } } return theTypes; } - (NSArray *) fetchTypesAsArray /*" Return an array of the fields' types. NB: Returned object is immutable. "*/ { NSMutableArray *theArray = [self fetchTypesAsType:MCPTypeArray]; if (theArray) { return [NSArray arrayWithArray:theArray]; } else { return nil; } } - (NSDictionary*) fetchTypesAsDictionary /*" Return a dictionnary of the fields' types (keys are the fields' names). NB: Returned object is immutable. "*/ { NSMutableDictionary *theDict = [self fetchTypesAsType:MCPTypeDictionary]; if (theDict) { return [NSDictionary dictionaryWithDictionary:theDict]; } else { return nil; } } - (BOOL) isBlobAtIndex:(unsigned int) index /*" Return YES if the field with the given index is a BLOB. It should be used to discriminates between BLOBs and TEXTs. #{NOT YET IMPLEMENTED}, return YES for both BLOBs and TEXTs... "*/ { BOOL theRet; unsigned int theNumFields; MYSQL_FIELD *theField; if (mResult == NULL) { // If no results, give an empty array. Maybe it's better to give a nil pointer? return (NO); } theNumFields = [self numOfFields]; theField = mysql_fetch_fields(mResult); if (index >= theNumFields) { // Out of range... should raise an exception theRet = NO; } else { switch(theField[index].type) { case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: theRet = YES; break; default: theRet = NO; break; } } return theRet; } - (BOOL) isBlobForKey:(NSString *) key /*" Return YES if the field (by name) with the given index is a BLOB. It should be used to discriminates between BLOBs and TEXTs. #{NOT YET IMPLEMENTED}, return YES for both BLOBs and TEXTs... "*/ { BOOL theRet; unsigned int theNumFields, index; MYSQL_FIELD *theField; if (mResult == NULL) { // If no results, give an empty array. Maybe it's better to give a nil pointer? return (NO); } if (mNames == NULL) { [self fetchFieldsName]; } theNumFields = [self numOfFields]; theField = mysql_fetch_fields(mResult); if ((index = [mNames in... [truncated message content] |