mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-20 18:32:06 +00:00
Post notifications on connect and disconnect.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@25309 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
3dea330f47
commit
fb09bfd147
4 changed files with 296 additions and 121 deletions
|
@ -1,7 +1,14 @@
|
||||||
|
2007-07-09 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* SQLClient.m: Post notifications upon connect and disconnect.
|
||||||
|
|
||||||
2007-07-07 Richard Frith-Macdonald <rfm@gnu.org>
|
2007-07-07 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* SQLClient.m: Fix error causing loss of some debug output when an
|
* SQLClient.m: Fix error causing loss of some debug output when an
|
||||||
exception occurs in a transaction.
|
exception occurs in a transaction.
|
||||||
|
Rewrite transaction code to support execution with automatic retry of
|
||||||
|
statements when batching.
|
||||||
|
* JDBC.m: Update for new transaction code
|
||||||
|
|
||||||
2007-04-01 Richard Frith-Macdonald <rfm@gnu.org>
|
2007-04-01 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
|
106
JDBC.m
106
JDBC.m
|
@ -1675,64 +1675,39 @@ static int JDBCVARCHAR = 0;
|
||||||
|
|
||||||
@implementation _JDBCTransaction
|
@implementation _JDBCTransaction
|
||||||
|
|
||||||
// Marker for the end of data owned by a statement
|
- (BOOL) _batchable: (NSArray*)a
|
||||||
static id marker = @"End of statement data";
|
|
||||||
|
|
||||||
- (NSString*) description
|
|
||||||
{
|
{
|
||||||
return [NSString stringWithFormat: @"%@ with SQL '%@' for %@",
|
unsigned c = [a count];
|
||||||
[super description],
|
unsigned i;
|
||||||
(_count == 0 ? (id)@"" : (id)[_info objectAtIndex: 0]), _db];
|
|
||||||
|
for (i = 0; i < c; i++)
|
||||||
|
{
|
||||||
|
if ([[a objectAtIndex: i] count] > 1)
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _addInfo: (NSArray*)info
|
- (void) _merge: (NSMutableArray*)a
|
||||||
{
|
{
|
||||||
if (_count == 0)
|
unsigned c = [_info count];
|
||||||
{
|
unsigned i;
|
||||||
id o = [info objectAtIndex: 0];
|
|
||||||
NSMutableArray *ma;
|
|
||||||
|
|
||||||
if ([o isKindOfClass: [NSString class]] == YES)
|
for (i = 0; i < c; i++)
|
||||||
|
{
|
||||||
|
id o = [_info objectAtIndex: i];
|
||||||
|
|
||||||
|
if ([o isKindOfClass: [NSArray class]] == YES)
|
||||||
{
|
{
|
||||||
ma = [[NSMutableArray alloc] initWithObjects: &o count: 1];
|
[a addObject: o];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ma = [(NSArray*)o mutableCopy];
|
[(_JDBCTransaction*)o _merge: a];
|
||||||
}
|
}
|
||||||
[_info addObjectsFromArray: info];
|
|
||||||
[_info replaceObjectAtIndex: 0 withObject: ma];
|
|
||||||
RELEASE(ma);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned c = [info count];
|
|
||||||
unsigned i = 1;
|
|
||||||
id o = [info objectAtIndex: 0];
|
|
||||||
NSMutableArray *ma = [_info objectAtIndex: 0];
|
|
||||||
|
|
||||||
if ([o isKindOfClass: [NSString class]] == YES)
|
|
||||||
{
|
|
||||||
[ma addObject: (NSString*)o];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[ma addObjectsFromArray: (NSArray*)o];
|
|
||||||
}
|
|
||||||
while (i < c)
|
|
||||||
{
|
|
||||||
[_info addObject: [info objectAtIndex: i++]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the info item being added is a simple statement rather than the
|
|
||||||
* content of another transaction, we must add an end-of-statement marker.
|
|
||||||
*/
|
|
||||||
if ([info lastObject] != marker)
|
|
||||||
{
|
|
||||||
[_info addObject: marker];
|
|
||||||
}
|
|
||||||
_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) execute
|
- (void) execute
|
||||||
|
@ -1768,13 +1743,16 @@ static id marker = @"End of statement data";
|
||||||
|
|
||||||
NS_DURING
|
NS_DURING
|
||||||
{
|
{
|
||||||
NSMutableArray *statements = [_info objectAtIndex: 0];
|
NSMutableArray *statements;
|
||||||
unsigned numberOfStatements = [statements count];
|
unsigned numberOfStatements;
|
||||||
unsigned statement;
|
unsigned statement;
|
||||||
unsigned pos = 1;
|
|
||||||
NSTimeInterval _duration = [_db durationLogging];
|
NSTimeInterval _duration = [_db durationLogging];
|
||||||
NSTimeInterval start = 0.0;
|
NSTimeInterval start = 0.0;
|
||||||
|
|
||||||
|
statements = [NSMutableArray arrayWithCapacity: 100];
|
||||||
|
[self _merge: statements];
|
||||||
|
numberOfStatements = [statements count];
|
||||||
|
|
||||||
if (_duration >= 0)
|
if (_duration >= 0)
|
||||||
{
|
{
|
||||||
start = GSTickerTimeNow();
|
start = GSTickerTimeNow();
|
||||||
|
@ -1786,15 +1764,12 @@ static id marker = @"End of statement data";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numberOfStatements > 1 && ji->addBatch != 0
|
if (numberOfStatements > 1 && ji->addBatch != 0
|
||||||
&& [_info count] == numberOfStatements + 1)
|
&& [self _batchable: statements] == YES)
|
||||||
{
|
{
|
||||||
jintArray ja;
|
jintArray ja;
|
||||||
jint *array;
|
jint *array;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
/* We have multiple statements without arguments ... so this
|
|
||||||
* is batchable.
|
|
||||||
*/
|
|
||||||
for (statement = 0; statement < numberOfStatements; statement++)
|
for (statement = 0; statement < numberOfStatements; statement++)
|
||||||
{
|
{
|
||||||
NSString *stmt = [statements objectAtIndex: statement];
|
NSString *stmt = [statements objectAtIndex: statement];
|
||||||
|
@ -1837,20 +1812,20 @@ static id marker = @"End of statement data";
|
||||||
*/
|
*/
|
||||||
for (statement = 0; statement < numberOfStatements; statement++)
|
for (statement = 0; statement < numberOfStatements; statement++)
|
||||||
{
|
{
|
||||||
NSString *stmt = [statements objectAtIndex: statement];
|
NSArray *info = [statements objectAtIndex: statement];
|
||||||
|
NSString *stmt = [info objectAtIndex: 0];
|
||||||
|
unsigned c = [info count];
|
||||||
jmethodID jm;
|
jmethodID jm;
|
||||||
jobject js;
|
jobject js;
|
||||||
|
|
||||||
if ([_info objectAtIndex: pos] == marker)
|
if (c == 1)
|
||||||
{
|
{
|
||||||
pos++; // Step past end of statement data.
|
|
||||||
(*env)->CallIntMethod (env, ji->statement,
|
(*env)->CallIntMethod (env, ji->statement,
|
||||||
ji->executeUpdate, JStringFromNSString(env, stmt));
|
ji->executeUpdate, JStringFromNSString(env, stmt));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSData *data;
|
unsigned i;
|
||||||
int i = 1;
|
|
||||||
jclass jc;
|
jclass jc;
|
||||||
|
|
||||||
stmt = [stmt stringByReplacingString: @"'?'''?'"
|
stmt = [stmt stringByReplacingString: @"'?'''?'"
|
||||||
|
@ -1868,9 +1843,12 @@ static id marker = @"End of statement data";
|
||||||
|
|
||||||
/* Get data arguments for statement.
|
/* Get data arguments for statement.
|
||||||
*/
|
*/
|
||||||
while ((data = [_info objectAtIndex: pos++]) != marker)
|
for (i = 1; i < c; i++)
|
||||||
{
|
{
|
||||||
(*env)->CallIntMethod (env, js, jm, i++,
|
NSData *data;
|
||||||
|
|
||||||
|
data = [info objectAtIndex: i];
|
||||||
|
(*env)->CallIntMethod (env, js, jm, i,
|
||||||
ByteArrayFromNSData(env, data));
|
ByteArrayFromNSData(env, data));
|
||||||
JException(env);
|
JException(env);
|
||||||
}
|
}
|
||||||
|
|
56
SQLClient.h
56
SQLClient.h
|
@ -77,6 +77,10 @@
|
||||||
Support for standalone web applications ... eg to allow data to be
|
Support for standalone web applications ... eg to allow data to be
|
||||||
added to the database by people posting web forms to the application.
|
added to the database by people posting web forms to the application.
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
Supports notification of connection to and disconnection from the
|
||||||
|
database server.
|
||||||
|
</item>
|
||||||
</list>
|
</list>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
@ -187,6 +191,18 @@
|
||||||
@class NSString;
|
@class NSString;
|
||||||
@class SQLTransaction;
|
@class SQLTransaction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification sent when an instance becomes connected to the database
|
||||||
|
* server. The notification object is the instance connected.
|
||||||
|
*/
|
||||||
|
NSString *SQLClientDidConnectNotification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification sent when an instance becomes disconnected from the database
|
||||||
|
* server. The notification object is the instance disconnected.
|
||||||
|
*/
|
||||||
|
NSString *SQLClientDidDisconnectNotification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>An enhanced array to represent a record returned from a query.
|
* <p>An enhanced array to represent a record returned from a query.
|
||||||
* You should <em>NOT</em> try to create instances of this class
|
* You should <em>NOT</em> try to create instances of this class
|
||||||
|
@ -971,6 +987,16 @@ extern unsigned SQLClientTimeTick();
|
||||||
*/
|
*/
|
||||||
@interface SQLClient(Convenience)
|
@interface SQLClient(Convenience)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a transaction object configured to handle batching and
|
||||||
|
* execute part of a batch of statements if execution of the whole
|
||||||
|
* 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 failued statements.
|
||||||
|
*/
|
||||||
|
- (SQLTransaction*) batch: (BOOL)stopOnFailure;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a query (like the -query:,... method) and checks the result
|
* Executes a query (like the -query:,... method) and checks the result
|
||||||
* (raising an exception if the query did not contain a single record)
|
* (raising an exception if the query did not contain a single record)
|
||||||
|
@ -998,6 +1024,7 @@ extern unsigned SQLClientTimeTick();
|
||||||
* use the receiver as the database connection to perform transactions.
|
* use the receiver as the database connection to perform transactions.
|
||||||
*/
|
*/
|
||||||
- (SQLTransaction*) transaction;
|
- (SQLTransaction*) transaction;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1154,11 +1181,13 @@ extern unsigned SQLClientTimeTick();
|
||||||
* database operations should be. If you have multiple threads, you
|
* database operations should be. If you have multiple threads, you
|
||||||
* should create multiple SQLTransaction instances, at least one per thread.
|
* should create multiple SQLTransaction instances, at least one per thread.
|
||||||
*/
|
*/
|
||||||
@interface SQLTransaction : NSObject
|
@interface SQLTransaction : NSObject <NSCopying>
|
||||||
{
|
{
|
||||||
SQLClient *_db;
|
SQLClient *_db;
|
||||||
NSMutableArray *_info;
|
NSMutableArray *_info;
|
||||||
unsigned _count;
|
unsigned _count;
|
||||||
|
BOOL _batch;
|
||||||
|
BOOL _stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1176,7 +1205,7 @@ extern unsigned SQLClientTimeTick();
|
||||||
- (void) add: (NSString*)stmt with: (NSDictionary*)values;
|
- (void) add: (NSString*)stmt with: (NSDictionary*)values;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends all the statements from the other transaction to the receiver.<br />
|
* Appends a copy of the other transaction to the receiver.<br />
|
||||||
* This provides a convenient way of merging transactions which have been
|
* This provides a convenient way of merging transactions which have been
|
||||||
* built by different code modules, in order to have them all executed
|
* built by different code modules, in order to have them all executed
|
||||||
* together in a single operation (for efficiency etc).<br />
|
* together in a single operation (for efficiency etc).<br />
|
||||||
|
@ -1188,6 +1217,11 @@ extern unsigned SQLClientTimeTick();
|
||||||
*/
|
*/
|
||||||
- (void) append: (SQLTransaction*)other;
|
- (void) append: (SQLTransaction*)other;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a copy of the receiver.
|
||||||
|
*/
|
||||||
|
- (id) copyWithZone: (NSZone*)z;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of statements in this transaction.
|
* Returns the number of statements in this transaction.
|
||||||
*/
|
*/
|
||||||
|
@ -1218,6 +1252,24 @@ extern unsigned SQLClientTimeTick();
|
||||||
*/
|
*/
|
||||||
- (void) execute;
|
- (void) execute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>This is similar to the -execute method, but may allow partial
|
||||||
|
* execution of the transaction if appropriate:
|
||||||
|
* </p>
|
||||||
|
* <p>If the transaction was created using the [SQLClient-batch:] method and
|
||||||
|
* the transaction as a whole fails, individual statements are retried.<br />
|
||||||
|
* The stopOnFailure flag for the batch creation indicates whether the
|
||||||
|
* retries are stopped at the first statement to fail, or continue (skipping
|
||||||
|
* any failed statements).
|
||||||
|
* </p>
|
||||||
|
* <p>If the transaction has had transactions appended to it, those
|
||||||
|
* subsidiary transactions may succeed or fail atomically depending
|
||||||
|
* on their individual attributes.
|
||||||
|
* </p>
|
||||||
|
* The method returns the number of statements which actually succeeded.
|
||||||
|
*/
|
||||||
|
- (unsigned) executeBatch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the transaction, removing all previously added statements.
|
* Resets the transaction, removing all previously added statements.
|
||||||
* This allows the transaction object to be re-used for multiple
|
* This allows the transaction object to be re-used for multiple
|
||||||
|
|
248
SQLClient.m
248
SQLClient.m
|
@ -63,6 +63,12 @@
|
||||||
#define SUBCLASS_RESPONSIBILITY
|
#define SUBCLASS_RESPONSIBILITY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
NSString *SQLClientDidConnectNotification
|
||||||
|
= @"SQLClientDidConnectNotification";
|
||||||
|
|
||||||
|
NSString *SQLClientDidDisconnectNotification
|
||||||
|
= @"SQLClientDidDisconnectNotification";
|
||||||
|
|
||||||
static NSNull *null = nil;
|
static NSNull *null = nil;
|
||||||
static Class NSStringClass = 0;
|
static Class NSStringClass = 0;
|
||||||
static Class NSArrayClass = 0;
|
static Class NSArrayClass = 0;
|
||||||
|
@ -1110,6 +1116,12 @@ static unsigned int maxConnections = 8;
|
||||||
NS_ENDHANDLER
|
NS_ENDHANDLER
|
||||||
}
|
}
|
||||||
[lock unlock];
|
[lock unlock];
|
||||||
|
if (connected == YES)
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
postNotificationName: SQLClientDidConnectNotification
|
||||||
|
object: self];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return connected;
|
return connected;
|
||||||
}
|
}
|
||||||
|
@ -1190,6 +1202,9 @@ static unsigned int maxConnections = 8;
|
||||||
NS_ENDHANDLER
|
NS_ENDHANDLER
|
||||||
}
|
}
|
||||||
[lock unlock];
|
[lock unlock];
|
||||||
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
postNotificationName: SQLClientDidDisconnectNotification
|
||||||
|
object: self];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1659,6 +1674,7 @@ static unsigned int maxConnections = 8;
|
||||||
|
|
||||||
[lock lock];
|
[lock lock];
|
||||||
statement = [info objectAtIndex: 0];
|
statement = [info objectAtIndex: 0];
|
||||||
|
|
||||||
if ([statement isEqualToString: commitString])
|
if ([statement isEqualToString: commitString])
|
||||||
{
|
{
|
||||||
isCommit = YES;
|
isCommit = YES;
|
||||||
|
@ -2292,6 +2308,20 @@ static unsigned int maxConnections = 8;
|
||||||
|
|
||||||
@implementation SQLClient(Convenience)
|
@implementation SQLClient(Convenience)
|
||||||
|
|
||||||
|
- (SQLTransaction*) batch: (BOOL)stopOnFailure
|
||||||
|
{
|
||||||
|
TDefs transaction;
|
||||||
|
|
||||||
|
transaction = (TDefs)NSAllocateObject([SQLTransaction class], 0,
|
||||||
|
NSDefaultMallocZone());
|
||||||
|
|
||||||
|
transaction->_db = RETAIN(self);
|
||||||
|
transaction->_info = [NSMutableArray new];
|
||||||
|
transaction->_batch = YES;
|
||||||
|
transaction->_stop = stopOnFailure;
|
||||||
|
return AUTORELEASE((SQLTransaction*)transaction);
|
||||||
|
}
|
||||||
|
|
||||||
- (SQLRecord*) queryRecord: (NSString*)stmt, ...
|
- (SQLRecord*) queryRecord: (NSString*)stmt, ...
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -2539,101 +2569,209 @@ static unsigned int maxConnections = 8;
|
||||||
(_count == 0 ? (id)@"" : (id)[_info objectAtIndex: 0]), _db];
|
(_count == 0 ? (id)@"" : (id)[_info objectAtIndex: 0]), _db];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _addInfo: (NSArray*)info
|
|
||||||
{
|
|
||||||
if (_count == 0)
|
|
||||||
{
|
|
||||||
NSMutableString *ms = [[info objectAtIndex: 0] mutableCopy];
|
|
||||||
|
|
||||||
[_info addObjectsFromArray: info];
|
|
||||||
[_info replaceObjectAtIndex: 0 withObject: ms];
|
|
||||||
RELEASE(ms);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSMutableString *ms = [_info objectAtIndex: 0];
|
|
||||||
unsigned c = [info count];
|
|
||||||
unsigned i = 1;
|
|
||||||
|
|
||||||
[ms appendString: @";"];
|
|
||||||
[ms appendString: [info objectAtIndex: 0]];
|
|
||||||
while (i < c)
|
|
||||||
{
|
|
||||||
[_info addObject: [info objectAtIndex: i++]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) add: (NSString*)stmt,...
|
- (void) add: (NSString*)stmt,...
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start (ap, stmt);
|
va_start (ap, stmt);
|
||||||
[self _addInfo: [_db _prepare: stmt args: ap]];
|
[_info addObject: [_db _prepare: stmt args: ap]];
|
||||||
|
_count++;
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) add: (NSString*)stmt with: (NSDictionary*)values
|
- (void) add: (NSString*)stmt with: (NSDictionary*)values
|
||||||
{
|
{
|
||||||
[self _addInfo: [_db _substitute: stmt with: values]];
|
[_info addObject: [_db _substitute: stmt with: values]];
|
||||||
|
_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) append: (SQLTransaction*)other
|
- (void) append: (SQLTransaction*)other
|
||||||
{
|
{
|
||||||
if (other != nil && other->_count > 0)
|
if (other != nil && other->_count > 0)
|
||||||
{
|
{
|
||||||
[self _addInfo: other->_info];
|
other = [other copy];
|
||||||
|
[_info addObject: other];
|
||||||
|
_count += other->_count;
|
||||||
|
RELEASE(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id) copyWithZone: (NSZone*)z
|
||||||
|
{
|
||||||
|
SQLTransaction *c;
|
||||||
|
|
||||||
|
c = (SQLTransaction*)NSCopyObject(self, 0, z);
|
||||||
|
c->_info = [c->_info mutableCopy];
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
- (SQLClient*) db
|
- (SQLClient*) db
|
||||||
{
|
{
|
||||||
return _db;
|
return _db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) _addSQL: (NSMutableString*)sql andArgs: (NSMutableArray*)args
|
||||||
|
{
|
||||||
|
unsigned count = [_info count];
|
||||||
|
unsigned index;
|
||||||
|
|
||||||
|
for (index = 0; index < count; index++)
|
||||||
|
{
|
||||||
|
id o = [_info objectAtIndex: index];
|
||||||
|
|
||||||
|
if ([o isKindOfClass: NSArrayClass] == YES)
|
||||||
|
{
|
||||||
|
unsigned c = [(NSArray*)o count];
|
||||||
|
|
||||||
|
if (c > 0)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
[sql appendString: [(NSArray*)o objectAtIndex: 0]];
|
||||||
|
[sql appendString: @";"];
|
||||||
|
for (i = 1; i < c; i++)
|
||||||
|
{
|
||||||
|
[args addObject: [(NSArray*)o objectAtIndex: i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[(SQLTransaction*)o _addSQL: sql andArgs: args];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) _countLength: (unsigned*)length andArgs: (unsigned*)args
|
||||||
|
{
|
||||||
|
unsigned count = [_info count];
|
||||||
|
unsigned index;
|
||||||
|
|
||||||
|
for (index = 0; index < count; index++)
|
||||||
|
{
|
||||||
|
id o = [_info objectAtIndex: index];
|
||||||
|
|
||||||
|
if ([o isKindOfClass: NSArrayClass] == YES)
|
||||||
|
{
|
||||||
|
unsigned c = [(NSArray*)o count];
|
||||||
|
|
||||||
|
if (c > 0)
|
||||||
|
{
|
||||||
|
length += [[(NSArray*)o objectAtIndex: 0] length] + 1;
|
||||||
|
args += c - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[(SQLTransaction*)o _countLength: length andArgs: args];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void) execute
|
- (void) execute
|
||||||
{
|
{
|
||||||
if (_count > 0)
|
if (_count > 0)
|
||||||
{
|
{
|
||||||
BOOL wrapped = NO;
|
NSMutableArray *info = nil;
|
||||||
NSMutableString *sql = [_info objectAtIndex: 0];
|
|
||||||
|
|
||||||
NS_DURING
|
NS_DURING
|
||||||
{
|
{
|
||||||
if (_count > 1 && [_db isInTransaction] == NO)
|
NSMutableString *sql;
|
||||||
{
|
unsigned sqlSize = 0;
|
||||||
wrapped = YES;
|
unsigned argCount = 0;
|
||||||
[sql replaceCharactersInRange: NSMakeRange(0, 0)
|
|
||||||
withString: @"begin;"];
|
[self _countLength: &sqlSize andArgs: &argCount];
|
||||||
[sql replaceCharactersInRange: NSMakeRange([sql length], 0)
|
|
||||||
withString: @";commit"];
|
/* Allocate and initialise the transaction statement.
|
||||||
}
|
*/
|
||||||
[_db simpleExecute: _info];
|
info = [[NSMutableArray alloc] initWithCapacity: argCount + 1];
|
||||||
if (wrapped == YES)
|
sql = [[NSMutableString alloc] initWithCapacity: sqlSize + 13];
|
||||||
{
|
[info addObject: sql];
|
||||||
wrapped = NO;
|
RELEASE(sql);
|
||||||
[sql replaceCharactersInRange: NSMakeRange([sql length] - 7, 7)
|
if ([_db isInTransaction] == NO)
|
||||||
withString: @""];
|
{
|
||||||
[sql replaceCharactersInRange: NSMakeRange(0, 6)
|
[sql appendString: @"begin;"];
|
||||||
withString: @""];
|
}
|
||||||
}
|
|
||||||
|
[self _addSQL: sql andArgs: info];
|
||||||
|
|
||||||
|
if ([_db isInTransaction] == NO)
|
||||||
|
{
|
||||||
|
[sql appendString: @"commit;"];
|
||||||
|
}
|
||||||
|
|
||||||
|
[_db simpleExecute: info];
|
||||||
}
|
}
|
||||||
NS_HANDLER
|
NS_HANDLER
|
||||||
{
|
{
|
||||||
if (wrapped == YES)
|
RELEASE(info);
|
||||||
{
|
|
||||||
[sql replaceCharactersInRange: NSMakeRange([sql length] - 7, 7)
|
|
||||||
withString: @""];
|
|
||||||
[sql replaceCharactersInRange: NSMakeRange(0, 6)
|
|
||||||
withString: @""];
|
|
||||||
}
|
|
||||||
[localException raise];
|
[localException raise];
|
||||||
}
|
}
|
||||||
NS_ENDHANDLER
|
NS_ENDHANDLER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (unsigned) executeBatch
|
||||||
|
{
|
||||||
|
unsigned executed = 0;
|
||||||
|
|
||||||
|
if (_count > 0)
|
||||||
|
{
|
||||||
|
NS_DURING
|
||||||
|
{
|
||||||
|
[self execute];
|
||||||
|
executed = _count;
|
||||||
|
}
|
||||||
|
NS_HANDLER
|
||||||
|
{
|
||||||
|
if (_batch == YES)
|
||||||
|
{
|
||||||
|
unsigned count = [_info count];
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
BOOL success = NO;
|
||||||
|
|
||||||
|
NS_DURING
|
||||||
|
{
|
||||||
|
id o = [_info objectAtIndex: i];
|
||||||
|
|
||||||
|
if ([o isKindOfClass: NSArrayClass] == YES)
|
||||||
|
{
|
||||||
|
[_db simpleExecute: (NSArray*)o];
|
||||||
|
executed++;
|
||||||
|
success = YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned result;
|
||||||
|
|
||||||
|
result = [(SQLTransaction*)o executeBatch];
|
||||||
|
executed += result;
|
||||||
|
if (result == [(SQLTransaction*)o count])
|
||||||
|
{
|
||||||
|
success = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NS_HANDLER
|
||||||
|
{
|
||||||
|
success = NO;
|
||||||
|
}
|
||||||
|
NS_ENDHANDLER
|
||||||
|
if (success == NO && _stop == YES)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NS_ENDHANDLER
|
||||||
|
}
|
||||||
|
return executed;
|
||||||
|
}
|
||||||
|
|
||||||
- (void) reset
|
- (void) reset
|
||||||
{
|
{
|
||||||
[_info removeAllObjects];
|
[_info removeAllObjects];
|
||||||
|
|
Loading…
Reference in a new issue