diff --git a/ChangeLog b/ChangeLog index e7f5a84..9d77d6e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2014-12-11 Richard Frith-Macdonald + + * SQLClient.h: + * SQLClient.m: + * GNUmakefile: + Expose method to prepare a statement and a convenience method to + check for an existing cached value (using a prepared statement + as the cache key). + Bumped version to 1.8.3. + 2014-12-11 Richard Frith-Macdonald * Postgres.m: Fix minor thread safety issue. diff --git a/GNUmakefile b/GNUmakefile index d2bb58e..3cd0bbe 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -21,7 +21,7 @@ include $(GNUSTEP_MAKEFILES)/common.make -include config.make PACKAGE_NAME = SQLClient -PACKAGE_VERSION = 1.8.2 +PACKAGE_VERSION = 1.8.3 CVS_MODULE_NAME = gnustep/dev-libs/SQLClient CVS_TAG_NAME = SQLClient SVN_BASE_URL=svn+ssh://svn.gna.org/svn/gnustep/libs diff --git a/SQLClient.h b/SQLClient.h index 2b4007c..c761de2 100644 --- a/SQLClient.h +++ b/SQLClient.h @@ -716,6 +716,19 @@ SQLCLIENT_PRIVATE */ - (NSString*) password; +/** + * This is the method used to convert a query or statement to a standard + * form used internally by other methods.
+ * This works to build an sql string by quoting any non-string objects + * and concatenating the resulting strings in a nil terminated list.
+ * Returns an array containing the statement as the first object and + * any NSData objects following. The NSData objects appear in the + * statement strings as the marker sequence - '?'''?'
+ * If the returned array contains a single object, that object is a + * simple SQL query/statement. + */ +- (NSMutableArray*) prepare: (NSString*)stmt args: (va_list)args; + /** *

Perform arbitrary query which returns values. *

@@ -1331,6 +1344,11 @@ SQLCLIENT_PRIVATE */ - (GSCache*) cache; +/** Returns an autoreleased mutable copy of the cached object corresponding + * to the supplied query/statement (or nil if no such object is cached). + */ +- (NSMutableArray*) cacheCheckSimpleQuery: (NSString*)stmt; + /** * Calls -cache:simpleQuery:recordType:listType: with the default * record class, array class, and with a query string formed from @@ -1356,8 +1374,8 @@ SQLCLIENT_PRIVATE /** * If the result of the query is already cached and has not expired, - * return it. Otherwise, perform the query and cache the result - * giving it the specified lifetime in seconds.
+ * return an autoreleased mutable copy. Otherwise, perform the query + * and cache the result giving it the specified lifetime in seconds.
* If seconds is negative, the query is performed irrespective of * whether it is already cached, and its absolute value is used to * set the lifetime of the results.
@@ -1373,7 +1391,10 @@ SQLCLIENT_PRIVATE * to add records to the list.
* If ltype is nil then the [NSMutableArray] class is used.
* The list produced by this argument is used as the return value of - * this method.
+ * this method.
+ * NB. cache lookups for the instance created from ltype will be provided + * by sending -mutableCopy and -autorelease messages to the original + * instance.
* If a cache thread has been set using the -setCacheThread: method, and the * -cache:simpleQuery:recordType:listType: method is called from a * thread other than the cache thread, then any query to retrieve diff --git a/SQLClient.m b/SQLClient.m index 6b5640b..1114769 100644 --- a/SQLClient.m +++ b/SQLClient.m @@ -691,15 +691,6 @@ static NSArray *rollbackStatement = nil; */ - (void) _populateCache: (CacheQuery*)a; -/** - * Internal method to build an sql string by quoting any non-string objects - * and concatenating the resulting strings in a nil terminated list.
- * Returns an array containing the statement as the first object and - * any NSData objects following. The NSData objects appear in the - * statement strings as the marker sequence - '?'''?' - */ -- (NSMutableArray*) _prepare: (NSString*)stmt args: (va_list)args; - /** Internal method called to record the 'main' thread in which automated * cache updates are to be performed. */ @@ -954,7 +945,7 @@ static int poolConnections = 0; * First check validity and concatenate parts of the query. */ va_start (ap, stmt); - sql = [[self _prepare: stmt args: ap] objectAtIndex: 0]; + sql = [[self prepare: stmt args: ap] objectAtIndex: 0]; va_end (ap); return sql; @@ -1211,7 +1202,7 @@ static int poolConnections = 0; va_list ap; va_start (ap, stmt); - info = [self _prepare: stmt args: ap]; + info = [self prepare: stmt args: ap]; va_end (ap); return [self simpleExecute: info]; } @@ -1405,6 +1396,47 @@ static int poolConnections = 0; return _password; } +- (NSMutableArray*) prepare: (NSString*)stmt args: (va_list)args +{ + NSMutableArray *ma = [NSMutableArray arrayWithCapacity: 2]; + NSString *tmp = va_arg(args, NSString*); + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + + if (tmp != nil) + { + NSMutableString *s = [NSMutableString stringWithCapacity: 1024]; + + [s appendString: stmt]; + /* + * Append any values from the nil terminated varargs + */ + while (tmp != nil) + { + if ([tmp isKindOfClass: NSStringClass] == NO) + { + if ([tmp isKindOfClass: [NSData class]] == YES) + { + [ma addObject: tmp]; + [s appendString: @"'?'''?'"]; // Marker. + } + else + { + [s appendString: [self quote: tmp]]; + } + } + else + { + [s appendString: tmp]; + } + tmp = va_arg(args, NSString*); + } + stmt = s; + } + [ma insertObject: stmt atIndex: 0]; + [arp release]; + return ma; +} + - (NSMutableArray*) query: (NSString*)stmt, ... { va_list ap; @@ -1414,7 +1446,7 @@ static int poolConnections = 0; * First check validity and concatenate parts of the query. */ va_start (ap, stmt); - stmt = [[self _prepare: stmt args: ap] objectAtIndex: 0]; + stmt = [[self prepare: stmt args: ap] objectAtIndex: 0]; va_end (ap); result = [self simpleQuery: stmt]; @@ -2304,47 +2336,6 @@ static int poolConnections = 0; lifetime: a->lifetime]; } -- (NSMutableArray*) _prepare: (NSString*)stmt args: (va_list)args -{ - NSMutableArray *ma = [NSMutableArray arrayWithCapacity: 2]; - NSString *tmp = va_arg(args, NSString*); - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - - if (tmp != nil) - { - NSMutableString *s = [NSMutableString stringWithCapacity: 1024]; - - [s appendString: stmt]; - /* - * Append any values from the nil terminated varargs - */ - while (tmp != nil) - { - if ([tmp isKindOfClass: NSStringClass] == NO) - { - if ([tmp isKindOfClass: [NSData class]] == YES) - { - [ma addObject: tmp]; - [s appendString: @"'?'''?'"]; // Marker. - } - else - { - [s appendString: [self quote: tmp]]; - } - } - else - { - [s appendString: tmp]; - } - tmp = va_arg(args, NSString*); - } - stmt = s; - } - [ma insertObject: stmt atIndex: 0]; - [arp release]; - return ma; -} - - (void) _recordMainThread { mainThread = [NSThread currentThread]; @@ -2645,7 +2636,7 @@ static int poolConnections = 0; SQLRecord *record; va_start (ap, stmt); - stmt = [[self _prepare: stmt args: ap] objectAtIndex: 0]; + stmt = [[self prepare: stmt args: ap] objectAtIndex: 0]; va_end (ap); result = [self simpleQuery: stmt]; @@ -2671,7 +2662,7 @@ static int poolConnections = 0; SQLRecord *record; va_start (ap, stmt); - stmt = [[self _prepare: stmt args: ap] objectAtIndex: 0]; + stmt = [[self prepare: stmt args: ap] objectAtIndex: 0]; va_end (ap); result = [self simpleQuery: stmt]; @@ -2761,13 +2752,24 @@ static int poolConnections = 0; return [c autorelease]; } +- (NSMutableArray*) cacheCheckSimpleQuery: (NSString*)stmt +{ + NSMutableArray *result = [[self cache] objectForKey: stmt]; + + if (result != nil) + { + result = [[result mutableCopy] autorelease]; + } + return result; +} + - (NSMutableArray*) cache: (int)seconds query: (NSString*)stmt,... { va_list ap; va_start (ap, stmt); - stmt = [[self _prepare: stmt args: ap] objectAtIndex: 0]; + stmt = [[self prepare: stmt args: ap] objectAtIndex: 0]; va_end (ap); return [self cache: seconds simpleQuery: stmt]; @@ -3180,7 +3182,7 @@ static int poolConnections = 0; NSMutableArray *p; va_start (ap, stmt); - p = [_db _prepare: stmt args: ap]; + p = [_db prepare: stmt args: ap]; va_end (ap); [self _merge: p]; }