aboutsummaryrefslogtreecommitdiff
path: root/ext/jni/src
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2023-11-15 04:55:38 +0000
committerstephan <stephan@noemail.net>2023-11-15 04:55:38 +0000
commitd7ef0e8f87fd5dcff55f14a95a3d3dc9a59c1d9c (patch)
tree79c13a05de1d24d3481b13bfb5844f23b1e9aeac /ext/jni/src
parent253727b33d78443e53f4b6f3ec5ffa7d879e082a (diff)
downloadsqlite-d7ef0e8f87fd5dcff55f14a95a3d3dc9a59c1d9c.tar.gz
sqlite-d7ef0e8f87fd5dcff55f14a95a3d3dc9a59c1d9c.zip
JNI: add CONFIG_LOG and CONFIG_SQLLOG support to wrapper1. Code-adjacent cleanups.
FossilOrigin-Name: 83c49b9e71e5ae8852bab60a6fa630e22164c8efbf074c85450136781d0fffd3
Diffstat (limited to 'ext/jni/src')
-rw-r--r--ext/jni/src/c/sqlite3-jni.h2
-rw-r--r--ext/jni/src/org/sqlite/jni/capi/CApi.java6
-rw-r--r--ext/jni/src/org/sqlite/jni/capi/ConfigSqlLogCallback.java (renamed from ext/jni/src/org/sqlite/jni/capi/ConfigSqllogCallback.java)4
-rw-r--r--ext/jni/src/org/sqlite/jni/capi/Tester1.java4
-rw-r--r--ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java114
-rw-r--r--ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java64
6 files changed, 135 insertions, 59 deletions
diff --git a/ext/jni/src/c/sqlite3-jni.h b/ext/jni/src/c/sqlite3-jni.h
index f691197f8..082a20212 100644
--- a/ext/jni/src/c/sqlite3-jni.h
+++ b/ext/jni/src/c/sqlite3-jni.h
@@ -1300,7 +1300,7 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config_1_1CONFIG_1
/*
* Class: org_sqlite_jni_capi_CApi
* Method: sqlite3_config__SQLLOG
- * Signature: (Lorg/sqlite/jni/capi/ConfigSqllogCallback;)I
+ * Signature: (Lorg/sqlite/jni/capi/ConfigSqlLogCallback;)I
*/
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config_1_1SQLLOG
(JNIEnv *, jclass, jobject);
diff --git a/ext/jni/src/org/sqlite/jni/capi/CApi.java b/ext/jni/src/org/sqlite/jni/capi/CApi.java
index 59d025b96..9f1daa4a2 100644
--- a/ext/jni/src/org/sqlite/jni/capi/CApi.java
+++ b/ext/jni/src/org/sqlite/jni/capi/CApi.java
@@ -1052,10 +1052,10 @@ public final class CApi {
);
/**
- Internal level of indirection for sqlite3_config(ConfigSqllogCallback).
+ Internal level of indirection for sqlite3_config(ConfigSqlLogCallback).
*/
private static native int sqlite3_config__SQLLOG(
- @Nullable ConfigSqllogCallback logger
+ @Nullable ConfigSqlLogCallback logger
);
/**
@@ -1091,7 +1091,7 @@ public final class CApi {
the rest of the library. This must not be called when any other
library APIs are being called.
*/
- public static int sqlite3_config( @Nullable ConfigSqllogCallback logger ){
+ public static int sqlite3_config( @Nullable ConfigSqlLogCallback logger ){
return sqlite3_config__SQLLOG(logger);
}
diff --git a/ext/jni/src/org/sqlite/jni/capi/ConfigSqllogCallback.java b/ext/jni/src/org/sqlite/jni/capi/ConfigSqlLogCallback.java
index df753e651..a5530b49a 100644
--- a/ext/jni/src/org/sqlite/jni/capi/ConfigSqllogCallback.java
+++ b/ext/jni/src/org/sqlite/jni/capi/ConfigSqlLogCallback.java
@@ -16,10 +16,10 @@ package org.sqlite.jni.capi;
/**
A callback for use with sqlite3_config().
*/
-public interface ConfigSqllogCallback {
+public interface ConfigSqlLogCallback {
/**
Must function as described for a C-level callback for
- {@link CApi#sqlite3_config(ConfigSqllogCallback)}, with the slight signature change.
+ {@link CApi#sqlite3_config(ConfigSqlLogCallback)}, with the slight signature change.
*/
void call(sqlite3 db, String msg, int msgType );
}
diff --git a/ext/jni/src/org/sqlite/jni/capi/Tester1.java b/ext/jni/src/org/sqlite/jni/capi/Tester1.java
index 3ff93a9ce..d21d75e3b 100644
--- a/ext/jni/src/org/sqlite/jni/capi/Tester1.java
+++ b/ext/jni/src/org/sqlite/jni/capi/Tester1.java
@@ -2007,7 +2007,7 @@ public class Tester1 implements Runnable {
if( sqlLog ){
if( sqlite3_compileoption_used("ENABLE_SQLLOG") ){
- final ConfigSqllogCallback log = new ConfigSqllogCallback() {
+ final ConfigSqlLogCallback log = new ConfigSqlLogCallback() {
@Override public void call(sqlite3 db, String msg, int op){
switch(op){
case 0: outln("Opening db: ",db); break;
@@ -2018,7 +2018,7 @@ public class Tester1 implements Runnable {
};
int rc = sqlite3_config( log );
affirm( 0==rc );
- rc = sqlite3_config( (ConfigSqllogCallback)null );
+ rc = sqlite3_config( (ConfigSqlLogCallback)null );
affirm( 0==rc );
rc = sqlite3_config( log );
affirm( 0==rc );
diff --git a/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java b/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java
index 0b18676b4..5dbf79466 100644
--- a/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java
+++ b/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java
@@ -209,6 +209,10 @@ public final class Sqlite implements AutoCloseable {
public static final int DBCONFIG_STMT_SCANSTATUS = CApi.SQLITE_DBCONFIG_STMT_SCANSTATUS;
public static final int DBCONFIG_REVERSE_SCANORDER = CApi.SQLITE_DBCONFIG_REVERSE_SCANORDER;
+ public static final int CONFIG_SINGLETHREAD = CApi.SQLITE_CONFIG_SINGLETHREAD;
+ public static final int CONFIG_MULTITHREAD = CApi.SQLITE_CONFIG_MULTITHREAD;
+ public static final int CONFIG_SERIALIZED = CApi.SQLITE_CONFIG_SERIALIZED;
+
public static final int UTF8 = CApi.SQLITE_UTF8;
public static final int UTF16 = CApi.SQLITE_UTF16;
public static final int UTF16LE = CApi.SQLITE_UTF16LE;
@@ -261,6 +265,32 @@ public final class Sqlite implements AutoCloseable {
private static final java.util.Map<org.sqlite.jni.capi.sqlite3, Sqlite> nativeToWrapper
= new java.util.HashMap<>();
+
+ /**
+ When any given thread is done using the SQLite library, calling
+ this will free up any native-side resources which may be
+ associated specifically with that thread. This is not strictly
+ necessary, in particular in applications which only use SQLite
+ from a single thread, but may help free some otherwise errant
+ resources.
+
+ Calling into SQLite from a given thread after this has been
+ called in that thread is harmless. The library will simply start
+ to re-cache certain state for that thread.
+
+ Contrariwise, failing to call this will effectively leak a small
+ amount of cached state for the thread, which may add up to
+ significant amounts if the application uses SQLite from many
+ threads.
+
+ This must never be called while actively using SQLite from this
+ thread, e.g. from within a query loop or a callback which is
+ operating on behalf of the library.
+ */
+ static void uncacheThread(){
+ CApi.sqlite3_java_uncache_thread();
+ }
+
/**
Returns the Sqlite object associated with the given sqlite3
object, or null if there is no such mapping.
@@ -342,6 +372,9 @@ public final class Sqlite implements AutoCloseable {
private static boolean hasNormalizeSql =
compileOptionUsed("ENABLE_NORMALIZE");
+ private static boolean hasSqlLog =
+ compileOptionUsed("ENABLE_SQLLOG");
+
/**
Throws UnsupportedOperationException if check is false.
flag is expected to be the name of an SQLITE_ENABLE_...
@@ -410,7 +443,7 @@ public final class Sqlite implements AutoCloseable {
new org.sqlite.jni.capi.OutputPointer.Int64();
org.sqlite.jni.capi.OutputPointer.Int64 pHighwater =
new org.sqlite.jni.capi.OutputPointer.Int64();
- checkRc2( CApi.sqlite3_status64(op, pCurrent, pHighwater, resetStats) );
+ checkRcStatic( CApi.sqlite3_status64(op, pCurrent, pHighwater, resetStats) );
final Status s = new Status();
s.current = pCurrent.value;
s.peak = pHighwater.value;
@@ -489,7 +522,7 @@ public final class Sqlite implements AutoCloseable {
Like checkRc() but behaves as if that function were
called with a null db object.
*/
- private static void checkRc2(int rc){
+ private static void checkRcStatic(int rc){
if( 0!=rc ){
if( CApi.SQLITE_NOMEM==rc ){
throw new OutOfMemoryError();
@@ -1859,4 +1892,81 @@ public final class Sqlite implements AutoCloseable {
return new Blob(this, out.take());
}
+ /**
+ Callback for use with libConfigLog().
+ */
+ public interface ConfigLog {
+ /**
+ Must function as described for a C-level callback for
+ sqlite3_config()'s SQLITE_CONFIG_LOG callback, with the slight
+ signature change. Any exceptions thrown from this callback are
+ necessarily suppressed.
+ */
+ void call(int errCode, String msg);
+ }
+
+ /**
+ Analog to sqlite3_config() with the SQLITE_CONFIG_LOG option,
+ this sets or (if log is null) clears the current logger.
+ */
+ public static void libConfigLog(ConfigLog log){
+ final org.sqlite.jni.capi.ConfigLogCallback l =
+ null==log
+ ? null
+ : new org.sqlite.jni.capi.ConfigLogCallback() {
+ @Override public void call(int errCode, String msg){
+ log.call(errCode, msg);
+ }
+ };
+ checkRcStatic(CApi.sqlite3_config(l));
+ }
+
+ /**
+ Callback for use with libConfigSqlLog().
+ */
+ public interface ConfigSqlLog {
+ /**
+ Must function as described for a C-level callback for
+ sqlite3_config()'s SQLITE_CONFIG_SQLLOG callback, with the
+ slight signature change. Any exceptions thrown from this
+ callback are necessarily suppressed.
+ */
+ void call(Sqlite db, String msg, int msgType);
+ }
+
+ /**
+ Analog to sqlite3_config() with the SQLITE_CONFIG_SQLLOG option,
+ this sets or (if log is null) clears the current logger.
+
+ If SQLite is built without SQLITE_ENABLE_SQLLOG defined then this
+ will throw an UnsupportedOperationException.
+ */
+ public static void libConfigSqlLog(ConfigSqlLog log){
+ Sqlite.checkSupported(hasNormalizeSql, "SQLITE_ENABLE_SQLLOG");
+ final org.sqlite.jni.capi.ConfigSqlLogCallback l =
+ null==log
+ ? null
+ : new org.sqlite.jni.capi.ConfigSqlLogCallback() {
+ @Override public void call(sqlite3 db, String msg, int msgType){
+ try{
+ log.call(fromNative(db), msg, msgType);
+ }catch(Exception e){
+ /* Suppressed */
+ }
+ }
+ };
+ checkRcStatic(CApi.sqlite3_config(l));
+ }
+
+ /**
+ Analog to the C-level sqlite3_config() with one of the
+ SQLITE_CONFIG_... constants defined as CONFIG_... in this
+ class. Throws on error, including passing of an unknown option or
+ if a specified option is not supported by the underlying build of
+ the SQLite library.
+ */
+ public static void libConfigOp( int op ){
+ checkRcStatic(CApi.sqlite3_config(op));
+ }
+
}
diff --git a/ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java b/ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java
index e6b665fcc..681712f96 100644
--- a/ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java
+++ b/ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java
@@ -762,9 +762,9 @@ public class Tester2 implements Runnable {
affirm( newHook == oldHook );
execSql(db, "BEGIN; update t set a='i' where a='h'; COMMIT;");
affirm( 5 == counter.value );
- hookResult.value = CApi.SQLITE_ERROR;
+ hookResult.value = Sqlite.ERROR;
int rc = execSql(db, false, "BEGIN; update t set a='j' where a='i'; COMMIT;");
- affirm( CApi.SQLITE_CONSTRAINT_COMMITHOOK == rc );
+ affirm( Sqlite.CONSTRAINT_COMMITHOOK == rc );
affirm( 6 == counter.value );
db.close();
}
@@ -994,8 +994,7 @@ public class Tester2 implements Runnable {
listErrors.add(e);
}
}finally{
- affirm( CApi.sqlite3_java_uncache_thread() );
- affirm( !CApi.sqlite3_java_uncache_thread() );
+ Sqlite.uncacheThread();
}
}
@@ -1068,38 +1067,28 @@ public class Tester2 implements Runnable {
if( sqlLog ){
if( Sqlite.compileOptionUsed("ENABLE_SQLLOG") ){
- final ConfigSqllogCallback log = new ConfigSqllogCallback() {
- @Override public void call(sqlite3 db, String msg, int op){
+ Sqlite.libConfigSqlLog( new Sqlite.ConfigSqlLog() {
+ @Override public void call(Sqlite db, String msg, int op){
switch(op){
case 0: outln("Opening db: ",db); break;
case 1: outln("SQL ",db,": ",msg); break;
case 2: outln("Closing db: ",db); break;
}
}
- };
- int rc = CApi.sqlite3_config( log );
- affirm( 0==rc );
- rc = CApi.sqlite3_config( (ConfigSqllogCallback)null );
- affirm( 0==rc );
- rc = CApi.sqlite3_config( log );
- affirm( 0==rc );
+ }
+ );
}else{
outln("WARNING: -sqllog is not active because library was built ",
"without SQLITE_ENABLE_SQLLOG.");
}
}
if( configLog ){
- final ConfigLogCallback log = new ConfigLogCallback() {
+ Sqlite.libConfigLog( new Sqlite.ConfigLog() {
@Override public void call(int code, String msg){
- outln("ConfigLogCallback: ",ResultCode.getEntryForInt(code),": ", msg);
+ outln("ConfigLog: ",Sqlite.errstr(code),": ", msg);
};
- };
- int rc = CApi.sqlite3_config( log );
- affirm( 0==rc );
- rc = CApi.sqlite3_config( (ConfigLogCallback)null );
- affirm( 0==rc );
- rc = CApi.sqlite3_config( log );
- affirm( 0==rc );
+ }
+ );
}
quietMode = squelchTestOutput;
@@ -1132,39 +1121,16 @@ public class Tester2 implements Runnable {
}
final long timeStart = System.currentTimeMillis();
- int nLoop = 0;
- switch( CApi.sqlite3_threadsafe() ){ /* Sanity checking */
- case 0:
- affirm( CApi.SQLITE_ERROR==CApi.sqlite3_config( CApi.SQLITE_CONFIG_SINGLETHREAD ),
- "Could not switch to single-thread mode." );
- affirm( CApi.SQLITE_ERROR==CApi.sqlite3_config( CApi.SQLITE_CONFIG_MULTITHREAD ),
- "Could switch to multithread mode." );
- affirm( CApi.SQLITE_ERROR==CApi.sqlite3_config( CApi.SQLITE_CONFIG_SERIALIZED ),
- "Could not switch to serialized threading mode." );
- outln("This is a single-threaded build. Not using threads.");
- nThread = 1;
- break;
- case 1:
- case 2:
- affirm( 0==CApi.sqlite3_config( CApi.SQLITE_CONFIG_SINGLETHREAD ),
- "Could not switch to single-thread mode." );
- affirm( 0==CApi.sqlite3_config( CApi.SQLITE_CONFIG_MULTITHREAD ),
- "Could not switch to multithread mode." );
- affirm( 0==CApi.sqlite3_config( CApi.SQLITE_CONFIG_SERIALIZED ),
- "Could not switch to serialized threading mode." );
- break;
- default:
- affirm( false, "Unhandled SQLITE_THREADSAFE value." );
- }
outln("libversion_number: ",
- CApi.sqlite3_libversion_number(),"\n",
- CApi.sqlite3_libversion(),"\n",CApi.SQLITE_SOURCE_ID,"\n",
+ Sqlite.libVersionNumber(),"\n",
+ Sqlite.libVersion(),"\n",Sqlite.libSourceId(),"\n",
"SQLITE_THREADSAFE=",CApi.sqlite3_threadsafe());
final boolean showLoopCount = (nRepeat>1 && nThread>1);
if( showLoopCount ){
outln("Running ",nRepeat," loop(s) with ",nThread," thread(s) each.");
}
if( takeNaps ) outln("Napping between tests is enabled.");
+ int nLoop = 0;
for( int n = 0; n < nRepeat; ++n ){
++nLoop;
if( showLoopCount ) out((1==nLoop ? "" : " ")+nLoop);
@@ -1206,7 +1172,7 @@ public class Tester2 implements Runnable {
if( doSomethingForDev ){
CApi.sqlite3_jni_internal_details();
}
- affirm( 0==CApi.sqlite3_release_memory(1) );
+ affirm( 0==Sqlite.libReleaseMemory(1) );
CApi.sqlite3_shutdown();
int nMethods = 0;
int nNatives = 0;