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

Reply via email to