mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-21 02:41:07 +00:00
Add SQLTransaction to perform easy, efficient combining of multiple
statements into a single transaction. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@19775 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
058155c245
commit
69be0270db
3 changed files with 176 additions and 2 deletions
|
@ -1,4 +1,11 @@
|
|||
Thy Jul 15 09:40:00 2004 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
Mon Jul 26 09:50:00 2004 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* SQLClient.h: Add -transaction method and SQLTransaction class
|
||||
* SQLClient.m: Implement -transaction method and SQLTransaction class
|
||||
to provide a simple convenient mechanism for executing a sequence
|
||||
of statements as a single transaction.
|
||||
|
||||
Thu Jul 15 09:40:00 2004 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* WebServer.m: ([_didRead:]) more informative logging upon reading
|
||||
an unexpected end-of-file
|
||||
|
|
58
SQLClient.h
58
SQLClient.h
|
@ -167,6 +167,7 @@
|
|||
@class NSDate;
|
||||
@class NSRecursiveLock;
|
||||
@class NSString;
|
||||
@class SQLTransaction;
|
||||
|
||||
/**
|
||||
* An enhanced array to represent a record returned from a query.
|
||||
|
@ -351,7 +352,7 @@ extern NSString *SQLUniqueException;
|
|||
/**
|
||||
* Perform arbitrary operation <em>which does not return any value.</em><br />
|
||||
* This arguments to this method are a nil terminated list which are
|
||||
* concatenated in the manner of the * -prepare:args: method.<br />
|
||||
* concatenated in the manner of the -query:,... method.<br />
|
||||
* Any string arguments are assumed to have been quoted appropriately
|
||||
* already, but non-string arguments are automatically quoted using the
|
||||
* -quote: method.
|
||||
|
@ -772,6 +773,12 @@ extern NSString *SQLUniqueException;
|
|||
* returned by the query to an array containing the fields.
|
||||
*/
|
||||
- (void) singletons: (NSMutableArray*)records;
|
||||
|
||||
/**
|
||||
* Creates and returns an autoreleased SQLTransaction instance which will
|
||||
* use the receiver as the database connection to perform transactions.
|
||||
*/
|
||||
- (SQLTransaction*) transaction;
|
||||
@end
|
||||
|
||||
|
||||
|
@ -835,5 +842,54 @@ extern NSString *SQLUniqueException;
|
|||
- (void) setDurationLogging: (NSTimeInterval)threshold;
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* The SQLTransaction transaction class provides a convenient mechanism
|
||||
* for grouping together a series of SQL statements to be executed as a
|
||||
* single transaction. It avoids the need for handling begin/commit,
|
||||
* and shouldbe as efficient as reasonably possible.<br />
|
||||
* You obtain an instance by calling [SQLClient-transaction], add SQL
|
||||
* statements to it using the -add:,... and/or -add:with: methods, and
|
||||
* then use the -execute method to perform all the statements as a
|
||||
* single operation.<br />
|
||||
* Any exception is caught and re-raised in the -execute method after any
|
||||
* tidying up to leave the database in a consistent state.
|
||||
*/
|
||||
@interface SQLTransaction : NSObject
|
||||
{
|
||||
SQLClient *_db;
|
||||
NSMutableArray *_info;
|
||||
unsigned _count;
|
||||
}
|
||||
/**
|
||||
* Adds an SQL statement to the transaction. This is similar to
|
||||
* [SQLClient-execute:,...] but does not cause any database operation
|
||||
* until -execute is called, so it will not raise a database exception.
|
||||
*/
|
||||
- (void) add: (NSString*)stmt,...;
|
||||
|
||||
/**
|
||||
* Adds an SQL statement to the transaction. This is similar to
|
||||
* [SQLClient-execute:with:] but does not cause any database operation
|
||||
* until -execute is called, so it will not raise a database exception.
|
||||
*/
|
||||
- (void) add: (NSString*)stmt with: (NSDictionary*)values;
|
||||
|
||||
/**
|
||||
* Performs any statements added to the transaction as a single operation.
|
||||
* If any problem occurs, an NSException is raised, but the database connection
|
||||
* is left in a consistent state and a partially completed operation is
|
||||
* rolled back.
|
||||
*/
|
||||
- (void) execute;
|
||||
|
||||
/**
|
||||
* Resets the transaction, removing all previously added statements.
|
||||
* This allows the transaction object to be re-used for multiple
|
||||
* transactions.
|
||||
*/
|
||||
- (void) reset;
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
|
|
111
SQLClient.m
111
SQLClient.m
|
@ -47,6 +47,10 @@
|
|||
|
||||
#include "SQLClient.h"
|
||||
|
||||
typedef struct {
|
||||
@defs(SQLTransaction);
|
||||
} *TDefs;
|
||||
|
||||
@implementation SQLRecord
|
||||
+ (id) allocWithZone: (NSZone*)aZone
|
||||
{
|
||||
|
@ -1497,5 +1501,112 @@ static unsigned int maxConnections = 8;
|
|||
}
|
||||
}
|
||||
|
||||
- (SQLTransaction*) transaction
|
||||
{
|
||||
TDefs transaction;
|
||||
|
||||
transaction = (TDefs)NSAllocateObject([SQLTransaction class], 0,
|
||||
NSDefaultMallocZone());
|
||||
|
||||
transaction->_db = RETAIN(self);
|
||||
transaction->_info = [NSMutableArray new];
|
||||
return AUTORELEASE((SQLTransaction*)transaction);
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation SQLTransaction
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(_db);
|
||||
DESTROY(_info);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (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,...
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, stmt);
|
||||
[self _addInfo: [_db _prepare: stmt args: ap]];
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
- (void) add: (NSString*)stmt with: (NSDictionary*)values
|
||||
{
|
||||
[self _addInfo: [_db _substitute: stmt with: values]];
|
||||
}
|
||||
|
||||
- (void) execute
|
||||
{
|
||||
if (_count > 0)
|
||||
{
|
||||
BOOL transaction = NO;
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
if (_count > 1)
|
||||
{
|
||||
[_db begin];
|
||||
transaction = YES;
|
||||
}
|
||||
[_db simpleExecute: _info];
|
||||
if (transaction == YES)
|
||||
{
|
||||
transaction = NO;
|
||||
[_db commit];
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
if (transaction == YES)
|
||||
{
|
||||
NS_DURING
|
||||
{
|
||||
[_db rollback];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSLog(@"Exception rolling back transaction: %@",
|
||||
localException);
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
}
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
}
|
||||
}
|
||||
|
||||
- (void) reset
|
||||
{
|
||||
[_info removeAllObjects];
|
||||
_count = 0;
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
Loading…
Reference in a new issue