Tidied and added some logging capability

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@19252 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2004-05-07 08:16:16 +00:00
parent f62f928f91
commit ced08a42d3
10 changed files with 223 additions and 115 deletions

View file

@ -1,3 +1,9 @@
Fri May 07 09:15:00 2004 Richard Frith-Macdonald <rfm@gnu.org>
Add methods to log duration of any statements over a certain
limit.
Tidy instance variables ... prefix mprivate ones with underscore.
Thu Apr 29 15:20:00 2004 Richard Frith-Macdonald <rfm@gnu.org>
* SQLClient.h: Fix URLs in documentation as suggested by Adam.

View file

@ -142,7 +142,9 @@ static NSDate *future = nil;
{
if (connected == NO)
{
if (database != nil && user != nil && password != nil)
if ([self database] != nil
&& [self user] != nil
&& [self password] != nil)
{
Class c = NSClassFromString(@"CmdClient");
@ -157,10 +159,10 @@ static NSDate *future = nil;
const char *client_c;
EXEC SQL END DECLARE SECTION;
database_c = [database UTF8String];
user_c = [user UTF8String];
password_c = [password UTF8String];
client_c = [client UTF8String];
database_c = [[self database] UTF8String];
user_c = [[self user] UTF8String];
password_c = [[self password] UTF8String];
client_c = [[self clientName] UTF8String];
if (c != 0)
{
@ -216,27 +218,27 @@ static NSDate *future = nil;
const char *client_c;
EXEC SQL END DECLARE SECTION;
if (inTransaction == YES)
if ([self isInTransaction] == YES)
{
[self rollback];
}
client_c = [client UTF8String];
client_c = [[self clientName] UTF8String];
if ([self debugging] > 0)
{
[self debug: @"Disconnecting client %@", client];
[self debug: @"Disconnecting client %@", [self clientName]];
}
EXEC SQL DISCONNECT :client_c;
if ([self debugging] > 0)
{
[self debug: @"Disconnected client %@", client];
[self debug: @"Disconnected client %@", [self clientName]];
}
}
NS_HANDLER
{
[self debug: @"Error disconnecting from database (%@): %@",
client, localException];
[self clientName], localException];
}
NS_ENDHANDLER
connected = NO;
@ -407,7 +409,7 @@ static unsigned int trim(char *str)
{
EXEC SQL ALLOCATE DESCRIPTOR myDesc;
EXEC SQL PREPARE myQuery from :query;
if (inTransaction == NO)
if ([self isInTransaction] == NO)
{
EXEC SQL AT :handle BEGIN;
localTransaction = YES;

24
MySQL.m
View file

@ -71,11 +71,13 @@ static NSNull *null = nil;
{
if (connected == NO)
{
if (database != nil && user != nil && password != nil)
if ([self database] != nil
&& [self user] != nil
&& [self password] != nil)
{
NSString *host = nil;
NSString *port = nil;
NSString *dbase = database;
NSString *dbase = [self database];
NSRange r;
[[self class] purgeConnections: nil];
@ -95,13 +97,13 @@ static NSNull *null = nil;
if ([self debugging] > 0)
{
[self debug: @"Connect to '%@' as %@", database, [self name]];
[self debug: @"Connect to '%@' as %@", [self database], [self name]];
}
extra = mysql_init(0);
if (mysql_real_connect(connection,
[host UTF8String],
[user UTF8String],
[password UTF8String],
[[self user] UTF8String],
[[self password] UTF8String],
[dbase UTF8String],
[port intValue],
NULL,
@ -109,7 +111,7 @@ static NSNull *null = nil;
) == 0)
{
[self debug: @"Error connecting to '%@' (%@) - %s",
[self name], database, mysql_error(connection)];
[self name], [self database], mysql_error(connection)];
mysql_close(connection);
extra = 0;
}
@ -117,7 +119,7 @@ static NSNull *null = nil;
else if (mysql_query(connection, "SET CHARACTER SET utf8") != 0)
{
[self debug: @"Error setting utf8 support for '%@' (%@) - %s",
[self name], database, mysql_error(connection)];
[self name], [self database], mysql_error(connection)];
mysql_close(connection);
extra = 0;
}
@ -148,26 +150,26 @@ static NSNull *null = nil;
{
NS_DURING
{
if (inTransaction == YES)
if ([self isInTransaction] == YES)
{
[self rollback];
}
if ([self debugging] > 0)
{
[self debug: @"Disconnecting client %@", client];
[self debug: @"Disconnecting client %@", [self clientName]];
}
mysql_close(connection);
extra = 0;
if ([self debugging] > 0)
{
[self debug: @"Disconnected client %@", client];
[self debug: @"Disconnected client %@", [self clientName]];
}
}
NS_HANDLER
{
[self debug: @"Error disconnecting from database (%@): %@",
client, localException];
[self clientName], localException];
}
NS_ENDHANDLER
connected = NO;

View file

@ -119,7 +119,9 @@ void SQLClientOracleErrorHandler()
{
if (connected == NO)
{
if (database != nil && user != nil && password != nil)
if ([self database] != nil
&& [self user] != nil
&& [self password] != nil)
{
Class c = NSClassFromString(@"CmdClient");
@ -135,16 +137,16 @@ void SQLClientOracleErrorHandler()
EXEC SQL END DECLARE SECTION;
/* Database is the Oracle Net identifier for the database. */
database_c = [database UTF8String];
database_c = [[self database] UTF8String];
/* User and password are used to connect to the database. */
user_c = [user UTF8String];
password_c = [password UTF8String];
user_c = [[self user] UTF8String];
password_c = [[self password] UTF8String];
/* Client is only used to give this connection a name
* and distinguish it from other connections.
*/
client_c = [client UTF8String];
client_c = [[self clientName] UTF8String];
if (c != 0)
{
@ -187,14 +189,14 @@ void SQLClientOracleErrorHandler()
const char *client_c;
EXEC SQL END DECLARE SECTION;
if (inTransaction == YES)
if ([self isInTransaction] == YES)
{
[self rollback];
}
client_c = [client UTF8String];
client_c = [[self clientName] UTF8String];
[self debug: @"(Oracle) Disconnecting client %@", client];
[self debug: @"(Oracle) Disconnecting client %@", [self clientName]];
/* To disconnect from the database, we issuse a COMMIT
* statement with the RELEASE option. The RELEASE option
@ -202,12 +204,12 @@ void SQLClientOracleErrorHandler()
*/
EXEC SQL AT :client_c COMMIT WORK RELEASE;
[self debug: @"(Oracle) Disconnected client %@", client];
[self debug: @"(Oracle) Disconnected client %@", [self clientName]];
}
NS_HANDLER
{
[self error: @"(Oracle) Error disconnecting from database (%@): %@",
client, localException];
[self clientName], localException];
}
NS_ENDHANDLER
connected = NO;
@ -246,7 +248,7 @@ void SQLClientOracleErrorHandler()
NS_DURING
{
if (inTransaction == NO)
if ([self isInTransaction] == NO)
{
manuallyAutoCommit = YES;
}
@ -349,7 +351,7 @@ static unsigned int trim(char *str)
CREATE_AUTORELEASE_POOL(arp);
NSMutableArray *records;
BOOL isOpen = NO;
BOOL wasInTransaction = inTransaction;
BOOL wasInTransaction = [self isInTransaction];
BOOL allocatedDescriptor = NO;
length = [stmt length];
@ -381,10 +383,10 @@ static unsigned int trim(char *str)
allocatedDescriptor = YES;
EXEC SQL AT :handle PREPARE myQuery from :query;
if (inTransaction == NO)
if ([self isInTransaction] == NO)
{
/* EXEC SQL AT :handle BEGIN; */
inTransaction = YES;
_inTransaction = YES;
}
EXEC SQL AT :handle DECLARE myCursor CURSOR FOR myQuery;
EXEC SQL AT :handle OPEN myCursor;
@ -605,10 +607,10 @@ static unsigned int trim(char *str)
isOpen = NO;
EXEC SQL AT :handle CLOSE myCursor;
if (wasInTransaction == NO && inTransaction == YES)
if (wasInTransaction == NO && [self isInTransaction] == YES)
{
EXEC SQL AT :handle COMMIT;
inTransaction = NO;
_inTransaction = NO;
}
EXEC SQL DEALLOCATE DESCRIPTOR 'myDesc';
allocatedDescriptor = NO;
@ -626,19 +628,19 @@ static unsigned int trim(char *str)
{
EXEC SQL AT :handle CLOSE myCursor;
}
if (wasInTransaction == NO && inTransaction == YES)
if (wasInTransaction == NO && [self isInTransaction] == YES)
{
EXEC SQL AT :handle ROLLBACK;
inTransaction = NO;
_inTransaction = NO;
}
}
NS_HANDLER
{
NSString *e = [localException name];
if (wasInTransaction == NO && inTransaction == YES)
if (wasInTransaction == NO && [self isInTransaction] == YES)
{
inTransaction = NO;
_inTransaction = NO;
}
if ([e isEqual: SQLConnectionException] == YES)
{
@ -664,7 +666,7 @@ static unsigned int trim(char *str)
if ([n isEqual: SQLConnectionException] == YES)
{
inTransaction = NO;
_inTransaction = NO;
[self backendDisconnect];
}

View file

@ -90,11 +90,11 @@ connectQuote(NSString *str)
if (connection == 0)
{
connected = YES;
if (database != nil)
if ([self database] != nil)
{
NSString *host = nil;
NSString *port = nil;
NSString *dbase = database;
NSString *dbase = [self database];
NSString *str;
NSRange r;
NSMutableString *m;
@ -138,13 +138,13 @@ connectQuote(NSString *str)
[m appendString: @" port="];
[m appendString: str];
}
str = connectQuote(user);
str = connectQuote([self user]);
if (str != nil)
{
[m appendString: @" user="];
[m appendString: str];
}
str = connectQuote(password);
str = connectQuote([self password]);
if (str != nil)
{
[m appendString: @" password="];
@ -188,26 +188,26 @@ connectQuote(NSString *str)
{
NS_DURING
{
if (inTransaction == YES)
if ([self isInTransaction] == YES)
{
[self rollback];
}
if ([self debugging] > 0)
{
[self debug: @"Disconnecting client %@", client];
[self debug: @"Disconnecting client %@", [self clientName]];
}
PQfinish(connection);
extra = 0;
if ([self debugging] > 0)
{
[self debug: @"Disconnected client %@", client];
[self debug: @"Disconnected client %@", [self clientName]];
}
}
NS_HANDLER
{
[self debug: @"Error disconnecting from database (%@): %@",
client, localException];
[self clientName], localException];
}
NS_ENDHANDLER
connected = NO;

View file

@ -186,6 +186,8 @@ extern NSString *SQLUniqueException;
*/
@interface SQLClient : NSObject
{
void *extra; /** For subclass specific data */
NSRecursiveLock *lock; /** Maintain thread-safety */
/**
* A flag indicating whether this instance is currently connected to
* the backend database server. This variable must <em>only</em> be
@ -197,20 +199,19 @@ extern NSString *SQLUniqueException;
* transaction. This variable must <em>only</em> be
* set by the -begin, -commit or -rollback methods.
*/
BOOL inTransaction; /** Are we inside a transaction? */
NSString *name; /** Unique identifier for instance */
NSString *client; /** Identifier within backend */
NSString *database; /** The configured database name/host */
NSString *password; /** The configured password */
NSString *user; /** The configured user */
BOOL _inTransaction; /** Are we inside a transaction? */
NSString *_name; /** Unique identifier for instance */
NSString *_client; /** Identifier within backend */
NSString *_database; /** The configured database name/host */
NSString *_password; /** The configured password */
NSString *_user; /** The configured user */
/**
* Timestamp of last operation.<br />
* Maintained by the -simpleExecute: and -simpleQuery: methods.
*/
NSDate *lastOperation;
NSRecursiveLock *lock; /** Maintain thread-safety */
unsigned int debugging; /** The current debugging level */
void *extra; /** For subclass specific data */
NSDate *_lastOperation;
NSTimeInterval _duration;
unsigned int _debugging; /** The current debugging level */
}
/**
@ -766,15 +767,26 @@ extern NSString *SQLUniqueException;
@interface SQLClient (Logging)
/**
* Return the class-wide debugging level, which is inherited by all
* newly created minstances.
* newly created instances.
*/
+ (unsigned int) debugging;
/**
* Return the class-wide duration logging threshold, which is inherited by all
* newly created instances.
*/
+ (NSTimeInterval) durationLogging;
/**
* Set the debugging level to be inherited by all new instances.
*/
+ (void) setDebugging: (unsigned int)level;
/**
* Set the duration logging threshold to be inherited by all new instances.
*/
+ (void) setDurationLogging: (NSTimeInterval)threshold;
/**
* The default implementation calls NSLogv to log a debug message.<br />
* Override this in a category to provide more sophisticated logging.
@ -786,11 +798,26 @@ extern NSString *SQLUniqueException;
*/
- (unsigned int) debugging;
/**
* Returns the threshold above which queries and statements taking a long
* time to execute are logged. A negative value (default) indicates that
* this logging is disabled. A value of zero means that all statements
* are logged.
*/
- (NSTimeInterval) durationLogging;
/**
* Set the debugging level of this instance ... overrides the default
* level inherited from the class.
*/
- (void) setDebugging: (unsigned int)level;
/**
* Set a threshold above which queries and statements taking a long
* time to execute are logged. A negative value (default) disables
* this logging. A value of zero logs all statements.
*/
- (void) setDurationLogging: (NSTimeInterval)threshold;
@end
#endif

View file

@ -176,17 +176,28 @@ NSString *SQLUniqueException = @"SQLUniqueException";
@implementation SQLClient (Logging)
static unsigned int classDebugging = 0;
static NSTimeInterval classDuration = -1;
+ (unsigned int) debugging
{
return classDebugging;
}
+ (NSTimeInterval) durationLogging
{
return classDuration;
}
+ (void) setDebugging: (unsigned int)level
{
classDebugging = level;
}
+ (void) setDurationLogging: (NSTimeInterval)threshold
{
classDuration = threshold;
}
- (void) debug: (NSString*)fmt, ...
{
va_list ap;
@ -198,12 +209,22 @@ static unsigned int classDebugging = 0;
- (unsigned int) debugging
{
return debugging;
return _debugging;
}
- (NSTimeInterval) durationLogging
{
return _duration;
}
- (void) setDebugging: (unsigned int)level
{
debugging = level;
_debugging = level;
}
- (void) setDurationLogging: (NSTimeInterval)threshold
{
_duration = threshold;
}
@end
@ -377,17 +398,17 @@ static unsigned int maxConnections = 8;
- (void) begin
{
[lock lock];
if (inTransaction == NO)
if (_inTransaction == NO)
{
inTransaction = YES;
_inTransaction = YES;
NS_DURING
{
[self backendExecute: beginStatement];
[self simpleExecute: beginStatement];
}
NS_HANDLER
{
[lock unlock];
inTransaction = NO;
_inTransaction = NO;
[localException raise];
}
NS_ENDHANDLER
@ -402,13 +423,13 @@ static unsigned int maxConnections = 8;
- (NSString*) clientName
{
return client;
return _client;
}
- (void) commit
{
[lock lock];
if (inTransaction == NO)
if (_inTransaction == NO)
{
[lock unlock];
[NSException raise: NSInternalInconsistencyException
@ -416,14 +437,14 @@ static unsigned int maxConnections = 8;
}
NS_DURING
{
[self backendExecute: commitStatement];
inTransaction = NO;
[self simpleExecute: commitStatement];
_inTransaction = NO;
[lock unlock]; // Locked by -begin
[lock unlock]; // Locked at start of -commit
}
NS_HANDLER
{
inTransaction = NO;
_inTransaction = NO;
[lock unlock]; // Locked by -begin
[lock unlock]; // Locked at start of -commit
[localException raise];
@ -461,7 +482,7 @@ static unsigned int maxConnections = 8;
- (NSString*) database
{
return database;
return _database;
}
- (void) dealloc
@ -470,20 +491,20 @@ static unsigned int maxConnections = 8;
nc = [NSNotificationCenter defaultCenter];
[nc removeObserver: self];
if (name != nil)
if (_name != nil)
{
[cacheLock lock];
NSMapRemove(cache, (void*)name);
NSMapRemove(cache, (void*)_name);
[cacheLock unlock];
}
[self disconnect];
DESTROY(lock);
DESTROY(client);
DESTROY(database);
DESTROY(password);
DESTROY(user);
DESTROY(name);
DESTROY(lastOperation);
DESTROY(_client);
DESTROY(_database);
DESTROY(_password);
DESTROY(_user);
DESTROY(_name);
DESTROY(_lastOperation);
[super dealloc];
}
@ -491,14 +512,14 @@ static unsigned int maxConnections = 8;
{
NSMutableString *s = AUTORELEASE([NSMutableString new]);
[s appendFormat: @"Database - %@\n", client];
[s appendFormat: @" Name - %@\n", name];
[s appendFormat: @" DBase - %@\n", database];
[s appendFormat: @" DB User - %@\n", user];
[s appendFormat: @"Database - %@\n", [self clientName]];
[s appendFormat: @" Name - %@\n", [self name]];
[s appendFormat: @" DBase - %@\n", [self database]];
[s appendFormat: @" DB User - %@\n", [self user]];
[s appendFormat: @" Password - %@\n",
password == nil ? @"unknown" : @"known"];
[self password] == nil ? @"unknown" : @"known"];
[s appendFormat: @" Connected - %@\n", connected ? @"yes" : @"no"];
[s appendFormat: @" Transaction - %@\n\n", inTransaction ? @"yes" : @"no"];
[s appendFormat: @" Transaction - %@\n\n", _inTransaction ? @"yes" : @"no"];
return s;
}
@ -575,6 +596,7 @@ static unsigned int maxConnections = 8;
{
lock = [GSLazyRecursiveLock new]; // Ensure thread-safety.
[self setDebugging: [[self class] debugging]];
[self setDurationLogging: [[self class] durationLogging]];
[self setName: reference]; // Set name and store in cache.
if (config == nil)
@ -614,22 +636,22 @@ static unsigned int maxConnections = 8;
- (BOOL) isInTransaction
{
return inTransaction;
return _inTransaction;
}
- (NSDate*) lastOperation
{
return lastOperation;
return _lastOperation;
}
- (NSString*) name
{
return name;
return _name;
}
- (NSString*) password
{
return password;
return _password;
}
- (NSMutableArray*) query: (NSString*)stmt, ...
@ -764,7 +786,7 @@ static unsigned int maxConnections = 8;
- (void) rollback
{
[lock lock];
if (inTransaction == NO)
if (_inTransaction == NO)
{
[lock unlock];
[NSException raise: NSInternalInconsistencyException
@ -772,14 +794,14 @@ static unsigned int maxConnections = 8;
}
NS_DURING
{
[self backendExecute: rollbackStatement];
inTransaction = NO;
[self simpleExecute: rollbackStatement];
_inTransaction = NO;
[lock unlock]; // Locked by -begin
[lock unlock]; // Locked at start of -rollback
}
NS_HANDLER
{
inTransaction = NO;
_inTransaction = NO;
[lock unlock]; // Locked by -begin
[lock unlock]; // Locked at start of -rollback
[localException raise];
@ -789,22 +811,22 @@ static unsigned int maxConnections = 8;
- (void) setDatabase: (NSString*)s
{
if ([s isEqual: database] == NO)
if ([s isEqual: _database] == NO)
{
if (connected == YES)
{
[self disconnect];
}
ASSIGNCOPY(database, s);
ASSIGNCOPY(_database, s);
}
}
- (void) setName: (NSString*)s
{
if ([s isEqual: name] == NO)
if ([s isEqual: _name] == NO)
{
[lock lock];
if ([s isEqual: name] == YES)
if ([s isEqual: _name] == YES)
{
[lock unlock];
return;
@ -825,10 +847,10 @@ static unsigned int maxConnections = 8;
[self disconnect];
}
RETAIN(self);
NSMapRemove(cache, (void*)name);
ASSIGNCOPY(name, s);
ASSIGN(client, [[NSProcessInfo processInfo] globallyUniqueString]);
NSMapInsert(cache, (void*)name, (void*)self);
NSMapRemove(cache, (void*)_name);
ASSIGNCOPY(_name, s);
ASSIGN(_client, [[NSProcessInfo processInfo] globallyUniqueString]);
NSMapInsert(cache, (void*)_name, (void*)self);
[cacheLock unlock];
[lock unlock];
RELEASE(self);
@ -837,25 +859,25 @@ static unsigned int maxConnections = 8;
- (void) setPassword: (NSString*)s
{
if ([s isEqual: password] == NO)
if ([s isEqual: _password] == NO)
{
if (connected == YES)
{
[self disconnect];
}
ASSIGNCOPY(password, s);
ASSIGNCOPY(_password, s);
}
}
- (void) setUser: (NSString*)s
{
if ([s isEqual: client] == NO)
if ([s isEqual: _client] == NO)
{
if (connected == YES)
{
[self disconnect];
}
ASSIGNCOPY(user, s);
ASSIGNCOPY(_user, s);
}
}
@ -864,9 +886,37 @@ static unsigned int maxConnections = 8;
[lock lock];
NS_DURING
{
NSDate *start = nil;
if (_duration >= 0)
{
start = [NSDate date];
}
[self backendExecute: info];
RELEASE(lastOperation);
lastOperation = [NSDate new];
RELEASE(_lastOperation);
_lastOperation = [NSDate new];
if (_duration >= 0)
{
NSTimeInterval d;
d = [_lastOperation timeIntervalSinceDate: start];
if (d >= _duration)
{
/*
* For higher debug levels, we log data objects as well
* as the query string, otherwise we omit them.
*/
if ([self debugging] > 1)
{
[self debug: @"Duration %g for statement %@", d, info];
}
else
{
[self debug: @"Duration %g for statement %@",
d, [info objectAtIndex: 0]];
}
}
}
}
NS_HANDLER
{
@ -884,9 +934,25 @@ static unsigned int maxConnections = 8;
[lock lock];
NS_DURING
{
NSDate *start = nil;
if (_duration >= 0)
{
start = [NSDate date];
}
result = [self backendQuery: stmt];
RELEASE(lastOperation);
lastOperation = [NSDate new];
RELEASE(_lastOperation);
_lastOperation = [NSDate new];
if (_duration >= 0)
{
NSTimeInterval d;
d = [_lastOperation timeIntervalSinceDate: start];
if (d >= _duration)
{
[self debug: @"Duration %g for query %@", d, stmt];
}
}
}
NS_HANDLER
{
@ -900,7 +966,7 @@ static unsigned int maxConnections = 8;
- (NSString*) user
{
return user;
return _user;
}
@end
@ -1034,10 +1100,10 @@ static unsigned int maxConnections = 8;
[self debug: @"Unable to find SQLClientReferences config dictionary"];
d = nil;
}
d = [d objectForKey: name];
d = [d objectForKey: _name];
if ([d isKindOfClass: [NSDictionary class]] == NO)
{
[self debug: @"Unable to find config for client '%@'", name];
[self debug: @"Unable to find config for client '%@'", _name];
d = nil;
}

View file

@ -61,6 +61,7 @@ main()
data = [NSData dataWithBytes: dbuf length: i];
db = [SQLClient clientWithConfiguration: nil name: @"test"];
[db setDurationLogging: 0];
NS_DURING
[db execute: @"drop table xxx", nil];

View file

@ -61,6 +61,7 @@ main()
data = [NSData dataWithBytes: dbuf length: i];
db = [SQLClient clientWithConfiguration: nil name: @"test"];
[db setDurationLogging: 0];
NS_DURING
[db execute: @"drop table xxx", nil];

View file

@ -61,6 +61,7 @@ main()
data = [NSData dataWithBytes: dbuf length: i];
db = [SQLClient clientWithConfiguration: nil name: @"test"];
[db setDurationLogging: 0];
NS_DURING
[db execute: @"drop table xxx", nil];