diff options
-rw-r--r-- | Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h | 25 | ||||
-rw-r--r-- | Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m | 126 | ||||
-rw-r--r-- | Frameworks/MCPKit/MCPFoundationKit/MCPResult.m | 2 | ||||
-rw-r--r-- | Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m | 2 | ||||
-rw-r--r-- | Source/SPCustomQuery.m | 7 | ||||
-rw-r--r-- | Source/SPTableContent.m | 15 |
6 files changed, 161 insertions, 16 deletions
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h index 60a7febf..c37e286d 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.h @@ -25,15 +25,34 @@ #import <Cocoa/Cocoa.h> #import <Foundation/Foundation.h> +enum wkbType +{ + wkb_point = 1, + wkb_linestring = 2, + wkb_polygon = 3, + wkb_multipoint = 4, + wkb_multilinestring = 5, + wkb_multipolygon = 6, + wkb_geometrycollection = 7 +}; + +typedef struct st_point_2d_ +{ + double x; + double y; +} st_point_2d; + @interface MCPGeometryData : NSObject <NSCoding, NSCopying> { - char *geoBuffer; + Byte *geoBuffer; NSUInteger bufferLength; } -- (id)initWithData:(NSData*)geoData; -+ (id)dataWithData:(NSData*)geoData; +- (id)initWithBytes:(Byte*)geoData length:(NSUInteger)length; ++ (id)dataWithBytes:(Byte*)geoData length:(NSUInteger)length; - (NSString*)description; - (NSUInteger)length; +- (NSData*)data; +- (NSString*)wktString; @end diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m index 9f7ac19a..6a41e657 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPGeometryData.m @@ -25,6 +25,11 @@ #import "MCPGeometryData.h" +#define SIZEOF_STORED_UINT32 4 +#define SIZEOF_STORED_DOUBLE 8 +#define POINT_DATA_SIZE (SIZEOF_STORED_DOUBLE*2) +#define WKB_HEADER_SIZE (1+SIZEOF_STORED_UINT32) + @implementation MCPGeometryData - (id)copyWithZone:(NSZone *)zone { return [self retain]; } @@ -38,20 +43,20 @@ return self; } -- (id)initWithData:(NSData*)geoData +- (id)initWithBytes:(Byte*)geoData length:(NSUInteger)length { if ((self = [self init])) { - bufferLength = [geoData length]; + bufferLength = length; geoBuffer = malloc(bufferLength); - memcpy(geoBuffer, [geoData bytes], bufferLength); + memcpy(geoBuffer, geoData, bufferLength); } return self; } -+ (id)dataWithData:(NSData*)geoData ++ (id)dataWithBytes:(Byte*)geoData length:(NSUInteger)length { - return [[[MCPGeometryData alloc] initWithData:geoData] autorelease]; + return [[[MCPGeometryData alloc] initWithBytes:geoData length:length] autorelease]; } - (NSString*)description @@ -64,6 +69,117 @@ return bufferLength; } +- (NSData*)data +{ + return [NSData dataWithBytes:geoBuffer length:bufferLength]; +} + +- (NSString*)wktString +{ + char byteOrder; + UInt32 geoType, c, c1; + st_point_2d aPoint; + NSUInteger ptr; + double x, y; + NSMutableString *wkt = [NSMutableString string]; + NSUInteger i,j; + BOOL raw = NO; + + if (bufferLength < WKB_HEADER_SIZE) + return @"Error"; + + ptr = (raw) ? 0 : 4; + + byteOrder = geoBuffer[ptr]; + + if(byteOrder != 0x1) + return @"Byte order not yet supported"; + + ptr++; + geoType = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32; + + NSData *d; + switch(geoType) { + case wkb_point: + memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + return [NSString stringWithFormat:@"POINT(%.16g %.16g)",aPoint.x, aPoint.y]; + break; + case wkb_linestring: + [wkt setString:@"LINESTRING("]; + c = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32; + for(i=0; i<c; i++) { + memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (i<c-1) ? @"," : @""]; + ptr += POINT_DATA_SIZE; + } + [wkt appendString:@")"]; + return wkt; + break; + case wkb_polygon: + [wkt setString:@"POLYGON("]; + c = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32; + for(i=0; i<c; i++) { + c1 = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32; + [wkt appendString:@"("]; + for(j=0; j<c1; j++) { + memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (j<c1-1) ? @"," : @""]; + ptr += POINT_DATA_SIZE; + } + [wkt appendFormat:@")%@", (i<c-1) ? @"," : @""]; + } + [wkt appendString:@")"]; + return wkt; + break; + case wkb_multipoint: + [wkt setString:@"MULTIPOINT("]; + c = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32+WKB_HEADER_SIZE; + for(i=0; i<c; i++) { + memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (i<c-1) ? @"," : @""]; + ptr += POINT_DATA_SIZE+WKB_HEADER_SIZE; + } + [wkt appendString:@")"]; + return wkt; + break; + case wkb_multilinestring: + [wkt setString:@"MULTILINESTRING("]; + c = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32+WKB_HEADER_SIZE; + for(i=0; i<c; i++) { + c1 = geoBuffer[ptr]; + ptr += SIZEOF_STORED_UINT32; + [wkt appendString:@"("]; + for(j=0; j<c1; j++) { + memcpy(&aPoint, &geoBuffer[ptr], POINT_DATA_SIZE); + [wkt appendFormat:@"%.16g %.16g%@", aPoint.x, aPoint.y, (j<c1-1) ? @"," : @""]; + ptr += POINT_DATA_SIZE; + } + ptr += WKB_HEADER_SIZE; + [wkt appendFormat:@")%@", (i<c-1) ? @"," : @""]; + } + [wkt appendString:@")"]; + return wkt; + break; + case wkb_multipolygon: + // NSLog(@"ml %@", geoData); + + [wkt setString:@"MULTIPOLYGON be patient"]; + break; + case wkb_geometrycollection: + [wkt setString:@"GEOMETRYCOLLECTION be patient"]; + break; + default: + return @"Error geometry type parsing"; + } + return wkt; +} + - (void)dealloc { if(geoBuffer && bufferLength) free(geoBuffer); diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m b/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m index 82b0636e..24d14193 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m @@ -470,7 +470,7 @@ const OUR_CHARSET our_charsets60[] = break; case FIELD_TYPE_GEOMETRY: - theCurrentObj = [MCPGeometryData dataWithData:[NSData dataWithBytes:theData length:theLengths[i]]]; + theCurrentObj = [MCPGeometryData dataWithBytes:theData length:theLengths[i]]; break; default: diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m b/Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m index 7822d896..d26dbafc 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPStreamingResult.m @@ -322,7 +322,7 @@ void _bytes2bin(Byte *n, NSUInteger nbytes, NSUInteger len, char *buf); break; case FIELD_TYPE_GEOMETRY: - cellData = [MCPGeometryData dataWithData:[NSData dataWithBytes:theData length:fieldLengths[i]]]; + cellData = [MCPGeometryData dataWithBytes:theData length:fieldLengths[i]]; break; default: diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m index 44ba5987..a945a53d 100644 --- a/Source/SPCustomQuery.m +++ b/Source/SPCustomQuery.m @@ -1752,6 +1752,9 @@ else if ([[field objectForKey:@"typegrouping"] isEqualToString:@"integer"]) { [fieldIDQueryStr appendFormat:@"%@=%@ AND ", [[field objectForKey:@"org_name"] backtickQuotedString], [aValue description]]; } + else if ([[field objectForKey:@"typegrouping"] isEqualToString:@"geometry"]) { + [fieldIDQueryStr appendFormat:@"%@=X'%@' AND ", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection prepareBinaryData:[aValue data]]]; + } else { [fieldIDQueryStr appendFormat:@"%@='%@' AND ", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection prepareString:aValue]]; } @@ -1848,7 +1851,7 @@ return [prefs objectForKey:SPNullValue]; if ([theValue isKindOfClass:[MCPGeometryData class]]) - return [theValue description]; + return [theValue wktString]; return theValue; } @@ -1902,6 +1905,8 @@ newObject = @"CURRENT_TIMESTAMP"; } else if([anObject isEqualToString:[prefs stringForKey:SPNullValue]]) { newObject = @"NULL"; + } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"geometry"]) { + newObject = [NSString stringWithFormat:@"GeomFromText('%@')", anObject]; } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"bit"]) { newObject = [NSString stringWithFormat:@"b'%@'", ((![[anObject description] length] || [[anObject description] isEqualToString:@"0"]) ? @"0" : [anObject description])]; } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"date"] diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m index cc5eb6bd..fd8f1703 100644 --- a/Source/SPTableContent.m +++ b/Source/SPTableContent.m @@ -1547,6 +1547,9 @@ else if ([[field objectForKey:@"typegrouping"] isEqualToString:@"integer"]) { [fieldIDQueryStr appendFormat:@"%@=%@ AND ", [[field objectForKey:@"org_name"] backtickQuotedString], [aValue description]]; } + else if ([[field objectForKey:@"typegrouping"] isEqualToString:@"geometry"]) { + [fieldIDQueryStr appendFormat:@"%@=X'%@' AND ", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection prepareBinaryData:[aValue data]]]; + } else { [fieldIDQueryStr appendFormat:@"%@='%@' AND ", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection prepareString:aValue]]; } @@ -2673,12 +2676,12 @@ if ([[[tableDataInstance columnWithName:NSArrayObjectAtIndex(keys, i)] objectForKey:@"type"] isEqualToString:@"BIT"]) { [value setString:[NSString stringWithFormat:@"b'%@'", [mySQLConnection prepareString:tempValue]]]; } + else if ([tempValue isKindOfClass:[MCPGeometryData class]]) { + [value setString:[NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:[tempValue data]]]]; + } // BLOB/TEXT data else if ([tempValue isKindOfClass:[NSData class]]) { - if([tableDataInstance columnIsGeometry:NSArrayObjectAtIndex(keys, i)]) - [value setString:[NSString stringWithFormat:@"GeomFromText('%@')", [[[NSString alloc] initWithData:tempValue encoding:NSASCIIStringEncoding] autorelease]]]; - else - [value setString:[NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:tempValue]]]; + [value setString:[NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:tempValue]]]; } else [value setString:[NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:tempValue]]]; @@ -3401,7 +3404,7 @@ } if([theValue isKindOfClass:[MCPGeometryData class]]) - return [theValue description]; + return [theValue wktString]; if ([theValue isNSNull]) return [prefs objectForKey:SPNullValue]; @@ -3542,6 +3545,8 @@ newObject = @"CURRENT_TIMESTAMP"; } else if([anObject isEqualToString:[prefs stringForKey:SPNullValue]]) { newObject = @"NULL"; + } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"geometry"]) { + newObject = [NSString stringWithFormat:@"GeomFromText('%@')", anObject]; } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"bit"]) { newObject = [NSString stringWithFormat:@"b'%@'", ((![[anObject description] length] || [[anObject description] isEqualToString:@"0"]) ? @"0" : [anObject description])]; } else if ([[columnDefinition objectForKey:@"typegrouping"] isEqualToString:@"date"] |