aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h39
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m73
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPKit.h1
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPResult.m336
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m3
-rw-r--r--Source/SPCopyTable.m6
-rw-r--r--Source/SPCustomQuery.m3
-rw-r--r--Source/SPTableContent.m45
-rw-r--r--sequel-pro.xcodeproj/project.pbxproj9
9 files changed, 319 insertions, 196 deletions
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h
new file mode 100644
index 00000000..60a7febf
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h
@@ -0,0 +1,39 @@
+//
+// $Id$
+//
+// MCPGeometryData.h
+// sequel-pro
+//
+// Created by Hans-Jörg Bibiko on October 07, 2010
+//
+// 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://code.google.com/p/sequel-pro/>
+
+#import <Cocoa/Cocoa.h>
+#import <Foundation/Foundation.h>
+
+@interface MCPGeometryData : NSObject <NSCoding, NSCopying>
+{
+ char *geoBuffer;
+ NSUInteger bufferLength;
+}
+
+- (id)initWithData:(NSData*)geoData;
++ (id)dataWithData:(NSData*)geoData;
+- (NSString*)description;
+- (NSUInteger)length;
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m
new file mode 100644
index 00000000..9f7ac19a
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m
@@ -0,0 +1,73 @@
+//
+// $Id$
+//
+// MCPGeometryData.m
+// sequel-pro
+//
+// Created by Hans-Jörg Bibiko on October 07, 2010
+//
+// 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://code.google.com/p/sequel-pro/>
+
+#import "MCPGeometryData.h"
+
+
+@implementation MCPGeometryData
+
+- (id)copyWithZone:(NSZone *)zone { return [self retain]; }
+
+- (id)init
+{
+ if ((self = [super init])) {
+ geoBuffer = nil;
+ bufferLength = 0;
+ }
+ return self;
+}
+
+- (id)initWithData:(NSData*)geoData
+{
+ if ((self = [self init])) {
+ bufferLength = [geoData length];
+ geoBuffer = malloc(bufferLength);
+ memcpy(geoBuffer, [geoData bytes], bufferLength);
+ }
+ return self;
+}
+
+
++ (id)dataWithData:(NSData*)geoData
+{
+ return [[[MCPGeometryData alloc] initWithData:geoData] autorelease];
+}
+
+- (NSString*)description
+{
+ return [[NSData dataWithBytes:geoBuffer length:bufferLength] description];
+}
+
+- (NSUInteger)length
+{
+ return bufferLength;
+}
+
+- (void)dealloc
+{
+ if(geoBuffer && bufferLength) free(geoBuffer);
+ [super dealloc];
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPKit.h b/Frameworks/MCPKit/MCPFoundationKit/MCPKit.h
index 11d2c72e..b83ebb69 100644
--- a/Frameworks/MCPKit/MCPFoundationKit/MCPKit.h
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPKit.h
@@ -37,5 +37,6 @@
#import <MCPKit/MCPResultPlus.h>
#import <MCPKit/MCPFastQueries.h>
#import <MCPKit/MCPConnectionProxy.h>
+#import <MCPKit/MCPGeometryData.h>
#import "mysql.h"
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m b/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m
index be8a85eb..82b0636e 100644
--- a/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m
@@ -30,6 +30,7 @@
#import "MCPNull.h"
#import "MCPNumber.h"
#import "MCPResult.h"
+#import "MCPGeometryData.h"
NSCalendarDate *MCPYear0000;
@@ -196,28 +197,28 @@ const OUR_CHARSET our_charsets60[] =
/**
* 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.
+ * 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];
+ * 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);
+ * 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++;
+ * i++;
* }
*/
@@ -245,12 +246,12 @@ const OUR_CHARSET our_charsets60[] =
mEncoding = [MCPConnection defaultMySQLEncoding];
mReturnDataAsStrings = NO;
mTimeZone = nil;
-
+
if (mResult) {
mysql_free_result(mResult);
mResult = NULL;
}
-
+
if (mNames) {
[mNames release];
mNames = nil;
@@ -258,12 +259,12 @@ const OUR_CHARSET our_charsets60[] =
mNumOfFields = 0;
}
-
- return self;
+
+ return self;
}
/**
- * Initialise a MCPResult, it is used internally by MCPConnection !{queryString:} method: the only proper
+ * 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
@@ -272,19 +273,19 @@ const OUR_CHARSET our_charsets60[] =
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);
}
@@ -292,12 +293,12 @@ const OUR_CHARSET our_charsets60[] =
mNumOfFields = 0;
}
}
-
+
return self;
}
/**
- * This metod is used internally by MCPConnection object when it have already a MYSQL_RES object to initialise
+ * 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.
*/
@@ -307,19 +308,19 @@ const OUR_CHARSET our_charsets60[] =
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);
}
@@ -327,8 +328,8 @@ const OUR_CHARSET our_charsets60[] =
mNumOfFields = 0;
}
}
-
- return self;
+
+ return self;
}
#pragma mark -
@@ -342,7 +343,7 @@ const OUR_CHARSET our_charsets60[] =
if (mResult) {
return mysql_num_rows(mResult);
}
-
+
return 0;
}
@@ -354,7 +355,7 @@ const OUR_CHARSET our_charsets60[] =
if (mResult) {
return mNumOfFields = mysql_num_fields(mResult);
}
-
+
return mNumOfFields = 0;
}
@@ -376,23 +377,23 @@ const OUR_CHARSET our_charsets60[] =
*/
- (id)fetchRowAsType:(MCPReturnType)aType
{
- MYSQL_ROW theRow;
- unsigned long *theLengths;
- MYSQL_FIELD *theField;
- NSInteger i;
- id theReturn;
-
+ MYSQL_ROW theRow;
+ unsigned long *theLengths;
+ MYSQL_FIELD *theField;
+ NSInteger 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];
@@ -408,13 +409,13 @@ const OUR_CHARSET our_charsets60[] =
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 {
@@ -422,7 +423,7 @@ const OUR_CHARSET our_charsets60[] =
//char *theUselLess;
memcpy(theData, theRow[i],theLengths[i]);
theData[theLengths[i]] = '\0';
-
+
switch (theField[i].type) {
case FIELD_TYPE_TINY:
case FIELD_TYPE_SHORT:
@@ -445,60 +446,64 @@ const OUR_CHARSET our_charsets60[] =
case FIELD_TYPE_NEWDATE: // Don't know what the format for this type is...
theCurrentObj = [NSString stringWithCString:theData encoding:mEncoding];
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)) {
+ 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 dataWithData:[NSData dataWithBytes:theData length:theLengths[i]]];
+ break;
+
default:
NSLog (@"in fetchRowAsType : Unknown type : %ld for column %ld, send back a NSData object", (NSInteger)theField[i].type, (NSInteger)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 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
+ * 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).
@@ -508,12 +513,12 @@ const OUR_CHARSET our_charsets60[] =
- (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
+ * 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).
@@ -541,20 +546,20 @@ const OUR_CHARSET our_charsets60[] =
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);
-
+ theField = mysql_fetch_fields(mResult);
+
for (i=0; i<theNumFields; i++) {
NSString *theName = [self stringWithCString:theField[i].name];
if ((theName) && (![theName isEqualToString:@""])) {
@@ -564,12 +569,12 @@ const OUR_CHARSET our_charsets60[] =
[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
+ * 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
@@ -579,12 +584,12 @@ const OUR_CHARSET our_charsets60[] =
NSInteger 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];
@@ -600,9 +605,9 @@ const OUR_CHARSET our_charsets60[] =
theTypes = [NSMutableArray arrayWithCapacity:mNumOfFields];
break;
}
-
+
theField = mysql_fetch_fields(mResult);
-
+
for (i=0; i<mNumOfFields; i++) {
NSString *theType;
switch (theField[i].type) {
@@ -676,12 +681,15 @@ const OUR_CHARSET our_charsets60[] =
case FIELD_TYPE_NEWDATE:
theType = @"newdate";
break;
+ case FIELD_TYPE_GEOMETRY:
+ theType = @"geometry";
+ break;
default:
theType = @"unknown";
NSLog (@"in fetchTypesAsArray : Unknown type for column %ld of the MCPResult, type = %ld", (NSInteger)i, (NSInteger)theField[i].type);
break;
}
-
+
switch (aType) {
case MCPTypeArray :
[theTypes addObject:theType];
@@ -694,7 +702,7 @@ const OUR_CHARSET our_charsets60[] =
break;
}
}
-
+
return theTypes;
}
@@ -706,7 +714,7 @@ const OUR_CHARSET our_charsets60[] =
- (NSArray *)fetchTypesAsArray
{
NSMutableArray *theArray = [self fetchTypesAsType:MCPTypeArray];
-
+
return (theArray) ? [NSArray arrayWithArray:theArray] : nil;
}
@@ -718,7 +726,7 @@ const OUR_CHARSET our_charsets60[] =
- (NSDictionary*) fetchTypesAsDictionary
{
NSMutableDictionary *theDict = [self fetchTypesAsType:MCPTypeDictionary];
-
+
return (theDict) ? [NSDictionary dictionaryWithDictionary:theDict] : nil;
}
@@ -728,62 +736,62 @@ const OUR_CHARSET our_charsets60[] =
- (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:[NSNumber numberWithInteger: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 */
+
+ /* 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]]
+ [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]]
+ // [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"];
@@ -802,34 +810,34 @@ const OUR_CHARSET our_charsets60[] =
// [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
+ [fieldStructure setObject:[self mysqlTypeToStringForType:theField[i].type
+ withCharsetNr:theField[i].charsetnr
withFlags:theField[i].flags
- withLength:theField[i].length
+ withLength:theField[i].length
] forKey:@"type"];
-
+
/* Table type group*/
- [fieldStructure setObject:[self mysqlTypeToGroupForType:theField[i].type
- withCharsetNr:theField[i].charsetnr
+ [fieldStructure setObject:[self mysqlTypeToGroupForType:theField[i].type
+ withCharsetNr:theField[i].charsetnr
withFlags:theField[i].flags
] forKey:@"typegrouping"];
-
+
[structureResult addObject:fieldStructure];
-
+
}
-
+
return structureResult;
-
+
}
/**
@@ -840,15 +848,15 @@ const OUR_CHARSET our_charsets60[] =
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 (index >= theNumFields) {
// Out of range... should raise an exception
theRet = 0;
@@ -856,7 +864,7 @@ const OUR_CHARSET our_charsets60[] =
else {
theRet = theField[index].flags;
}
-
+
return theRet;
}
@@ -868,39 +876,39 @@ const OUR_CHARSET our_charsets60[] =
NSUInteger theRet;
NSUInteger index;
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 {
index = [mNames indexOfObject:key];
-
+
theRet = theField[index].flags;
}
-
+
return theRet;
}
/**
- * Return YES if the field with the given index is a BLOB. It should be used to discriminates between BLOBs
+ * 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
+ * #{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
+ * #{NOTE} That the current version handles properly TEXT, and returns those as NSString (and not NSData as
* it used to be).
*/
- (BOOL)isBlobAtIndex:(NSUInteger)index
@@ -908,15 +916,15 @@ const OUR_CHARSET our_charsets60[] =
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 (index >= theNumFields) {
// Out of range... should raise an exception
theRet = NO;
@@ -934,18 +942,18 @@ const OUR_CHARSET our_charsets60[] =
break;
}
}
-
+
return theRet;
}
/**
- * Return YES if the field (by name) with the given index is a BLOB. It should be used to discriminates
+ * 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
+ * #{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
+ * #{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
@@ -953,25 +961,25 @@ const OUR_CHARSET our_charsets60[] =
BOOL theRet;
NSUInteger 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 == nil) {
[self fetchFieldNames];
}
-
+
theField = mysql_fetch_fields(mResult);
-
+
if ([mNames indexOfObject:key] == NSNotFound) {
// Non existent key... should raise an exception
theRet = NO;
}
else {
index = [mNames indexOfObject:key];
-
+
switch(theField[index].type) {
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_BLOB:
@@ -984,7 +992,7 @@ const OUR_CHARSET our_charsets60[] =
break;
}
}
-
+
return theRet;
}
@@ -1010,22 +1018,22 @@ const OUR_CHARSET our_charsets60[] =
- (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)
+ * 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
@@ -1039,26 +1047,26 @@ const OUR_CHARSET our_charsets60[] =
NSArray *theRow;
MYSQL_ROW_OFFSET thePosition;
BOOL trunc = [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])
+
+ while (theRow = [self fetchRowAsArray])
{
id theField = [theRow objectAtIndex:i];
-
+
if (trunc) {
if (([theField isKindOfClass:[NSString class]]) && (kLengthOfTruncationForLog < [(NSString *)theField length])) {
theField = [theField substringToIndex:kLengthOfTruncationForLog];
@@ -1067,37 +1075,37 @@ const OUR_CHARSET our_charsets60[] =
theField = [NSData dataWithBytes:[theField bytes] length:kLengthOfTruncationForLog];
}
}
-
- for (i=0; i<(mNumOfFields - 1); i++)
+
+ 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
+ * 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];
}
@@ -1121,38 +1129,38 @@ const OUR_CHARSET our_charsets60[] =
{
// 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 isUnsigned ? (isZerofill? @"DECIMAL UNSIGNED ZEROFILL" : @"DECIMAL UNSIGNED"):
return @"DECIMAL";
case MYSQL_TYPE_TINY:
- // return isUnsigned ? (isZerofill? @"TINYINT UNSIGNED ZEROFILL" : @"TINYINT UNSIGNED"):
+ // return isUnsigned ? (isZerofill? @"TINYINT UNSIGNED ZEROFILL" : @"TINYINT UNSIGNED"):
return @"TINYINT";
case MYSQL_TYPE_SHORT:
- // return isUnsigned ? (isZerofill? @"SMALLINT UNSIGNED ZEROFILL" : @"SMALLINT UNSIGNED"):
+ // return isUnsigned ? (isZerofill? @"SMALLINT UNSIGNED ZEROFILL" : @"SMALLINT UNSIGNED"):
return @"SMALLINT";
case MYSQL_TYPE_LONG:
- // return isUnsigned ? (isZerofill? @"INT UNSIGNED ZEROFILL" : @"INT UNSIGNED"):
+ // return isUnsigned ? (isZerofill? @"INT UNSIGNED ZEROFILL" : @"INT UNSIGNED"):
return @"INT";
case MYSQL_TYPE_FLOAT:
- // return isUnsigned ? (isZerofill? @"FLOAT UNSIGNED ZEROFILL" : @"FLOAT UNSIGNED"):
+ // return isUnsigned ? (isZerofill? @"FLOAT UNSIGNED ZEROFILL" : @"FLOAT UNSIGNED"):
return @"FLOAT";
case MYSQL_TYPE_DOUBLE:
- // return isUnsigned ? (isZerofill? @"DOUBLE UNSIGNED ZEROFILL" : @"DOUBLE UNSIGNED"):
+ // 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 isUnsigned ? (isZerofill? @"BIGINT UNSIGNED ZEROFILL" : @"BIGINT UNSIGNED") :
return @"BIGINT";
case MYSQL_TYPE_INT24:
- // return isUnsigned ? (isZerofill? @"MEDIUMINT UNSIGNED ZEROFILL" : @"MEDIUMINT UNSIGNED") :
+ // return isUnsigned ? (isZerofill? @"MEDIUMINT UNSIGNED ZEROFILL" : @"MEDIUMINT UNSIGNED") :
return @"MEDIUMINT";
case MYSQL_TYPE_DATE:
return @"DATE";
@@ -1281,7 +1289,7 @@ const OUR_CHARSET our_charsets60[] =
return @"geometry";
default:
return @"blobdata";
-
+
}
}
@@ -1291,13 +1299,13 @@ const OUR_CHARSET our_charsets60[] =
- (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";
}
@@ -1307,13 +1315,13 @@ const OUR_CHARSET our_charsets60[] =
- (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";
}
@@ -1324,13 +1332,13 @@ const OUR_CHARSET our_charsets60[] =
- (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;
}
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m b/Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m
index 5883bdc2..7822d896 100644
--- a/Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m
@@ -27,6 +27,7 @@
#import "MCPConnection.h"
#import "MCPNull.h"
#import "MCPNumber.h"
+#import "MCPGeometryData.h"
/**
* IMPORTANT NOTE
@@ -321,7 +322,7 @@ void _bytes2bin(Byte *n, NSUInteger nbytes, NSUInteger len, char *buf);
break;
case FIELD_TYPE_GEOMETRY:
- cellData = [NSData dataWithBytes:theData length:fieldLengths[i]];
+ cellData = [MCPGeometryData dataWithData:[NSData dataWithBytes:theData length:fieldLengths[i]]];
break;
default:
diff --git a/Source/SPCopyTable.m b/Source/SPCopyTable.m
index e53e714a..9d014839 100644
--- a/Source/SPCopyTable.m
+++ b/Source/SPCopyTable.m
@@ -669,8 +669,12 @@ NSInteger MENU_EDIT_COPY_AS_SQL = 2003;
// Retrieve the cell's content
contentString = [tableStorage cellDataAtRow:i column:columnIndex];
+ // TODO it's temporarily
+ if ([contentString isKindOfClass:[MCPGeometryData class]])
+ contentString = [contentString description];
+
// Replace NULLs with their placeholder string
- if ([contentString isNSNull]) {
+ else if ([contentString isNSNull]) {
contentString = [prefs objectForKey:SPNullValue];
// Same for cells for which loading has been deferred - likely blobs
diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m
index 5f658a1d..44ba5987 100644
--- a/Source/SPCustomQuery.m
+++ b/Source/SPCustomQuery.m
@@ -1847,6 +1847,9 @@
if ([theValue isNSNull])
return [prefs objectForKey:SPNullValue];
+ if ([theValue isKindOfClass:[MCPGeometryData class]])
+ return [theValue description];
+
return theValue;
}
else {
diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m
index b620cf0b..cc5eb6bd 100644
--- a/Source/SPTableContent.m
+++ b/Source/SPTableContent.m
@@ -2716,43 +2716,27 @@
*/
- (NSString *)fieldListForQuery
{
- NSInteger i;
- NSMutableArray *fields = [NSMutableArray array];
- NSArray *columnNames = [tableDataInstance columnNames];
- BOOL hasGeometryFields = NO;
+ if (([prefs boolForKey:SPLoadBlobsAsNeeded]) && [dataColumns count]) {
- if (([prefs boolForKey:SPLoadBlobsAsNeeded]) && ([dataColumns count] > 0)) {
+ NSMutableArray *fields = [NSMutableArray arrayWithCapacity:[dataColumns count]];
+ BOOL tableHasBlobs = NO;
+ NSString *fieldName;
- for (i = 0 ; i < [columnNames count]; i++)
- {
- if (![tableDataInstance columnIsBlobOrText:[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"name"]] ) {
- if([tableDataInstance columnIsGeometry:[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"name"]])
- [fields addObject:[NSString stringWithFormat:@"AsText(%@)", [NSArrayObjectAtIndex(columnNames, i) backtickQuotedString]]];
- else
- [fields addObject:[NSArrayObjectAtIndex(columnNames, i) backtickQuotedString]];
- }
+ for (NSDictionary* field in dataColumns)
+ if (![tableDataInstance columnIsBlobOrText:fieldName = [field objectForKey:@"name"]] )
+ [fields addObject:[fieldName backtickQuotedString]];
else {
// For blob/text fields, select a null placeholder so the column count is still correct
[fields addObject:@"NULL"];
+ tableHasBlobs = YES;
}
- }
- return [fields componentsJoinedByString:@","];
- } else {
+ return (tableHasBlobs) ? [fields componentsJoinedByString:@", "] : @"*";
- for (i = 0 ; i < [columnNames count]; i++)
- {
- if([tableDataInstance columnIsGeometry:[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"name"]]) {
- [fields addObject:[NSString stringWithFormat:@"AsText(%@)", [NSArrayObjectAtIndex(columnNames, i) backtickQuotedString]]];
- hasGeometryFields = YES;
- }
- else
- [fields addObject:[NSArrayObjectAtIndex(columnNames, i) backtickQuotedString]];
- }
- if(hasGeometryFields)
- return [fields componentsJoinedByString:@","];
- else
- return @"*";
+ }
+ else {
+
+ return @"*";
}
}
@@ -3416,6 +3400,9 @@
theValue = SPDataStorageObjectAtRowAndColumn(tableValues, rowIndex, columnIndex);
}
+ if([theValue isKindOfClass:[MCPGeometryData class]])
+ return [theValue description];
+
if ([theValue isNSNull])
return [prefs objectForKey:SPNullValue];
diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj
index a2cca3d9..868c7ff0 100644
--- a/sequel-pro.xcodeproj/project.pbxproj
+++ b/sequel-pro.xcodeproj/project.pbxproj
@@ -378,6 +378,8 @@
BCD06FC7120AAACB00C73602 /* SPStringAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1789343A0F30C1DD0097539A /* SPStringAdditions.h */; };
BCD0AD490FBBFC340066EA5C /* SPSQLTokenizer.l in Sources */ = {isa = PBXBuildFile; fileRef = BCD0AD480FBBFC340066EA5C /* SPSQLTokenizer.l */; };
BCE0025D11173D2A009DA533 /* SPFieldMapperController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCE0025C11173D2A009DA533 /* SPFieldMapperController.m */; };
+ BCE97AEE125DC4EC0091ED3C /* MCPGeometryData.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE97AEC125DC4EC0091ED3C /* MCPGeometryData.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ BCE97AEF125DC4EC0091ED3C /* MCPGeometryData.m in Sources */ = {isa = PBXBuildFile; fileRef = BCE97AED125DC4EC0091ED3C /* MCPGeometryData.m */; };
BCEC862012115A30002561DA /* SPQLPluginConnectionBundleWindowTemplate.html in Resources */ = {isa = PBXBuildFile; fileRef = BCEC861F12115A30002561DA /* SPQLPluginConnectionBundleWindowTemplate.html */; };
BCEF78C6115215CA0023F8C2 /* network-small.tif in Resources */ = {isa = PBXBuildFile; fileRef = BCEF78C5115215CA0023F8C2 /* network-small.tif */; };
/* End PBXBuildFile section */
@@ -1021,6 +1023,8 @@
BCD0AD4A0FBBFC480066EA5C /* SPSQLTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPSQLTokenizer.h; sourceTree = "<group>"; };
BCE0025B11173D2A009DA533 /* SPFieldMapperController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPFieldMapperController.h; sourceTree = "<group>"; };
BCE0025C11173D2A009DA533 /* SPFieldMapperController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPFieldMapperController.m; sourceTree = "<group>"; };
+ BCE97AEC125DC4EC0091ED3C /* MCPGeometryData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPGeometryData.h; sourceTree = "<group>"; };
+ BCE97AED125DC4EC0091ED3C /* MCPGeometryData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCPGeometryData.m; sourceTree = "<group>"; };
BCEC861D12115A2B002561DA /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = English; path = English.lproj/SPQLPluginConnectionBundleWindowTemplate.html; sourceTree = "<group>"; };
BCEC862112115A3D002561DA /* German */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = German; path = German.lproj/SPQLPluginConnectionBundleWindowTemplate.html; sourceTree = "<group>"; };
BCEF78C5115215CA0023F8C2 /* network-small.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "network-small.tif"; sourceTree = "<group>"; };
@@ -1468,6 +1472,8 @@
583B779810386B0200B21F7E /* MCPStreamingResult.m */,
17DCC5C5115C202700F89A00 /* MCPStringAdditions.h */,
17B7B5C6101603B200F057DE /* MCPConnectionProxy.h */,
+ BCE97AEC125DC4EC0091ED3C /* MCPGeometryData.h */,
+ BCE97AED125DC4EC0091ED3C /* MCPGeometryData.m */,
);
path = MCPFoundationKit;
sourceTree = "<group>";
@@ -2179,6 +2185,7 @@
17B7B5F1101603D200F057DE /* typelib.h in Headers */,
17DCC5C7115C202700F89A00 /* MCPStringAdditions.h in Headers */,
58587B5A11B4437C00D129ED /* NSNotificationAdditions.h in Headers */,
+ BCE97AEE125DC4EC0091ED3C /* MCPGeometryData.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2351,7 +2358,6 @@
isa = PBXProject;
buildConfigurationList = C05733CB08A9546B00998B17 /* Build configuration list for PBXProject "sequel-pro" */;
compatibilityVersion = "Xcode 3.1";
- developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
@@ -2586,6 +2592,7 @@
17B7B5E1101603B200F057DE /* MCPResultPlus.m in Sources */,
583B77D4103870C800B21F7E /* MCPStreamingResult.m in Sources */,
58587B5B11B4437C00D129ED /* NSNotificationAdditions.m in Sources */,
+ BCE97AEF125DC4EC0091ED3C /* MCPGeometryData.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};