Author: rfm
Date: Thu Dec 11 18:26:32 2014
New Revision: 38249

URL: http://svn.gna.org/viewcvs/gnustep?rev=38249&view=rev
Log:
convenience methods

Modified:
    libs/sqlclient/trunk/ChangeLog
    libs/sqlclient/trunk/Postgres.m
    libs/sqlclient/trunk/SQLClient.h
    libs/sqlclient/trunk/SQLClient.m
    libs/sqlclient/trunk/SQLClientPool.m
    libs/sqlclient/trunk/testPostgres.m

Modified: libs/sqlclient/trunk/ChangeLog
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/ChangeLog?rev=38249&r1=38248&r2=38249&view=diff
==============================================================================
--- libs/sqlclient/trunk/ChangeLog      (original)
+++ libs/sqlclient/trunk/ChangeLog      Thu Dec 11 18:26:32 2014
@@ -1,3 +1,11 @@
+2014-12-11 Richard Frith-Macdonald  <[email protected]>
+
+       * Postgres.m: Fix minor thread safety issue.
+        * SQLClient.h:
+        * SQLClient.m:
+        * SQLClientPool.m:
+       Convenience methods to let a pool act as a client for any one-off op.
+
 2014-11-19 Richard Frith-Macdonald  <[email protected]>
 
        * GNUmakefile: bump version to 1.8.2 for bugfix release.

Modified: libs/sqlclient/trunk/Postgres.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/Postgres.m?rev=38249&r1=38248&r2=38249&view=diff
==============================================================================
--- libs/sqlclient/trunk/Postgres.m     (original)
+++ libs/sqlclient/trunk/Postgres.m     Thu Dec 11 18:26:32 2014
@@ -1032,8 +1032,20 @@
 #ifdef HAVE_PQESCAPESTRINGCONN
   int          err;
 
-  [self connect];
-  l = PQescapeStringConn(connection, (char*)(to + 1), [d bytes], l, &err);
+  [lock lock];
+  NS_DURING
+    {
+      [self connect];
+      l = PQescapeStringConn(connection, (char*)(to + 1), [d bytes], l, &err);
+    }
+  NS_HANDLER
+    {
+      [lock unlock];
+      NSZoneFree(NSDefaultMallocZone(), to);
+      [localException raise];
+    }
+  NS_ENDHANDLER
+  [lock unlock];
 #else
   l = PQescapeString(to + 1, [d bytes], l);
 #endif

Modified: libs/sqlclient/trunk/SQLClient.h
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/SQLClient.h?rev=38249&r1=38248&r2=38249&view=diff
==============================================================================
--- libs/sqlclient/trunk/SQLClient.h    (original)
+++ libs/sqlclient/trunk/SQLClient.h    Thu Dec 11 18:26:32 2014
@@ -1187,36 +1187,11 @@
 @interface     SQLClient (Convenience)
 
 /**
- * Returns a transaction object configured to handle batching and
- * execute part of a batch of statements if execution of the whole
- * using the [SQLTransaction-executeBatch] method fails.<br />
- * If stopOnFailure is YES than execution of the transaction will
- * stop with the first statement to fail, otherwise it will execute
- * all the statements it can, skipping any failed statements.
- */
-- (SQLTransaction*) batch: (BOOL)stopOnFailure;
-
-/**
  * Convenience method to deal with the results of a query converting the
  * normal array of records into an array of record columns.  Each column
  * in the array is an array containing all the values from that column.
  */
