Author: rfm
Date: Thu Apr 30 11:12:47 2015
New Revision: 38467
URL: http://svn.gna.org/viewcvs/gnustep?rev=38467&view=rev
Log:
Optimisation tweaks
Modified:
libs/sqlclient/trunk/ChangeLog
libs/sqlclient/trunk/Postgres.m
libs/sqlclient/trunk/testPostgres.m
Modified: libs/sqlclient/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/ChangeLog?rev=38467&r1=38466&r2=38467&view=diff
==============================================================================
--- libs/sqlclient/trunk/ChangeLog (original)
+++ libs/sqlclient/trunk/ChangeLog Thu Apr 30 11:12:47 2015
@@ -1,9 +1,16 @@
+2015-04-30 Richard Frith-Macdonald <[email protected]>
+
+ * Postgres.m:
+ * testPostgres.m:
+ Fix error parsing timestamps in arrays when the server quoters them.
+ Also optimise string allocation, and add some tests.
+
2015-04-28 Richard Frith-Macdonald <[email protected]>
* SQLClient.h:
* SQLClient.m:
* Postgres.m:
- Deprecate trtansaction merging.
+ Deprecate transaction merging.
Rewrite SQLRecord concrete class to use a new SQLRecordKeys object
shared between all the records produced by a query (as a performance
enhancement for large queries).
Modified: libs/sqlclient/trunk/Postgres.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/Postgres.m?rev=38467&r1=38466&r2=38467&view=diff
==============================================================================
--- libs/sqlclient/trunk/Postgres.m (original)
+++ libs/sqlclient/trunk/Postgres.m Thu Apr 30 11:12:47 2015
@@ -73,14 +73,193 @@
static NSDate *future = nil;
static NSNull *null = nil;
+#if defined(GNUSTEP)
+static NSString *placeholder = nil;
+#else
+static Class stringClass = Nil;
+static SEL allocStringSel = 0;
+static IMP allocStringImp = 0;
+#endif
+static SEL initStringSel = 0;
+static IMP initStringImp = 0;
+
static NSTimeZone *zones[47]; // For -23 to +23 hours
+static inline NSString*
+newString(const char *b, int l, NSStringEncoding e)
+{
+#if defined(GNUSTEP)
+ return (*initStringImp)(placeholder, initStringSel, b, l, e);
+#else
+ NSString *s = (*allocStringImp)(stringClass, allocStringSel);
+ return (*initStringImp)(s, initStringSel, b, l, e);
+#endif
+}
+
+static NSDate*
+newDateFromBuffer(const char *b, int l)
+{
+ NSCalendarDate *d;
+ NSTimeZone *zone;
+ int milliseconds = 0;
+ int timezone = 0;
+ int day;
+ int month;
+ int year;
+ int hour;
+ int minute;
+ int second;
+ int i;
+
+ i = 0;
+
+ if (i >= l || !isdigit(b[i])) return nil;
+ year = b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ year = year * 10 + b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ year = year * 10 + b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ year = year * 10 + b[i++] - '0';
+
+ if (i >= l || b[i++] != '-') return nil;
+
+ if (i >= l || !isdigit(b[i])) return nil;
+ month = b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ month = month * 10 + b[i++] - '0';
+ if (month < 1 || month > 12) return nil;
+
+ if (i >= l || b[i++] != '-') return nil;
+
+ if (i >= l || !isdigit(b[i])) return nil;
+ day = b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ day = day * 10 + b[i++] - '0';
+ if (day < 1 || day > 31) return nil;
+
+ if (i == l)
+ {
+ hour = 0;
+ minute = 0;
+ second = 0;
+ }
+ else
+ {
+ if (i >= l || b[i++] != ' ') return nil;
+
+ if (i >= l || !isdigit(b[i])) return nil;
+ hour = b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ hour = hour * 10 + b[i++] - '0';
+ if (hour < 0 || hour > 23) return nil;
+
+ if (i >= l || b[i++] != ':') return nil;
+
+ if (i >= l || !isdigit(b[i])) return nil;
+ minute = b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ minute = minute * 10 + b[i++] - '0';
+ if (minute < 0 || minute > 59) return nil;
+
+ if (i >= l || b[i++] != ':') return nil;
+
+ if (i >= l || !isdigit(b[i])) return nil;
+ second = b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ second = second * 10 + b[i++] - '0';
+ if (second < 0 || second > 60) return nil;
+
+ if (i < l && '.' == b[i])
+ {
+ i++;
+ if (i >= l || !isdigit(b[i])) return nil;
+ milliseconds = b[i++] - '0';
+ milliseconds *=- 10;
+ if (i < l && isdigit(b[i]))
+ milliseconds += b[i++] - '0';
+ milliseconds *=- 10;
+ if (i < l && isdigit(b[i]))
+ milliseconds += b[i++] - '0';
+ while (i < l && isdigit(b[i]))
+ i++;
+ }
+
+ if (i < l && ('+' == b[i] || '-' == b[i]))
+ {
+ char sign = b[i++];
+
+ if (i >= l || !isdigit(b[i])) return nil;
+ timezone = b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ timezone = timezone * 10 + b[i++] - '0';
+ if (timezone < 0 || timezone > 23) return nil;
+ timezone *= 60; // Convert to minutes
+ if (i < l && ':' == b[i])
+ {
+ int tzmin;
+
+ if (i >= l || !isdigit(b[i])) return nil;
+ tzmin = b[i++] - '0';
+ if (i >= l || !isdigit(b[i])) return nil;
+ tzmin = tzmin * 10 + b[i++] - '0';
+ if (tzmin < 0 || tzmin > 59) return nil;
+
+ timezone += tzmin;
+ }
+ if ('-' == sign)
+ timezone = -timezone;
+ }
+ }
+ if (timezone % 60 == 0)
+ {
+ zone = zones[timezone / 60];
+ }
+ else
+ {
+ zone = [NSTimeZone timeZoneForSecondsFromGMT: timezone * 60];
+ }
+
+ d = [[NSCalendarDate alloc] initWithYear: year
+ month: month
+ day: day
+ hour: hour
+ minute: minute
+ second: second
+ timeZone: zone];
+
+ if (milliseconds > 0)
+ {
+ NSTimeInterval ti;
+
+ ti = milliseconds;
+ ti /= 1000.0;
+ ti += [d timeIntervalSinceReferenceDate];
+ d = [d initWithTimeIntervalSinceReferenceDate: ti];
+ [d setTimeZone: zone];
+ }
+ [d setCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"];
+ return d;
+}
+
@implementation SQLClientPostgres
+ (void) initialize
{
if (future == nil)
{
+ initStringSel = @selector(initWithBytes:length:encoding:);
+#if defined(GNUSTEP)
+ placeholder = [NSString alloc];
+ initStringImp
+ = [[placeholder class] instanceMethodForSelector: initStringSel];
+#else
+ stringClass = [NSString class];
+ allocStringSel = @selector(alloc);
+ allocStringImp = [stringClass methodForSelector: allocStringSel];
+ initStringImp = [stringClass instanceMethodForSelector: initStringSel];
+#endif
+
future = [NSCalendarDate dateWithString: @"9999-01-01 00:00:00 +0000"
calendarFormat: @"%Y-%m-%d %H:%M:%S %z"
locale: nil];
@@ -89,7 +268,8 @@
[null retain];
for (int i = -23; i <= 23; i++)
{
- zones[i + 23] = [[NSTimeZone timeZoneForSecondsFromGMT: i * 60 * 60]
retain];
+ zones[i + 23]
+ = [[NSTimeZone timeZoneForSecondsFromGMT: i * 60 * 60] retain];
}
}
}
@@ -529,7 +709,22 @@
}
if (len == (p - start))
{
- v = [[NSString alloc] initWithUTF8String: start];
+ if ('T' == t)
+ {
+ /* This is expected to be a timestamp
+ */
+ v = newDateFromBuffer(start, p - start);
+ }
+ else if ('D' == t)
+ {
+ /* This is expected to be bytea data
+ */
+ v = [[self dataFromBLOB: start] retain];
+ }
+ else
+ {
+ v = newString(start, p - start, NSUTF8StringEncoding);
+ }
}
else
{
@@ -549,7 +744,13 @@
buf[i++] = *ptr++;
}
buf[len] = '\0';
- if ('D' == t)
+ if ('T' == t)
+ {
+ /* This is expected to be a timestamp
+ */
+ v = newDateFromBuffer(buf, len);
+ }
+ else if ('D' == t)
{
/* This is expected to be bytea data
*/
@@ -588,7 +789,7 @@
}
else if ('T' == t)
{
- v = [[self dbToDateFromBuffer: start length: len] retain];
+ v = newDateFromBuffer(start, len);
}
else if ('D' == t)
{
@@ -603,7 +804,7 @@
}
else
{
- v = [[NSString alloc] initWithUTF8String: start];
+ v = newString(start, p - start, NSUTF8StringEncoding);
}
*p = save;
}
@@ -631,17 +832,15 @@
switch (t)
{
case 1082: // Date
- return [self newDateFromBuffer: p length: trim(p, s)];
+ return newDateFromBuffer(p, trim(p, s));
case 1083: // Time (treat as string)
s = trim(p, s);
- return [[NSString alloc] initWithBytes: p
- length: s
- encoding: NSASCIIStringEncoding];
+ return newString(p, s, NSASCIIStringEncoding);
case 1114: // Timestamp without time zone.
case 1184: // Timestamp with time zone.
- return [self newDateFromBuffer: p length: trim(p, s)];
+ return newDateFromBuffer(p, trim(p, s));
case 16: // BOOL
if (*p == 't')
@@ -657,18 +856,13 @@
return [[self dataFromBLOB: p] retain];
case 18: // "char"
- return [[NSString alloc] initWithBytes: p
- length: s
- encoding: NSUTF8StringEncoding];
+ return newString(p, s, NSUTF8StringEncoding);
case 20: // INT8
case 21: // INT2
case 23: // INT4
s = trim(p, s);
- return [[NSString alloc] initWithBytes: p
- length: s
- encoding: NSASCIIStringEncoding];
- break;
+ return newString(p, s, NSASCIIStringEncoding);
case 1182: // DATE ARRAY
case 1115: // TS without TZ ARRAY
@@ -706,9 +900,7 @@
{
s = trim(p, s);
}
- return [[NSString alloc] initWithBytes: p
- length: s
- encoding: NSUTF8StringEncoding];
+ return newString(p, s, NSUTF8StringEncoding);
}
}
@@ -1229,151 +1421,6 @@
return d;
}
-- (NSDate*) newDateFromBuffer: (char*)b length: (int)l
-{
- NSCalendarDate *d;
- NSTimeZone *zone;
- int milliseconds = 0;
- int timezone = 0;
- int day;
- int month;
- int year;
- int hour;
- int minute;
- int second;
- int i;
-
- i = 0;
-
- if (i >= l || !isdigit(b[i])) return nil;
- year = b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- year = year * 10 + b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- year = year * 10 + b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- year = year * 10 + b[i++] - '0';
-
- if (i >= l || b[i++] != '-') return nil;
-
- if (i >= l || !isdigit(b[i])) return nil;
- month = b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- month = month * 10 + b[i++] - '0';
- if (month < 1 || month > 12) return nil;
-
- if (i >= l || b[i++] != '-') return nil;
-
- if (i >= l || !isdigit(b[i])) return nil;
- day = b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- day = day * 10 + b[i++] - '0';
- if (day < 1 || day > 31) return nil;
-
- if (i == l)
- {
- hour = 0;
- minute = 0;
- second = 0;
- }
- else
- {
- if (i >= l || b[i++] != ' ') return nil;
-
- if (i >= l || !isdigit(b[i])) return nil;
- hour = b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- hour = hour * 10 + b[i++] - '0';
- if (hour < 0 || hour > 23) return nil;
-
- if (i >= l || b[i++] != ':') return nil;
-
- if (i >= l || !isdigit(b[i])) return nil;
- minute = b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- minute = minute * 10 + b[i++] - '0';
- if (minute < 0 || minute > 59) return nil;
-
- if (i >= l || b[i++] != ':') return nil;
-
- if (i >= l || !isdigit(b[i])) return nil;
- second = b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- second = second * 10 + b[i++] - '0';
- if (second < 0 || second > 60) return nil;
-
- if (i < l && '.' == b[i])
- {
- i++;
- if (i >= l || !isdigit(b[i])) return nil;
- milliseconds = b[i++] - '0';
- milliseconds *=- 10;
- if (i < l && isdigit(b[i]))
- milliseconds += b[i++] - '0';
- milliseconds *=- 10;
- if (i < l && isdigit(b[i]))
- milliseconds += b[i++] - '0';
- while (i < l && isdigit(b[i]))
- i++;
- }
-
- if (i < l && ('+' == b[i] || '-' == b[i]))
- {
- char sign = b[i++];
-
- if (i >= l || !isdigit(b[i])) return nil;
- timezone = b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- timezone = timezone * 10 + b[i++] - '0';
- if (timezone < 0 || timezone > 23) return nil;
- timezone *= 60; // Convert to minutes
- if (i < l && ':' == b[i])
- {
- int tzmin;
-
- if (i >= l || !isdigit(b[i])) return nil;
- tzmin = b[i++] - '0';
- if (i >= l || !isdigit(b[i])) return nil;
- tzmin = tzmin * 10 + b[i++] - '0';
- if (tzmin < 0 || tzmin > 59) return nil;
-
- timezone += tzmin;
- }
- if ('-' == sign)
- timezone = -timezone;
- }
- }
- if (timezone % 60 == 0)
- {
- zone = zones[timezone / 60];
- }
- else
- {
- zone = [NSTimeZone timeZoneForSecondsFromGMT: timezone * 60];
- }
-
- d = [[NSCalendarDate alloc] initWithYear: year
- month: month
- day: day
- hour: hour
- minute: minute
- second: second
- timeZone: zone];
-
- if (milliseconds > 0)
- {
- NSTimeInterval ti;
-
- ti = milliseconds;
- ti /= 1000.0;
- ti += [d timeIntervalSinceReferenceDate];
- d = [d initWithTimeIntervalSinceReferenceDate: ti];
- [d setTimeZone: zone];
- }
- [d setCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"];
- return d;
-}
-
- (void) dealloc
{
if (extra != 0)
Modified: libs/sqlclient/trunk/testPostgres.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/testPostgres.m?rev=38467&r1=38466&r2=38467&view=diff
==============================================================================
--- libs/sqlclient/trunk/testPostgres.m (original)
+++ libs/sqlclient/trunk/testPostgres.m Thu Apr 30 11:12:47 2015
@@ -229,6 +229,7 @@
{
NSString *oddChars;
NSString *nonLatin;
+ id e1, e2, e3, e4, e5;
id r0;
id r1;
@@ -249,6 +250,7 @@
[db begin];
[db execute: @"create table xxx ( "
+ @"id int, "
@"k char(40), "
@"char1 char(1), "
@"boolval BOOL, "
@@ -264,9 +266,9 @@
@")",
nil];
- if (1 != [db execute: @"insert into xxx (k, char1, boolval, intval,"
+ if (1 != [db execute: @"insert into xxx (id, k, char1, boolval, intval,"
@" when1, when2, b, extra1, extra2, extra3, extra4, extra5) "
- @"values ("
+ @"values (1,"
@"'{hello', "
@"'X', "
@"TRUE, "
@@ -275,23 +277,23 @@
@"CURRENT_TIMESTAMP, ",
data, @", ",
[db quoteArray:
- [NSArray arrayWithObjects: @"1", @"2", [NSNull null], nil]
+ (e1 = [NSArray arrayWithObjects: @"1", @"2", [NSNull null], nil])
toString: nil
quotingStrings: NO], @", ",
[db quoteArray:
- [NSArray arrayWithObjects: @"on,e", @"t'wo", @"many", nil]
+ (e2 = [NSArray arrayWithObjects: @"on,e", @"t'wo", @"many", nil])
toString: nil
quotingStrings: YES], @", ",
[db quoteArray:
- [NSArray arrayWithObjects: data, nil]
+ (e3 = [NSArray arrayWithObjects: data, nil])
toString: nil
quotingStrings: YES], @", ",
[db quoteArray:
- [NSArray arrayWithObjects: @"TRUE", @"FALSE", nil]
+ (e4 =[NSArray arrayWithObjects: @"TRUE", @"FALSE", nil])
toString: nil
quotingStrings: NO], @", ",
[db quoteArray:
- [NSArray arrayWithObjects: [NSDate date], nil]
+ (e5 = [NSArray arrayWithObjects: [NSDate date], nil])
toString: nil
quotingStrings: YES], @")",
nil])
@@ -304,8 +306,8 @@
[db setDebugging: 0];
[db execute: @"insert into xxx "
- @"(k, char1, boolval, intval, when1, when2, b) "
- @"values ("
+ @"(id, k, char1, boolval, intval, when1, when2, b) "
+ @"values (2,"
@"'hello', "
@"'X', "
@"TRUE, "
@@ -316,8 +318,8 @@
@")",
nil];
[db execute: @"insert into xxx "
- @"(k, char1, boolval, intval, when1, when2, b) "
- @"values (",
+ @"(id, k, char1, boolval, intval, when1, when2, b) "
+ @"values (3,",
[db quote: oddChars],
@", ",
[db quote: nonLatin],
@@ -330,11 +332,11 @@
nil];
[db commit];
- r0 = [db cache: 1 query: @"select * from xxx", nil];
- r1 = [db cache: 1 query: @"select * from xxx", nil];
+ r0 = [db cache: 1 query: @"select * from xxx order by id", nil];
+ r1 = [db cache: 1 query: @"select * from xxx order by id", nil];
NSCAssert([r0 lastObject] == [r1 lastObject], @"Cache failed");
[NSThread sleepForTimeInterval: 2.0];
- records = [db cache: 1 query: @"select * from xxx", nil];
+ records = [db cache: 1 query: @"select * from xxx order by id", nil];
NSCAssert([r0 lastObject] != [records lastObject], @"Lifetime failed");
[db addObserver: l
@@ -372,6 +374,50 @@
{
NSLog(@"Retrieved odd chars (%@) does not match saved string
(%@)", o, oddChars);
}
+ record = [records objectAtIndex: 0];
+ o = [record objectForKey: @"extra1"];
+ if ([o isEqual: e1] == NO)
+ {
+ NSLog(@"Retrieved extra1 (%@) does not match saved (%@)", o, e1);
+ }
+ o = [record objectForKey: @"extra2"];
+ if ([o isEqual: e2] == NO)
+ {
+ NSLog(@"Retrieved extra2 (%@) does not match saved (%@)", o, e2);
+ }
+ o = [record objectForKey: @"extra3"];
+ if ([o isEqual: e3] == NO)
+ {
+ NSLog(@"Retrieved extra3 (%@) does not match saved (%@)", o, e3);
+ }
+ o = [record objectForKey: @"extra4"];
+ if ([o count] != [e4 count])
+ {
+ NSLog(@"Retrieved extra4 (%@) does not match saved (%@)", o, e4);
+ }
+ for (int i = 0; i < [o count]; i++)
+ {
+ if ([[o objectAtIndex: i] boolValue]
+ != [[e4 objectAtIndex: i] boolValue])
+ {
+ NSLog(@"Retrieved extra4 (%@) does not match saved (%@)",
+ o, e4);
+ }
+ }
+ o = [record objectForKey: @"extra5"];
+ if ([o count] != [e5 count])
+ {
+ NSLog(@"Retrieved extra5 (%@) does not match saved (%@)", o, e5);
+ }
+ for (int i = 0; i < [o count]; i++)
+ {
+ if (floor([[o objectAtIndex: i] timeIntervalSinceReferenceDate])
+ != floor([[e5 objectAtIndex: i]
timeIntervalSinceReferenceDate]))
+ {
+ NSLog(@"Retrieved extra5 (%@) does not match saved (%@)",
+ o, e5);
+ }
+ }
}
NSLog(@"Records - %@", [GSCache class]);
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs