aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorstuconnolly <stuart02@gmail.com>2012-09-08 08:57:46 +0000
committerstuconnolly <stuart02@gmail.com>2012-09-08 08:57:46 +0000
commit82a0a113aab3eabc90592723e4770baa99861c9a (patch)
tree44cda1d2c840262d3e9ea84fba7390a12e051436
parent11a170b25006f8a1546ab575c668fd95b49a43f7 (diff)
downloadsequelpro-82a0a113aab3eabc90592723e4770baa99861c9a.tar.gz
sequelpro-82a0a113aab3eabc90592723e4770baa99861c9a.tar.bz2
sequelpro-82a0a113aab3eabc90592723e4770baa99861c9a.zip
Rework data type handling.
-rw-r--r--Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.h1
-rw-r--r--Frameworks/PostgresKit/Source/FLXPostgresResult.m24
-rw-r--r--Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.h5
-rw-r--r--Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.m147
-rw-r--r--Frameworks/PostgresKit/Source/FLXPostgresTypeHandlerProtocol.h12
-rw-r--r--Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.h4
-rw-r--r--Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.m100
-rw-r--r--Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.m8
8 files changed, 137 insertions, 164 deletions
diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.h b/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.h
index 351b1d24..6567cd0b 100644
--- a/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.h
+++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.h
@@ -20,6 +20,7 @@
// the License.
#import "FLXPostgresConnection.h"
+#import "FLXPostgresTypeHandlerProtocol.h"
@interface FLXPostgresConnection (FLXPostgresConnectionTypeHandling)
diff --git a/Frameworks/PostgresKit/Source/FLXPostgresResult.m b/Frameworks/PostgresKit/Source/FLXPostgresResult.m
index 1aaeb1de..3cb44252 100644
--- a/Frameworks/PostgresKit/Source/FLXPostgresResult.m
+++ b/Frameworks/PostgresKit/Source/FLXPostgresResult.m
@@ -30,8 +30,8 @@ static NSString *FLXPostgresResultError = @"FLXPostgresResultError";
@interface FLXPostgresResult ()
- (void)_populateFields;
-- (id)_objectForRow:(unsigned int)row column:(unsigned int)column;
-- (id <FLXPostgresTypeHandlerProtocol>)_typeHandlerForColumn:(unsigned int)column withType:(FLXPostgresOid)type;
+- (id)_objectForRow:(NSUInteger)row column:(NSUInteger)column;
+- (id <FLXPostgresTypeHandlerProtocol>)_typeHandlerForColumn:(NSUInteger)column withType:(FLXPostgresOid)type;
@end
@@ -64,10 +64,8 @@ static NSString *FLXPostgresResultError = @"FLXPostgresResultError";
*
* @return The result wrapper.
*/
-- (id)initWithResult:(PGresult *)result connection:(FLXPostgresConnection *)connection
-{
- NSParameterAssert(result);
-
+- (id)initWithResult:(void *)result connection:(FLXPostgresConnection *)connection
+{
if ((self = [super init])) {
_row = 0;
@@ -196,17 +194,14 @@ static NSString *FLXPostgresResultError = @"FLXPostgresResultError";
*
* @return The native object or nil if out of this result's range.
*/
-- (id)_objectForRow:(unsigned int)row column:(unsigned int)column
+- (id)_objectForRow:(NSUInteger)row column:(NSUInteger)column
{
if (row >= _numberOfRows || column >= _numberOfFields) return nil;
// Check for null
if (PQgetisnull(_result, row, column)) return [NSNull null];
- // Get bytes and length
FLXPostgresOid type = PQftype(_result, column);
- const void *bytes = PQgetvalue(_result, row, column);
- NSUInteger length = PQgetlength(_result, row, column);
// Get handler for this type
id <FLXPostgresTypeHandlerProtocol> handler = [self _typeHandlerForColumn:column withType:type];
@@ -214,10 +209,15 @@ static NSString *FLXPostgresResultError = @"FLXPostgresResultError";
if (!handler) {
NSLog(@"PostgresKit: Warning: No type handler found for type %d, return NSData.", type);
+ const void *bytes = PQgetvalue(_result, row, column);
+ NSUInteger length = PQgetlength(_result, row, column);
+
+ if (!bytes || !length) return nil;
+
return [NSData dataWithBytes:bytes length:length];
}
- return [handler objectFromRemoteData:bytes length:length type:type];
+ return [handler objectFromResult:_result atRow:row column:column];
}
/**
@@ -227,7 +227,7 @@ static NSString *FLXPostgresResultError = @"FLXPostgresResultError";
*
* @return The type handler or nil if out of this result's range.
*/
-- (id <FLXPostgresTypeHandlerProtocol>)_typeHandlerForColumn:(unsigned int)column withType:(FLXPostgresOid)type
+- (id <FLXPostgresTypeHandlerProtocol>)_typeHandlerForColumn:(NSUInteger)column withType:(FLXPostgresOid)type
{
if (column >= _numberOfFields) return nil;
diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.h b/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.h
index b83eba76..4b148bbc 100644
--- a/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.h
+++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.h
@@ -20,13 +20,8 @@
// License for the specific language governing permissions and limitations under
// the License.
-@class FLXPostgresTypeNumberHandler;
-
#import "FLXPostgresTypeHandler.h"
@interface FLXPostgresTypeDateTimeHandler : FLXPostgresTypeHandler <FLXPostgresTypeHandlerProtocol>
-{
- FLXPostgresTypeNumberHandler *_numberHandler;
-}
@end
diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.m b/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.m
index 861e1727..1494478c 100644
--- a/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.m
+++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.m
@@ -26,9 +26,6 @@
#import "FLXPostgresConnection.h"
#import "FLXPostgresConnectionTypeHandling.h"
-// Microseconds per second
-#define USECS_PER_SEC 1000000
-
static FLXPostgresOid FLXPostgresTypeDateTimeTypes[] =
{
FLXPostgresOidDate,
@@ -42,11 +39,11 @@ static FLXPostgresOid FLXPostgresTypeDateTimeTypes[] =
@interface FLXPostgresTypeDateTimeHandler ()
-- (NSDate *)_postgresEpochDate;
-- (NSDate *)_dateFromBytes:(const void *)bytes length:(NSUInteger)length;
-- (NSDate *)_timeFromBytes:(const void *)bytes length:(NSUInteger)length;
-- (NSDate *)_timestampFromBytes:(const void *)bytes length:(NSUInteger)length;
-- (NSDate *)_dateByAddingComponents:(NSDateComponents *)components toDate:(NSDate *)date;
+- (NSDate *)_dateFromResult:(const PGresult *)result atRow:(NSUInteger)row column:(NSUInteger)column;
+- (NSDate *)_timeFromResult:(const PGresult *)result atRow:(NSUInteger)row column:(NSUInteger)column;
+- (NSDate *)_timestmpFromResult:(const PGresult *)result atRow:(NSUInteger)row column:(NSUInteger)column;
+
+- (NSDate *)_dateFromComponents:(NSDateComponents *)components;
@end
@@ -70,25 +67,21 @@ static FLXPostgresOid FLXPostgresTypeDateTimeTypes[] =
return nil;
}
-- (id)objectFromRemoteData:(const void *)bytes length:(NSUInteger)length type:(FLXPostgresOid)type
-{
- if (!bytes || !type) return nil;
-
- if (!_numberHandler) {
- _numberHandler = (FLXPostgresTypeNumberHandler *)[_connection typeHandlerForClass:[NSNumber class]];
- }
+- (id)objectFromResult:(const PGresult *)result atRow:(unsigned int)row column:(unsigned int)column
+{
+ FLXPostgresOid type = PQftype(result, column);
switch (type)
{
case FLXPostgresOidDate:
- return [self _dateFromBytes:bytes length:length];
+ return [self _dateFromResult:result atRow:row column:column];
case FLXPostgresOidTime:
case FLXPostgresOidTimeTZ:
case FLXPostgresOidAbsTime:
- return [self _timeFromBytes:bytes length:length];
+ return [self _timeFromResult:result atRow:row column:column];
case FLXPostgresOidTimestamp:
case FLXPostgresOidTimestampTZ:
- return [self _timestampFromBytes:bytes length:length];
+ return [self _timestmpFromResult:result atRow:row column:column];
default:
return nil;
}
@@ -98,112 +91,98 @@ static FLXPostgresOid FLXPostgresTypeDateTimeTypes[] =
#pragma mark Private API
/**
- * Returns the internal expoch date used by Postgres.
+ * Returns an NSDate created from a date value.
*
- * @return The epoch date as an NSDate.
+ * @param result The result to extract the value from.
+ * @param row The row to extract the value from.
+ * @param column The column to extract the value from.
+ *
+ * @return The NSDate representation.
*/
-- (NSDate *)_postgresEpochDate
-{
- NSDateComponents *components = [[NSDateComponents alloc] init];
-
- [components setDay:1];
- [components setMonth:1];
- [components setYear:2000];
-
- NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
+- (NSDate *)_dateFromResult:(const PGresult *)result atRow:(NSUInteger)row column:(NSUInteger)column
+{
+ PGdate date;
- NSDate *date = [gregorian dateFromComponents:components];
+ PQgetf(result, row, "%date", column, &date);
+
+ NSDateComponents *components = [[NSDateComponents alloc] init];
- [components release];
- [gregorian release];
+ [components setDay:date.mday];
+ [components setMonth:date.mon + 1]; // Months are indexed from 0
+ [components setYear:date.year];
- return date;
+ return [self _dateFromComponents:components];
}
/**
- * Converts the supplied bytes representing a date to an NSDate instance.
+ * Returns an NSDate created from a time value.
+ *
+ * @note The date part should be ignored as it's set to a default value.
*
- * @param bytes The bytes to convert.
- * @param length The number of bytes.
+ * @param result The result to extract the value from.
+ * @param row The row to extract the value from.
+ * @param column The column to extract the value from.
*
* @return The NSDate representation.
*/
-- (NSDate *)_dateFromBytes:(const void *)bytes length:(NSUInteger)length
-{
- NSDateComponents *components = [[NSDateComponents alloc] init];
+- (NSDate *)_timeFromResult:(const PGresult *)result atRow:(NSUInteger)row column:(NSUInteger)column
+{
+ PGtime time;
- [components setDay:[[_numberHandler integerObjectFromBytes:bytes length:length] integerValue]];
+ PQgetf(result, row, "%time", column, &time);
- NSDate *date = [self _dateByAddingComponents:components toDate:[self _postgresEpochDate]];
+ NSDateComponents *components = [[NSDateComponents alloc] init];
- [components release];
+ // Default date values; should be ignored
+ [components setDay:1];
+ [components setMonth:1];
+ [components setYear:2000];
- return date;
-}
-
-/**
- * Converts the supplied bytes representing the time to an NSDate instance.
- *
- * @param bytes The bytes to convert.
- * @param length The number of bytes.
- *
- * @return The NSDate representation.
- */
-- (NSDate *)_timeFromBytes:(const void *)bytes length:(NSUInteger)length
-{
- NSNumber *time = [_numberHandler integerObjectFromBytes:bytes length:length];
+ [components setHour:time.hour];
+ [components setMinute:time.min];
+ [components setSecond:time.sec];
+
+ // TODO: handle timezone
- return [NSDate dateWithTimeIntervalSince1970:(NSTimeInterval)[time doubleValue]];
+ return [self _dateFromComponents:components];
}
/**
- * Converts the supplied bytes representing a timestamp to an NSDate instance.
+ * Returns an NSDate created from a timestamp value.
*
- * @param bytes The bytes to convert.
- * @param length The number of bytes.
+ * @param result The result to extract the value from.
+ * @param row The row to extract the value from.
+ * @param column The column to extract the value from.
*
* @return The NSDate representation.
*/
-- (NSDate *)_timestampFromBytes:(const void *)bytes length:(NSUInteger)length
+- (NSDate *)_timestmpFromResult:(const PGresult *)result atRow:(NSUInteger)row column:(NSUInteger)column
{
- NSDate *date = nil;
- NSUInteger seconds = 0;
-
- if ([[[_connection parameters] valueForParameter:FLXPostgresParameterIntegerDateTimes] boolValue]) {
- seconds = ([[_numberHandler integerObjectFromBytes:bytes length:length] doubleValue] / (double)USECS_PER_SEC);
- }
- else {
- seconds = [_numberHandler float64FromBytes:bytes];
- }
+ PGtimestamp timestamp;
- NSDateComponents *components = [[NSDateComponents alloc] init];
+ PQgetf(result, row, "%timestamp", column, &timestamp);
- [components setSecond:seconds];
+ // TODO: handle timezone
- date = [self _dateByAddingComponents:components toDate:[self _postgresEpochDate]];
-
- [components release];
-
- return date;
+ return [NSDate dateWithTimeIntervalSince1970:timestamp.epoch];
}
/**
- * Returns the result of adding the supplied components to the supplied date.
+ * Returns an NSDate created from the supplied components.
*
- * @param components The date components to add.
- * @param date The date to add the components to.
+ * @param The components to create the date from.
*
- * @return The result of the addition to the date.
+ * @return The NSDate created.
*/
-- (NSDate *)_dateByAddingComponents:(NSDateComponents *)components toDate:(NSDate *)date
+- (NSDate *)_dateFromComponents:(NSDateComponents *)components
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
- NSDate *newDate = [gregorian dateByAddingComponents:components toDate:date options:0];
+ NSDate *date = [gregorian dateFromComponents:components];
[gregorian release];
- return newDate;
+ return date;
}
@end
diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeHandlerProtocol.h b/Frameworks/PostgresKit/Source/FLXPostgresTypeHandlerProtocol.h
index 05b3acef..5c05af63 100644
--- a/Frameworks/PostgresKit/Source/FLXPostgresTypeHandlerProtocol.h
+++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeHandlerProtocol.h
@@ -20,8 +20,6 @@
// License for the specific language governing permissions and limitations under
// the License.
-#import "FLXPostgresTypes.h"
-
@class FLXPostgresConnection;
/**
@@ -51,14 +49,14 @@
- (NSArray *)classAliases;
/**
- * Convert the supplied remote data into an object.
+ * Convert the value at the specified row and column in the supplied result to a native object.
*
- * @param bytes The remote data to convert.
- * @param length The length of the data.
- * @param type The type of data.
+ * @param result The result to extract the value from.
+ * @param row The row to extract the value from.
+ * @param column The column to extract the value from.
*
* @return An object represenation of the data.
*/
-- (id)objectFromRemoteData:(const void *)bytes length:(NSUInteger)length type:(FLXPostgresOid)type;
+- (id)objectFromResult:(const PGresult *)result atRow:(unsigned int)row column:(unsigned int)column;
@end
diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.h b/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.h
index 375251d4..a3305e19 100644
--- a/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.h
+++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.h
@@ -24,9 +24,5 @@
@interface FLXPostgresTypeNumberHandler : FLXPostgresTypeHandler <FLXPostgresTypeHandlerProtocol>
-- (Float64)float64FromBytes:(const void *)bytes;
-
-- (NSNumber *)integerObjectFromBytes:(const void *)bytes length:(NSUInteger)length;
-
@end
diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.m b/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.m
index 0a4ad011..2f0fc2ad 100644
--- a/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.m
+++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.m
@@ -21,7 +21,6 @@
// the License.
#import "FLXPostgresTypeNumberHandler.h"
-#import "FLXPostgresTypes.h"
static FLXPostgresOid FLXPostgresTypeNumberTypes[] =
{
@@ -34,56 +33,70 @@ static FLXPostgresOid FLXPostgresTypeNumberTypes[] =
0
};
+@interface FLXPostgresTypeNumberHandler ()
+
+- (SInt16)_int16FromBytes:(const void *)bytes;
+- (SInt32)_int32FromBytes:(const void *)bytes;
+- (SInt64)_int64FromBytes:(const void *)bytes;
+
+- (Float32)_float32FromBytes:(const void *)bytes;
+- (Float64)_float64FromBytes:(const void *)bytes;
+
+@end
+
@implementation FLXPostgresTypeNumberHandler
#pragma mark -
#pragma mark Integer & Unsigned Integer
-- (SInt16)int16FromBytes:(const void *)bytes
-{
- if (!bytes) return 0;
+- (NSNumber *)_integerObjectFromBytes:(const void *)bytes length:(NSUInteger)length
+{
+ switch (length)
+ {
+ case 2:
+ return [NSNumber numberWithShort:[self _int16FromBytes:bytes]];
+ case 4:
+ return [NSNumber numberWithInteger:[self _int32FromBytes:bytes]];
+ case 8:
+ return [NSNumber numberWithLongLong:[self _int64FromBytes:bytes]];
+ }
+ return nil;
+}
+
+- (SInt16)_int16FromBytes:(const void *)bytes
+{
return EndianS16_BtoN(*((SInt16 *)bytes));
}
-- (SInt32)int32FromBytes:(const void *)bytes
+- (SInt32)_int32FromBytes:(const void *)bytes
{
- if (!bytes) return 0;
-
return EndianS32_BtoN(*((SInt32 *)bytes));
}
-- (SInt64)int64FromBytes:(const void *)bytes
-{
- if (!bytes) return 0;
-
+- (SInt64)_int64FromBytes:(const void *)bytes
+{
return EndianS64_BtoN(*((SInt64 *)bytes));
}
-- (NSNumber *)integerObjectFromBytes:(const void *)bytes length:(NSUInteger)length
-{
- if (!bytes) return nil;
-
+#pragma mark -
+#pragma mark Floating Point
+
+- (NSNumber *)_floatObjectFromBytes:(const void *)bytes length:(NSUInteger)length
+{
switch (length)
{
- case 2:
- return [NSNumber numberWithShort:[self int16FromBytes:bytes]];
case 4:
- return [NSNumber numberWithInteger:[self int32FromBytes:bytes]];
+ return [NSNumber numberWithFloat:[self _float32FromBytes:bytes]];
case 8:
- return [NSNumber numberWithLongLong:[self int64FromBytes:bytes]];
+ return [NSNumber numberWithDouble:[self _float64FromBytes:bytes]];
}
return nil;
}
-#pragma mark -
-#pragma mark Floating Point
-
-- (Float32)float32FromBytes:(const void *)bytes
+- (Float32)_float32FromBytes:(const void *)bytes
{
- if (!bytes) return 0;
-
union { Float32 r; UInt32 i; } u32;
u32.r = *((Float32 *)bytes);
@@ -92,10 +105,8 @@ static FLXPostgresOid FLXPostgresTypeNumberTypes[] =
return u32.r;
}
-- (Float64)float64FromBytes:(const void *)bytes
-{
- if (!bytes) return 0;
-
+- (Float64)_float64FromBytes:(const void *)bytes
+{
union { Float64 r; UInt64 i; } u64;
u64.r = *((Float64 *)bytes);
@@ -104,25 +115,12 @@ static FLXPostgresOid FLXPostgresTypeNumberTypes[] =
return u64.r;
}
-- (NSNumber *)floatObjectFromBytes:(const void *)bytes length:(NSUInteger)length
-{
- switch (length)
- {
- case 4:
- return [NSNumber numberWithFloat:[self float32FromBytes:bytes]];
- case 8:
- return [NSNumber numberWithDouble:[self float64FromBytes:bytes]];
- }
-
- return nil;
-}
-
#pragma mark -
#pragma mark Boolean
-- (NSNumber *)booleanObjectFromBytes:(const void *)bytes length:(NSUInteger)length
+- (NSNumber *)_booleanObjectFromBytes:(const void *)bytes length:(NSUInteger)length
{
- if (!bytes || length != 1) return nil;
+ if (length != 1) return nil;
return [NSNumber numberWithBool:*((const int8_t *)bytes) ? YES : NO];
}
@@ -145,21 +143,25 @@ static FLXPostgresOid FLXPostgresTypeNumberTypes[] =
return nil;
}
-- (id)objectFromRemoteData:(const void *)bytes length:(NSUInteger)length type:(FLXPostgresOid)type
+- (id)objectFromResult:(const PGresult *)result atRow:(unsigned int)row column:(unsigned int)column
{
- if (!bytes || !length || !type) return nil;
+ FLXPostgresOid type = PQftype(result, column);
+ NSUInteger length = PQgetlength(result, row, column);
+ const void *bytes = PQgetvalue(result, row, column);
+
+ if (!bytes || !length) return nil;
switch (type)
{
case FLXPostgresOidInt8:
case FLXPostgresOidInt2:
case FLXPostgresOidInt4:
- return [self integerObjectFromBytes:bytes length:length];
+ return [self _integerObjectFromBytes:bytes length:length];
case FLXPostgresOidFloat4:
case FLXPostgresOidFloat8:
- return [self floatObjectFromBytes:bytes length:length];
+ return [self _floatObjectFromBytes:bytes length:length];
case FLXPostgresOidBool:
- return [self booleanObjectFromBytes:bytes length:length];
+ return [self _booleanObjectFromBytes:bytes length:length];
default:
return nil;
}
diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.m b/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.m
index a2e364f8..fb72346b 100644
--- a/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.m
+++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.m
@@ -22,7 +22,6 @@
#import "FLXPostgresTypeStringHandler.h"
#import "FLXPostgresConnection.h"
-#import "FLXPostgresTypes.h"
static FLXPostgresOid FLXPostgresTypeStringTypes[] =
{
@@ -55,9 +54,12 @@ static FLXPostgresOid FLXPostgresTypeStringTypes[] =
return [NSArray arrayWithObject:@"NSCFString"];
}
-- (id)objectFromRemoteData:(const void *)bytes length:(NSUInteger)length type:(FLXPostgresOid)type
+- (id)objectFromResult:(const PGresult *)result atRow:(unsigned int)row column:(unsigned int)column
{
- if (!bytes || !type) return nil;
+ const void *bytes = PQgetvalue(result, row, column);
+ NSUInteger length = PQgetlength(result, row, column);
+
+ if (!bytes || !length) return @"";
return [[[NSString alloc] initWithBytes:bytes length:length encoding:[_connection stringEncoding]] autorelease];
}