-- (NSMutableArray*) columns: (NSMutableArray*)records;
-
-/**
- * Executes a query (like the -query:,... method) and checks the result
- * (raising an exception if the query did not contain a single record)
- * and returns the resulting record.
- */
-- (SQLRecord*) queryRecord: (NSString*)stmt,...;
-
-/**
- * Executes a query (like the -query:,... method) and checks the result.<br />
- * Raises an exception if the query did not contain a single record, or
- * if the record did not contain a single field.<br />
- * Returns the resulting field as a <em>string</em>.
- */
-- (NSString*) queryString: (NSString*)stmt,...;
++ (NSMutableArray*) columns: (NSMutableArray*)records;
 
 /**
  * Convenience method to deal with the results of a query where each
@@ -1226,6 +1201,39 @@
  * actually instances of [SQLRecord], so you must ensure you don't
  * call it more than once on the same array (something that may happen
  * if you retrieve the array using a cache based query).
+ */
++ (void) singletons: (NSMutableArray*)records;
+
+/**
+ * Returns a transaction object configured to handle batching and
+ * execute part of a batch of statements if execution of the whole
+ * using the [SQLTransaction-executeBatch] method fails.<br />
+ * If stopOnFailure is YES than execution of the transaction will
+ * stop with the first statement to fail, otherwise it will execute
+ * all the statements it can, skipping any failed statements.
+ */
+- (SQLTransaction*) batch: (BOOL)stopOnFailure;
+
+/** The same as the [SQLClient+columns:] method.
+ */
+- (NSMutableArray*) columns: (NSMutableArray*)records;
+
+/**
+ * Executes a query (like the -query:,... method) and checks the result
+ * (raising an exception if the query did not contain a single record)
+ * and returns the resulting record.
+ */
+- (SQLRecord*) queryRecord: (NSString*)stmt,...;
+
+/**
+ * Executes a query (like the -query:,... method) and checks the result.<br />
+ * Raises an exception if the query did not contain a single record, or
+ * if the record did not contain a single field.<br />
+ * Returns the resulting field as a <em>string</em>.
+ */
+- (NSString*) queryString: (NSString*)stmt,...;
+
+/** The same as the [SQLClient+singletons:] method.
  */
 - (void) singletons: (NSMutableArray*)records;
 
@@ -1531,6 +1539,47 @@
 
 @end
 
