First tentative steps towards a jdbc backend

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@23313 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2006-08-18 15:05:17 +00:00
parent 47f03c5d6a
commit 9d9f5a83d2
7 changed files with 2586 additions and 376 deletions

View file

@ -95,6 +95,32 @@ testPostgres_LIB_DIRS += -L./$(GNUSTEP_OBJ_DIR)
testPostgres_TOOL_LIBS += -lSQLClient
endif
ifneq ($(JDBC),)
ifeq ($(LINKSQLCLIENT),1)
BUNDLE_NAME += JDBC
JDBC_OBJC_FILES = JDBC.m
JDBC_LIB_DIRS = -L./$(GNUSTEP_OBJ_DIR) $(JDBC_VM_LIBDIRS)
JDBC_BUNDLE_LIBS += -lSQLClient $(JDBC_VM_LIBS)
JDBC_PRINCIPAL_CLASS = SQLClientJDBC
else
BUNDLE_NAME += JDBC
JDBC_OBJC_FILES = JDBC.m
JDBC_LIB_DIRS = -L./$(GNUSTEP_OBJ_DIR) $(JDBC_VM_LIBDIRS)
JDBC_BUNDLE_LIBS += $(JDBC_VM_LIBS)
JDBC_PRINCIPAL_CLASS = SQLClientJDBC
BUNDLE_NAME += JDBC_libs
JDBC_libs_OBJC_FILES = JDBC.m
JDBC_libs_LIB_DIRS = -L./$(GNUSTEP_OBJ_DIR) $(JDBC_VM_LIBDIRS)
JDBC_libs_BUNDLE_LIBS += -lSQLClient -lPerformance \
-lgnustep-base -lobjc $(JDBC_VM_LIBS)
JDBC_libs_PRINCIPAL_CLASS = SQLClientJDBC_libs
endif
TEST_TOOL_NAME += testJDBC
testJDBC_OBJC_FILES = testJDBC.m
testJDBC_LIB_DIRS += -L./$(GNUSTEP_OBJ_DIR)
testJDBC_TOOL_LIBS += -lSQLClient
endif
ifneq ($(MYSQL),)
ifeq ($(LINKSQLCLIENT),1)
BUNDLE_NAME += MySQL

1186
JDBC.m Normal file

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,9 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <jni.h> header file. */
#undef HAVE_JNI_H
/* Define to 1 if you have the `ecpg' library (-lecpg). */
#undef HAVE_LIBECPG

View file

@ -1,5 +1,8 @@
ECPG=@ECPG@
JDBC=@JDBC@
JDBC_VM_LIBS=@JDBC_VM_LIBS@
JDBC_VM_LIBDIRS=@JDBC_VM_LIBDIRS@
MYSQL=@MYSQL@
SQLITE=@SQLITE@
ORACLE_HOME=@ORACLE_HOME@

1430
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -49,6 +49,30 @@ if test "$postgres_topdir" != "no"; then
LIBD="$LIBD -L$postgres_topdir/lib"
fi
AC_CHECK_HEADERS(jni.h)
if test "$ac_cv_header_jni_h" = "yes"; then
JDBC=yes
JDBC_VM_LIBS="-ljava -ljvm -lhpi"
jre_lib="$JAVA_HOME/jre/lib"
case "$GNUSTEP_HOST_CPU" in
ix86) JAVA_CPU=i386;;
x86_64) JAVA_CPU=amd64;;
*) JAVA_CPU=i386;;
esac
jre_cpu="$jre_lib/$JAVA_CPU"
JDBC_VM_LIBDIRS="-L$jre_cpu -L$jre_cpu/native_threads -L$jre_cpu/classic -L$jre_cpu/server"
else
JDBC=
JDBC_VM_LIBS=
JDBC_VM_LIBDIRS=
echo "*********************************************"
echo "Unable to locate jni header (is it installed)"
echo "*********************************************"
fi
AC_SUBST(JDBC)
AC_SUBST(JDBC_VM_LIBS)
AC_SUBST(JDBC_VM_LIBDIRS)
AC_CHECK_HEADERS(mysql/mysql.h)
if test "$ac_cv_header_mysql_mysql_h" = "yes"; then
MYSQL=yes
@ -228,6 +252,13 @@ AC_SUBST(INCD)
AC_SUBST(LIBD)
AC_SUBST(LIBS)
if test "$JDBC" = "yes"; then
BUNDLE="The JDBC backend bundle will be built"
else
BUNDLE="The JDBC backend bundle will NOT be built"
fi
AC_MSG_RESULT(${BUNDLE})
if test "$MYSQL" = "yes"; then
BUNDLE="The MySQL backend bundle will be built"
else

