From 95d2e4acc393e91aa70ed4c71daa1f776454a936 Mon Sep 17 00:00:00 2001 From: Bibiko Date: Thu, 7 Oct 2010 14:15:07 +0000 Subject: =?UTF-8?q?=E2=80=A2=20removed=20approach=20to=20query=20spatial?= =?UTF-8?q?=20data=20by=20using=20AsText()=20since=20it=20breaks=20some=20?= =?UTF-8?q?column=20definition=20approaches=20-=20instead=20introduced=20a?= =?UTF-8?q?=20new=20MCPKit=20class=20MCPGeometryData=20-=20up=20to=20now?= =?UTF-8?q?=20the=20spatial=20data=20will=20be=20displayed=20as=20hex=20by?= =?UTF-8?q?tes=20-=20work=20on=20it=20will=20come=20soon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MCPKit/MCPFoundationKit/MCPGeometryData.h | 39 +++ .../MCPKit/MCPFoundationKit/MCPGeometryData.m | 73 +++++ Frameworks/MCPKit/MCPFoundationKit/MCPKit.h | 1 + Frameworks/MCPKit/MCPFoundationKit/MCPResult.m | 336 +++++++++++---------- .../MCPKit/MCPFoundationKit/MCPStreamingResult.m | 3 +- Source/SPCopyTable.m | 6 +- Source/SPCustomQuery.m | 3 + Source/SPTableContent.m | 45 +-- sequel-pro.xcodeproj/project.pbxproj | 9 +- 9 files changed, 319 insertions(+), 196 deletions(-) create mode 100644 Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h create mode 100644 Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m 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 + +#import +#import + +@interface MCPGeometryData : NSObject +{ + 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 + +#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 #import #import +#import #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= 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 = ""; }; BCE0025B11173D2A009DA533 /* SPFieldMapperController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPFieldMapperController.h; sourceTree = ""; }; BCE0025C11173D2A009DA533 /* SPFieldMapperController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPFieldMapperController.m; sourceTree = ""; }; + BCE97AEC125DC4EC0091ED3C /* MCPGeometryData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPGeometryData.h; sourceTree = ""; }; + BCE97AED125DC4EC0091ED3C /* MCPGeometryData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCPGeometryData.m; sourceTree = ""; }; BCEC861D12115A2B002561DA /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = English; path = English.lproj/SPQLPluginConnectionBundleWindowTemplate.html; sourceTree = ""; }; BCEC862112115A3D002561DA /* German */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = German; path = German.lproj/SPQLPluginConnectionBundleWindowTemplate.html; sourceTree = ""; }; BCEF78C5115215CA0023F8C2 /* network-small.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "network-small.tif"; sourceTree = ""; }; @@ -1468,6 +1472,8 @@ 583B779810386B0200B21F7E /* MCPStreamingResult.m */, 17DCC5C5115C202700F89A00 /* MCPStringAdditions.h */, 17B7B5C6101603B200F057DE /* MCPConnectionProxy.h */, + BCE97AEC125DC4EC0091ED3C /* MCPGeometryData.h */, + BCE97AED125DC4EC0091ED3C /* MCPGeometryData.m */, ); path = MCPFoundationKit; sourceTree = ""; @@ -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; }; -- cgit v1.2.3