+
+static int
+vatest2(va_list ap)
+{
+ return 0;
+}
static int
vatest(char **x, ...)
{
va_list ap;
@@ -437,10 +443,13 @@
}
int
main(int argc, char **argv)
{
+ /* Check if we can convert char ** to va_list. */
+ vatest2((va_list) argv);
+ /* Check if parameters are passed through stack. */
exit(vatest(NULL, vatest, 0.0, 0, NULL));
}
],[USE_VFUNCS=1],[USE_VFUNCS=0],[USE_VFUNCS=0])
if test "$USE_VFUNCS" = "1" ; then
@@ -554,19 +563,20 @@
JDBCVER=JDBC2
$JAVA_RUN -version 2>&1 | grep 'version "1.1' >/dev/null && JDBCVER=JDBC1
$JAVA_RUN -version 2>&1 | grep 'version "1.4' >/dev/null && JDBCVER=JDBC2x
$JAVA_RUN -version 2>&1 | grep 'version "1.5' >/dev/null && JDBCVER=JDBC2y
$JAVA_RUN -version 2>&1 | grep 'version "1.6' >/dev/null && JDBCVER=JDBC2z
- $JAVA_RUN -version 2>&1 | grep 'version "1.7' >/dev/null && JDBCVER=JDBC2z1
+ $JAVA_RUN -version 2>&1 | grep 'version "1.[78]' >/dev/null && JDBCVER=JDBC2z1
$JAVA_RUN -version 2>&1 | grep 'JSR169' >/dev/null && JDBCVER=JDBC0
else
AC_MSG_WARN([overriding JDBC driver: $JDBCVER])
fi
AC_MSG_RESULT([using JDBC driver from $JDBCVER directory])
# default to pre 1.7 source
-cp SQLite/JDBCDriver.java16 SQLite/JDBCDriver
+cp SQLite/JDBCDriver.java16 SQLite/JDBCDriver.java
+cp SQLite/JDBCDataSource.javajsr169 SQLite/JDBCDataSource.java
if test "$JDBCVER" = "JDBC2y" ; then
# 1.5 gives one unchecked warning on SQLite/TableResult.java
JAVAC="$JAVAC -nowarn"
fi
@@ -576,10 +586,11 @@
fi
if test "$JDBCVER" = "JDBC2z1" ; then
# 1.7 gives some unchecked warnings, e.g. on SQLite/TableResult.java
JAVAC="$JAVAC -nowarn"
cp SQLite/JDBCDriver.java17 SQLite/JDBCDriver.java
+ cp SQLite/JDBCDataSource.java17 SQLite/JDBCDataSource.java
fi
if test "x$NATIVE_LIB_DIR" = "x" ; then
NATIVE_LIB_DIR=$libdir
fi
Index: doc/overview.html
==================================================================
--- doc/overview.html
+++ doc/overview.html
@@ -23,14 +23,14 @@
Since September, 2004, SQLite3 (minimum 3.0.7) is supported. The JNI part can
be generated to include support for both SQLite 2.x and 3.x and detects at
runtime the type of the database.
The current source tarball can be downloaded from
-
-javasqlite-20111222.tar.gz.
-It has been tested on Linux, using SQLite 2.8.17 and 3.7.9,
-and JDK 1.4/1.5/1.6 from
+
+javasqlite-20150419.tar.gz.
+It has been tested on Linux, using SQLite 2.8.17 and 3.7.15,
+and JDK 1.4/1.5/1.6/1.7 from
Sun.
The change log starting from August 2007 is here.
For rebuilding the following requirements must be met:
Index: doc/title.html
==================================================================
--- doc/title.html
+++ doc/title.html
@@ -1,4 +1,4 @@
SQLite Java Wrapper/JDBC Driver
-2011-12-22
+2015-04-19
Index: javasqlite.mak
==================================================================
--- javasqlite.mak
+++ javasqlite.mak
@@ -5,30 +5,30 @@
# Change this to the location where your Java2 SDK is installed
JAVA_HOME = C:\j2sdk1.4.2_03
# Change this to the location where your Java2 Runtime is installed
-JRE_HOME = $(JAVA_HOME)\jre
+JRE_HOME = "$(JAVA_HOME)\jre"
# See comment at top
SQLITE = sqlite-2.8.17
CC = cl
SQLITE_INC = $(SQLITE)
SQLITE_LIB = $(SQLITE)\libsqlite.lib
-JAVAH = $(JAVA_HOME)\bin\javah -jni
-JAVA_RUN = $(JAVA_HOME)\bin\java
-JAVAC = $(JAVA_HOME)\bin\javac
-JAVADOC = $(JAVA_HOME)\bin\javadoc
-JAR = $(JAVA_HOME)\bin\jar
-JNIINCLUDE = $(JAVA_HOME)\include
+JAVAH = "$(JAVA_HOME)\bin\javah" -jni
+JAVA_RUN = "$(JAVA_HOME)\bin\java"
+JAVAC = "$(JAVA_HOME)\bin\javac"
+JAVADOC = "$(JAVA_HOME)\bin\javadoc"
+JAR = "$(JAVA_HOME)\bin\jar"
+JNIINCLUDE = "$(JAVA_HOME)\include"
JDBCVER = JDBC2x
-EXTENSION_DIR = $(JRE_HOME)\lib\ext
+EXTENSION_DIR = "$(JRE_HOME)\lib\ext"
-NATIVE_LIB_DIR = $(JRE_HOME)\bin
+NATIVE_LIB_DIR = "$(JRE_HOME)\bin"
CFLAGS = -nologo -Oti -Gs -W3 -D_MT -D_WIN32 \
-I$(SQLITE_INC) -I$(JNIINCLUDE) -I$(JNIINCLUDE)\win32 \
-DHAVE_SQLITE_FUNCTION_TYPE=1 -DHAVE_SQLITE_SET_AUTHORIZER=1 \
-DHAVE_SQLITE_COMPILE=1 -DHAVE_SQLITE_TRACE=1 \
@@ -41,11 +41,11 @@
LIBS = $(SQLITE_LIB)
.SUFFIXES: .java .class .jar
.java.class:
- $(JAVAC) $(JAVAC_FLAGS) $<
+ $(JAVAC) $(JAVAC_FLAGS) "$<"
CLASSES = \
SQLite/Authorizer.class \
SQLite/BusyHandler.class \
SQLite/Callback.class \
Index: javasqlite23.mak
==================================================================
--- javasqlite23.mak
+++ javasqlite23.mak
@@ -6,11 +6,11 @@
# Change this to the location where your Java2 SDK is installed
JAVA_HOME = C:\j2sdk1.4.2_03
# Change this to the location where your Java2 Runtime is installed
-JRE_HOME = $(JAVA_HOME)\jre
+JRE_HOME = "$(JAVA_HOME)\jre"
# See comment at top
SQLITE = sqlite-2.8.17
SQLITE3 = sqlite-amalgamation-3070701
@@ -17,22 +17,22 @@
CC = cl
SQLITE_INC = $(SQLITE)
SQLITE_LIB = $(SQLITE)\libsqlite.lib
SQLITE3_INC = $(SQLITE3)
SQLITE3_LIB = $(SQLITE3)\libsqlite3.lib
-JAVAH = $(JAVA_HOME)\bin\javah -jni
-JAVA_RUN = $(JAVA_HOME)\bin\java
-JAVAC = $(JAVA_HOME)\bin\javac
-JAVADOC = $(JAVA_HOME)\bin\javadoc
-JAR = $(JAVA_HOME)\bin\jar
-JNIINCLUDE = $(JAVA_HOME)\include
+JAVAH = "$(JAVA_HOME)\bin\javah" -jni
+JAVA_RUN = "$(JAVA_HOME)\bin\java"
+JAVAC = "$(JAVA_HOME)\bin\javac"
+JAVADOC = "$(JAVA_HOME)\bin\javadoc"
+JAR = "$(JAVA_HOME)\bin\jar"
+JNIINCLUDE = "$(JAVA_HOME)\include"
JDBCVER = JDBC2x
-EXTENSION_DIR = $(JRE_HOME)\lib\ext
+EXTENSION_DIR = "$(JRE_HOME)\lib\ext"
-NATIVE_LIB_DIR = $(JRE_HOME)\bin
+NATIVE_LIB_DIR = "$(JRE_HOME)\bin"
CFLAGS = -nologo -Oti -Gs -W3 -D_MT -D_WIN32 \
-I$(SQLITE_INC) -I$(SQLITE3_INC) \
-I$(JNIINCLUDE) -I$(JNIINCLUDE)\win32 \
-DHAVE_SQLITE_FUNCTION_TYPE=1 -DHAVE_SQLITE_SET_AUTHORIZER=1 \
@@ -69,11 +69,11 @@
LIBS = $(SQLITE_LIB) $(SQLITE3_LIB)
.SUFFIXES: .java .class .jar
.java.class:
- $(JAVAC) $(JAVAC_FLAGS) $<
+ $(JAVAC) $(JAVAC_FLAGS) "$<"
CLASSES = \
SQLite/Authorizer.class \
SQLite/BusyHandler.class \
SQLite/Callback.class \
Index: javasqlite3-dll.mak
==================================================================
--- javasqlite3-dll.mak
+++ javasqlite3-dll.mak
@@ -4,30 +4,30 @@
# Change this to the location where your Java2 SDK is installed
JAVA_HOME = C:\j2sdk1.4.2_03
# Change this to the location where your Java2 Runtime is installed
-JRE_HOME = $(JAVA_HOME)\jre
+JRE_HOME = "$(JAVA_HOME)\jre"
# See comment at top
SQLITE3 = .
CC = cl
SQLITE3_INC = $(SQLITE3)
SQLITE3_LIB = $(SQLITE3)\sqlite3.lib
-JAVAH = $(JAVA_HOME)\bin\javah -jni
-JAVA_RUN = $(JAVA_HOME)\bin\java
-JAVAC = $(JAVA_HOME)\bin\javac
-JAVADOC = $(JAVA_HOME)\bin\javadoc
-JAR = $(JAVA_HOME)\bin\jar
-JNIINCLUDE = $(JAVA_HOME)\include
+JAVAH = "$(JAVA_HOME)\bin\javah" -jni
+JAVA_RUN = "$(JAVA_HOME)\bin\java"
+JAVAC = "$(JAVA_HOME)\bin\javac"
+JAVADOC = "$(JAVA_HOME)\bin\javadoc"
+JAR = "$(JAVA_HOME)\bin\jar"
+JNIINCLUDE = "$(JAVA_HOME)\include"
JDBCVER = JDBC2x
-EXTENSION_DIR = $(JRE_HOME)\lib\ext
+EXTENSION_DIR = "$(JRE_HOME)\lib\ext"
-NATIVE_LIB_DIR = $(JRE_HOME)\bin
+NATIVE_LIB_DIR = "$(JRE_HOME)\bin"
CFLAGS = -nologo -Oti -Gs -W3 -D_MT -D_WIN32 \
-I$(SQLITE3_INC) -I$(JNIINCLUDE) -I$(JNIINCLUDE)\win32 \
-DHAVE_SQLITE_SET_AUTHORIZER=1 -DHAVE_SQLITE3=1 \
-DHAVE_SQLITE3_MALLOC=1 \
@@ -58,11 +58,11 @@
LIBS = $(SQLITE3_LIB)
.SUFFIXES: .java .class .jar
.java.class:
- $(JAVAC) $(JAVAC_FLAGS) $<
+ $(JAVAC) $(JAVAC_FLAGS) "$<"
CLASSES = \
SQLite/Authorizer.class \
SQLite/BusyHandler.class \
SQLite/Callback.class \
Index: javasqlite3-see.mak
==================================================================
--- javasqlite3-see.mak
+++ javasqlite3-see.mak
@@ -5,30 +5,30 @@
# Change this to the location where your Java2 SDK is installed
JAVA_HOME = C:\j2sdk1.4.2_03
# Change this to the location where your Java2 Runtime is installed
-JRE_HOME = $(JAVA_HOME)\jre
+JRE_HOME = "$(JAVA_HOME)\jre"
# See comment at top
SQLITE3 = sqlite-3-see
CC = cl
SQLITE3_INC = $(SQLITE3)
SQLITE3_LIB = $(SQLITE3)\libsqlite3see.lib
-JAVAH = $(JAVA_HOME)\bin\javah -jni
-JAVA_RUN = $(JAVA_HOME)\bin\java
-JAVAC = $(JAVA_HOME)\bin\javac
-JAVADOC = $(JAVA_HOME)\bin\javadoc
-JAR = $(JAVA_HOME)\bin\jar
-JNIINCLUDE = $(JAVA_HOME)\include
+JAVAH = "$(JAVA_HOME)\bin\javah" -jni
+JAVA_RUN = "$(JAVA_HOME)\bin\java"
+JAVAC = "$(JAVA_HOME)\bin\javac"
+JAVADOC = "$(JAVA_HOME)\bin\javadoc"
+JAR = "$(JAVA_HOME)\bin\jar"
+JNIINCLUDE = "$(JAVA_HOME)\include"
JDBCVER = JDBC2x
-EXTENSION_DIR = $(JRE_HOME)\lib\ext
+EXTENSION_DIR = "$(JRE_HOME)\lib\ext"
-NATIVE_LIB_DIR = $(JRE_HOME)\bin
+NATIVE_LIB_DIR = "$(JRE_HOME)\bin"
CFLAGS = -nologo -Oti -Gs -W3 -D_MT -D_WIN32 \
-I$(SQLITE3_INC) -I$(JNIINCLUDE) -I$(JNIINCLUDE)\win32 \
-DHAVE_SQLITE_SET_AUTHORIZER=1 -DHAVE_SQLITE3=1 \
-DHAVE_SQLITE3_MALLOC=1 \
@@ -54,11 +54,11 @@
LIBS = $(SQLITE3_LIB)
.SUFFIXES: .java .class .jar
.java.class:
- $(JAVAC) $(JAVAC_FLAGS) $<
+ $(JAVAC) $(JAVAC_FLAGS) "$<"
CLASSES = \
SQLite/Authorizer.class \
SQLite/BusyHandler.class \
SQLite/Callback.class \
Index: javasqlite3.mak
==================================================================
--- javasqlite3.mak
+++ javasqlite3.mak
@@ -5,30 +5,30 @@
# Change this to the location where your Java2 SDK is installed
JAVA_HOME = C:\j2sdk1.4.2_03
# Change this to the location where your Java2 Runtime is installed
-JRE_HOME = $(JAVA_HOME)\jre
+JRE_HOME = "$(JAVA_HOME)\jre"
# See comment at top
SQLITE3 = sqlite-amalgamation-3070701
CC = cl
SQLITE3_INC = $(SQLITE3)
SQLITE3_LIB = $(SQLITE3)\libsqlite3.lib
-JAVAH = $(JAVA_HOME)\bin\javah -jni
-JAVA_RUN = $(JAVA_HOME)\bin\java
-JAVAC = $(JAVA_HOME)\bin\javac
-JAVADOC = $(JAVA_HOME)\bin\javadoc
-JAR = $(JAVA_HOME)\bin\jar
-JNIINCLUDE = $(JAVA_HOME)\include
+JAVAH = "$(JAVA_HOME)\bin\javah" -jni
+JAVA_RUN = "$(JAVA_HOME)\bin\java"
+JAVAC = "$(JAVA_HOME)\bin\javac"
+JAVADOC = "$(JAVA_HOME)\bin\javadoc"
+JAR = "$(JAVA_HOME)\bin\jar"
+JNIINCLUDE = "$(JAVA_HOME)\include"
JDBCVER = JDBC2x
-EXTENSION_DIR = $(JRE_HOME)\lib\ext
+EXTENSION_DIR = "$(JRE_HOME)\lib\ext"
-NATIVE_LIB_DIR = $(JRE_HOME)\bin
+NATIVE_LIB_DIR = "$(JRE_HOME)\bin"
CFLAGS = -nologo -Oti -Gs -W3 -D_MT -D_WIN32 \
-I$(SQLITE3_INC) -I$(JNIINCLUDE) -I$(JNIINCLUDE)\win32 \
-DHAVE_SQLITE_SET_AUTHORIZER=1 -DHAVE_SQLITE3=1 \
-DHAVE_SQLITE3_MALLOC=1 \
@@ -59,11 +59,11 @@
LIBS = $(SQLITE3_LIB)
.SUFFIXES: .java .class .jar
.java.class:
- $(JAVAC) $(JAVAC_FLAGS) $<
+ $(JAVAC) $(JAVAC_FLAGS) "$<"
CLASSES = \
SQLite/Authorizer.class \
SQLite/BusyHandler.class \
SQLite/Callback.class \
Index: native/mkconst.c
==================================================================
--- native/mkconst.c
+++ native/mkconst.c
@@ -290,20 +290,60 @@
#ifndef SQLITE_IGNORE
#define SQLITE_IGNORE 2
#endif
QCONST(SQLITE_IGNORE);
-#ifndef SQLITE_OPEN_NOMUTEX
-#define SQLITE_OPEN_NOMUTEX 0
+#ifndef SQLITE_OPEN_AUTOPROXY
+#define SQLITE_OPEN_AUTOPROXY 0
+#endif
+ QCONST(SQLITE_OPEN_AUTOPROXY);
+
+#ifndef SQLITE_OPEN_CREATE
+#define SQLITE_OPEN_CREATE 0
+#endif
+ QCONST(SQLITE_OPEN_CREATE);
+
+#ifndef SQLITE_OPEN_DELETEONCLOSE
+#define SQLITE_OPEN_DELETEONCLOSE 0
+#endif
+ QCONST(SQLITE_OPEN_DELETEONCLOSE);
+
+#ifndef SQLITE_OPEN_EXCLUSIVE
+#define SQLITE_OPEN_EXCLUSIVE 0
#endif
- QCONST(SQLITE_OPEN_NOMUTEX);
+ QCONST(SQLITE_OPEN_EXCLUSIVE);
#ifndef SQLITE_OPEN_FULLMUTEX
#define SQLITE_OPEN_FULLMUTEX 0
#endif
QCONST(SQLITE_OPEN_FULLMUTEX);
+#ifndef SQLITE_OPEN_MAIN_DB
+#define SQLITE_OPEN_MAIN_DB 0
+#endif
+ QCONST(SQLITE_OPEN_MAIN_DB);
+
+#ifndef SQLITE_OPEN_MAIN_JOURNAL
+#define SQLITE_OPEN_MAIN_JOURNAL 0
+#endif
+ QCONST(SQLITE_OPEN_MAIN_JOURNAL);
+
+#ifndef SQLITE_OPEN_MASTER_JOURNAL
+#define SQLITE_OPEN_MASTER_JOURNAL 0
+#endif
+ QCONST(SQLITE_OPEN_MASTER_JOURNAL);
+
+#ifndef SQLITE_OPEN_NOMUTEX
+#define SQLITE_OPEN_NOMUTEX 0
+#endif
+ QCONST(SQLITE_OPEN_NOMUTEX);
+
+#ifndef SQLITE_OPEN_PRIVATECACHE
+#define SQLITE_OPEN_PRIVATECACHE 0
+#endif
+ QCONST(SQLITE_OPEN_PRIVATECACHE);
+
#ifndef SQLITE_OPEN_READONLY
#define SQLITE_OPEN_READONLY 0
#endif
QCONST(SQLITE_OPEN_READONLY);
@@ -310,29 +350,59 @@
#ifndef SQLITE_OPEN_READWRITE
#define SQLITE_OPEN_READWRITE 0
#endif
QCONST(SQLITE_OPEN_READWRITE);
-#ifndef SQLITE_OPEN_CREATE
-#define SQLITE_OPEN_CREATE 0
-#endif
- QCONST(SQLITE_OPEN_CREATE);
-
-#ifndef SQLITE_STATUS_MEMORY_USED
-#define SQLITE_STATUS_MEMORY_USED 0
-#endif
- QCONST(SQLITE_STATUS_MEMORY_USED);
+#ifndef SQLITE_OPEN_SHAREDCACHE
+#define SQLITE_OPEN_SHAREDCACHE 0
+#endif
+ QCONST(SQLITE_OPEN_SHAREDCACHE);
+
+#ifndef SQLITE_OPEN_SUBJOURNAL
+#define SQLITE_OPEN_SUBJOURNAL 0
+#endif
+ QCONST(SQLITE_OPEN_SUBJOURNAL);
+
+#ifndef SQLITE_OPEN_TEMP_DB
+#define SQLITE_OPEN_TEMP_DB 0
+#endif
+ QCONST(SQLITE_OPEN_TEMP_DB);
+
+#ifndef SQLITE_OPEN_TEMP_JOURNAL
+#define SQLITE_OPEN_TEMP_JOURNAL 0
+#endif
+ QCONST(SQLITE_OPEN_TEMP_JOURNAL);
+
+#ifndef SQLITE_OPEN_TRANSIENT_DB
+#define SQLITE_OPEN_TRANSIENT_DB 0
+#endif
+ QCONST(SQLITE_OPEN_TRANSIENT_DB);
+
+#ifndef SQLITE_OPEN_URI
+#define SQLITE_OPEN_URI 0
+#endif
+ QCONST(SQLITE_OPEN_URI);
+
+#ifndef SQLITE_OPEN_WAL
+#define SQLITE_OPEN_WAL 0
+#endif
+ QCONST(SQLITE_OPEN_WAL);
+
+#ifndef SQLITE_STATUS_MALLOC_COUNT
+#define SQLITE_STATUS_MALLOC_COUNT 0
+#endif
+ QCONST(SQLITE_STATUS_MALLOC_COUNT);
#ifndef SQLITE_STATUS_MALLOC_SIZE
#define SQLITE_STATUS_MALLOC_SIZE 0
#endif
QCONST(SQLITE_STATUS_MALLOC_SIZE);
-#ifndef SQLITE_STATUS_PAGECACHE_USED
-#define SQLITE_STATUS_PAGECACHE_USED 0
+#ifndef SQLITE_STATUS_MEMORY_USED
+#define SQLITE_STATUS_MEMORY_USED 0
#endif
- QCONST(SQLITE_STATUS_PAGECACHE_USED);
+ QCONST(SQLITE_STATUS_MEMORY_USED);
#ifndef SQLITE_STATUS_PAGECACHE_OVERFLOW
#define SQLITE_STATUS_PAGECACHE_OVERFLOW 0
#endif
QCONST(SQLITE_STATUS_PAGECACHE_OVERFLOW);
@@ -340,14 +410,19 @@
#ifndef SQLITE_STATUS_PAGECACHE_SIZE
#define SQLITE_STATUS_PAGECACHE_SIZE 0
#endif
QCONST(SQLITE_STATUS_PAGECACHE_SIZE);
-#ifndef SQLITE_STATUS_SCRATCH_USED
-#define SQLITE_STATUS_SCRATCH_USED 0
+#ifndef SQLITE_STATUS_PAGECACHE_USED
+#define SQLITE_STATUS_PAGECACHE_USED 0
+#endif
+ QCONST(SQLITE_STATUS_PAGECACHE_USED);
+
+#ifndef SQLITE_STATUS_PARSER_STACK
+#define SQLITE_STATUS_PARSER_STACK 0
#endif
- QCONST(SQLITE_STATUS_SCRATCH_USED);
+ QCONST(SQLITE_STATUS_PARSER_STACK);
#ifndef SQLITE_STATUS_SCRATCH_OVERFLOW
#define SQLITE_STATUS_SCRATCH_OVERFLOW 0
#endif
QCONST(SQLITE_STATUS_SCRATCH_OVERFLOW);
@@ -355,24 +430,59 @@
#ifndef SQLITE_STATUS_SCRATCH_SIZE
#define SQLITE_STATUS_SCRATCH_SIZE 0
#endif
QCONST(SQLITE_STATUS_SCRATCH_SIZE);
-#ifndef SQLITE_STATUS_PARSER_STACK
-#define SQLITE_STATUS_PARSER_STACK 0
+#ifndef SQLITE_STATUS_SCRATCH_USED
+#define SQLITE_STATUS_SCRATCH_USED 0
+#endif
+ QCONST(SQLITE_STATUS_SCRATCH_USED);
+
+#ifndef SQLITE_DBSTATUS_CACHE_HIT
+#define SQLITE_DBSTATUS_CACHE_HIT 0
+#endif
+ QCONST(SQLITE_DBSTATUS_CACHE_HIT);
+
+#ifndef SQLITE_DBSTATUS_CACHE_MISS
+#define SQLITE_DBSTATUS_CACHE_MISS 0
+#endif
+ QCONST(SQLITE_DBSTATUS_CACHE_MISS);
+
+#ifndef SQLITE_DBSTATUS_CACHE_USED
+#define SQLITE_DBSTATUS_CACHE_USED 0
+#endif
+ QCONST(SQLITE_DBSTATUS_CACHE_USED);
+
+#ifndef SQLITE_DBSTATUS_LOOKASIDE_HIT
+#define SQLITE_DBSTATUS_LOOKASIDE_HIT 0
+#endif
+ QCONST(SQLITE_DBSTATUS_LOOKASIDE_HIT);
+
+#ifndef SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
+#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 0
+#endif
+ QCONST(SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE);
+
+#ifndef SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
+#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 0
#endif
- QCONST(SQLITE_STATUS_PARSER_STACK);
+ QCONST(SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL);
#ifndef SQLITE_DBSTATUS_LOOKASIDE_USED
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
#endif
QCONST(SQLITE_DBSTATUS_LOOKASIDE_USED);
-#ifndef SQLITE_DBSTATUS_CACHE_USED
-#define SQLITE_DBSTATUS_CACHE_USED 0
+#ifndef SQLITE_DBSTATUS_SCHEMA_USED
+#define SQLITE_DBSTATUS_SCHEMA_USED 0
+#endif
+ QCONST(SQLITE_DBSTATUS_SCHEMA_USED);
+
+#ifndef SQLITE_DBSTATUS_STMT_USED
+#define SQLITE_DBSTATUS_STMT_USED 0
#endif
- QCONST(SQLITE_DBSTATUS_CACHE_USED);
+ QCONST(SQLITE_DBSTATUS_STMT_USED);
#ifndef SQLITE_STMTSTATUS_FULLSCAN_STEP
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 0
#endif
QCONST(SQLITE_STMTSTATUS_FULLSCAN_STEP);
Index: native/sqlite_jni.c
==================================================================
--- native/sqlite_jni.c
+++ native/sqlite_jni.c
@@ -1,8 +1,14 @@
#include
#include
#include
+#ifdef __STDC__
+#include
+#else
+#undef inline
+#define inline
+#endif
#if HAVE_SQLITE2
#include "sqlite.h"
#endif
@@ -16,12 +22,13 @@
#define HAVE_SQLITE_TRACE 1
#if !HAVE_SQLITE3_MALLOC
#define sqlite3_malloc malloc
#define sqlite3_free free
#endif
+#define MAX_PARAMS3 1024
#if !HAVE_SQLITE3_BIND_PARAMETER_COUNT
-#define sqlite3_bind_parameter_count(dummy) (1000)
+#define sqlite3_bind_parameter_count(dummy) (MAX_PARAMS3)
#endif
#endif
#if HAVE_SQLITE2 && HAVE_SQLITE3
#define HAVE_BOTH_SQLITE 1
@@ -31,15 +38,21 @@
#define HAVE_SQLITE3_SHARED_CACHE 0
#endif
#include "sqlite_jni.h"
-#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
+#if (defined(_WIN32) && !defined(_WIN64)) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
#define MAX_PARAMS 256
#else
#define MAX_PARAMS 32
#endif
+
+#ifdef __STDC__
+#define INT2PTR(p) ((void *)(ptrdiff_t)(p))
+#else
+#define INT2PTR(p) ((void *)(p))
+#endif
/* free memory proc */
typedef void (freemem)(void *);
@@ -70,11 +83,11 @@
#endif
#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
struct hbl *blobs; /* SQLite3 blob handles */
#endif
#if HAVE_SQLITE3 && HAVE_SQLITE3_BACKUPAPI
- struct hbk *backups; /* SQLite3 backup handles */
+ struct hbk *backups; /* SQLite3 backup handles */
#endif
} handle;
/* internal handle for SQLite user defined function */
@@ -136,10 +149,11 @@
} transstr;
/* static cached weak class refs, field and method ids */
static jclass C_java_lang_String = 0;
+static jclass C_SQLite_Database = 0;
static jfieldID F_SQLite_Database_handle = 0;
static jfieldID F_SQLite_Database_error_code = 0;
static jfieldID F_SQLite_FunctionContext_handle = 0;
static jfieldID F_SQLite_Vm_handle = 0;
@@ -155,11 +169,11 @@
static jmethodID M_java_lang_String_initBytes = 0;
static jmethodID M_java_lang_String_initBytes2 = 0;
static const char xdigits[] = "0123456789ABCDEF";
-static void
+static inline void
seterr(JNIEnv *env, jobject obj, int err)
{
jvalue v;
v.j = 0;
@@ -166,11 +180,11 @@
v.i = (jint) err;
(*env)->SetIntField(env, obj, F_SQLite_Database_error_code, v.i);
}
#if HAVE_SQLITE_COMPILE
-static void
+static inline void
setvmerr(JNIEnv *env, jobject obj, int err)
{
jvalue v;
v.j = 0;
@@ -177,21 +191,21 @@
v.i = (jint) err;
(*env)->SetIntField(env, obj, F_SQLite_Vm_error_code, v.i);
}
#if HAVE_SQLITE3
-static void
+static inline void
setstmterr(JNIEnv *env, jobject obj, int err)
{
jvalue v;
v.j = 0;
v.i = (jint) err;
(*env)->SetIntField(env, obj, F_SQLite_Stmt_error_code, v.i);
}
-static int
+static inline int
jstrlen(const jchar *jstr)
{
int len = 0;
if (jstr) {
@@ -202,73 +216,148 @@
return len;
}
#endif
#endif
-static void *
+static inline void *
gethandle(JNIEnv *env, jobject obj)
{
jvalue v;
v.j = (*env)->GetLongField(env, obj, F_SQLite_Database_handle);
return (void *) v.l;
}
+
+static inline void *
+getclrhandle(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ if ((*env)->MonitorEnter(env, obj) != JNI_OK) {
+ fprintf(stderr, "getclrhandle: MonitorEnter failed\n");
+ return 0;
+ }
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_Database_handle);
+ (*env)->SetLongField(env, obj, F_SQLite_Database_handle, 0);
+ (*env)->MonitorExit(env, obj);
+ return (void *) v.l;
+}
#if HAVE_SQLITE_COMPILE
-static void *
+static inline void *
gethvm(JNIEnv *env, jobject obj)
{
jvalue v;
v.j = (*env)->GetLongField(env, obj, F_SQLite_Vm_handle);
return (void *) v.l;
}
+
+static inline void *
+getclrhvm(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ if ((*env)->MonitorEnter(env, obj) != JNI_OK) {
+ fprintf(stderr, "getclrhvm: MonitorEnter failed\n");
+ return 0;
+ }
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_Vm_handle);
+ (*env)->SetLongField(env, obj, F_SQLite_Vm_handle, 0);
+ (*env)->MonitorExit(env, obj);
+ return (void *) v.l;
+}
#if HAVE_SQLITE3
-static void *
+static inline void *
gethstmt(JNIEnv *env, jobject obj)
{
jvalue v;
v.j = (*env)->GetLongField(env, obj, F_SQLite_Stmt_handle);
return (void *) v.l;
}
+
+static inline void *
+getclrhstmt(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ if ((*env)->MonitorEnter(env, obj) != JNI_OK) {
+ fprintf(stderr, "getclrhstmt: MonitorEnter failed\n");
+ return 0;
+ }
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_Stmt_handle);
+ (*env)->SetLongField(env, obj, F_SQLite_Stmt_handle, 0);
+ (*env)->MonitorExit(env, obj);
+ return (void *) v.l;
+}
#endif
#endif
#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
-static void *
+static inline void *
gethbl(JNIEnv *env, jobject obj)
{
jvalue v;
v.j = (*env)->GetLongField(env, obj, F_SQLite_Blob_handle);
return (void *) v.l;
}
+
+static inline void *
+getclrhbl(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ if ((*env)->MonitorEnter(env, obj) != JNI_OK) {
+ fprintf(stderr, "getclrhbl: MonitorEnter failed\n");
+ return 0;
+ }
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_Blob_handle);
+ (*env)->SetLongField(env, obj, F_SQLite_Blob_handle, 0);
+ (*env)->MonitorExit(env, obj);
+ return (void *) v.l;
+}
#endif
#if HAVE_SQLITE3 && HAVE_SQLITE3_BACKUPAPI
-static void *
+static inline void *
gethbk(JNIEnv *env, jobject obj)
{
jvalue v;
v.j = (*env)->GetLongField(env, obj, F_SQLite_Backup_handle);
return (void *) v.l;
}
+
+static inline void *
+getclrhbk(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ if ((*env)->MonitorEnter(env, obj) != JNI_OK) {
+ fprintf(stderr, "getclrhbk: MonitorEnter failed\n");
+ return 0;
+ }
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_Backup_handle);
+ (*env)->SetLongField(env, obj, F_SQLite_Backup_handle, 0);
+ (*env)->MonitorExit(env, obj);
+ return (void *) v.l;
+}
#endif
-static void
+static inline void
delglobrefp(JNIEnv *env, jobject *obj)
{
if (*obj) {
(*env)->DeleteGlobalRef(env, *obj);
*obj = 0;
}
}
-static jobject
+static inline jobject
globrefpop(JNIEnv *env, jobject *obj)
{
jobject ret = 0;
if (*obj) {
@@ -276,32 +365,32 @@
*obj = 0;
}
return ret;
}
-static void
+static inline void
globrefset(JNIEnv *env, jobject obj, jobject *ref)
{
if (ref) {
- if (obj) {
+ if (obj) {
*ref = (*env)->NewGlobalRef(env, obj);
} else {
*ref = 0;
}
}
}
-static void
+static inline void
freep(char **strp)
{
if (strp && *strp) {
free(*strp);
*strp = 0;
}
}
-static void
+static inline void
throwex(JNIEnv *env, const char *msg)
{
jclass except = (*env)->FindClass(env, "SQLite/Exception");
(*env)->ExceptionClear(env);
@@ -308,11 +397,11 @@
if (except) {
(*env)->ThrowNew(env, except, msg);
}
}
-static void
+static inline void
throwoom(JNIEnv *env, const char *msg)
{
jclass except = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
(*env)->ExceptionClear(env);
@@ -319,18 +408,18 @@
if (except) {
(*env)->ThrowNew(env, except, msg);
}
}
-static void
+static inline void
throwclosed(JNIEnv *env)
{
throwex(env, "database already closed");
}
#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
-static void
+static inline void
throwioex(JNIEnv *env, const char *msg)
{
jclass except = (*env)->FindClass(env, "java/io/IOException");
(*env)->ExceptionClear(env);
@@ -338,18 +427,18 @@
(*env)->ThrowNew(env, except, msg);
}
}
#endif
-static void
+static inline void
transfree(transstr *dest)
{
dest->result = 0;
freep(&dest->tofree);
}
-static char *
+static inline char *
trans2iso(JNIEnv *env, int haveutf, jstring enc, jstring src,
transstr *dest)
{
jbyteArray bytes = 0;
jthrowable exc;
@@ -393,20 +482,20 @@
dest->tofree = malloc(len + 1);
if (!dest->tofree) {
throwoom(env, "string translation failed");
return dest->result;
}
- dest->result = dest->tofree;
+ dest->result = dest->tofree;
(*env)->GetByteArrayRegion(env, bytes, 0, len, (jbyte *) dest->result);
dest->result[len] = '\0';
} else {
(*env)->DeleteLocalRef(env, exc);
}
return dest->result;
}
-static jstring
+static inline jstring
trans2utf(JNIEnv *env, int haveutf, jstring enc, const char *src,
transstr *dest)
{
jbyteArray bytes = 0;
int len;
@@ -768,11 +857,11 @@
}
static void
doclose(JNIEnv *env, jobject obj, int final)
{
- handle *h = gethandle(env, obj);
+ handle *h = getclrhandle(env, obj);
if (h) {
hfunc *f;
#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
hbl *bl;
@@ -780,11 +869,17 @@
#if HAVE_SQLITE3 && HAVE_SQLITE3_BACKUPAPI
hbk *bk;
#endif
#if HAVE_SQLITE_COMPILE
hvm *v;
+#endif
+ if ((*env)->MonitorEnter(env, C_SQLite_Database) != JNI_OK) {
+ fprintf(stderr, "doclose: MonitorEnter failed\n");
+ return;
+ }
+#if HAVE_SQLITE_COMPILE
while ((v = h->vms)) {
h->vms = v->next;
v->next = 0;
v->h = 0;
if (v->vm) {
@@ -857,24 +952,185 @@
sqlite3_backup_finish(bk->bkup);
}
bk->bkup = 0;
}
#endif
+ (*env)->MonitorExit(env, C_SQLite_Database);
delglobrefp(env, &h->bh);
delglobrefp(env, &h->cb);
delglobrefp(env, &h->ai);
delglobrefp(env, &h->tr);
delglobrefp(env, &h->ph);
delglobrefp(env, &h->enc);
free(h);
- (*env)->SetLongField(env, obj, F_SQLite_Database_handle, 0);
return;
}
if (!final) {
throwclosed(env);
}
}
+
+#if HAVE_SQLITE3
+static int sqlite3_enhanced_exec(sqlite3 *db, const char *sql,
+ sqlite3_callback cb, void *cbarg,
+ char **errmsg, int nargs, char **args)
+{
+ int rc = SQLITE_OK, argCount;
+ const char *leftsql = 0, *p;
+ sqlite3_stmt *stmt = 0;
+ char **azCols = 0;
+ int callbackIsInit;
+ char *q, *qsql = sqlite3_malloc(strlen(sql) + 1);
+
+ if (errmsg) {
+ *errmsg = 0;
+ }
+ if (!qsql) {
+ return SQLITE_NOMEM;
+ }
+ p = sql;
+ q = qsql;
+ argCount = 0;
+ while (*p) {
+ if (p[0] == '%') {
+ if (p[1] == 'Q' || p[1] == 'q' || p[1] == 's') {
+ *q++ = '?';
+ argCount++;
+ p++;
+ } else if (p[1] == '%') {
+ *q++ = '%';
+ p++;
+ } else {
+ *q++ = *p;
+ }
+ } else {
+ *q++ = *p;
+ }
+ ++p;
+ }
+ *q = '\0';
+ if (argCount != nargs) {
+ sqlite3_free(qsql);
+ p = "parameter count mismatch";
+ *errmsg = sqlite3_malloc(strlen(p) + 1);
+ if (*errmsg) {
+ strcpy(*errmsg, p);
+ rc = SQLITE_ERROR;
+ } else {
+ rc = SQLITE_NOMEM;
+ }
+ return rc;
+ }
+ sqlite3_mutex_enter(sqlite3_db_mutex(db));
+ argCount = 0;
+ q = qsql;
+ while (rc == SQLITE_OK && q[0]) {
+ int i, nCol, nPar;
+
+ stmt = 0;
+#if HAVE_SQLITE3_PREPARE_V2
+ rc = sqlite3_prepare_v2(db, q, -1, &stmt, &leftsql);
+#else
+ rc = sqlite3_prepare(db, q, -1, &stmt, &leftsql);
+#endif
+ if (rc != SQLITE_OK) {
+ continue;
+ }
+ if (!stmt) {
+ /* this happens for a comment or white-space */
+ q = (char *) leftsql;
+ continue;
+ }
+ /* bind parameters */
+ nPar = sqlite3_bind_parameter_count(stmt);
+ for (i = 1; i <= nPar; i++) {
+ if (argCount < nargs && args[argCount]) {
+ sqlite3_bind_text(stmt, i, args[argCount], -1, SQLITE_STATIC);
+ } else {
+ sqlite3_bind_null(stmt, i);
+ }
+ argCount++;
+ }
+
+ callbackIsInit = 0;
+ nCol = sqlite3_column_count(stmt);
+ while (1) {
+ char **azVals = 0;
+
+ rc = sqlite3_step(stmt);
+
+ /* invoke the callback function if required */
+ if (cb && (rc == SQLITE_ROW ||
+ (rc == SQLITE_DONE && !callbackIsInit))) {
+ if (!callbackIsInit) {
+ int n = 2 * nCol * sizeof (char *) + sizeof (char *);
+
+ azCols = sqlite3_malloc(n);
+ if (!azCols) {
+ rc = SQLITE_NOMEM;
+ goto execDone;
+ }
+ memset(azCols, 0, n);
+ for (i = 0; i < nCol; i++) {
+ azCols[i] = (char *) sqlite3_column_name(stmt, i);
+ }
+ callbackIsInit = 1;
+ }
+ if (rc == SQLITE_ROW) {
+ azVals = &azCols[nCol];
+ for (i = 0; i < nCol; i++) {
+ azVals[i] = (char *) sqlite3_column_text(stmt, i);
+ if (!azVals[i] &&
+ sqlite3_column_type(stmt, i) != SQLITE_NULL) {
+ rc = SQLITE_NOMEM;
+ goto execDone;
+ }
+ }
+ }
+ if (cb(cbarg, nCol, azVals, azCols) ){
+ rc = SQLITE_ABORT;
+ sqlite3_finalize(stmt);
+ stmt = 0;
+ goto execDone;
+ }
+ }
+ if (rc != SQLITE_ROW) {
+ rc = sqlite3_finalize(stmt);
+ stmt = 0;
+ q = (char *) leftsql;
+ break;
+ }
+ }
+ sqlite3_free(azCols);
+ azCols = 0;
+ }
+
+execDone:
+ if (qsql) {
+ sqlite3_free(qsql);
+ }
+ if (stmt) {
+ sqlite3_finalize(stmt);
+ }
+ if (azCols) {
+ sqlite3_free(azCols);
+ }
+
+ if (rc != SQLITE_OK && errmsg) {
+ int n = strlen(sqlite3_errstr(rc)) + 1;
+
+ *errmsg = sqlite3_malloc(n);
+ if (*errmsg) {
+ strcpy(*errmsg, sqlite3_errstr(rc));
+ } else {
+ rc = SQLITE_NOMEM;
+ }
+ }
+ sqlite3_mutex_leave(sqlite3_db_mutex(db));
+ return rc;
+}
+#endif
JNIEXPORT void JNICALL
Java_SQLite_Database__1close(JNIEnv *env, jobject obj)
{
doclose(env, obj, 0);
@@ -1048,11 +1304,11 @@
JNIEXPORT void JNICALL
Java_SQLite_Database__1open4(JNIEnv *env, jobject obj, jstring file, jint mode,
jstring vfs, jboolean ver2)
{
- handle *h = gethandle(env, obj);
+ handle *h = gethandle(env, obj), *hh = 0;
jthrowable exc;
char *err = 0;
transstr filename;
int maj, min, lev;
#if HAVE_SQLITE3_OPEN_V2
@@ -1081,11 +1337,11 @@
#endif
#endif
h->sqlite = 0;
}
} else {
- h = malloc(sizeof (handle));
+ h = hh = malloc(sizeof (handle));
if (!h) {
throwoom(env, "unable to get SQLite handle");
return;
}
h->sqlite = 0;
@@ -1117,25 +1373,34 @@
h->backups = 0;
#endif
}
h->env = 0;
if (!file) {
+ if (hh) {
+ free(hh);
+ }
throwex(env, err ? err : "invalid file name");
return;
}
trans2iso(env, h->haveutf, h->enc, file, &filename);
exc = (*env)->ExceptionOccurred(env);
if (exc) {
+ if (hh) {
+ free(hh);
+ }
(*env)->DeleteLocalRef(env, exc);
return;
}
#if HAVE_SQLITE3_OPEN_V2
if (vfs) {
trans2iso(env, 1, h->enc, vfs, &vfsname);
exc = (*env)->ExceptionOccurred(env);
if (exc) {
transfree(&filename);
+ if (hh) {
+ free(hh);
+ }
(*env)->DeleteLocalRef(env, exc);
return;
}
}
#endif
@@ -1214,18 +1479,22 @@
sqlite3_close((sqlite3 *) h->sqlite);
#endif
#endif
}
h->sqlite = 0;
+ if (hh) {
+ free(hh);
+ }
return;
}
if (h->sqlite) {
jvalue v;
v.j = 0;
v.l = (jobject) h;
(*env)->SetLongField(env, obj, F_SQLite_Database_handle, v.j);
+ hh = 0;
#if HAVE_SQLITE2
if (err) {
sqlite_freemem(err);
}
#endif
@@ -1249,10 +1518,13 @@
#endif
#endif
#endif
h->ver = ((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (lev & 0xFF);
return;
+ }
+ if (hh) {
+ free(hh);
}
throwex(env, err ? err : "unknown error in open");
#if HAVE_SQLITE2
if (err) {
sqlite_freemem(err);
@@ -1425,10 +1697,11 @@
Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2_3Ljava_lang_String_2
(JNIEnv *env, jobject obj, jstring sql, jobject cb, jobjectArray args)
{
handle *h = gethandle(env, obj);
freemem *freeproc = 0;
+ int max_params = MAX_PARAMS;
if (!sql) {
throwex(env, "invalid SQL statement");
return;
}
@@ -1444,29 +1717,39 @@
jobject obj;
transstr trans;
} *argv = 0;
char **cargv = 0;
jobject oldcb = globrefpop(env, &h->cb);
+
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ max_params = MAX_PARAMS3;
+ }
+#else
+#if HAVE_SQLITE3
+ max_params = MAX_PARAMS3;
+#endif
+#endif
globrefset(env, cb, &h->cb);
p = (char *) str;
nargs = 0;
while (*p) {
if (*p == '%') {
++p;
if (*p == 'q' || *p == 's') {
nargs++;
- if (nargs > MAX_PARAMS) {
+ if (nargs > max_params) {
(*env)->ReleaseStringUTFChars(env, sql, str);
delglobrefp(env, &h->cb);
h->cb = oldcb;
throwex(env, "too much SQL parameters");
return;
}
} else if (h->ver >= 0x020500 && *p == 'Q') {
nargs++;
- if (nargs > MAX_PARAMS) {
+ if (nargs > max_params) {
(*env)->ReleaseStringUTFChars(env, sql, str);
delglobrefp(env, &h->cb);
h->cb = oldcb;
throwex(env, "too much SQL parameters");
return;
@@ -1479,21 +1762,20 @@
return;
}
}
++p;
}
- cargv = malloc((sizeof (*argv) + sizeof (char *))
- * MAX_PARAMS);
+ cargv = malloc((sizeof (*argv) + sizeof (char *)) * max_params);
if (!cargv) {
(*env)->ReleaseStringUTFChars(env, sql, str);
delglobrefp(env, &h->cb);
h->cb = oldcb;
throwoom(env, "unable to allocate arg vector");
return;
}
- argv = (struct args *) (cargv + MAX_PARAMS);
- for (i = 0; i < MAX_PARAMS; i++) {
+ argv = (struct args *) (cargv + max_params);
+ for (i = 0; i < max_params; i++) {
cargv[i] = 0;
argv[i].arg = 0;
argv[i].obj = 0;
argv[i].trans.result = argv[i].trans.tofree = 0;
}
@@ -1530,42 +1812,17 @@
trans2iso(env, h->haveutf, h->enc, sql, &sqlstr);
exc = (*env)->ExceptionOccurred(env);
if (!exc) {
#if HAVE_BOTH_SQLITE
if (h->is3) {
-#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
- char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
-#else
- char *s = sqlite3_mprintf(sqlstr.result,
- cargv[0], cargv[1],
- cargv[2], cargv[3],
- cargv[4], cargv[5],
- cargv[6], cargv[7],
- cargv[8], cargv[9],
- cargv[10], cargv[11],
- cargv[12], cargv[13],
- cargv[14], cargv[15],
- cargv[16], cargv[17],
- cargv[18], cargv[19],
- cargv[20], cargv[21],
- cargv[22], cargv[23],
- cargv[24], cargv[25],
- cargv[26], cargv[27],
- cargv[28], cargv[29],
- cargv[30], cargv[31]);
-#endif
-
- if (s) {
- rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback,
- h, &err);
- sqlite3_free(s);
- } else {
- rc = SQLITE_NOMEM;
- }
+ rc = sqlite3_enhanced_exec((sqlite3 *) h->sqlite,
+ sqlstr.result,
+ callback, h, &err,
+ nargs, cargv);
freeproc = (freemem *) sqlite3_free;
} else {
-#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
+#if (defined(_WIN32) && !defined(_WIN64)) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
rc = sqlite_exec_vprintf((sqlite *) h->sqlite,
sqlstr.result, callback, h, &err,
(char *) cargv);
#else
rc = sqlite_exec_printf((sqlite *) h->sqlite,
@@ -1590,11 +1847,11 @@
#endif
freeproc = (freemem *) sqlite_freemem;
}
#else
#if HAVE_SQLITE2
-#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
+#if (defined(_WIN32) && !defined(_WIN64)) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
rc = sqlite_exec_vprintf((sqlite *) h->sqlite, sqlstr.result,
callback, h, &err, (char *) cargv);
#else
rc = sqlite_exec_printf((sqlite *) h->sqlite, sqlstr.result,
callback, h, &err,
@@ -1616,39 +1873,14 @@
cargv[30], cargv[31]);
#endif
freeproc = (freemem *) sqlite_freemem;
#endif
#if HAVE_SQLITE3
-#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
- char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
-#else
- char *s = sqlite3_mprintf(sqlstr.result,
- cargv[0], cargv[1],
- cargv[2], cargv[3],
- cargv[4], cargv[5],
- cargv[6], cargv[7],
- cargv[8], cargv[9],
- cargv[10], cargv[11],
- cargv[12], cargv[13],
- cargv[14], cargv[15],
- cargv[16], cargv[17],
- cargv[18], cargv[19],
- cargv[20], cargv[21],
- cargv[22], cargv[23],
- cargv[24], cargv[25],
- cargv[26], cargv[27],
- cargv[28], cargv[29],
- cargv[30], cargv[31]);
-#endif
-
- if (s) {
- rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback,
- h, &err);
- sqlite3_free(s);
- } else {
- rc = SQLITE_NOMEM;
- }
+ rc = sqlite3_enhanced_exec((sqlite3 *) h->sqlite,
+ sqlstr.result,
+ callback, h, &err,
+ nargs, cargv);
freeproc = (freemem *) sqlite3_free;
#endif
#endif
exc = (*env)->ExceptionOccurred(env);
}
@@ -2455,13 +2687,17 @@
#if HAVE_SQLITE_COMPILE
static void
dovmfinal(JNIEnv *env, jobject obj, int final)
{
- hvm *v = gethvm(env, obj);
+ hvm *v = getclrhvm(env, obj);
if (v) {
+ if ((*env)->MonitorEnter(env, C_SQLite_Database) != JNI_OK) {
+ fprintf(stderr, "dovmfinal: MonitorEnter failed\n");
+ return;
+ }
if (v->h) {
handle *h = v->h;
hvm *vv, **vvp;
vvp = &h->vms;
@@ -2473,10 +2709,11 @@
}
vvp = &vv->next;
vv = *vvp;
}
}
+ (*env)->MonitorExit(env, C_SQLite_Database);
if (v->vm) {
#if HAVE_BOTH_SQLITE
if (v->is3) {
sqlite3_finalize((sqlite3_stmt *) v->vm);
} else {
@@ -2491,11 +2728,10 @@
#endif
#endif
v->vm = 0;
}
free(v);
- (*env)->SetLongField(env, obj, F_SQLite_Vm_handle, 0);
return;
}
if (!final) {
throwex(env, "vm already closed");
}
@@ -2504,13 +2740,17 @@
#if HAVE_SQLITE3
static void
dostmtfinal(JNIEnv *env, jobject obj)
{
- hvm *v = gethstmt(env, obj);
+ hvm *v = getclrhstmt(env, obj);
if (v) {
+ if ((*env)->MonitorEnter(env, C_SQLite_Database) != JNI_OK) {
+ fprintf(stderr, "dostmtfinal: MonitorEnter failed\n");
+ return;
+ }
if (v->h) {
handle *h = v->h;
hvm *vv, **vvp;
vvp = &h->vms;
@@ -2522,27 +2762,31 @@
}
vvp = &vv->next;
vv = *vvp;
}
}
+ (*env)->MonitorExit(env, C_SQLite_Database);
if (v->vm) {
sqlite3_finalize((sqlite3_stmt *) v->vm);
}
v->vm = 0;
free(v);
- (*env)->SetLongField(env, obj, F_SQLite_Stmt_handle, 0);
}
}
#endif
#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
static void
doblobfinal(JNIEnv *env, jobject obj)
{
- hbl *bl = gethbl(env, obj);
+ hbl *bl = getclrhbl(env, obj);
if (bl) {
+ if ((*env)->MonitorEnter(env, C_SQLite_Database) != JNI_OK) {
+ fprintf(stderr, "doblobfinal: MonitorEnter failed\n");
+ return;
+ }
if (bl->h) {
handle *h = bl->h;
hbl *blc, **blp;
blp = &h->blobs;
@@ -2554,16 +2798,16 @@
}
blp = &blc->next;
blc = *blp;
}
}
+ (*env)->MonitorExit(env, C_SQLite_Database);
if (bl->blob) {
sqlite3_blob_close(bl->blob);
}
bl->blob = 0;
free(bl);
- (*env)->SetLongField(env, obj, F_SQLite_Blob_handle, 0);
(*env)->SetIntField(env, obj, F_SQLite_Blob_size, 0);
}
}
#endif
@@ -2617,10 +2861,11 @@
hvm *v = gethvm(env, obj);
if (v && v->vm && v->h) {
jthrowable exc;
int ret;
+ char *err = 0;
#if HAVE_SQLITE2
int tmp;
#endif
long ncol = 0;
#if HAVE_SQLITE3
@@ -2639,11 +2884,10 @@
data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
if (data) {
data[0] = (const char *) ncol;
++data;
cols = data + ncol + 1;
- blob = cols + ncol + 1;
freeproc = free_tab;
} else {
ret = SQLITE_NOMEM;
}
}
@@ -2723,14 +2967,13 @@
if (ret == SQLITE_DONE && v->hh.row1) {
ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
if (ncol > 0) {
data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
if (data) {
- data[0] = (const char *) ncol;
+ data[0] = INT2PTR(ncol);
++data;
cols = data + ncol + 1;
- blob = cols + ncol + 1;
freeproc = free_tab;
} else {
ret = SQLITE_NOMEM;
}
}
@@ -2745,11 +2988,11 @@
} else if (ret == SQLITE_ROW) {
ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
if (ncol > 0) {
data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
if (data) {
- data[0] = (const char *) ncol;
+ data[0] = INT2PTR(ncol);
++data;
cols = data + ncol + 1;
blob = cols + ncol + 1;
freeproc = free_tab;
} else {
@@ -2808,10 +3051,11 @@
#endif
callback((void *) &v->hh, ncol, (char **) data, (char **) cols);
#if HAVE_SQLITE3
if (data && freeproc) {
freeproc((void *) data);
+ data = 0;
}
#endif
exc = (*env)->ExceptionOccurred(env);
if (exc) {
(*env)->DeleteLocalRef(env, exc);
@@ -2834,10 +3078,11 @@
#endif
callback((void *) &v->hh, ncol, (char **) 0, (char **) cols);
#if HAVE_SQLITE3
if (data && freeproc) {
freeproc((void *) data);
+ data = 0;
}
#endif
exc = (*env)->ExceptionOccurred(env);
if (exc) {
(*env)->DeleteLocalRef(env, exc);
@@ -2859,26 +3104,56 @@
#endif
v->vm = 0;
return JNI_FALSE;
}
#if HAVE_BOTH_SQLITE
+ if (v->is3) {
+ err = (char *) sqlite3_errmsg((sqlite3 *) v->h->sqlite);
+ } else {
+ err = sqlite_error_string(ret);
+ }
+ if (err) {
+ int n = strlen(err);
+ char *p = malloc(n + 1);
+
+ if (p) {
+ memcpy(p, err, n + 1);
+ }
+ err = p;
+ }
if (v->is3) {
sqlite3_finalize((sqlite3_stmt *) v->vm);
} else {
sqlite_finalize((sqlite_vm *) v->vm, 0);
}
#else
+#if HAVE_SQLITE2
+ err = sqlite_error_string(ret);
+#endif
+#if HAVE_SQLITE3
+ err = (char *) sqlite3_errmsg((sqlite3 *) v->h->sqlite);
+#endif
+ if (err) {
+ int n = strlen(err);
+ char *p = malloc(n + 1);
+
+ if (p) {
+ memcpy(p, err, n + 1);
+ }
+ err = p;
+ }
#if HAVE_SQLITE2
sqlite_finalize((sqlite_vm *) v->vm, 0);
#endif
#if HAVE_SQLITE3
sqlite3_finalize((sqlite3_stmt *) v->vm);
#endif
#endif
setvmerr(env, obj, ret);
v->vm = 0;
- throwex(env, "error in step");
+ throwex(env, err ? err : "error in step");
+ freep(&err);
return JNI_FALSE;
}
throwex(env, "vm already closed");
#else
throwex(env, "unsupported");
@@ -2891,11 +3166,11 @@
{
#if HAVE_SQLITE_COMPILE
hvm *v = gethvm(env, obj);
void *svm = 0;
char *err = 0;
-#ifdef HAVE_SQLITE2
+#if HAVE_SQLITE2
char *errfr = 0;
#endif
const char *tail;
int ret;
@@ -3160,10 +3435,11 @@
v->hh.vms = 0;
v->hh.env = 0;
vv.j = 0;
vv.l = (jobject) v;
(*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j);
+ transfree(&tr);
#else
throwex(env, "unsupported");
#endif
}
@@ -3185,11 +3461,11 @@
#else
#if HAVE_SQLITE2
throwex(env, "unsupported");
#endif
#endif
-#if HAVE_SQLITE3
+#if HAVE_SQLITE3
if (!h || !h->sqlite) {
throwclosed(env);
return;
}
if (!vm) {
@@ -3203,29 +3479,30 @@
void *svm = 0;
hvm *v;
jvalue vv;
jthrowable exc;
int rc = SQLITE_ERROR, nargs, i;
- char *p;
+ char *p, *q, *qsql = 0;
const char *str = (*env)->GetStringUTFChars(env, sql, 0);
const char *tail;
transstr sqlstr;
struct args {
char *arg;
jobject obj;
transstr trans;
} *argv = 0;
char **cargv = 0;
+ int npar, max_params = MAX_PARAMS3;
p = (char *) str;
nargs = 0;
while (*p) {
if (*p == '%') {
++p;
if (*p == 'q' || *p == 'Q' || *p == 's') {
nargs++;
- if (nargs > MAX_PARAMS) {
+ if (nargs > max_params) {
(*env)->ReleaseStringUTFChars(env, sql, str);
throwex(env, "too much SQL parameters");
return;
}
} else if (*p != '%') {
@@ -3234,18 +3511,45 @@
return;
}
}
++p;
}
- cargv = malloc((sizeof (*argv) + sizeof (char *)) * MAX_PARAMS);
+ p = (char *) str;
+ qsql = q = malloc(strlen(p) + 1);
+ nargs = 0;
+ if (!q) {
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ throwoom(env, "unable to copy SQL string");
+ return;
+ }
+ while (*p) {
+ if (*p == '%') {
+ if (p[1] == 'q' || p[1] == 'Q' || p[1] == 's') {
+ *q++= '?';
+ nargs++;
+ p++;
+ } else if (p[1] == '%') {
+ *q++ = '%';
+ p++;
+ } else {
+ *q++ = *p;
+ }
+ } else {
+ *q++ = *p;
+ }
+ ++p;
+ }
+ *q = '\0';
+ cargv = malloc((sizeof (*argv) + sizeof (char *)) * max_params);
if (!cargv) {
+ freep(&qsql);
(*env)->ReleaseStringUTFChars(env, sql, str);
throwoom(env, "unable to allocate arg vector");
return;
}
- argv = (struct args *) (cargv + MAX_PARAMS);
- for (i = 0; i < MAX_PARAMS; i++) {
+ argv = (struct args *) (cargv + max_params);
+ for (i = 0; i < max_params; i++) {
cargv[i] = 0;
argv[i].arg = 0;
argv[i].obj = 0;
argv[i].trans.result = argv[i].trans.tofree = 0;
}
@@ -3268,78 +3572,52 @@
for (i = 0; i < nargs; i++) {
if (argv[i].obj) {
transfree(&argv[i].trans);
}
}
+ freep(&qsql);
freep((char **) &cargv);
(*env)->ReleaseStringUTFChars(env, sql, str);
return;
}
h->row1 = 1;
trans2iso(env, 1, 0, sql, &sqlstr);
exc = (*env)->ExceptionOccurred(env);
if (!exc) {
-#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
- char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
-#else
- char *s = sqlite3_mprintf(sqlstr.result,
- cargv[0], cargv[1],
- cargv[2], cargv[3],
- cargv[4], cargv[5],
- cargv[6], cargv[7],
- cargv[8], cargv[9],
- cargv[10], cargv[11],
- cargv[12], cargv[13],
- cargv[14], cargv[15],
- cargv[16], cargv[17],
- cargv[18], cargv[19],
- cargv[20], cargv[21],
- cargv[22], cargv[23],
- cargv[24], cargv[25],
- cargv[26], cargv[27],
- cargv[28], cargv[29],
- cargv[30], cargv[31]);
-#endif
- if (!s) {
- rc = SQLITE_NOMEM;
- } else {
#if HAVE_SQLITE3_PREPARE_V2
- rc = sqlite3_prepare_v2((sqlite3 *) h->sqlite, s, -1,
- (sqlite3_stmt **) &svm, &tail);
-#else
- rc = sqlite3_prepare((sqlite3 *) h->sqlite, s, -1,
- (sqlite3_stmt **) &svm, &tail);
-#endif
- if (rc != SQLITE_OK) {
- if (svm) {
- sqlite3_finalize((sqlite3_stmt *) svm);
- svm = 0;
- }
- }
- }
- if (rc != SQLITE_OK) {
- sqlite3_free(s);
+ rc = sqlite3_prepare_v2((sqlite3 *) h->sqlite, qsql, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#else
+ rc = sqlite3_prepare((sqlite3 *) h->sqlite, qsql, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#endif
+ if (rc != SQLITE_OK) {
+ if (svm) {
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ svm = 0;
+ }
for (i = 0; i < nargs; i++) {
if (argv[i].obj) {
transfree(&argv[i].trans);
}
}
+ freep(&qsql);
freep((char **) &cargv);
transfree(&sqlstr);
(*env)->ReleaseStringUTFChars(env, sql, str);
setvmerr(env, vm, rc);
throwex(env, "error in prepare");
return;
}
- v = malloc(sizeof (hvm) + strlen(tail) + 1);
+ v = malloc(sizeof (hvm) + 1);
if (!v) {
- sqlite3_free(s);
for (i = 0; i < nargs; i++) {
if (argv[i].obj) {
transfree(&argv[i].trans);
}
}
+ freep(&qsql);
freep((char **) &cargv);
transfree(&sqlstr);
(*env)->ReleaseStringUTFChars(env, sql, str);
sqlite3_finalize((sqlite3_stmt *) svm);
setvmerr(env, vm, SQLITE_NOMEM);
@@ -3352,12 +3630,11 @@
v->h = h;
v->tail = (char *) (v + 1);
#if HAVE_BOTH_SQLITE
v->is3 = v->hh.is3 = h->is3;
#endif
- strcpy(v->tail, tail);
- sqlite3_free(s);
+ v->tail[0] = '\0';
v->hh.sqlite = 0;
v->hh.haveutf = h->haveutf;
v->hh.ver = h->ver;
v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
v->hh.row1 = 1;
@@ -3366,16 +3643,26 @@
v->hh.vms = 0;
v->hh.env = 0;
vv.j = 0;
vv.l = (jobject) v;
(*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j);
+ }
+ npar = sqlite3_bind_parameter_count((sqlite3_stmt *) svm);
+ for (i = 0; i < nargs && i < npar; i++) {
+ if (cargv[i]) {
+ sqlite3_bind_text((sqlite3_stmt *) svm, i + 1, cargv[i],
+ -1, SQLITE_TRANSIENT);
+ } else {
+ sqlite3_bind_null((sqlite3_stmt *) svm, i + 1);
+ }
}
for (i = 0; i < nargs; i++) {
if (argv[i].obj) {
transfree(&argv[i].trans);
}
}
+ freep(&qsql);
freep((char **) &cargv);
transfree(&sqlstr);
(*env)->ReleaseStringUTFChars(env, sql, str);
if (exc) {
(*env)->DeleteLocalRef(env, exc);
@@ -4556,20 +4843,23 @@
}
JNIEXPORT void
JNICALL Java_SQLite_Database__1key(JNIEnv *env, jobject obj, jbyteArray key)
{
- jsize len;
- jbyte *data;
+ jsize len = 0;
+ jbyte *data = 0;
#if HAVE_SQLITE3_KEY
handle *h = gethandle(env, obj);
#endif
- len = (*env)->GetArrayLength(env, key);
- data = (*env)->GetByteArrayElements(env, key, 0);
- if (len == 0) {
- data = 0;
+ if (key) {
+ len = (*env)->GetArrayLength(env, key);
+ data = (*env)->GetByteArrayElements(env, key, 0);
+ if (len == 0) {
+ (*env)->ReleaseByteArrayElements(env, key, data, 0);
+ data = 0;
+ }
}
if (!data) {
len = 0;
}
#if HAVE_SQLITE3_KEY
@@ -4583,38 +4873,44 @@
}
#endif
sqlite3_key((sqlite3 *) h->sqlite, data, len);
if (data) {
memset(data, 0, len);
+ (*env)->ReleaseByteArrayElements(env, key, data, 0);
}
} else {
if (data) {
memset(data, 0, len);
+ (*env)->ReleaseByteArrayElements(env, key, data, 0);
}
throwclosed(env);
}
#else
if (data) {
memset(data, 0, len);
+ (*env)->ReleaseByteArrayElements(env, key, data, 0);
}
/* no error */
#endif
}
JNIEXPORT void JNICALL
Java_SQLite_Database__1rekey(JNIEnv *env, jobject obj, jbyteArray key)
{
- jsize len;
- jbyte *data;
+ jsize len = 0;
+ jbyte *data = 0;
#if HAVE_SQLITE3_KEY
handle *h = gethandle(env, obj);
#endif
- len = (*env)->GetArrayLength(env, key);
- data = (*env)->GetByteArrayElements(env, key, 0);
- if (len == 0) {
- data = 0;
+ if (key) {
+ len = (*env)->GetArrayLength(env, key);
+ data = (*env)->GetByteArrayElements(env, key, 0);
+ if (len == 0) {
+ (*env)->ReleaseByteArrayElements(env, key, data, 0);
+ data = 0;
+ }
}
if (!data) {
len = 0;
}
#if HAVE_SQLITE3_KEY
@@ -4628,20 +4924,23 @@
}
#endif
sqlite3_rekey((sqlite3 *) h->sqlite, data, len);
if (data) {
memset(data, 0, len);
+ (*env)->ReleaseByteArrayElements(env, key, data, 0);
}
} else {
if (data) {
memset(data, 0, len);
+ (*env)->ReleaseByteArrayElements(env, key, data, 0);
}
throwclosed(env);
}
#else
if (data) {
memset(data, 0, len);
+ (*env)->ReleaseByteArrayElements(env, key, data, 0);
}
throwex(env, "unsupported");
#endif
}
@@ -4743,15 +5042,19 @@
JNIEXPORT void JNICALL
Java_SQLite_Backup__1finalize(JNIEnv *env, jobject obj)
{
#if HAVE_SQLITE3 && HAVE_SQLITE3_BACKUPAPI
- hbk *bk = gethbk(env, obj);
+ hbk *bk = getclrhbk(env, obj);
int ret = SQLITE_OK;
char *err = 0;
if (bk) {
+ if ((*env)->MonitorEnter(env, C_SQLite_Database) != JNI_OK) {
+ fprintf(stderr, "SQLite.Backup.finalize: MonitorEnter failed\n");
+ return;
+ }
if (bk->h) {
handle *h = bk->h;
hbk *bkc, **bkp;
bkp = &h->backups;
@@ -4763,19 +5066,19 @@
}
bkp = &bkc->next;
bkc = *bkp;
}
}
+ (*env)->MonitorExit(env, C_SQLite_Database);
if (bk->bkup) {
ret = sqlite3_backup_finish(bk->bkup);
if (ret != SQLITE_OK && bk->h) {
err = (char *) sqlite3_errmsg((sqlite3 *) bk->h->sqlite);
}
}
bk->bkup = 0;
free(bk);
- (*env)->SetLongField(env, obj, F_SQLite_Backup_handle, 0);
if (ret != SQLITE_OK) {
throwex(env, err ? err : "unknown error");
}
}
#endif
@@ -5027,11 +5330,11 @@
#if !defined(DONT_USE_JNI_ONLOAD) && defined(JNI_VERSION_1_2)
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv *env;
- jclass cls;
+ jclass cls1, cls2;
#ifndef _WIN32
#if HAVE_SQLITE2
if (strcmp(sqlite_libencoding(), "UTF-8") != 0) {
fprintf(stderr, "WARNING: using non-UTF SQLite2 engine\n");
@@ -5039,15 +5342,20 @@
#endif
#endif
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) {
return JNI_ERR;
}
- cls = (*env)->FindClass(env, "java/lang/String");
- if (!cls) {
+ cls1 = (*env)->FindClass(env, "java/lang/String");
+ if (!cls1) {
+ return JNI_ERR;
+ }
+ cls2 = (*env)->FindClass(env, "SQLite/Database");
+ if (!cls2) {
return JNI_ERR;
}
- C_java_lang_String = (*env)->NewGlobalRef(env, cls);
+ C_java_lang_String = (*env)->NewGlobalRef(env, cls1);
+ C_SQLite_Database = (*env)->NewGlobalRef(env, cls2);
return JNI_VERSION_1_2;
}
JNIEXPORT void JNICALL
JNI_OnUnload(JavaVM *vm, void *reserved)
@@ -5054,12 +5362,16 @@
{
JNIEnv *env;
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) {
return;
+ }
+ if (C_SQLite_Database) {
+ (*env)->DeleteGlobalRef(env, C_SQLite_Database);
+ C_SQLite_Database = 0;
}
if (C_java_lang_String) {
(*env)->DeleteGlobalRef(env, C_java_lang_String);
C_java_lang_String = 0;
}
}
#endif
ADDED test3.java
Index: test3.java
==================================================================
--- /dev/null
+++ test3.java
@@ -0,0 +1,253 @@
+import SQLite.*;
+import java.io.*;
+
+public class test3 implements SQLite.Trace, SQLite.Profile {
+
+ public void trace(String stmt) {
+ System.out.println("TRACE: " + stmt);
+ }
+
+ public void profile(String stmt, long est) {
+ System.out.println("PROFILE(" + est + "): " + stmt);
+ }
+
+ SQLite.Stmt prep_ins(SQLite.Database db, String sql)
+ throws SQLite.Exception {
+ return db.prepare(sql);
+ }
+
+ void do_ins(SQLite.Stmt stmt) throws SQLite.Exception {
+ stmt.reset();
+ while (stmt.step()) {
+ }
+ }
+
+ void do_ins(SQLite.Stmt stmt, int i, double d, String t, byte[] b)
+ throws SQLite.Exception {
+ stmt.reset();
+ stmt.bind(1, i);
+ stmt.bind(2, d);
+ stmt.bind(3, t);
+ stmt.bind(4, b);
+ while (stmt.step()) {
+ }
+ }
+
+ void do_exec(SQLite.Database db, String sql) throws SQLite.Exception {
+ SQLite.Stmt stmt = db.prepare(sql);
+ while (stmt.step()) {
+ }
+ stmt.close();
+ }
+
+ void do_select(SQLite.Database db, String sql) throws SQLite.Exception {
+ SQLite.Stmt stmt = db.prepare(sql);
+ int row = 0;
+ while (stmt.step()) {
+ int i, ncol = stmt.column_count();
+ System.out.println("=== ROW " + row + "===");
+ for (i = 0; i < ncol; i++) {
+ try {
+ System.out.print(stmt.column_database_name(i) + "." +
+ stmt.column_table_name(i) + "." +
+ stmt.column_origin_name(i) + "<" +
+ stmt.column_decltype(i) + ">=");
+ } catch (SQLite.Exception se) {
+ System.out.print("COLUMN#" + i + "<" +
+ stmt.column_decltype(i) + ">=");
+ }
+ Object obj = stmt.column(i);
+ if (obj == null) {
+ System.out.println("null");
+ } else if (obj instanceof byte[]) {
+ byte[] b = (byte[]) obj;
+ String sep = "";
+ System.out.print("{");
+ for (i = 0; i < b.length; i++) {
+ System.out.print(sep + b[i]);
+ sep = ",";
+ }
+ System.out.print("}");
+ } else {
+ System.out.print(obj.toString());
+ }
+ if (obj != null) {
+ System.out.println("<" + obj.getClass().getName() + ">");
+ }
+ }
+ row++;
+ }
+ stmt.close();
+ }
+
+ public static void main(String args[]) {
+ boolean error = true;
+ test3 T = new test3();
+ System.out.println("LIB version: " + SQLite.Database.version());
+ SQLite.Database db = new SQLite.Database();
+ try {
+ byte[] b;
+ db.open("db3", 0666);
+ System.out.println("DB version: " + db.dbversion());
+ db.busy_timeout(1000);
+ db.busy_handler(null);
+ db.trace(T);
+ db.profile(T);
+ T.do_exec(db, "create table TEST3("+
+ "i integer, d double, t text, b blob)");
+ T.do_exec(db, "create table B(" +
+ "id integer primary key, val blob)");
+ T.do_select(db, "select * from sqlite_master");
+ Stmt ins = T.prep_ins(db, "insert into TEST3(i,d,t,b)" +
+ " VALUES(:one,:two,:three,:four)");
+ System.out.println("INFO: " + ins.bind_parameter_count() +
+ " parameters");
+ for (int i = 1; i <= ins.bind_parameter_count(); i++) {
+ String name = ins.bind_parameter_name(i);
+ if (name != null) {
+ System.out.println("INFO: name for " + i + " is " + name);
+ System.out.println("INFO: index of " + name + " is " +
+ ins.bind_parameter_index(name));
+ }
+ }
+ b = new byte[4];
+ b[0] = 1; b[1] = 1; b[2] = 2; b[3] = 3;
+ T.do_ins(ins, 1, 2.4, "two point four", b);
+ T.do_ins(ins);
+ b[0] = -1; b[1] = -2; b[2] = -3; b[3] = -4;
+ T.do_ins(ins, 2, 4.8, "four point eight", b);
+ T.do_ins(ins);
+ T.do_ins(ins, 3, -3.333, null, null);
+ ins.close();
+ T.do_select(db, "select * from TEST3");
+ T.do_exec(db, "insert into B values(NULL, zeroblob(128))");
+ T.do_exec(db, "insert into B values(NULL, zeroblob(128))");
+ T.do_exec(db, "insert into B values(NULL, zeroblob(128))");
+ T.do_select(db, "select id from B");
+ byte[] b128 = new byte[128];
+ for (int i = 0; i < b128.length; i++) {
+ b128[i] = (byte) i;
+ }
+ Blob blob = db.open_blob("main", "B", "val", 1, true);
+ OutputStream os = blob.getOutputStream();
+ os.write(b128);
+ os.close();
+ blob.close();
+ blob = db.open_blob("main", "B", "val", 3, true);
+ os = blob.getOutputStream();
+ os.write(b128);
+ os.close();
+ blob.close();
+ T.do_select(db, "select * from B");
+ blob = db.open_blob("main", "B", "val", 1, false);
+ InputStream is = blob.getInputStream();
+ is.skip(96);
+ is.read(b);
+ is.close();
+ blob.close();
+ System.out.println("INFO: expecting {96,97,98,99} got {" +
+ b[0] + "," + b[1] + "," +
+ b[2] + "," + b[3] + "}");
+ System.out.println("INFO: backup begin");
+ try {
+ SQLite.Database dbdest = new SQLite.Database();
+ dbdest.open("db3-backup", 0666);
+ dbdest.busy_timeout(1000);
+ dbdest.busy_handler(null);
+ Backup backup = db.backup(dbdest, "main", "main");
+ while (!backup.step(1)) {
+ System.out.println("INFO: backup step: "
+ + backup.remaining() + "/"
+ + backup.pagecount());
+ }
+ b = null;
+ System.out.println("INFO: backup end");
+ } catch (java.lang.Exception ee) {
+ System.err.println("error: " + ee);
+ }
+ int info[] = new int[2];
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_MALLOC_COUNT, info, false);
+ System.out.println("INFO: status(STATUS_MALLOC_COUNT) = "
+ + info[0] + "/" + info[1]);
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_MALLOC_SIZE, info, false);
+ System.out.println("INFO: status(STATUS_MALLOC_SIZE) = "
+ + info[0] + "/" + info[1]);
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_MEMORY_USED, info, false);
+ System.out.println("INFO: status(STATUS_MEMORY_USED) = "
+ + info[0] + "/" + info[1]);
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_PAGECACHE_OVERFLOW, info, false);
+ System.out.println("INFO: status(STATUS_PAGECACHE_OVERFLOW) = "
+ + info[0] + "/" + info[1]);
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_PAGECACHE_SIZE, info, false);
+ System.out.println("INFO: status(STATUS_PAGECACHE_SIZE) = "
+ + info[0] + "/" + info[1]);
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_PAGECACHE_USED, info, false);
+ System.out.println("INFO: status(STATUS_PAGECACHE_USED) = "
+ + info[0] + "/" + info[1]);
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_PARSER_STACK, info, false);
+ System.out.println("INFO: status(STATUS_PARSER_STACK) = "
+ + info[0] + "/" + info[1]);
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_SCRATCH_OVERFLOW, info, false);
+ System.out.println("INFO: status(STATUS_SCRATCH_OVERFLOW) = "
+ + info[0] + "/" + info[1]);
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_SCRATCH_SIZE, info, false);
+ System.out.println("INFO: status(STATUS_SCRATCH_SIZE) = "
+ + info[0] + "/" + info[1]);
+ SQLite.Database.status(SQLite.Constants.SQLITE_STATUS_SCRATCH_USED, info, false);
+ System.out.println("INFO: status(STATUS_SCRATCH_USED) = "
+ + info[0] + "/" + info[1]);
+ db.db_status(SQLite.Constants.SQLITE_DBSTATUS_CACHE_HIT, info, false);
+ System.out.println("INFO: db_status(DBSTATUS_CACHE_HIT) = "
+ + info[0] + "/" + info[1]);
+ db.db_status(SQLite.Constants.SQLITE_DBSTATUS_CACHE_MISS, info, false);
+ System.out.println("INFO: db_status(DBSTATUS_CACHE_MISS) = "
+ + info[0] + "/" + info[1]);
+ db.db_status(SQLite.Constants.SQLITE_DBSTATUS_CACHE_USED, info, false);
+ System.out.println("INFO: db_status(DBSTATUS_CACHE_USED) = "
+ + info[0] + "/" + info[1]);
+ db.db_status(SQLite.Constants.SQLITE_DBSTATUS_LOOKASIDE_HIT, info, false);
+ System.out.println("INFO: db_status(DBSTATUS_LOOKASIZE_HIT) = "
+ + info[0] + "/" + info[1]);
+ db.db_status(SQLite.Constants.SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, info, false);
+ System.out.println("INFO: db_status(DBSTATUS_LOOKASIZE_MISS_FULL) = "
+ + info[0] + "/" + info[1]);
+ db.db_status(SQLite.Constants.SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, info, false);
+ System.out.println("INFO: db_status(DBSTATUS_LOOKASIZE_MISS_SIZE) = "
+ + info[0] + "/" + info[1]);
+ db.db_status(SQLite.Constants.SQLITE_DBSTATUS_LOOKASIDE_USED, info, false);
+ System.out.println("INFO: db_status(DBSTATUS_LOOKASIZE_USED) = "
+ + info[0] + "/" + info[1]);
+ db.db_status(SQLite.Constants.SQLITE_DBSTATUS_SCHEMA_USED, info, false);
+ System.out.println("INFO: db_status(DBSTATUS_SCHEMA_USED) = "
+ + info[0] + "/" + info[1]);
+ db.db_status(SQLite.Constants.SQLITE_DBSTATUS_STMT_USED, info, false);
+ System.out.println("INFO: db_status(DBSTATUS_STMT_USED) = "
+ + info[0] + "/" + info[1]);
+ T.do_exec(db, "drop table TEST3");
+ T.do_exec(db, "drop table B");
+ T.do_select(db, "select * from sqlite_master");
+ error = false;
+ } catch (java.lang.Exception e) {
+ System.err.println("error: " + e);
+ e.printStackTrace();
+ } finally {
+ try {
+ System.err.println("cleaning up ...");
+ try {
+ T.do_exec(db, "drop table TEST3");
+ T.do_exec(db, "drop table B");
+ } catch(SQLite.Exception e) {
+ }
+ db.close();
+ } catch(java.lang.Exception e) {
+ System.err.println("error: " + e);
+ error = true;
+ } finally {
+ System.err.println("done.");
+ }
+ }
+ if (error) {
+ System.exit(1);
+ }
+ }
+}
ADDED testg.java
Index: testg.java
==================================================================
--- /dev/null
+++ testg.java
@@ -0,0 +1,26 @@
+import SQLite.Constants;
+import SQLite.Database;
+import SQLite.Exception;
+import SQLite.Stmt;
+
+public class testg {
+ public static void main(String[] args) throws Exception {
+ Database db = new Database();
+ db.open(":memory:", Constants.SQLITE_OPEN_READWRITE);
+ Stmt createTable = db.prepare("CREATE TABLE test (col1)");
+ createTable.step();
+ createTable.close();
+ Stmt beginTx = db.prepare("BEGIN TRANSACTION");
+ beginTx.step();
+ beginTx.close();
+ for (int i = 0; i < 1000000; i++) {
+ Stmt insert = db.prepare("INSERT INTO test VALUES ('whatever')");
+ insert.step();
+ insert.close();
+ }
+ Stmt commitTx = db.prepare("COMMIT TRANSACTION");
+ commitTx.step();
+ commitTx.close();
+ db.close();
+ }
+}