mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-20 18:32:06 +00:00
convenience methods
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@38249 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
d985eb2650
commit
35eb805b78
6 changed files with 420 additions and 80 deletions
|
@ -1,3 +1,11 @@
|
|||
2014-12-11 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* 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 <rfm@gnu.org>
|
||||
|
||||
* GNUmakefile: bump version to 1.8.2 for bugfix release.
|
||||
|
|
16
Postgres.m
16
Postgres.m
|
@ -1032,8 +1032,20 @@ static unsigned int trim(char *str)
|
|||
#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
|
||||
|
|
73
SQLClient.h
73
SQLClient.h
|
@ -1186,6 +1186,24 @@ SQLCLIENT_PRIVATE
|
|||
*/
|
||||
@interface SQLClient (Convenience)
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Convenience method to deal with the results of a query where each
|
||||
* record contains a single field ... it converts the array of records
|
||||
* returned by the query to an array containing the fields.<br />
|
||||
* NB. This does not check that the contents of the records array are
|
||||
* 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
|
||||
|
@ -1196,10 +1214,7 @@ SQLCLIENT_PRIVATE
|
|||
*/
|
||||
- (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.
|
||||
/** The same as the [SQLClient+columns:] method.
|
||||
*/
|
||||
- (NSMutableArray*) columns: (NSMutableArray*)records;
|
||||
|
||||
|
@ -1218,14 +1233,7 @@ SQLCLIENT_PRIVATE
|
|||
*/
|
||||
- (NSString*) queryString: (NSString*)stmt,...;
|
||||
|
||||
/**
|
||||
* Convenience method to deal with the results of a query where each
|
||||
* record contains a single field ... it converts the array of records
|
||||
* returned by the query to an array containing the fields.<br />
|
||||
* NB. This does not check that the contents of the records array are
|
||||
* 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).
|
||||
/** The same as the [SQLClient+singletons:] method.
|
||||
*/
|
||||
- (void) singletons: (NSMutableArray*)records;
|
||||
|
||||
|
@ -1531,6 +1539,47 @@ SQLCLIENT_PRIVATE
|
|||
|
||||
@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
|
||||
|
|
54
SQLClient.m
54
SQLClient.m
|
@ -2539,21 +2539,7 @@ static int poolConnections = 0;
|
|||
|
||||
@implementation SQLClient(Convenience)
|
||||
|
||||
- (SQLTransaction*) batch: (BOOL)stopOnFailure
|
||||
{
|
||||
SQLTransaction *transaction;
|
||||
|
||||
transaction = (SQLTransaction*)NSAllocateObject([SQLTransaction class], 0,
|
||||
NSDefaultMallocZone());
|
||||
|
||||
transaction->_db = [self retain];
|
||||
transaction->_info = [NSMutableArray new];
|
||||
transaction->_batch = YES;
|
||||
transaction->_stop = stopOnFailure;
|
||||
return [(SQLTransaction*)transaction autorelease];
|
||||
}
|
||||
|
||||
- (NSMutableArray*) columns: (NSMutableArray*)records
|
||||
+ (NSMutableArray*) columns: (NSMutableArray*)records
|
||||
{
|
||||
SQLRecord *r = [records lastObject];
|
||||
unsigned rowCount = [records count];
|
||||
|
@ -2590,6 +2576,36 @@ static int poolConnections = 0;
|
|||
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;
|
||||
|
||||
transaction = (SQLTransaction*)NSAllocateObject([SQLTransaction class], 0,
|
||||
NSDefaultMallocZone());
|
||||
|
||||
transaction->_db = [self retain];
|
||||
transaction->_info = [NSMutableArray new];
|
||||
transaction->_batch = YES;
|
||||
transaction->_stop = stopOnFailure;
|
||||
return [(SQLTransaction*)transaction autorelease];
|
||||
}
|
||||
|
||||
- (NSMutableArray*) columns: (NSMutableArray*)records
|
||||
{
|
||||
return [SQLClient columns: records];
|
||||
}
|
||||
|
||||
- (SQLRecord*) queryRecord: (NSString*)stmt, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -2649,13 +2665,7 @@ static int poolConnections = 0;
|
|||
|
||||
- (void) singletons: (NSMutableArray*)records
|
||||
{
|
||||
unsigned c = [records count];
|
||||
|
||||
while (c-- > 0)
|
||||
{
|
||||
[records replaceObjectAtIndex: c
|
||||
withObject: [[records objectAtIndex: c] lastObject]];
|
||||
}
|
||||
[SQLClient singletons: records];
|
||||
}
|
||||
|
||||
- (SQLTransaction*) transaction
|
||||
|
|
348
SQLClientPool.m
348
SQLClientPool.m
|
@ -542,60 +542,320 @@
|
|||
|
||||
@end
|
||||
|
||||
@implementation SQLClientPool (Proxying)
|
||||
@interface SQLClient (Private)
|
||||
- (NSMutableArray*) _prepare: (NSString*)stmt args: (va_list)args;
|
||||
@end
|
||||
|
||||
static BOOL
|
||||
selIsBad(SEL aSelector)
|
||||
@implementation SQLClientPool (ConvenienceMethods)
|
||||
|
||||
- (NSString*) buildQuery: (NSString*)stmt, ...
|
||||
{
|
||||
const char *n = sel_getName(aSelector);
|
||||
SQLClient *db = [self provideClient];
|
||||
NSString *sql = nil;
|
||||
va_list ap;
|
||||
|
||||
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];
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
|
||||
- (NSString*) buildQuery: (NSString*)stmt with: (NSDictionary*)values
|
||||
{
|
||||
NSMethodSignature *methodSig;
|
||||
SQLClient *db = [self provideClient];
|
||||
NSString *result = [db buildQuery: stmt with: values];
|
||||
|
||||
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];
|
||||
}
|
||||
[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
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ main()
|
|||
#endif
|
||||
db = [sp provideClient];
|
||||
[sp swallowClient: db];
|
||||
[sp queryString: @"SELECT CURRENT_TIMESTAMP", nil];
|
||||
db = [sp provideClient];
|
||||
|
||||
l = [Logger new];
|
||||
|
|
Loading…
Reference in a new issue