+/** This category lists the convenience methods provided by a pool instance
+ * for proxying messages to a one-off client instance in the pool.<br />
+ * The behavior of each method is, of course, as documentf for instances
+ * of the [SQLClient] class.
+ */
+@interface      SQLClientPool (Convenience)
+- (NSString*) buildQuery: (NSString*)stmt,...;
+- (NSString*) buildQuery: (NSString*)stmt with: (NSDictionary*)values;
+- (NSMutableArray*) cache: (int)seconds
+                   query: (NSString*)stmt,...;
+- (NSMutableArray*) cache: (int)seconds
+                   query: (NSString*)stmt
+                    with: (NSDictionary*)values;
+- (NSMutableArray*) cache: (int)seconds simpleQuery: (NSString*)stmt;
+- (NSMutableArray*) cache: (int)seconds
+             simpleQuery: (NSString*)stmt
+              recordType: (id)rtype
+                listType: (id)ltype;
+- (NSMutableArray*) columns: (NSMutableArray*)records;
+- (NSInteger) execute: (NSString*)stmt,...;
+- (NSInteger) execute: (NSString*)stmt with: (NSDictionary*)values;
+- (NSMutableArray*) query: (NSString*)stmt,...;
+- (NSMutableArray*) query: (NSString*)stmt with: (NSDictionary*)values;
+- (SQLRecord*) queryRecord: (NSString*)stmt,...;
+- (NSString*) queryString: (NSString*)stmt,...;
+- (NSString*) quote: (id)obj;
+- (NSString*) quotef: (NSString*)fmt, ...;
+- (NSString*) quoteBigInteger: (int64_t)i;
+- (NSString*) quoteCString: (const char *)s;
+- (NSString*) quoteChar: (char)c;
+- (NSString*) quoteFloat: (float)f;
+- (NSString*) quoteInteger: (int)i;
+- (NSString*) quoteString: (NSString *)s;
+- (NSInteger) simpleExecute: (NSArray*)info;
+- (void) singletons: (NSMutableArray*)records;
+- (NSMutableArray*) simpleQuery: (NSString*)stmt;
+- (NSMutableArray*) simpleQuery: (NSString*)stmt
+                    recordType: (id)rtype
+                      listType: (id)ltype;
+@end
+
 /**
  * The SQLTransaction transaction class provides a convenient mechanism
  * for grouping together a series of SQL statements to be executed as a

Modified: libs/sqlclient/trunk/SQLClient.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/SQLClient.m?rev=38249&r1=38248&r2=38249&view=diff
==============================================================================
--- libs/sqlclient/trunk/SQLClient.m    (original)
+++ libs/sqlclient/trunk/SQLClient.m    Thu Dec 11 18:26:32 2014
@@ -2539,6 +2539,54 @@
 
 @implementation        SQLClient(Convenience)
 
++ (NSMutableArray*) columns: (NSMutableArray*)records
+{
+  SQLRecord            *r = [records lastObject];
+  unsigned             rowCount = [records count];
+  unsigned             colCount = [r count];
+  NSMutableArray       *m;
+
+  if (rowCount == 0 || colCount == 0)
+    {
+      m = [NSMutableArray array];
+    }
+  else
+    {
+      NSMutableArray   *cols[colCount];
+      unsigned         i;
+
+      m = [NSMutableArray arrayWithCapacity: colCount];
+      for (i = 0; i < colCount; i++)
+       {
+         cols[i] = [[NSMutableArray alloc] initWithCapacity: rowCount];
+         [m addObject: cols[i]];
+         [cols[i] release];
+       }
+      for (i = 0; i < rowCount; i++)
+       {
+         unsigned      j;
+
+         r = [records objectAtIndex: i];
+         for (j = 0; j < colCount; j++)
+           {
+             [cols[j] addObject: [r objectAtIndex: j]];
+           }
+       }
+    }
+  return m;
+}
+
++ (void) singletons: (NSMutableArray*)records
+{
+  unsigned     c = [records count];
+
+  while (c-- > 0)
+    {
+      [records replaceObjectAtIndex: c
+                        withObject: [[records objectAtIndex: c] lastObject]];
+    }
+}
+
 - (SQLTransaction*) batch: (BOOL)stopOnFailure
 {
   SQLTransaction        *transaction;
@@ -2555,39 +2603,7 @@
 
 - (NSMutableArray*) columns: (NSMutableArray*)records
 {
-  SQLRecord            *r = [records lastObject];
-  unsigned             rowCount = [records count];
-  unsigned             colCount = [r count];
-  NSMutableArray       *m;
-
-  if (rowCount == 0 || colCount == 0)
-    {
-      m = [NSMutableArray array];
-    }
-  else
-    {
-      NSMutableArray   *cols[colCount];
-      unsigned         i;
-
-      m = [NSMutableArray arrayWithCapacity: colCount];
-      for (i = 0; i < colCount; i++)
-       {
-         cols[i] = [[NSMutableArray alloc] initWithCapacity: rowCount];
-         [m addObject: cols[i]];
-         [cols[i] release];
-       }
-      for (i = 0; i < rowCount; i++)
-       {
-         unsigned      j;
-
-         r = [records objectAtIndex: i];
-         for (j = 0; j < colCount; j++)
-           {
-             [cols[j] addObject: [r objectAtIndex: j]];
-           }
-       }
-    }
-  return m;
+  return [SQLClient columns: records];
 }
 
 - (SQLRecord*) queryRecord: (NSString*)stmt, ...
@@ -2649,13 +2665,7 @@
 
 - (void) singletons: (NSMutableArray*)records
 {
-  unsigned     c = [records count];
-
-  while (c-- > 0)
-    {
-      [records replaceObjectAtIndex: c
-                        withObject: [[records objectAtIndex: c] lastObject]];
-    }
+  [SQLClient singletons: records];
 }
 
 - (SQLTransaction*) transaction

Modified: libs/sqlclient/trunk/SQLClientPool.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/SQLClientPool.m?rev=38249&r1=38248&r2=38249&view=diff
==============================================================================
--- libs/sqlclient/trunk/SQLClientPool.m        (original)
+++ libs/sqlclient/trunk/SQLClientPool.m        Thu Dec 11 18:26:32 2014
@@ -542,60 +542,320 @@
 
 @end
 
-@implementation SQLClientPool (Proxying)
-
-static BOOL
-selIsBad(SEL aSelector)
-{
-  const char    *n = sel_getName(aSelector);
-
-  if (strncmp(n, "set", 3) == 0)
-    {
-      return YES;
-    }
-  if (strncmp(n, "backend", 7) == 0)
-    {
-      return YES;
-    }
-  if (strcmp(n, "begin") == 0)
-    {
-      return YES;
-    }
-  return NO;
-}
-
-- (void) forwardInvocation: (NSInvocation*)anInvocation
-{
-  SQLClient     *db;
-
-  db = [self provideClient];
-  [anInvocation invokeWithTarget: db];
-  [self swallowClient: db];
-}
-
-- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
-{
-  NSMethodSignature     *methodSig;
-
-  methodSig = [super methodSignatureForSelector: aSelector];
-  if (nil == methodSig && 0 != c && NO == selIsBad(aSelector))
-    {
-      methodSig = [c[0] methodSignatureForSelector: aSelector];
-    }
-  return methodSig;
-}
-
-- (BOOL) respondsToSelector: (SEL)aSelector
-{
-  BOOL  result;
-
-  result = [super respondsToSelector: aSelector];
-  if (NO == result && 0 != c && NO == selIsBad(aSelector))
-    {
-      result = [c[0] respondsToSelector: aSelector];
-    }
-  return result;
-}
-
+@interface      SQLClient (Private)
+- (NSMutableArray*) _prepare: (NSString*)stmt args: (va_list)args;
 @end
 
+@implementation SQLClientPool (ConvenienceMethods)
+
+- (NSString*) buildQuery: (NSString*)stmt, ...
+{
+  SQLClient     *db = [self provideClient];
+  NSString     *sql = nil;
+  va_list      ap;
+
+  /*
+   * First check validity and concatenate parts of the query.
+   */
+  va_start (ap, stmt);
+  sql = [[db _prepare: stmt args: ap] objectAtIndex: 0];
+  va_end (ap);
+  [self swallowClient: db];
+
+  return sql;
+}
+
+- (NSString*) buildQuery: (NSString*)stmt with: (NSDictionary*)values
+{
+  SQLClient     *db = [self provideClient];
+  NSString      *result = [db buildQuery: stmt with: values];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSMutableArray*) cache: (int)seconds
+                   query: (NSString*)stmt,...
+{
+  SQLClient             *db = [self provideClient];
+  NSMutableArray        *result;
+  va_list              ap;
+
+  va_start (ap, stmt);
+  stmt = [[db _prepare: stmt args: ap] objectAtIndex: 0];
+  va_end (ap);
+  result = [db cache: seconds simpleQuery: stmt];
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSMutableArray*) cache: (int)seconds
+                   query: (NSString*)stmt
+                    with: (NSDictionary*)values
+{
+  SQLClient             *db = [self provideClient];
+  NSMutableArray        *result = [db cache: seconds query: stmt with: values];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSMutableArray*) cache: (int)seconds simpleQuery: (NSString*)stmt;
+{
+  SQLClient             *db = [self provideClient];
+  NSMutableArray        *result = [db cache: seconds simpleQuery: stmt];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSMutableArray*) cache: (int)seconds
+             simpleQuery: (NSString*)stmt
+              recordType: (id)rtype
+                listType: (id)ltype
+{
+  SQLClient             *db = [self provideClient];
+  NSMutableArray        *result;
+
+  result = [db cache: seconds
+         simpleQuery: stmt
+          recordType: rtype
+            listType: ltype];
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSMutableArray*) columns: (NSMutableArray*)records
+{
+  return [SQLClient columns: records];
+}
+
+- (NSInteger) execute: (NSString*)stmt, ...
+{
+  SQLClient     *db = [self provideClient];
+  NSInteger     result;
+  NSArray      *info;
+  va_list      ap;
+
+  va_start (ap, stmt);
+  info = [db _prepare: stmt args: ap];
+  va_end (ap);
+  result = [db simpleExecute: info];
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSInteger) execute: (NSString*)stmt with: (NSDictionary*)values
+{
+  SQLClient     *db = [self provideClient];
+  NSInteger     result = [db execute: stmt with: values];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSMutableArray*) query: (NSString*)stmt, ...
+{
+  SQLClient             *db = [self provideClient];
+  NSMutableArray       *result = nil;
+  va_list              ap;
+
+  /*
+   * First check validity and concatenate parts of the query.
+   */
+  va_start (ap, stmt);
+  stmt = [[db _prepare: stmt args: ap] objectAtIndex: 0];
+  va_end (ap);
+  result = [db simpleQuery: stmt];
+  [self swallowClient: db];
+
+  return result;
+}
+
+- (NSMutableArray*) query: (NSString*)stmt with: (NSDictionary*)values
+{
+  SQLClient             *db = [self provideClient];
+  NSMutableArray        *result = [db query: stmt with: values];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (SQLRecord*) queryRecord: (NSString*)stmt, ...
+{
+  SQLClient     *db = [self provideClient];
+  NSArray      *result = nil;
+  SQLRecord    *record;
+  va_list      ap;
+
+  va_start (ap, stmt);
+  stmt = [[db _prepare: stmt args: ap] objectAtIndex: 0];
+  va_end (ap);
+  result = [db simpleQuery: stmt];
+  [self swallowClient: db];
+
+  if ([result count] > 1)
+    {
+      [NSException raise: NSInvalidArgumentException
+                 format: @"Query returns more than one record -\n%@\n", stmt];
+    }
+  record = [result lastObject];
+  if (record == nil)
+    {
+      [NSException raise: SQLEmptyException
+                 format: @"Query returns no data -\n%@\n", stmt];
+    }
+  return record;
+}
+
+- (NSString*) queryString: (NSString*)stmt, ...
+{
+  SQLClient     *db = [self provideClient];
+  NSArray      *result = nil;
+  SQLRecord    *record;
+  va_list      ap;
+
+  va_start (ap, stmt);
+  stmt = [[db _prepare: stmt args: ap] objectAtIndex: 0];
+  va_end (ap);
+  result = [db simpleQuery: stmt];
+  [self swallowClient: db];
+
+  if ([result count] > 1)
+    {
+      [NSException raise: NSInvalidArgumentException
+                 format: @"Query returns more than one record -\n%@\n", stmt];
+    }
+  record = [result lastObject];
+  if (record == nil)
+    {
+      [NSException raise: SQLEmptyException
+                 format: @"Query returns no data -\n%@\n", stmt];
+    }
+  if ([record count] > 1)
+    {
+      [NSException raise: NSInvalidArgumentException
+                 format: @"Query returns multiple fields -\n%@\n", stmt];
+    }
+  return [[record lastObject] description];
+}
+
+- (NSString*) quote: (id)obj
+{
+  SQLClient     *db = [self provideClient];
+  NSString      *result = [db quote: obj];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSString*) quotef: (NSString*)fmt, ...
+{
+  SQLClient     *db = [self provideClient];
+  va_list      ap;
+  NSString     *str;
+  NSString     *quoted;
+
+  va_start(ap, fmt);
+  str = [[NSString allocWithZone: NSDefaultMallocZone()]
+    initWithFormat: fmt arguments: ap];
+  va_end(ap);
+  quoted = [self quoteString: str];
+  [self swallowClient: db];
+  [str release];
+  return quoted;
+}
+
+- (NSString*) quoteBigInteger: (int64_t)i
+{
+  SQLClient     *db = [self provideClient];
+  NSString      *result = [db quoteBigInteger: i];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSString*) quoteCString: (const char *)s
+{
+  SQLClient     *db = [self provideClient];
+  NSString      *result = [db quoteCString: s];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSString*) quoteChar: (char)chr
+{
+  SQLClient     *db = [self provideClient];
+  NSString      *result = [db quoteChar: chr];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSString*) quoteFloat: (float)f
+{
+  SQLClient     *db = [self provideClient];
+  NSString      *result = [db quoteFloat: f];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSString*) quoteInteger: (int)i
+{
+  SQLClient     *db = [self provideClient];
+  NSString      *result = [db quoteInteger: i];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSString*) quoteString: (NSString *)s
+{
+  SQLClient     *db = [self provideClient];
+  NSString      *result = [db quoteString: s];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSInteger) simpleExecute: (NSArray*)info
+{
+  SQLClient     *db = [self provideClient];
+  NSInteger     result = [db simpleExecute: info];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSMutableArray*) simpleQuery: (NSString*)stmt
+{
+  SQLClient             *db = [self provideClient];
+  NSMutableArray        *result = [db simpleQuery: stmt];
+
+  [self swallowClient: db];
+  return result;
+}
+
+- (NSMutableArray*) simpleQuery: (NSString*)stmt
+                    recordType: (id)rtype
+                      listType: (id)ltype
+{
+  SQLClient             *db = [self provideClient];
+  NSMutableArray        *result;
+
+  result = [db simpleQuery: stmt
+                recordType: rtype
+                  listType: ltype];
+  [self swallowClient: db];
+  return result;
+}
+
+- (void) singletons: (NSMutableArray*)records
+{
+  [SQLClient singletons: records];
+}
+
+@end
+

Modified: libs/sqlclient/trunk/testPostgres.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/testPostgres.m?rev=38249&r1=38248&r2=38249&view=diff
==============================================================================
--- libs/sqlclient/trunk/testPostgres.m (original)
+++ libs/sqlclient/trunk/testPostgres.m Thu Dec 11 18:26:32 2014
@@ -95,6 +95,7 @@
 #endif
   db = [sp provideClient];
   [sp swallowClient: db];
+  [sp queryString: @"SELECT CURRENT_TIMESTAMP", nil];
   db = [sp provideClient];
 
   l = [Logger new];


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to