libs-sqlclient/testPostgres.m
Richard Frith-MacDonald db4f1f32cb tweaks
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@40494 72102866-910b-0410-8b05-ffd578937521
2017-04-27 09:12:22 +00:00

518 lines
15 KiB
Objective-C

/**
Copyright (C) 2004 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
Date: April 2004
This file is part of the SQLClient Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
$Date$ $Revision$
*/
#import <Foundation/Foundation.h>
#import <Performance/GSCache.h>
#import "SQLClient.h"
@interface Logger : NSObject
- (void) notified: (NSNotification*)n;
@end
@implementation Logger
- (void) notified: (NSNotification*)n
{
NSLog(@"Received %@", n);
}
@end
int
main()
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
SQLClientPool *sp;
SQLClient *db;
NSUserDefaults *defs;
NSMutableArray *records;
SQLRecord *record;
unsigned char dbuf[256];
unsigned int i;
NSData *data;
NSString *name;
Logger *l;
defs = [NSUserDefaults standardUserDefaults];
[defs registerDefaults:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
@"template1@localhost", @"Database",
@"postgres", @"User",
@"postgres", @"Password",
@"Postgres", @"ServerType",
nil],
@"test",
nil],
@"SQLClientReferences",
nil]
];
sp = [[[SQLClientPool alloc] initWithConfiguration: nil
name: @"test"
max: 2
min: 1] autorelease];
#if 0
{
NSAutoreleasePool *p;
NSAutoreleasePool *q;
SQLClient *c0;
SQLClient *c1;
[sp setDebugging: 4];
p = [NSAutoreleasePool new];
c0 = [sp provideClientExclusive];
c1 = [sp provideClientExclusive];
NSLog(@"Got two clients from pool");
[c0 connect];
[c1 connect];
NSLog(@"Now putting clients back in pool again");
[sp swallowClient: c0];
[sp swallowClient: c1];
NSLog(@"And emptying autorelease pool");
[p release];
p = [NSAutoreleasePool new];
[sp setPurgeAll: 60 min: 1];
[NSThread sleepForTimeInterval: 1.0];
NSLog(@"Expecting purge to disconnect one client");
[sp purge];
c0 = [sp provideClientExclusive];
c1 = [sp provideClientExclusive];
NSLog(@"Expecting connected: %@", [c0 connected] ? @"YES" : @"NO");
NSLog(@"Expecting not connected: %@", [c1 connected] ? @"NO" : @"YES");
NSLog(@"Pool has provided both it's clients ... now try for another with a 15 second timeout");
[sp provideClientBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 15.0]
exclusive: YES];
NSLog(@"Emptying autorelease pool ... clients should be put back in pool");
[p release];
p = [NSAutoreleasePool new];
NSLog(@"Getting two clients again");
c0 = [sp provideClientExclusive];
c1 = [sp provideClientExclusive];
NSLog(@"Pool has provided both it's clients ... now try for another with a 15 second timeout");
[sp provideClientBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 15.0]
exclusive: YES];
NSLog(@"Emptying autorelease pool again");
[p release];
p = [NSAutoreleasePool new];
c0 = [sp provideClient];
q = [NSAutoreleasePool new];
c1 = [sp provideClient];
if (c0 != c1)
{
NSLog(@"ERROR was expecting provideClient to give the same object");
exit(1);
}
[q release];
[c0 connect];
[p release];
NSLog(@"Expect to get client immediately");
}
#endif
db = [sp provideClientExclusive];
[sp swallowClient: db];
[sp queryString: @"SELECT CURRENT_TIMESTAMP", nil];
db = [sp provideClientExclusive];
l = [Logger new];
[[NSNotificationCenter defaultCenter] addObserver: l
selector: @selector(notified:)
name: SQLClientDidConnectNotification
object: db];
[[NSNotificationCenter defaultCenter] addObserver: l
selector: @selector(notified:)
name: SQLClientDidDisconnectNotification
object: db];
if ((name = [defs stringForKey: @"Producer"]) != nil)
{
NS_DURING
{
[db execute: @"CREATE TABLE Queue ( "
@"ID SERIAL, "
@"Consumer CHAR(40) NOT NULL, "
@"ServiceID INT NOT NULL, "
@"Status CHAR(1) DEFAULT 'Q' NOT NULL, "
@"Delivery TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, "
@"Reference CHAR(128), "
@"Destination CHAR(15) NOT NULL, "
@"Payload CHAR(250) DEFAULT '' NOT NULL,"
@")",
nil];
[db execute:
@"CREATE UNIQUE INDEX QueueIDX ON Queue (ID)",
nil];
[db execute:
@"CREATE INDEX ServiceIDX ON Queue (ServiceID)",
nil];
[db execute:
@"CREATE INDEX ConsumerIDX ON Queue (Consumer,Status,Delivery)",
nil];
[db execute:
@"CREATE INDEX ReferenceIDX ON Queue (Reference,Consumer)",
nil];
}
NS_HANDLER
{
NSLog(@"%@", localException);
}
NS_ENDHANDLER
NSLog(@"Start producing");
for (i = 0; i < 100000; i++)
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
NSString *destination = [NSString stringWithFormat: @"%d", i];
NSString *sid = [NSString stringWithFormat: @"%d", i%100];
if (i % 1000 == 999)
{
[db postNotificationName: @"Producing"
payload: [NSString stringWithFormat: @"%d", i]];
}
[db execute: @"INSERT INTO Queue (Consumer, Destination,"
@" ServiceID, Payload) VALUES (",
[db quote: name], @", ",
[db quote: destination], @", ",
sid, @", ",
@"'helo there'",
@")", nil];
[arp release];
}
NSLog(@"End producing");
}
else if ((name = [defs stringForKey: @"Consumer"]) != nil)
{
[db addObserver: l
selector: @selector(notified:)
name: @"Producing"];
NSLog(@"Start consuming");
for (i = 0; i < 100000;)
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
unsigned count;
int j;
[db begin];
records = [db query: @"SELECT * FROM Queue WHERE Consumer = ",
[db quote: name],
@" AND Status = 'Q' AND Delivery < CURRENT_TIMESTAMP",
@" ORDER BY Delivery LIMIT 1000 FOR UPDATE" , nil];
count = [records count];
if (count == 0)
{
[db commit];
[NSThread sleepForTimeInterval: 1.0];
[db begin];
records = [db query: @"SELECT * FROM Queue WHERE Consumer = ",
[db quote: name],
@" AND Status = 'Q' AND Delivery < CURRENT_TIMESTAMP",
@" ORDER BY Delivery LIMIT 50 FOR UPDATE" , nil];
count = [records count];
if (count == 0)
{
break;
}
}
for (j = 0; j < count; j++)
{
SQLRecord *record = [records objectAtIndex: j];
NSString *reference = [record objectForKey: @"ID"];
[db execute: @"UPDATE Queue SET Status = 'S', Reference = ",
[db quote: reference], @" WHERE ID = ",
[record objectForKey: @"ID"], nil];
[db execute: @"UPDATE Queue SET Status = 'D'",
@" WHERE Consumer = ", [db quote: name],
@" AND Reference = ", [db quote: reference],
nil];
}
[db commit];
i += count;
[arp release];
}
NSLog(@"End consuming (%d records)", i);
/*
[db execute: @"DROP INDEX ReferenceIDX", nil];
[db execute: @"DROP INDEX ServiceIDX", nil];
[db execute: @"DROP INDEX ConsumerIDX", nil];
[db execute: @"DROP INDEX QueueIDX", nil];
[db execute: @"DROP TABLE Queue", nil];
*/
}
else
{
NSString *oddChars;
NSString *oddNoNul;
NSString *nonLatin;
id e1, e2, e3, e4, e5;
id d;
id d0;
id d1;
id d2;
id r0;
id r1;
oddChars = @"'a\\b'c\0\r\nd'\\ed\\";
oddNoNul = @"'a\\b'c\r\nd'\\ed\\";
nonLatin = [[NSString stringWithCString: "\"\\U2A11\""] propertyList];
for (i = 0; i < 256; i++)
{
dbuf[i] = i;
}
data = [NSData dataWithBytes: dbuf length: i];
NS_DURING
[db execute: @"drop table xxx", nil];
NS_HANDLER
NS_ENDHANDLER
[db setDurationLogging: 0];
[db begin];
[db execute: @"create table xxx ( "
@"id int, "
@"k char(40), "
@"char1 char(1), "
@"boolval BOOL, "
@"intval int, "
@"when1 timestamp with time zone, "
@"when2 timestamp, "
@"b bytea,"
@"extra1 int[],"
@"extra2 varchar[],"
@"extra3 bytea[],"
@"extra4 boolean[],"
@"extra5 timestamp with time zone[]"
@")",
nil];
if (1 != [db execute: @"INSERT into xxx (id, k, char1, boolval, intval,"
@" when1, when2, b, extra1, extra2, extra3, extra4, extra5) "
@"values (1,"
@"'{hello', "
@"'X', "
@"TRUE, "
@"1, "
@"CURRENT_TIMESTAMP, "
@"CURRENT_TIMESTAMP, ",
data, @", ",
[db quoteArray:
(e1 = [NSArray arrayWithObjects: @"1", @"2", [NSNull null], nil])
toString: nil
quotingStrings: NO], @", ",
[db quoteArray:
(e2 = [NSArray arrayWithObjects: @"on,e", @"t'wo", @"many", nil])
toString: nil
quotingStrings: YES], @", ",
[db quoteArray:
(e3 = [NSArray arrayWithObjects: data, nil])
toString: nil
quotingStrings: YES], @", ",
[db quoteArray:
(e4 =[NSArray arrayWithObjects: @"TRUE", @"FALSE", nil])
toString: nil
quotingStrings: NO], @", ",
[db quoteArray:
(e5 = [NSArray arrayWithObjects: [NSDate date], nil])
toString: nil
quotingStrings: YES], @")",
nil])
{
NSLog(@"Insert failed to return row count");
}
[db setDebugging: 0];
[db query: @"select * from xxx", nil];
[db setDebugging: 0];
[db execute: @"INSERT into xxx "
@"(id, k, char1, boolval, intval, when1, when2, b) "
@"values (2,"
@"'hello', "
@"'X', "
@"TRUE, "
@"1, ",
[NSDate date], @", ",
[NSDate date], @", ",
[NSData dataWithBytes: "" length: 0],
@")",
nil];
[db execute: @"INSERT into xxx "
@"(id, k, char1, boolval, intval, when1, when2, b) "
@"values (3,",
[db quote: oddChars],
@", ",
[db quote: nonLatin],
@",TRUE, "
@"1, ",
[NSDate date], @", ",
[NSDate date], @", ",
[NSData dataWithBytes: "" length: 0],
@")",
nil];
[db commit];
r0 = [db cache: 1 query: @"select * from xxx order by id", nil];
r1 = [db cache: 1 query: @"select * from xxx order by id", nil];
NSCAssert([r0 lastObject] == [r1 lastObject], @"Cache failed");
[NSThread sleepForTimeInterval: 2.0];
records = [db cache: 1 query: @"select * from xxx order by id", nil];
NSCAssert([r0 lastObject] != [records lastObject], @"Lifetime failed");
db = [[[SQLClient alloc] initWithConfiguration: nil
name: @"test"] autorelease];
[db addObserver: l
selector: @selector(notified:)
name: @"foo"];
[db postNotificationName: @"foo" payload: @"hello"];
[db execute: @"drop table xxx", nil];
if ([records count] != 3)
{
NSLog(@"Expected 3 records but got %lu", [records count]);
}
else
{
int i;
record = [records objectAtIndex: 0];
if ([[record objectForKey: @"b"] isEqual: data] == NO)
{
NSLog(@"Retrieved data does not match saved data %@ %@",
data, [record objectForKey: @"b"]);
}
record = [records objectAtIndex: 1];
if ([[record objectForKey: @"b"] isEqual: [NSData data]] == NO)
{
NSLog(@"Retrieved empty data does not match saved data");
}
record = [records objectAtIndex: 2];
if ([[record objectForKey: @"char1"] isEqual: nonLatin] == NO)
{
NSLog(@"Retrieved non-latin does not match saved string");
}
id o = [[record objectForKey: @"k"] stringByTrimmingSpaces];
if ([o isEqual: oddNoNul] == NO)
{
NSLog(@"Retrieved odd chars (%@) does not match oddNoNul (%@)",
o, oddNoNul);
}
else
{
NSLog(@"Embedded nul correctly removed");
}
record = [records objectAtIndex: 0];
o = [record objectForKey: @"extra1"];
if ([o isEqual: e1] == NO)
{
NSLog(@"Retrieved extra1 (%@) does not match saved (%@)", o, e1);
}
o = [record objectForKey: @"extra2"];
if ([o isEqual: e2] == NO)
{
NSLog(@"Retrieved extra2 (%@) does not match saved (%@)", o, e2);
}
o = [record objectForKey: @"extra3"];
if ([o isEqual: e3] == NO)
{
NSLog(@"Retrieved extra3 (%@) does not match saved (%@)", o, e3);
}
o = [record objectForKey: @"extra4"];
if ([o count] != [e4 count])
{
NSLog(@"Retrieved extra4 (%@) does not match saved (%@)", o, e4);
}
for (i = 0; i < [o count]; i++)
{
if ([[o objectAtIndex: i] boolValue]
!= [[e4 objectAtIndex: i] boolValue])
{
NSLog(@"Retrieved extra4 (%@) does not match saved (%@)",
o, e4);
}
}
o = [record objectForKey: @"extra5"];
if ([o count] != [e5 count])
{
NSLog(@"Retrieved extra5 (%@) does not match saved (%@)", o, e5);
}
for (i = 0; i < [o count]; i++)
{
if (floor([[o objectAtIndex: i] timeIntervalSinceReferenceDate])
!= floor([[e5 objectAtIndex: i] timeIntervalSinceReferenceDate]))
{
NSLog(@"Retrieved extra5 (%@) does not match saved (%@)",
o, e5);
}
}
}
NSLog(@"Records - %@", [GSCache class]);
d = [NSCalendarDate date];
[d setTimeZone: [NSTimeZone timeZoneForSecondsFromGMT: 240]];
[db begin];
[db execute: @"create table xxx ( "
@"id int, "
@"when0 timestamp with time zone, "
@"when1 timestamp with time zone, "
@"when2 timestamp)",
nil];
[db execute: @"INSERT into xxx (id, when0, when1, when2) "
@"values (99,",
d, @", ",
[NSDate distantPast], @", ",
[NSDate distantFuture], @")",
nil];
r0 = [[db query: @"select * from xxx where id=99", nil] lastObject];
[db execute: @"drop table xxx", nil];
[db commit];
d0 = [r0 objectForKey:@"when0"];
NSCAssert(floor([d0 timeIntervalSinceReferenceDate])
== floor([d timeIntervalSinceReferenceDate]),
NSInternalInconsistencyException);
d1 = [r0 objectForKey:@"when1"];
NSCAssert([d1 timeIntervalSinceReferenceDate]
== [[NSDate distantPast] timeIntervalSinceReferenceDate],
NSInternalInconsistencyException);
d2 = [r0 objectForKey:@"when2"];
NSCAssert([d2 timeIntervalSinceReferenceDate]
== [[NSDate distantFuture] timeIntervalSinceReferenceDate],
NSInternalInconsistencyException);
}
NSLog(@"Pool stats:\n%@", [sp statistics]);
[pool release];
return 0;
}