283
testJDBC.m Normal file
View file

@ -0,0 +1,283 @@
/**
Copyright (C) 2006 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
Date: August 2006
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 Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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: 2006-05-25 12:34:03 +0100 (Thu, 25 May 2006) $ $Revision: 22982 $
*/
#include <Foundation/Foundation.h>
#include <Performance/GSCache.h>
#include "SQLClient.h"
int
main()
{
CREATE_AUTORELEASE_POOL(pool);
SQLClient *db;
NSUserDefaults *defs;
NSMutableArray *records;
SQLRecord *record;
unsigned char dbuf[256];
unsigned int i;
NSData *data;
NSString *name;
defs = [NSUserDefaults standardUserDefaults];
[defs registerDefaults:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
@"org.postgresql.Driver:jdbc:postgresql://localhost/template1",
@"Database",
@"postgres", @"User",
@"postgres", @"Password",
@"JDBC", @"ServerType",
nil],
@"test",
nil],
@"SQLClientReferences",
nil]
];
db = [SQLClient clientWithConfiguration: nil name: @"test"];
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++)
{
CREATE_AUTORELEASE_POOL(arp);
NSString *destination = [NSString stringWithFormat: @"%d", i];
NSString *sid = [NSString stringWithFormat: @"%d", i%100];
[db execute: @"INSERT INTO Queue (Consumer, Destination, ServiceID, Payload) VALUES (",
[db quote: name], @", ", [db quote: destination], @", ", sid, @", ",
@"'helo there'", @")", nil];
RELEASE(arp);
}
NSLog(@"End producing");
}
else if ((name = [defs stringForKey: @"Consumer"]) != nil)
{
NSLog(@"Start consuming");
for (i = 0; i < 100000;)
{
CREATE_AUTORELEASE_POOL(arp);
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];
sleep(1);
[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;
RELEASE(arp);
}
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 *nonLatin;
id r0;
id r1;
oddChars = @"'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 ( "
@"k char(40), "
@"char1 char(1), "
@"boolval BOOL, "
@"intval int, "
@"when1 timestamp with time zone, "
@"when2 timestamp, "
@"b bytea"
@")",
nil];
[db execute: @"insert into xxx "
@"(k, char1, boolval, intval, when1, when2, b) "
@"values ("
@"'hello', "
@"'X', "
@"TRUE, "
@"1, "
@"CURRENT_TIMESTAMP, "
@"CURRENT_TIMESTAMP, ",
data,
@")",
nil];
[db execute: @"insert into xxx "
@"(k, char1, boolval, intval, when1, when2, b) "
@"values ("
@"'hello', "
@"'X', "
@"TRUE, "
@"1, ",
[NSDate date], @", ",
[NSDate date], @", ",
[NSData dataWithBytes: "" length: 0],
@")",
nil];
[db execute: @"insert into xxx "
@"(k, char1, boolval, intval, when1, when2, b) "
@"values (",
[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", nil];
r1 = [db cache: 1 query: @"select * from xxx", nil];
NSCAssert([r0 lastObject] == [r1 lastObject], @"Cache failed");
sleep(2);
records = [db cache: 1 query: @"select * from xxx", nil];
NSCAssert([r0 lastObject] != [records lastObject], @"Lifetime failed");
[db execute: @"drop table xxx", nil];
if ([records count] != 3)
{
NSLog(@"Expected 3 records but got %u", [records count]);
}
else
{
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");
}
if ([[record objectForKey: @"k"] isEqual: oddChars] == NO)
{
NSLog(@"Retrieved odd chars does not match saved string");
}
}
NSLog(@"Records - %@", [GSCache class]);
}
RELEASE(pool);
return 0;
}