aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2012-03-17 15:32:00 +0000
committerrowanbeentje <rowan@beent.je>2012-03-17 15:32:00 +0000
commitac8ebfe4bba6d7da6edad87c75b174156d919621 (patch)
tree08a3c2843d3c520090f40e6341b26043a7ccf014 /Frameworks/MCPKit/MCPFoundationKit/MCPResult.m
parent8886d935e933c6239aa9b35e900d96f7d07527c7 (diff)
parenteab6df4de773259f90dd5a1d25e44ca4d2765bbf (diff)
downloadsequelpro-ac8ebfe4bba6d7da6edad87c75b174156d919621.tar.gz
sequelpro-ac8ebfe4bba6d7da6edad87c75b174156d919621.tar.bz2
sequelpro-ac8ebfe4bba6d7da6edad87c75b174156d919621.zip
Merge in the SPMySQL Framework. This new framework should provide much of the functionality required from MCPKit and is based around its interface for relatively easy integration.
Externally visible changes as a result of this merge: - Speed improvements, particularly when loading large data sets - Stability improvements, particularly related to connection state after the connection is dropped (eg Issue #1256) - Improved support for new MySQL data types, which should address Issue #1052. - Database structure retrieval and query cancellation now use a single persistent helper connection instead of lots of connections on-demand. This should help Issue #1097. - More internal commands now use queries instead of MySQL functions; for example USE queries are now used to trigger database selection, improving transcripts. This addresses Issue #1247. - Improved internal encoding work; while this needs support within the UI, it lays the foundation for issues like Issue #1280. Code improvements: - Much improved class layouts including extensive category usage - Improved documentation across framework methods - Support for fast enumeration across result objects - Rewrite fixes use of a number of deprecate functions - Much less code duplication across result set types - Improved encapsultation within the framework, limiting the number of methods exposed, and also not exposing all the MySQL headers From the Readme file: The SPMySQL Framework is intended to provide a stable MySQL connection framework, with the ability to run text-based queries and rapidly retrieve result sets with conversion from MySQL data types to Cocoa objects. SPMySQL.framework has an interface loosely based around that provided by MCPKit by Serge Cohen and Bertrand Mansion (http://mysql-cocoa.sourceforge.net/), and in particular the heavily modified Sequel Pro version (http://www.sequelpro.com/). It is a full rewrite of the original framework, although it includes code from patches implementing the following Sequel Pro functionality, largely contributed by Hans-Jörg Bibiko, Stuart Connolly, Jakob Egger, and Rowan Beentje: - Connection locking (Jakob et al) - Ping & keepalive (Rowan et al) - Query cancellation (Rowan et al) - Delegate setup (Stuart et al) - SSL support (Rowan et al) - Connection checking (Rowan et al) - Version state (Stuart et al) - Maximum packet size control (Hans et al) - Result multithreading and streaming (Rowan et al) - Improved encoding support & switching (Rowan et al) - Database structure; moved to inside the app (Hans et al) - Query reattempts and error-handling approach (Rowan et al) - Geometry result class (Hans et al) - Connection proxy (Stuart et al)
Diffstat (limited to 'Frameworks/MCPKit/MCPFoundationKit/MCPResult.m')
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPResult.m1354
1 files changed, 0 insertions, 1354 deletions
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m b/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m
deleted file mode 100644
index f112a02d..00000000
--- a/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m
+++ /dev/null
@@ -1,1354 +0,0 @@
-//
-// $Id$
-//
-// MCPResult.m
-// MCPKit
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on 08/12/2002.
-// Copyright (c) 2001 Serge Cohen. All rights reserved.
-//
-// Forked by the Sequel Pro team (sequelpro.com), April 2009
-//
-// This program 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
-// (at your option) any later version.
-//
-// This program 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.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, 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/>
-// More info at <http://code.google.com/p/sequel-pro/>
-
-#import "MCPConnection.h"
-#import "MCPNull.h"
-#import "MCPNumber.h"
-#import "MCPResult.h"
-#import "MCPGeometryData.h"
-
-NSCalendarDate *MCPYear0000;
-
-const OUR_CHARSET our_charsets60[] =
-{
- {1, "big5","big5_chinese_ci", 1, 2},
- {3, "dec8", "dec8_swedisch_ci", 1, 1},
- {4, "cp850", "cp850_general_ci", 1, 1},
- {6, "hp8", "hp8_english_ci", 1, 1},
- {7, "koi8r", "koi8r_general_ci", 1, 1},
- {8, "latin1", "latin1_swedish_ci", 1, 1},
- {9, "latin2", "latin2_general_ci", 1, 1},
- {10, "swe7", "swe7_swedish_ci", 1, 1},
- {11, "ascii", "ascii_general_ci", 1, 1},
- {12, "ujis", "ujis_japanese_ci", 1, 3},
- {13, "sjis", "sjis_japanese_ci", 1, 2},
- {16, "hebrew", "hebrew_general_ci", 1, 1},
- {18, "tis620", "tis620_thai_ci", 1, 1},
- {19, "euckr", "euckr_korean_ci", 1, 2},
- {22, "koi8u", "koi8u_general_ci", 1, 1},
- {24, "gb2312", "gb2312_chinese_ci", 1, 2},
- {25, "greek", "greek_general_ci", 1, 1},
- {26, "cp1250", "cp1250_general_ci", 1, 1},
- {28, "gbk", "gbk_chinese_ci", 1, 2},
- {30, "latin5", "latin5_turkish_ci", 1, 1},
- {32, "armscii8", "armscii8_general_ci", 1, 1},
- {33, "utf8", "utf8_general_ci", 1, 3},
- {35, "ucs2", "ucs2_general_ci", 2, 2},
- {36, "cp866", "cp866_general_ci", 1, 1},
- {37, "keybcs2", "keybcs2_general_ci", 1, 1},
- {38, "macce", "macce_general_ci", 1, 1},
- {39, "macroman", "macroman_general_ci", 1, 1},
- {40, "cp852", "cp852_general_ci", 1, 1},
- {41, "latin7", "latin7_general_ci", 1, 1},
- {51, "cp1251", "cp1251_general_ci", 1, 1},
- {57, "cp1256", "cp1256_general_ci", 1, 1},
- {59, "cp1257", "cp1257_general_ci", 1, 1},
- {63, "binary", "binary", 1, 1},
- {92, "geostd8", "geostd8_general_ci", 1, 1},
- {95, "cp932", "cp932_japanese_ci", 1, 2},
- {97, "eucjpms", "eucjpms_japanese_ci", 1, 3},
- {2, "latin2", "latin2_czech_cs", 1, 1},
- {5, "latin1", "latin1_german_ci", 1, 1},
- {14, "cp1251", "cp1251_bulgarian_ci", 1, 1},
- {15, "latin1", "latin1_danish_ci", 1, 1},
- {17, "filename", "filename", 1, 5},
- {20, "latin7", "latin7_estonian_cs", 1, 1},
- {21, "latin2", "latin2_hungarian_ci", 1, 1},
- {23, "cp1251", "cp1251_ukrainian_ci", 1, 1},
- {27, "latin2", "latin2_croatian_ci", 1, 1},
- {29, "cp1257", "cp1257_lithunian_ci", 1, 1},
- {31, "latin1", "latin1_german2_ci", 1, 1},
- {34, "cp1250", "cp1250_czech_cs", 1, 1},
- {42, "latin7", "latin7_general_cs", 1, 1},
- {43, "macce", "macce_bin", 1, 1},
- {44, "cp1250", "cp1250_croatian_ci", 1, 1},
- {45, "utf8", "utf8_general_ci", 1, 1},
- {46, "utf8", "utf8_bin", 1, 1},
- {47, "latin1", "latin1_bin", 1, 1},
- {48, "latin1", "latin1_general_ci", 1, 1},
- {49, "latin1", "latin1_general_cs", 1, 1},
- {50, "cp1251", "cp1251_bin", 1, 1},
- {52, "cp1251", "cp1251_general_cs", 1, 1},
- {53, "macroman", "macroman_bin", 1, 1},
- {58, "cp1257", "cp1257_bin", 1, 1},
- {60, "armascii8", "armascii8_bin", 1, 1},
- {65, "ascii", "ascii_bin", 1, 1},
- {66, "cp1250", "cp1250_bin", 1, 1},
- {67, "cp1256", "cp1256_bin", 1, 1},
- {68, "cp866", "cp866_bin", 1, 1},
- {69, "dec8", "dec8_bin", 1, 1},
- {70, "greek", "greek_bin", 1, 1},
- {71, "hebew", "hebrew_bin", 1, 1},
- {72, "hp8", "hp8_bin", 1, 1},
- {73, "keybcs2", "keybcs2_bin", 1, 1},
- {74, "koi8r", "koi8r_bin", 1, 1},
- {75, "koi8u", "koi8u_bin", 1, 1},
- {77, "latin2", "latin2_bin", 1, 1},
- {78, "latin5", "latin5_bin", 1, 1},
- {79, "latin7", "latin7_bin", 1, 1},
- {80, "cp850", "cp850_bin", 1, 1},
- {81, "cp852", "cp852_bin", 1, 1},
- {82, "swe7", "swe7_bin", 1, 1},
- {93, "geostd8", "geostd8_bin", 1, 1},
- {83, "utf8", "utf8_bin", 1, 3},
- {84, "big5", "big5_bin", 1, 2},
- {85, "euckr", "euckr_bin", 1, 2},
- {86, "gb2312", "gb2312_bin", 1, 2},
- {87, "gbk", "gbk_bin", 1, 2},
- {88, "sjis", "sjis_bin", 1, 2},
- {89, "tis620", "tis620_bin", 1, 1},
- {90, "ucs2", "ucs2_bin", 2, 2},
- {91, "ujis", "ujis_bin", 1, 3},
- {94, "latin1", "latin1_spanish_ci", 1, 1},
- {96, "cp932", "cp932_bin", 1, 2},
- {99, "cp1250", "cp1250_polish_ci", 1, 1},
- {98, "eucjpms", "eucjpms_bin", 1, 3},
- {128, "ucs2", "ucs2_unicode_ci", 2, 2},
- {129, "ucs2", "ucs2_icelandic_ci", 2, 2},
- {130, "ucs2", "ucs2_latvian_ci", 2, 2},
- {131, "ucs2", "ucs2_romanian_ci", 2, 2},
- {132, "ucs2", "ucs2_slovenian_ci", 2, 2},
- {133, "ucs2", "ucs2_polish_ci", 2, 2},
- {134, "ucs2", "ucs2_estonian_ci", 2, 2},
- {135, "ucs2", "ucs2_spanish_ci", 2, 2},
- {136, "ucs2", "ucs2_swedish_ci", 2, 2},
- {137, "ucs2", "ucs2_turkish_ci", 2, 2},
- {138, "ucs2", "ucs2_czech_ci", 2, 2},
- {139, "ucs2", "ucs2_danish_ci", 2, 2},
- {140, "ucs2", "ucs2_lithunian_ci", 2, 2},
- {141, "ucs2", "ucs2_slovak_ci", 2, 2},
- {142, "ucs2", "ucs2_spanish2_ci", 2, 2},
- {143, "ucs2", "ucs2_roman_ci", 2, 2},
- {144, "ucs2", "ucs2_persian_ci", 2, 2},
- {145, "ucs2", "ucs2_esperanto_ci", 2, 2},
- {146, "ucs2", "ucs2_hungarian_ci", 2, 2},
- {147, "ucs2", "ucs2_sinhala_ci", 2, 2},
- {192, "utf8mb3", "utf8mb3_general_ci", 1, 3},
- {193, "utf8mb3", "utf8mb3_icelandic_ci", 1, 3},
- {194, "utf8mb3", "utf8mb3_latvian_ci", 1, 3},
- {195, "utf8mb3", "utf8mb3_romanian_ci", 1, 3},
- {196, "utf8mb3", "utf8mb3_slovenian_ci", 1, 3},
- {197, "utf8mb3", "utf8mb3_polish_ci", 1, 3},
- {198, "utf8mb3", "utf8mb3_estonian_ci", 1, 3},
- {119, "utf8mb3", "utf8mb3_spanish_ci", 1, 3},
- {200, "utf8mb3", "utf8mb3_swedish_ci", 1, 3},
- {201, "utf8mb3", "utf8mb3_turkish_ci", 1, 3},
- {202, "utf8mb3", "utf8mb3_czech_ci", 1, 3},
- {203, "utf8mb3", "utf8mb3_danish_ci", 1, 3},
- {204, "utf8mb3", "utf8mb3_lithunian_ci", 1, 3},
- {205, "utf8mb3", "utf8mb3_slovak_ci", 1, 3},
- {206, "utf8mb3", "utf8mb3_spanish2_ci", 1, 3},
- {207, "utf8mb3", "utf8mb3_roman_ci", 1, 3},
- {208, "utf8mb3", "utf8mb3_persian_ci", 1, 3},
- {209, "utf8mb3", "utf8mb3_esperanto_ci", 1, 3},
- {210, "utf8mb3", "utf8mb3_hungarian_ci", 1, 3},
- {211, "utf8mb3", "utf8mb3_sinhala_ci", 1, 3},
- {224, "utf8", "utf8_unicode_ci", 1, 3},
- {225, "utf8", "utf8_icelandic_ci", 1, 3},
- {226, "utf8", "utf8_latvian_ci", 1, 3},
- {227, "utf8", "utf8_romanian_ci", 1, 3},
- {228, "utf8", "utf8_slovenian_ci", 1, 3},
- {229, "utf8", "utf8_polish_ci", 1, 3},
- {230, "utf8", "utf8_estonian_ci", 1, 3},
- {231, "utf8", "utf8_spanish_ci", 1, 3},
- {232, "utf8", "utf8_swedish_ci", 1, 3},
- {233, "utf8", "utf8_turkish_ci", 1, 3},
- {234, "utf8", "utf8_czech_ci", 1, 3},
- {235, "utf8", "utf8_danish_ci", 1, 3},
- {236, "utf8", "utf8_lithuanian_ci", 1, 3},
- {237, "utf8", "utf8_slovak_ci", 1, 3},
- {238, "utf8", "utf8_spanish2_ci", 1, 3},
- {239, "utf8", "utf8_roman_ci", 1, 3},
- {240, "utf8", "utf8_persian_ci", 1, 3},
- {241, "utf8", "utf8_esperanto_ci", 1, 3},
- {242, "utf8", "utf8_hungarian_ci", 1, 3},
- {243, "utf8", "utf8_sinhala_ci", 1, 3},
- {254, "utf8mb3", "utf8mb3_general_cs", 1, 3},
- {0, NULL, NULL, 0, 0}
-};
-
-@implementation MCPResult
-
-/**
- * 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;
- * NSDictionary *theDict;
- * NSArray *theColNames;
- * int i, j;
- *
- * theConnec = [theConnec initToHost:@"albert.com" withLogin:@"toto" password:@"albert" usingPort: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 objectAtIndex:j], [theDict objectForKey:[theColNames objectAtIndex:j]]);
- * }
- * i++;
- * }
- */
-
-/**
- * Initialize the class version to 3.0.1
- */
-+ (void)initialize
-{
- if ((self = [MCPResult class])) {
- [self setVersion:030001]; // Ma.Mi.Re -> MaMiRe
- MCPYear0000 = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:-63146822400.0];
- [MCPYear0000 setCalendarFormat:@"%Y"];
- }
-}
-
-#pragma mark -
-#pragma mark Initialisation
-
-/**
- * Empty init, normaly of NO use to the user, again, MCPResult should be made through calls to MCPConnection
- */
-- (id)init
-{
- if ((self = [super init])) {
- mEncoding = [MCPConnection defaultMySQLEncoding];
- mReturnDataAsStrings = NO;
- mTimeZone = nil;
-
- if (mResult) {
- mysql_free_result(mResult);
- mResult = NULL;
- }
-
- if (mNames) {
- [mNames release];
- mNames = nil;
- }
-
- mNumOfFields = 0;
- }
-
- return self;
-}
-
-/**
- * Initialise a MCPResult, it is used internally by MCPConnection !{queryString:} method: the only proper
- * way to get a running MCPResult object.
- */
-- (id)initWithMySQLPtr:(MYSQL *)mySQLPtr encoding:(NSStringEncoding)iEncoding timeZone:(NSTimeZone *)iTimeZone
-{
- if ((self = [super init])) {
- mEncoding = iEncoding;
- mTimeZone = [iTimeZone retain];
- mReturnDataAsStrings = NO;
-
- if (mResult) {
- mysql_free_result(mResult);
- mResult = NULL;
- }
-
- if (mNames) {
- [mNames release];
- mNames = nil;
- }
-
- mResult = mysql_store_result(mySQLPtr);
-
- if (mResult) {
- mNumOfFields = mysql_num_fields(mResult);
- }
- else {
- mNumOfFields = 0;
- }
- }
-
- return self;
-}
-
-/**
- * This metod 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.
- */
-- (id)initWithResPtr:(MYSQL_RES *)mySQLResPtr encoding:(NSStringEncoding)iEncoding timeZone:(NSTimeZone *)iTimeZone
-{
- if ((self = [super init])) {
- mEncoding = iEncoding;
- mTimeZone = [iTimeZone retain];
- mReturnDataAsStrings = NO;
-
- if (mResult) {
- mysql_free_result(mResult);
- mResult = NULL;
- }
-
- if (mNames) {
- [mNames release];
- mNames = nil;
- }
-
- mResult = mySQLResPtr;
-
- if (mResult) {
- mNumOfFields = mysql_num_fields(mResult);
- }
- else {
- mNumOfFields = 0;
- }
- }
-
- return self;
-}
-
-#pragma mark -
-#pragma mark Result info
-
-/**
- * Return the number of rows selected by the query.
- */
-- (my_ulonglong)numOfRows
-{
- if (mResult) {
- return mysql_num_rows(mResult);
- }
-
- return 0;
-}
-
-/**
- * Return the number of fields selected by the query. As a side effect it forces an update of the number of fields.
- */
-- (NSUInteger)numOfFields
-{
- if (mResult) {
- return mNumOfFields = mysql_num_fields(mResult);
- }
-
- return mNumOfFields = 0;
-}
-
-#pragma mark -
-#pragma mark Rows
-
-/**
- * Go to a precise row in the selected result. 0 is the very first row.
- */
-- (void)dataSeek:(my_ulonglong)row
-{
- my_ulonglong theRow = (row < 1)? 0 : row;
- theRow = (theRow < [self numOfRows]) ? theRow : ([self numOfRows] - 1);
- mysql_data_seek(mResult,theRow);
-}
-
-/**
- *
- */
-- (id)fetchRowAsType:(MCPReturnType)aType
-{
- MYSQL_ROW theRow;
- unsigned long *theLengths;
- MYSQL_FIELD *theField;
- NSUInteger 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 fetchFieldNames];
- }
- theReturn = [NSMutableDictionary dictionaryWithCapacity:mNumOfFields];
- break;
- default :
- NSLog (@"Unknown type : %d, will return an Array!\n", (int)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 = theRow[i];
-
- switch (theField[i].type) {
- case FIELD_TYPE_TINY:
- case FIELD_TYPE_SHORT:
- case FIELD_TYPE_INT24:
- case FIELD_TYPE_LONG:
- case FIELD_TYPE_LONGLONG:
- case FIELD_TYPE_DECIMAL:
- case FIELD_TYPE_NEWDECIMAL:
- case FIELD_TYPE_FLOAT:
- case FIELD_TYPE_DOUBLE:
- case FIELD_TYPE_TIMESTAMP:
- case FIELD_TYPE_DATE:
- case FIELD_TYPE_TIME:
- case FIELD_TYPE_DATETIME:
- case FIELD_TYPE_YEAR:
- case FIELD_TYPE_VAR_STRING:
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_SET:
- case FIELD_TYPE_ENUM:
- case FIELD_TYPE_NEWDATE: // Don't know what the format for this type is...
- theCurrentObj = [[[NSString alloc] initWithBytes:theData length:theLengths[i] encoding:mEncoding] autorelease];
- break;
-
- case FIELD_TYPE_BIT:
- theCurrentObj = [NSString stringWithFormat:@"%u", theData[0]];
- 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]];
-
- // If the field is TEXT and NOT BLOB, or if force-return-as-string is
- // enabled, return a NSString instead of NSData
- if (mReturnDataAsStrings || !(theField[i].flags & BINARY_FLAG)) {
- theCurrentObj = [self stringWithText:theCurrentObj];
- }
-
- break;
-
- case FIELD_TYPE_NULL:
- theCurrentObj = [NSNull null];
- break;
-
- case FIELD_TYPE_GEOMETRY:
- theCurrentObj = [MCPGeometryData dataWithBytes:theData length:theLengths[i]];
- break;
-
- default:
- NSLog (@"in fetchRowAsType : Unknown type : %d for column %lu, send back a NSData object", (int)theField[i].type, (unsigned long)i);
- theCurrentObj = [NSData dataWithBytes:theData length:theLengths[i]];
- break;
- }
-
- // Some of the creators return nil object...
- if (theCurrentObj == nil) {
- theCurrentObj = [NSNull null];
- }
- }
-
- switch (aType) {
- case MCPTypeDictionary :
- [theReturn setObject:theCurrentObj forKey:[mNames objectAtIndex:i]];
- break;
-
- case MCPTypeArray :
- default :
- [theReturn addObject:theCurrentObj];
- break;
- }
- }
-
- return theReturn;
-}
-
-/**
- * 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.
- */
-- (NSArray *)fetchRowAsArray
-{
- NSMutableArray *theArray = [self fetchRowAsType:MCPTypeArray];
-
- return (theArray) ? [NSArray arrayWithArray:theArray] : nil;
-}
-
-/**
- * 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.
- */
-- (NSDictionary *)fetchRowAsDictionary
-{
- NSMutableDictionary *theDict = [self fetchRowAsType:MCPTypeDictionary];
-
- return (theDict) ? [NSDictionary dictionaryWithDictionary:theDict] : nil;
-}
-
-#pragma mark -
-#pragma mark Columns
-
-/**
- * Generate the mNames if not already generated, and return it.
- *
- * mNames is a NSArray holding the names of the fields(columns) of the results.
- */
-- (NSArray *)fetchFieldNames
-{
- NSUInteger i;
- NSUInteger theNumFields;
- 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 %ld", i]];
- }
- }
-
- return (mNames = [[NSArray arrayWithArray:theNamesArray] retain]);
-}
-
-/**
- * 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
- */
-- (id)fetchTypesAsType:(MCPReturnType)aType
-{
- NSUInteger 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 fetchFieldNames];
- }
- theTypes = [NSMutableDictionary dictionaryWithCapacity:mNumOfFields];
- break;
- default :
- NSLog (@"Unknown type : %d, will return an Array!\n", (int)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:
- case FIELD_TYPE_NEWDECIMAL:
- 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;
- case FIELD_TYPE_GEOMETRY:
- theType = @"geometry";
- break;
- default:
- theType = @"unknown";
- NSLog (@"in fetchTypesAsArray : Unknown type for column %lu of the MCPResult, type = %d", (unsigned long)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;
-}
-
-/**
- * Return an array of the fields' types.
- *
- * NB: Returned object is immutable.
- */
-- (NSArray *)fetchTypesAsArray
-{
- NSMutableArray *theArray = [self fetchTypesAsType:MCPTypeArray];
-
- return (theArray) ? [NSArray arrayWithArray:theArray] : nil;
-}
-
-/**
- * Return a dictionnary of the fields' types (keys are the fields' names).
- *
- * NB: Returned object is immutable.
- */
-- (NSDictionary*) fetchTypesAsDictionary
-{
- NSMutableDictionary *theDict = [self fetchTypesAsType:MCPTypeDictionary];
-
- return (theDict) ? [NSDictionary dictionaryWithDictionary:theDict] : nil;
-}
-
-/**
- * Return an array of dicts containg column data of the last executed query
- */
-- (NSArray *)fetchResultFieldsStructure
-{
- MYSQL_FIELD *theField;
-
- NSMutableArray *structureResult = [NSMutableArray array];
-
- NSUInteger i;
- NSUInteger numFields = mysql_num_fields(mResult);
-
- if (mResult == NULL) return nil;
-
- theField = mysql_fetch_fields(mResult);
-
- for (i=0; i < numFields; i++)
- {
- NSMutableDictionary *fieldStructure = [NSMutableDictionary dictionaryWithCapacity:39];
-
- /* Original column position */
- [fieldStructure setObject:[NSString stringWithFormat:@"%llu", (unsigned long long)i] forKey:@"datacolumnindex"];
-
- /* Name of column */
- [fieldStructure setObject:[self stringWithCString:theField[i].name] forKey:@"name"];
- // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].name_length] forKey:@"name_length"];
-
- /* Original column name, if an alias */
- [fieldStructure setObject:[self stringWithCString:theField[i].org_name] forKey:@"org_name"];
- // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].org_name_length] forKey:@"org_name_length"];
-
- /* Table of column if column was a field */
- [fieldStructure setObject:[self stringWithCString:theField[i].table] forKey:@"table"];
- // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].table_length] forKey:@"table_length"];
-
- /* Org table name, if table was an alias */
- [fieldStructure setObject:[self stringWithCString:theField[i].org_table] forKey:@"org_table"];
- // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].org_table_length] forKey:@"org_table_length"];
-
- /* Database for table */
- [fieldStructure setObject:[self stringWithCString:theField[i].db] forKey:@"db"];
- // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].db_length] forKey:@"db_length"];
-
- /* Catalog for table */
- // [fieldStructure setObject:[self stringWithCString:theField[i].catalog] forKey:@"catalog"];
- // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].catalog_length] forKey:@"catalog_length"];
-
- /* Default value (set by mysql_list_fields) */
- // [fieldStructure setObject:[self stringWithCString:theField[i].def] forKey:@"def"];
- // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].def_length] forKey:@"def_length"];
-
- /* Width of column (real length in bytes) */
- [fieldStructure setObject:[NSNumber numberWithUnsignedLongLong:theField[i].length] forKey:@"byte_length"];
- /* Width of column (as in create)*/
- [fieldStructure setObject:[NSNumber numberWithUnsignedLongLong:theField[i].length/[self findCharsetMaxByteLengthPerChar:theField[i].charsetnr]]
- forKey:@"char_length"];
- /* Max width (bytes) for selected set */
- [fieldStructure setObject:[NSNumber numberWithUnsignedLongLong:theField[i].max_length] forKey:@"max_byte_length"];
- /* Max width (chars) for selected set */
- // [fieldStructure setObject:[NSNumber numberWithUnsignedLongLong:theField[i].max_length/[self find_charsetMaxByteLengthPerChar:theField[i].charsetnr]]
- // forKey:@"max_char_length"];
-
- /* Div flags */
- [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].flags] forKey:@"flags"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & NOT_NULL_FLAG) ? YES : NO] forKey:@"null"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & PRI_KEY_FLAG) ? YES : NO] forKey:@"PRI_KEY_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & UNIQUE_KEY_FLAG) ? YES : NO] forKey:@"UNIQUE_KEY_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & MULTIPLE_KEY_FLAG) ? YES : NO] forKey:@"MULTIPLE_KEY_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & BLOB_FLAG) ? YES : NO] forKey:@"BLOB_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & UNSIGNED_FLAG) ? YES : NO] forKey:@"UNSIGNED_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & ZEROFILL_FLAG) ? YES : NO] forKey:@"ZEROFILL_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & BINARY_FLAG) ? YES : NO] forKey:@"BINARY_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & ENUM_FLAG) ? YES : NO] forKey:@"ENUM_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & AUTO_INCREMENT_FLAG) ? YES : NO] forKey:@"AUTO_INCREMENT_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & SET_FLAG) ? YES : NO] forKey:@"SET_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & NUM_FLAG) ? YES : NO] forKey:@"NUM_FLAG"];
- [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & PART_KEY_FLAG) ? YES : NO] forKey:@"PART_KEY_FLAG"];
- // [fieldStructure setObject:[NSNumber numberWithInt:(theField[i].flags & GROUP_FLAG) ? 1 : 0] forKey:@"GROUP_FLAG"];
- // [fieldStructure setObject:[NSNumber numberWithInt:(theField[i].flags & UNIQUE_FLAG) ? 1 : 0] forKey:@"UNIQUE_FLAG"];
- // [fieldStructure setObject:[NSNumber numberWithInt:(theField[i].flags & BINCMP_FLAG) ? 1 : 0] forKey:@"BINCMP_FLAG"];
-
- /* Number of decimals in field */
- [fieldStructure setObject:[NSNumber numberWithUnsignedInteger:theField[i].decimals] forKey:@"decimals"];
-
- /* Character set */
- [fieldStructure setObject:[NSNumber numberWithUnsignedInteger:theField[i].charsetnr] forKey:@"charsetnr"];
- [fieldStructure setObject:[self findCharsetName:theField[i].charsetnr] forKey:@"charset_name"];
- [fieldStructure setObject:[self findCharsetCollation:theField[i].charsetnr] forKey:@"charset_collation"];
-
- /* Table type */
- [fieldStructure setObject:[self mysqlTypeToStringForType:theField[i].type
- withCharsetNr:theField[i].charsetnr
- withFlags:theField[i].flags
- withLength:theField[i].length
- ] forKey:@"type"];
-
- /* Table type group*/
- [fieldStructure setObject:[self mysqlTypeToGroupForType:theField[i].type
- withCharsetNr:theField[i].charsetnr
- withFlags:theField[i].flags
- ] forKey:@"typegrouping"];
-
- [structureResult addObject:fieldStructure];
-
- }
-
- return structureResult;
-
-}
-
-/**
- * Return the MySQL flags of the column at the given index... Can be used to check if a number is signed or not...
- */
-- (NSUInteger)fetchFlagsAtIndex:(NSUInteger)anIndex
-{
- NSUInteger theRet;
- NSUInteger theNumFields;
- MYSQL_FIELD *theField;
-
- if (mResult == NULL) {
- // If no results, give an empty array. Maybe it's better to give a nil pointer?
- return (0);
- }
-
- theNumFields = [self numOfFields];
- theField = mysql_fetch_fields(mResult);
-
- if (anIndex >= theNumFields) {
- // Out of range... should raise an exception
- theRet = 0;
- }
- else {
- theRet = theField[anIndex].flags;
- }
-
- return theRet;
-}
-
-/**
- *
- */
-- (NSUInteger)fetchFlagsForKey:(NSString *)key
-{
- NSUInteger theRet;
- NSUInteger anIndex;
- MYSQL_FIELD *theField;
-
- if (mResult == NULL) {
- // If no results, give an empty array. Maybe it's better to give a nil pointer?
- return (0);
- }
-
- if (mNames == nil) {
- [self fetchFieldNames];
- }
-
- theField = mysql_fetch_fields(mResult);
-
- if ([mNames indexOfObject:key] == NSNotFound) {
- // Non existent key... should raise an exception
- theRet = 0;
- }
- else {
- anIndex = [mNames indexOfObject:key];
-
- theRet = theField[anIndex].flags;
- }
-
- return theRet;
-}
-
-/**
- * Return YES if the field with the given index is a BLOB. It should be used to discriminates between BLOBs
- * and TEXTs.
- *
- * #{DEPRECATED}, This method is not consistent with the C API which is supposed to return YES for BOTH
- * text and blob (and BTW is also deprecated)...
- *
- * #{NOTE} That the current version handles properly TEXT, and returns those as NSString (and not NSData as
- * it used to be).
- */
-- (BOOL)isBlobAtIndex:(NSUInteger)anIndex
-{
- BOOL theRet;
- NSUInteger 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 (anIndex >= theNumFields) {
- // Out of range... should raise an exception
- theRet = NO;
- }
- else {
- switch(theField[anIndex].type) {
- case FIELD_TYPE_TINY_BLOB:
- case FIELD_TYPE_BLOB:
- case FIELD_TYPE_MEDIUM_BLOB:
- case FIELD_TYPE_LONG_BLOB:
- theRet = (theField[anIndex].flags & BINARY_FLAG);
- break;
- default:
- theRet = NO;
- break;
- }
- }
-
- return theRet;
-}
-
-/**
- * Return YES if the field (by name) with the given index is a BLOB. It should be used to discriminates
- * between BLOBs and TEXTs.
- *
- * #{DEPRECATED}, This method is not consistent with the C API which is supposed to return YES for BOTH
- * text and blob (and BTW is also deprecated)...
- *
- * #{NOTE} That the current version handles properly TEXT, and returns those as NSString (and not NSData
- * as it used to be).
- */
-- (BOOL)isBlobForKey:(NSString *)key
-{
- BOOL theRet;
- NSUInteger anIndex;
- 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 == nil) {
- [self fetchFieldNames];
- }
-
- theField = mysql_fetch_fields(mResult);
-
- if ([mNames indexOfObject:key] == NSNotFound) {
- // Non existent key... should raise an exception
- theRet = NO;
- }
- else {
- anIndex = [mNames indexOfObject:key];
-
- switch(theField[anIndex].type) {
- case FIELD_TYPE_TINY_BLOB:
- case FIELD_TYPE_BLOB:
- case FIELD_TYPE_MEDIUM_BLOB:
- case FIELD_TYPE_LONG_BLOB:
- theRet = (theField[anIndex].flags & BINARY_FLAG);
- break;
- default:
- theRet = NO;
- break;
- }
- }
-
- return theRet;
-}
-
-#pragma mark -
-#pragma mark Conversion
-
-/**
- * Set whether the result should return data types as strings. This may be useful
- * for queries where the result may be returned in either string or data form, but
- * will be converted to string for display and use anyway.
- * Note that certain MySQL versions also return data types for strings - eg SHOW
- * commands like SHOW CREATE TABLE or SHOW VARIABLES, and this conversion can be
- * necessary there.
- */
-- (void) setReturnDataAsStrings:(BOOL)alwaysConvertData
-{
- mReturnDataAsStrings = alwaysConvertData;
-}
-
-/**
- * Use the string encoding to convert the returned NSData to a string (for a TEXT field).
- */
-- (NSString *)stringWithText:(NSData *)theTextData
-{
- NSString *theString;
-
- if (theTextData == nil) {
- return nil;
- }
-
- theString = [[NSString alloc] initWithData:theTextData encoding:mEncoding];
-
- if (theString) {
- [theString autorelease];
- }
-
- return theString;
-}
-
-/**
- * Return a (long) string containing the table of results, first line being the fields name, next line(s)
- * the row(s). Useful to have NSLog logging a MCPResult (example).
- */
-- (NSString *)description
-{
- if (mResult == NULL) {
- return @"This is an empty MCPResult\n";
- }
- else {
- NSMutableString *theString = [NSMutableString stringWithCapacity:0];
- NSUInteger i;
- NSArray *theRow;
- MYSQL_ROW_OFFSET thePosition;
- BOOL shouldTruncateFields = [MCPConnection truncateLongField];
-
- // First line, saying we are displaying a MCPResult
- [theString appendFormat:@"MCPResult: (encoding : %ld, dim %ld x %ld)\n", (long)mEncoding, (long)mNumOfFields, (long)[self numOfRows]];
-
- // Second line: the field names, tab separated
- [self fetchFieldNames];
-
- for (i=0; i<(mNumOfFields-1); i++) {
- [theString appendFormat:@"%@\t", [mNames objectAtIndex:i]];
- }
-
- [theString appendFormat:@"%@\n", [mNames objectAtIndex:i]];
- // Next lines, the records (saving current position to put it back after the full display)
- thePosition = mysql_row_tell(mResult);
- [self dataSeek:0];
-
- while ((theRow = [self fetchRowAsArray]))
- {
- id theField = [theRow objectAtIndex:i];
-
- if (shouldTruncateFields) {
- if (([theField isKindOfClass:[NSString class]]) && (kLengthOfTruncationForLog < [(NSString *)theField length])) {
- theField = [theField substringToIndex:kLengthOfTruncationForLog];
- }
- else if (([theField isKindOfClass:[NSData class]]) && (kLengthOfTruncationForLog < [(NSData *)theField length])) {
- theField = [NSData dataWithBytes:[theField bytes] length:kLengthOfTruncationForLog];
- }
- }
-
- for (i=0; i<(mNumOfFields - 1); i++)
- {
- [theString appendFormat:@"%@\t", theField];
- }
-
- [theString appendFormat:@"%@\n", theField];
- }
-
- // Returning to the proper row
- mysql_row_seek(mResult, thePosition);
-
- return theString;
- }
-}
-
-/**
- * For internal use only. Transform a NSString to a C type string (ended with \0) using ethe character set
- * from the MCPConnection. Lossy conversions are enabled.
- */
-- (const char *)cStringFromString:(NSString *)theString
-{
- NSMutableData *theData;
-
- if (!theString) {
- return (const char *)NULL;
- }
-
- theData = [NSMutableData dataWithData:[theString dataUsingEncoding:mEncoding allowLossyConversion:YES]];
- [theData increaseLengthBy:1];
-
- return (const char *)[theData bytes];
-}
-
-/**
- * Return a NSString from a C style string encoded with the character set of theMCPConnection.
- */
-- (NSString *)stringWithCString:(const char *)theCString
-{
- if (theCString == NULL) return @"";
-
- return [NSString stringWithCString:theCString encoding:mEncoding];
-}
-
-#pragma mark -
-#pragma mark Other
-
-/**
- * Convert a mysql_type to a string
- */
-- (NSString *)mysqlTypeToStringForType:(NSUInteger)type withCharsetNr:(NSUInteger)charsetnr withFlags:(NSUInteger)flags withLength:(unsigned long long)length
-{
- // BOOL isUnsigned = (flags & UNSIGNED_FLAG) != 0;
- // BOOL isZerofill = (flags & ZEROFILL_FLAG) != 0;
-
- switch (type) {
- case FIELD_TYPE_BIT:
- return @"BIT";
- case MYSQL_TYPE_DECIMAL:
- case MYSQL_TYPE_NEWDECIMAL:
- //return isUnsigned ? (isZerofill? @"DECIMAL UNSIGNED ZEROFILL" : @"DECIMAL UNSIGNED"):
- return @"DECIMAL";
- case MYSQL_TYPE_TINY:
- // return isUnsigned ? (isZerofill? @"TINYINT UNSIGNED ZEROFILL" : @"TINYINT UNSIGNED"):
- return @"TINYINT";
- case MYSQL_TYPE_SHORT:
- // return isUnsigned ? (isZerofill? @"SMALLINT UNSIGNED ZEROFILL" : @"SMALLINT UNSIGNED"):
- return @"SMALLINT";
- case MYSQL_TYPE_LONG:
- // return isUnsigned ? (isZerofill? @"INT UNSIGNED ZEROFILL" : @"INT UNSIGNED"):
- return @"INT";
- case MYSQL_TYPE_FLOAT:
- // return isUnsigned ? (isZerofill? @"FLOAT UNSIGNED ZEROFILL" : @"FLOAT UNSIGNED"):
- return @"FLOAT";
- case MYSQL_TYPE_DOUBLE:
- // return isUnsigned ? (isZerofill? @"DOUBLE UNSIGNED ZEROFILL" : @"DOUBLE UNSIGNED"):
- return @"DOUBLE";
- case MYSQL_TYPE_NULL:
- return @"NULL";
- case MYSQL_TYPE_TIMESTAMP:
- return @"TIMESTAMP";
- case MYSQL_TYPE_LONGLONG:
- // return isUnsigned ? (isZerofill? @"BIGINT UNSIGNED ZEROFILL" : @"BIGINT UNSIGNED") :
- return @"BIGINT";
- case MYSQL_TYPE_INT24:
- // return isUnsigned ? (isZerofill? @"MEDIUMINT UNSIGNED ZEROFILL" : @"MEDIUMINT UNSIGNED") :
- return @"MEDIUMINT";
- case MYSQL_TYPE_DATE:
- return @"DATE";
- case MYSQL_TYPE_TIME:
- return @"TIME";
- case MYSQL_TYPE_DATETIME:
- return @"DATETIME";
- case MYSQL_TYPE_TINY_BLOB:// should no appear over the wire
- case MYSQL_TYPE_MEDIUM_BLOB:// should no appear over the wire
- case MYSQL_TYPE_LONG_BLOB:// should no appear over the wire
- case MYSQL_TYPE_BLOB:
- {
- BOOL isBlob = (charsetnr == MAGIC_BINARY_CHARSET_NR);
- switch ((NSInteger)length/[self findCharsetMaxByteLengthPerChar:charsetnr]) {
- case 255: return isBlob? @"TINYBLOB":@"TINYTEXT";
- case 65535: return isBlob? @"BLOB":@"TEXT";
- case 16777215: return isBlob? @"MEDIUMBLOB":@"MEDIUMTEXT";
- case 4294967295: return isBlob? @"LONGBLOB":@"LONGTEXT";
- default:
- switch (length) {
- case 255: return isBlob? @"TINYBLOB":@"TINYTEXT";
- case 65535: return isBlob? @"BLOB":@"TEXT";
- case 16777215: return isBlob? @"MEDIUMBLOB":@"MEDIUMTEXT";
- case 4294967295: return isBlob? @"LONGBLOB":@"LONGTEXT";
- default:
- return @"UNKNOWN";
- }
- }
- }
- case MYSQL_TYPE_VAR_STRING:
- if (flags & ENUM_FLAG) {
- return @"ENUM";
- }
- if (flags & SET_FLAG) {
- return @"SET";
- }
- if (charsetnr == MAGIC_BINARY_CHARSET_NR) {
- return @"VARBINARY";
- }
- return @"VARCHAR";
- case MYSQL_TYPE_STRING:
- if (flags & ENUM_FLAG) {
- return @"ENUM";
- }
- if (flags & SET_FLAG) {
- return @"SET";
- }
- if ((flags & BINARY_FLAG) && charsetnr == MAGIC_BINARY_CHARSET_NR) {
- return @"BINARY";
- }
- return @"CHAR";
- case MYSQL_TYPE_ENUM:
- /* This should never happen */
- return @"ENUM";
- case MYSQL_TYPE_YEAR:
- return @"YEAR";
- case MYSQL_TYPE_SET:
- /* This should never happen */
- return @"SET";
- case MYSQL_TYPE_GEOMETRY:
- return @"GEOMETRY";
- default:
- return @"UNKNOWN";
- }
-}
-
-/**
- * Merge mysql_types into type groups
- */
-- (NSString *)mysqlTypeToGroupForType:(NSUInteger)type withCharsetNr:(NSUInteger)charsetnr withFlags:(NSUInteger)flags
-{
- switch(type){
- case FIELD_TYPE_BIT:
- return @"bit";
- case MYSQL_TYPE_TINY:
- case MYSQL_TYPE_SHORT:
- case MYSQL_TYPE_LONG:
- case MYSQL_TYPE_LONGLONG:
- case MYSQL_TYPE_INT24:
- return @"integer";
- case MYSQL_TYPE_FLOAT:
- case MYSQL_TYPE_DOUBLE:
- case MYSQL_TYPE_DECIMAL:
- case MYSQL_TYPE_NEWDECIMAL:
- return @"float";
- case MYSQL_TYPE_YEAR:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_TIMESTAMP:
- return @"date";
- case MYSQL_TYPE_VAR_STRING:
- if (flags & ENUM_FLAG) {
- return @"enum";
- }
- if (flags & SET_FLAG) {
- return @"enum";
- }
- if (charsetnr == MAGIC_BINARY_CHARSET_NR) {
- return @"binary";
- }
- return @"string";
- case MYSQL_TYPE_STRING:
- if (flags & ENUM_FLAG) {
- return @"enum";
- }
- if (flags & SET_FLAG) {
- return @"enum";
- }
- if ((flags & BINARY_FLAG) && charsetnr == MAGIC_BINARY_CHARSET_NR) {
- return @"binary";
- }
- return @"string";
- case MYSQL_TYPE_TINY_BLOB: // should no appear over the wire
- case MYSQL_TYPE_MEDIUM_BLOB: // should no appear over the wire
- case MYSQL_TYPE_LONG_BLOB: // should no appear over the wire
- case MYSQL_TYPE_BLOB:
- {
- if (charsetnr == MAGIC_BINARY_CHARSET_NR) {
- return @"blobdata";
- } else {
- return @"textdata";
- }
- }
- case MYSQL_TYPE_GEOMETRY:
- return @"geometry";
- default:
- return @"blobdata";
-
- }
-}
-
-/**
- * Convert a mysql_charsetnr into a charset name as string
- */
-- (NSString *)findCharsetName:(NSUInteger)charsetnr
-{
- const OUR_CHARSET * c = our_charsets60;
-
- do {
- if (c->nr == charsetnr)
- return [self stringWithCString:c->name];
- ++c;
- } while (c[0].nr != 0);
-
- return @"UNKNOWN";
-}
-
-/**
- * Convert a mysql_charsetnr into a collation name as string
- */
-- (NSString *)findCharsetCollation:(NSUInteger)charsetnr
-{
- const OUR_CHARSET * c = our_charsets60;
-
- do {
- if (c->nr == charsetnr)
- return [self stringWithCString:c->collation];
- ++c;
- } while (c[0].nr != 0);
-
- return @"UNKNOWN";
-}
-
-/**
- * Return the max byte length to store a char by using
- * a specific mysql_charsetnr
- */
-- (NSUInteger)findCharsetMaxByteLengthPerChar:(NSUInteger)charsetnr
-{
- const OUR_CHARSET * c = our_charsets60;
-
- do {
- if (c->nr == charsetnr)
- return c->char_maxlen;
- ++c;
- } while (c[0].nr != 0);
-
- return 1;
-}
-
-#pragma mark -
-
-/**
- * Do one really needs an explanation for this method? Which by the way you should not use...
- */
-- (void) dealloc
-{
- if (mResult) mysql_free_result(mResult);
- if (mNames) [mNames release];
- if (mTimeZone) [mTimeZone release];
-
- [super dealloc];
-}
-
-@end