mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-14 15:40:59 +00:00
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:
parent
47f03c5d6a
commit
9d9f5a83d2
7 changed files with 2586 additions and 376 deletions
26
GNUmakefile
26
GNUmakefile
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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@
|
||||
|
|
31
configure.ac
31
configure.ac
|
@ -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
283
testJDBC.m
Normal 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;
|
||||
}
|
||||
|
Loading…
Reference in a new issue