mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-22 11:21:20 +00:00
Another new method for pools and transactions
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@38718 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
ba050a9adf
commit
603235b671
4 changed files with 191 additions and 189 deletions
|
@ -5,6 +5,7 @@
|
||||||
* SQLClientPool.m:
|
* SQLClientPool.m:
|
||||||
Implement another missing convenience method.
|
Implement another missing convenience method.
|
||||||
Fix locking error when executing a batch.
|
Fix locking error when executing a batch.
|
||||||
|
Add -prepare:with: method for use by transactions.
|
||||||
|
|
||||||
2015-06-27 Richard Frith-Macdonald <rfm@gnu.org>
|
2015-06-27 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
|
|
@ -790,6 +790,11 @@ SQLCLIENT_PRIVATE
|
||||||
*/
|
*/
|
||||||
- (NSMutableArray*) prepare: (NSString*)stmt args: (va_list)args;
|
- (NSMutableArray*) prepare: (NSString*)stmt args: (va_list)args;
|
||||||
|
|
||||||
|
/** This method is like -prepare:args: but takes a dictionary of
|
||||||
|
* values to be substituted into the sql string.
|
||||||
|
*/
|
||||||
|
- (NSMutableArray*) prepare: (NSString*)stmt with: (NSDictionary*)values;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Perform arbitrary query <em>which returns values.</em>
|
* <p>Perform arbitrary query <em>which returns values.</em>
|
||||||
* </p>
|
* </p>
|
||||||
|
@ -1737,6 +1742,7 @@ SQLCLIENT_PRIVATE
|
||||||
- (NSInteger) execute: (NSString*)stmt,...;
|
- (NSInteger) execute: (NSString*)stmt,...;
|
||||||
- (NSInteger) execute: (NSString*)stmt with: (NSDictionary*)values;
|
- (NSInteger) execute: (NSString*)stmt with: (NSDictionary*)values;
|
||||||
- (NSMutableArray*) prepare: (NSString*)stmt args: (va_list)args;
|
- (NSMutableArray*) prepare: (NSString*)stmt args: (va_list)args;
|
||||||
|
- (NSMutableArray*) prepare: (NSString*)stmt with: (NSDictionary*)values;
|
||||||
- (NSMutableArray*) query: (NSString*)stmt,...;
|
- (NSMutableArray*) query: (NSString*)stmt,...;
|
||||||
- (NSMutableArray*) query: (NSString*)stmt with: (NSDictionary*)values;
|
- (NSMutableArray*) query: (NSString*)stmt with: (NSDictionary*)values;
|
||||||
- (SQLRecord*) queryRecord: (NSString*)stmt,...;
|
- (SQLRecord*) queryRecord: (NSString*)stmt,...;
|
||||||
|
|
368
SQLClient.m
368
SQLClient.m
|
@ -776,16 +776,6 @@ static NSArray *rollbackStatement = nil;
|
||||||
*/
|
*/
|
||||||
- (void) _recordMainThread;
|
- (void) _recordMainThread;
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal method to substitute values from the dictionary into
|
|
||||||
* a string containing markup identifying where the values should
|
|
||||||
* appear by name. Non-string objects in the dictionary are quoted.<br />
|
|
||||||
* 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 - <code>'?'''?'</code>
|
|
||||||
*/
|
|
||||||
- (NSMutableArray*) _substitute: (NSString*)str with: (NSDictionary*)vals;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called at one second intervals to ensure that our current timestamp
|
* Called at one second intervals to ensure that our current timestamp
|
||||||
* is reasonably accurate.
|
* is reasonably accurate.
|
||||||
|
@ -1086,7 +1076,7 @@ static int poolConnections = 0;
|
||||||
{
|
{
|
||||||
NSString *sql = nil;
|
NSString *sql = nil;
|
||||||
|
|
||||||
sql = [[self _substitute: stmt with: values] objectAtIndex: 0];
|
sql = [[self prepare: stmt with: values] objectAtIndex: 0];
|
||||||
|
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
@ -1352,7 +1342,7 @@ static int poolConnections = 0;
|
||||||
{
|
{
|
||||||
NSArray *info;
|
NSArray *info;
|
||||||
|
|
||||||
info = [self _substitute: stmt with: values];
|
info = [self prepare: stmt with: values];
|
||||||
return [self simpleExecute: info];
|
return [self simpleExecute: info];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1594,6 +1584,180 @@ static int poolConnections = 0;
|
||||||
return ma;
|
return ma;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSMutableArray*) prepare: (NSString*)stmt with: (NSDictionary*)values
|
||||||
|
{
|
||||||
|
unsigned int l = [stmt length];
|
||||||
|
NSRange r;
|
||||||
|
NSMutableArray *ma = [NSMutableArray arrayWithCapacity: 2];
|
||||||
|
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
||||||
|
|
||||||
|
if (l < 2)
|
||||||
|
{
|
||||||
|
[ma addObject: stmt]; // Can't contain a {...} sequence
|
||||||
|
}
|
||||||
|
else if ((r = [stmt rangeOfString: @"{"]).length == 0)
|
||||||
|
{
|
||||||
|
[ma addObject: stmt]; // No '{' markup
|
||||||
|
}
|
||||||
|
else if (l - r.location < 2)
|
||||||
|
{
|
||||||
|
[ma addObject: stmt]; // Can't contain a {...} sequence
|
||||||
|
}
|
||||||
|
else if ([stmt rangeOfString: @"}" options: NSLiteralSearch
|
||||||
|
range: NSMakeRange(r.location, l - r.location)].length == 0
|
||||||
|
&& [stmt rangeOfString: @"{{" options: NSLiteralSearch
|
||||||
|
range: NSMakeRange(0, l)].length == 0)
|
||||||
|
{
|
||||||
|
[ma addObject: stmt]; // No closing '}' or repeated '{{'
|
||||||
|
}
|
||||||
|
else if (r.length == 0)
|
||||||
|
{
|
||||||
|
[ma addObject: stmt]; // Nothing to do.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSMutableString *mtext = [[stmt mutableCopy] autorelease];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace {FieldName} with the value of the field
|
||||||
|
*/
|
||||||
|
while (r.length > 0)
|
||||||
|
{
|
||||||
|
unsigned pos = r.location;
|
||||||
|
unsigned nxt;
|
||||||
|
unsigned vLength;
|
||||||
|
NSArray *a;
|
||||||
|
NSRange s;
|
||||||
|
NSString *v;
|
||||||
|
NSString *alt;
|
||||||
|
id o;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
r.length = l - pos;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the length of the string from the '{' onwards is less than two,
|
||||||
|
* there is nothing to do and we can end processing.
|
||||||
|
*/
|
||||||
|
if (r.length < 2)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([mtext characterAtIndex: r.location + 1] == '{')
|
||||||
|
{
|
||||||
|
// Got '{{' ... remove one of them.
|
||||||
|
r.length = 1;
|
||||||
|
[mtext replaceCharactersInRange: r withString: @""];
|
||||||
|
l--;
|
||||||
|
r.location++;
|
||||||
|
r.length = l - r.location;
|
||||||
|
r = [mtext rangeOfString: @"{"
|
||||||
|
options: NSLiteralSearch
|
||||||
|
range: r];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = [mtext rangeOfString: @"}"
|
||||||
|
options: NSLiteralSearch
|
||||||
|
range: r];
|
||||||
|
if (r.length == 0)
|
||||||
|
{
|
||||||
|
break; // No closing bracket
|
||||||
|
}
|
||||||
|
nxt = NSMaxRange(r);
|
||||||
|
r = NSMakeRange(pos, nxt - pos);
|
||||||
|
s.location = r.location + 1;
|
||||||
|
s.length = r.length - 2;
|
||||||
|
v = [mtext substringWithRange: s];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the value contains a '?', it is actually in two parts,
|
||||||
|
* the first part is the field name, and the second part is
|
||||||
|
* an alternative text to be used if the value from the
|
||||||
|
* dictionary is empty.
|
||||||
|
*/
|
||||||
|
s = [v rangeOfString: @"?"];
|
||||||
|
if (s.length == 0)
|
||||||
|
{
|
||||||
|
alt = @""; // No alternative value.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alt = [v substringFromIndex: NSMaxRange(s)];
|
||||||
|
v = [v substringToIndex: s.location];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the value we are substituting contains dots, we split it apart.
|
||||||
|
* We use the value to make a reference into the dictionary we are
|
||||||
|
* given.
|
||||||
|
*/
|
||||||
|
a = [v componentsSeparatedByString: @"."];
|
||||||
|
o = values;
|
||||||
|
for (i = 0; i < [a count]; i++)
|
||||||
|
{
|
||||||
|
NSString *k = [a objectAtIndex: i];
|
||||||
|
|
||||||
|
if ([k length] > 0)
|
||||||
|
{
|
||||||
|
o = [(NSDictionary*)o objectForKey: k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (o == values)
|
||||||
|
{
|
||||||
|
v = nil; // Mo match found.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ([o isKindOfClass: NSStringClass] == YES)
|
||||||
|
{
|
||||||
|
v = (NSString*)o;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ([o isKindOfClass: [NSData class]] == YES)
|
||||||
|
{
|
||||||
|
[ma addObject: o];
|
||||||
|
v = @"'?'''?'";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v = [self quote: o];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([v length] == 0)
|
||||||
|
{
|
||||||
|
v = alt;
|
||||||
|
if (v == nil)
|
||||||
|
{
|
||||||
|
v = @"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vLength = [v length];
|
||||||
|
|
||||||
|
[mtext replaceCharactersInRange: r withString: v];
|
||||||
|
l += vLength; // Add length of string inserted
|
||||||
|
l -= r.length; // Remove length of string replaced
|
||||||
|
r.location += vLength;
|
||||||
|
|
||||||
|
if (r.location >= l)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
r.length = l - r.location;
|
||||||
|
r = [mtext rangeOfString: @"{"
|
||||||
|
options: NSLiteralSearch
|
||||||
|
range: r];
|
||||||
|
}
|
||||||
|
[ma insertObject: mtext atIndex: 0];
|
||||||
|
}
|
||||||
|
[arp release];
|
||||||
|
return ma;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSMutableArray*) query: (NSString*)stmt, ...
|
- (NSMutableArray*) query: (NSString*)stmt, ...
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -1615,7 +1779,7 @@ static int poolConnections = 0;
|
||||||
{
|
{
|
||||||
NSMutableArray *result = nil;
|
NSMutableArray *result = nil;
|
||||||
|
|
||||||
stmt = [[self _substitute: stmt with: values] objectAtIndex: 0];
|
stmt = [[self prepare: stmt with: values] objectAtIndex: 0];
|
||||||
|
|
||||||
result = [self simpleQuery: stmt];
|
result = [self simpleQuery: stmt];
|
||||||
|
|
||||||
|
@ -2514,180 +2678,6 @@ static int poolConnections = 0;
|
||||||
mainThread = [NSThread currentThread];
|
mainThread = [NSThread currentThread];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSMutableArray*) _substitute: (NSString*)str with: (NSDictionary*)vals
|
|
||||||
{
|
|
||||||
unsigned int l = [str length];
|
|
||||||
NSRange r;
|
|
||||||
NSMutableArray *ma = [NSMutableArray arrayWithCapacity: 2];
|
|
||||||
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
|
||||||
|
|
||||||
if (l < 2)
|
|
||||||
{
|
|
||||||
[ma addObject: str]; // Can't contain a {...} sequence
|
|
||||||
}
|
|
||||||
else if ((r = [str rangeOfString: @"{"]).length == 0)
|
|
||||||
{
|
|
||||||
[ma addObject: str]; // No '{' markup
|
|
||||||
}
|
|
||||||
else if (l - r.location < 2)
|
|
||||||
{
|
|
||||||
[ma addObject: str]; // Can't contain a {...} sequence
|
|
||||||
}
|
|
||||||
else if ([str rangeOfString: @"}" options: NSLiteralSearch
|
|
||||||
range: NSMakeRange(r.location, l - r.location)].length == 0
|
|
||||||
&& [str rangeOfString: @"{{" options: NSLiteralSearch
|
|
||||||
range: NSMakeRange(0, l)].length == 0)
|
|
||||||
{
|
|
||||||
[ma addObject: str]; // No closing '}' or repeated '{{'
|
|
||||||
}
|
|
||||||
else if (r.length == 0)
|
|
||||||
{
|
|
||||||
[ma addObject: str]; // Nothing to do.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSMutableString *mtext = [[str mutableCopy] autorelease];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Replace {FieldName} with the value of the field
|
|
||||||
*/
|
|
||||||
while (r.length > 0)
|
|
||||||
{
|
|
||||||
unsigned pos = r.location;
|
|
||||||
unsigned nxt;
|
|
||||||
unsigned vLength;
|
|
||||||
NSArray *a;
|
|
||||||
NSRange s;
|
|
||||||
NSString *v;
|
|
||||||
NSString *alt;
|
|
||||||
id o;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
r.length = l - pos;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the length of the string from the '{' onwards is less than two,
|
|
||||||
* there is nothing to do and we can end processing.
|
|
||||||
*/
|
|
||||||
if (r.length < 2)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([mtext characterAtIndex: r.location + 1] == '{')
|
|
||||||
{
|
|
||||||
// Got '{{' ... remove one of them.
|
|
||||||
r.length = 1;
|
|
||||||
[mtext replaceCharactersInRange: r withString: @""];
|
|
||||||
l--;
|
|
||||||
r.location++;
|
|
||||||
r.length = l - r.location;
|
|
||||||
r = [mtext rangeOfString: @"{"
|
|
||||||
options: NSLiteralSearch
|
|
||||||
range: r];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = [mtext rangeOfString: @"}"
|
|
||||||
options: NSLiteralSearch
|
|
||||||
range: r];
|
|
||||||
if (r.length == 0)
|
|
||||||
{
|
|
||||||
break; // No closing bracket
|
|
||||||
}
|
|
||||||
nxt = NSMaxRange(r);
|
|
||||||
r = NSMakeRange(pos, nxt - pos);
|
|
||||||
s.location = r.location + 1;
|
|
||||||
s.length = r.length - 2;
|
|
||||||
v = [mtext substringWithRange: s];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the value contains a '?', it is actually in two parts,
|
|
||||||
* the first part is the field name, and the second part is
|
|
||||||
* an alternative text to be used if the value from the
|
|
||||||
* dictionary is empty.
|
|
||||||
*/
|
|
||||||
s = [v rangeOfString: @"?"];
|
|
||||||
if (s.length == 0)
|
|
||||||
{
|
|
||||||
alt = @""; // No alternative value.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alt = [v substringFromIndex: NSMaxRange(s)];
|
|
||||||
v = [v substringToIndex: s.location];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the value we are substituting contains dots, we split it apart.
|
|
||||||
* We use the value to make a reference into the dictionary we are
|
|
||||||
* given.
|
|
||||||
*/
|
|
||||||
a = [v componentsSeparatedByString: @"."];
|
|
||||||
o = vals;
|
|
||||||
for (i = 0; i < [a count]; i++)
|
|
||||||
{
|
|
||||||
NSString *k = [a objectAtIndex: i];
|
|
||||||
|
|
||||||
if ([k length] > 0)
|
|
||||||
{
|
|
||||||
o = [(NSDictionary*)o objectForKey: k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (o == vals)
|
|
||||||
{
|
|
||||||
v = nil; // Mo match found.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ([o isKindOfClass: NSStringClass] == YES)
|
|
||||||
{
|
|
||||||
v = (NSString*)o;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ([o isKindOfClass: [NSData class]] == YES)
|
|
||||||
{
|
|
||||||
[ma addObject: o];
|
|
||||||
v = @"'?'''?'";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v = [self quote: o];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([v length] == 0)
|
|
||||||
{
|
|
||||||
v = alt;
|
|
||||||
if (v == nil)
|
|
||||||
{
|
|
||||||
v = @"";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vLength = [v length];
|
|
||||||
|
|
||||||
[mtext replaceCharactersInRange: r withString: v];
|
|
||||||
l += vLength; // Add length of string inserted
|
|
||||||
l -= r.length; // Remove length of string replaced
|
|
||||||
r.location += vLength;
|
|
||||||
|
|
||||||
if (r.location >= l)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
r.length = l - r.location;
|
|
||||||
r = [mtext rangeOfString: @"{"
|
|
||||||
options: NSLiteralSearch
|
|
||||||
range: r];
|
|
||||||
}
|
|
||||||
[ma insertObject: mtext atIndex: 0];
|
|
||||||
}
|
|
||||||
[arp release];
|
|
||||||
return ma;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void) _tick: (NSTimer*)t
|
+ (void) _tick: (NSTimer*)t
|
||||||
{
|
{
|
||||||
(void) GSTickerTimeNow();
|
(void) GSTickerTimeNow();
|
||||||
|
@ -2943,7 +2933,7 @@ static int poolConnections = 0;
|
||||||
query: (NSString*)stmt
|
query: (NSString*)stmt
|
||||||
with: (NSDictionary*)values
|
with: (NSDictionary*)values
|
||||||
{
|
{
|
||||||
stmt = [[self _substitute: stmt with: values] objectAtIndex: 0];
|
stmt = [[self prepare: stmt with: values] objectAtIndex: 0];
|
||||||
return [self cache: seconds simpleQuery: stmt];
|
return [self cache: seconds simpleQuery: stmt];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3375,7 +3365,7 @@ static int poolConnections = 0;
|
||||||
{
|
{
|
||||||
NSMutableArray *p;
|
NSMutableArray *p;
|
||||||
|
|
||||||
p = [_db _substitute: stmt with: values];
|
p = [_db prepare: stmt with: values];
|
||||||
[self _merge: p];
|
[self _merge: p];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -979,6 +979,11 @@
|
||||||
return [c[0] prepare: stmt args: args];
|
return [c[0] prepare: stmt args: args];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSMutableArray*) prepare: (NSString*)stmt with: (NSDictionary*)values
|
||||||
|
{
|
||||||
|
return [c[0] prepare: stmt with: values];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSMutableArray*) query: (NSString*)stmt, ...
|
- (NSMutableArray*) query: (NSString*)stmt, ...
|
||||||
{
|
{
|
||||||
SQLClient *db;
|
SQLClient *db;
|
||||||
|
|
Loading…
Reference in a new issue