Threading/notification improvments

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@38447 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2015-04-01 11:32:49 +00:00
parent 2250d65fc0
commit bb8284b4fe
5 changed files with 75 additions and 18 deletions

View file

@ -1,11 +1,28 @@
2015-04-01 Richard Frith-Macdonald <rfm@gnu.org>
* SQLClient.h:
* Postgres.m:
Fixup notification posting to be asynchronous using the default
notification queue for the thread so that the notifications do
not get delivered while the query/statement at which they were
detected is still in progress.
Add method to explicitly grab/release the client for the current
thread.
2015-03-11 Richard Frith-Macdonald <rfm@gnu.org>
* SQLClientPool.m: Fixup for ewxposing prepare method
* SQLClientPool.m: Fixup for exposing prepare method
* SQLClient.h:
* SQLClient.m:
* Postgres.m:
* testPostgres.m:
Add simple array support for char/varchar/text, integer/real,
timestamp, bool and bytea.
timestamp, bool and bytea. When a query returns an array of
one of these types, the resulting object is an NSArray containing
the database array elements rather than an NSString containing the
string literal representation of the database array.
Also added a method to convert an NSArray to a string literal
representation of a database array.
2015-03-02 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -35,6 +35,7 @@
#import <Foundation/NSFileHandle.h>
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSNotification.h>
#import <Foundation/NSNotificationQueue.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSMapTable.h>
#import <Foundation/NSLock.h>
@ -279,8 +280,8 @@ connectQuote(NSString *str)
- (void) _checkNotifications
{
static NSNotificationCenter *nc;
PGnotify *notify;
NSNotificationQueue *nq = nil;
PGnotify *notify;
while ((notify = PQnotifies(connection)) != 0)
{
@ -328,11 +329,14 @@ connectQuote(NSString *str)
userInfo: (NSDictionary*)userInfo];
[name release];
[userInfo release];
if (nil == nc)
if (nil == nq)
{
nc = [[NSNotificationCenter defaultCenter] retain];
nq = [NSNotificationQueue defaultQueue];
}
[nc postNotification: n];
/* Post asynchronously
*/
[nq enqueueNotification: n postingStyle: NSPostASAP];
}
NS_HANDLER
{
@ -523,9 +527,9 @@ static unsigned int trim(char *str)
}
if ('\"' == *p)
{
*p++ = '\0';
*p = '\0';
}
if (len == (p - start + 1))
if (len == (p - start))
{
v = [[NSString alloc] initWithUTF8String: start];
}
@ -562,6 +566,7 @@ static unsigned int trim(char *str)
freeWhenDone: YES];
}
}
*p++ = '\"';
}
else
{
@ -677,6 +682,7 @@ static unsigned int trim(char *str)
case 1002: // CHAR ARRAY
case 1009: // TEXT ARRAY
case 1015: // VARCHAR ARRAY
case 1263: // CSTRING ARRAY
if ('{' == *p)
{
NSMutableArray *a;
@ -1212,7 +1218,7 @@ static unsigned int trim(char *str)
else if ([o isKindOfClass: [NSDate class]])
{
[s appendString: [self quote: (NSString*)o]];
[s appendString: @"::timestamp"];
[s appendString: @"::timestamp with time zone"];
}
else if ([o isKindOfClass: [NSData class]])
{

View file

@ -488,6 +488,13 @@ SQLCLIENT_PRIVATE
*/
- (void) begin;
/** This grabs the receiver for use by the current thread.<br />
* If limit is nil or in the past, makes a single immediate attempt.<br />
* Returns NO if it fails to obtain a lock by the specified date.<br />
* Must be matched by an -unlock if it succeeds.
*/
- (BOOL) lockBeforeDate: (NSDate*)limit;
/**
* <p>Build an sql query string using the supplied arguments.
* </p>
@ -787,7 +794,12 @@ SQLCLIENT_PRIVATE
* YYYY-MM-DD hh:mm:ss.mmm ?ZZZZ<br />
* NSData objects are not quoted ... they must not appear in queries, and
* where used for insert/update operations, they need to be passed to the
* -backendExecute: method unchanged.
* -backendExecute: method unchanged.<br />
* NSArray and NSSet objects are quoted as sets containing the quoted
* elements from the array/set. If you want to use SQL arrays (and your
* database backend supports it) you must explicitly use the
* -quoteArray:toString:quotingString: to convert an NSArray to a literal
* database array representation.
*/
- (NSString*) quote: (id)obj;
@ -928,6 +940,10 @@ SQLCLIENT_PRIVATE
recordType: (id)rtype
listType: (id)ltype;
/** Releases a lock previously obtained using -lockbeforeDate:
*/
- (void) unlock;
/**
* Return the database user for this instance (or nil).
*/
@ -1088,7 +1104,8 @@ SQLCLIENT_PRIVATE
* which don't support asynchronous notifications.<br />
* If a backend <em>does</em> support asynchronous notifications,
* it should do so by posting NSNotification instances to
* [NSNotificationCenter defaultCenter] using the SQLClient instance as
* [NSNotificationQueue defaultQueue] with the posting style NSPostASAP
* (to post asynchronously) and using the SQLClient instance as
* the notification object and supplying any payload as a string using
* the 'Payload' key in the NSNotification userInfo dictionary.
* The userInfo dictionary should also contain a boolean (NSNumber) value,
@ -1182,11 +1199,14 @@ SQLCLIENT_PRIVATE
* as an action by this SQLClient instance.<br />
* If the 'Payload' value is not nil, then it is a string providing extra
* information about the notification.<br />
* NB. At the point when the observer is notified about an event the
* database client object will be locked and may not be used to query
* or modify the database (typically a database query will already be
* in progress). The method handling the notification must therefore
* handle any database operations in a later timeout.
* Notifications are posted asynchronously using the default notification
* queue for the current thread, so they should be delivered to the
* observer after the database statement in which they were detected
* has completed. However, delivery of the notification could still
* occur inside a transaction is the -begin and -commit statements
* are used. For this reason, observing code may want to use the
* -lockBeforeDate: -isInTransaction and -unlock methods to ensure
* that they don't interfere with ongoing transactions.
*/
- (void) addObserver: (id)anObserver
selector: (SEL)aSelector

View file

@ -1341,6 +1341,15 @@ static int poolConnections = 0;
return nil;
}
- (BOOL) lockBeforeDate: (NSDate*)limit
{
if (nil == limit)
{
return [lock tryLock];
}
return [lock lockBeforeDate: limit];
}
- (SQLClient*) longestIdle: (SQLClient*)other
{
NSTimeInterval t0;
@ -2015,6 +2024,11 @@ static int poolConnections = 0;
return result;
}
- (void) unlock
{
[lock unlock];
}
- (NSString*) user
{
return _user;

View file

@ -260,7 +260,7 @@ main()
@"extra2 varchar[],"
@"extra3 bytea[],"
@"extra4 boolean[],"
@"extra5 timestamp[]"
@"extra5 timestamp with time zone[]"
@")",
nil];