]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Bind sqlite3_progress_handler() to JNI. Add some metrics to Tester1.java.
authorstephan <stephan@noemail.net>
Sun, 30 Jul 2023 04:31:56 +0000 (04:31 +0000)
committerstephan <stephan@noemail.net>
Sun, 30 Jul 2023 04:31:56 +0000 (04:31 +0000)
FossilOrigin-Name: 437ecfe8abf8d294d429d191d811da6148e0b2ebb74cf66998480bfc8ef58bdf

ext/jni/src/c/sqlite3-jni.c
ext/jni/src/c/sqlite3-jni.h
ext/jni/src/org/sqlite/jni/ProgressHandler.java
ext/jni/src/org/sqlite/jni/SQLite3Jni.java
ext/jni/src/org/sqlite/jni/Tester1.java
manifest
manifest.uuid

index 25739904d58ef77930973aea4c32ab6d7ea58187..72cfaf209eaf0b66f0214662ea037dbf990c582b 100644 (file)
@@ -433,11 +433,11 @@ static void s3jni_free(void * p){
 */
 static int s3jni_db_error(sqlite3*db, int err_code, const char *zMsg){
   if( db!=0 ){
-    if( 0!=zMsg ){
+    if( 0==zMsg ){
+      sqlite3Error(db, err_code);
+    }else{
       const int nMsg = sqlite3Strlen30(zMsg);
       sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg);
-    }else{
-      sqlite3ErrorWithMsg(db, err_code, NULL);
     }
   }
   return err_code;
@@ -526,7 +526,7 @@ static PerDbStateJni * PerDbStateJni_alloc(JNIEnv *env, sqlite3 *pDb){
    Clears s's state and moves it to the free-list.
 */
 FIXME_THREADING
-static void PerDbStateJni_set_aside(PerDbStateJni *s){
+static void PerDbStateJni_set_aside(PerDbStateJni * const s){
   if(s){
     JNIEnv * const env = s->env;
     assert(s->pDb && "Else this object is already in the free-list.");
@@ -1726,6 +1726,50 @@ JDECL(jint,1prepare_1v3)(JNIEnv *env, jclass self, jobject jpDb, jbyteArray baSq
                                   prepFlags, outStmt, outTail);
 }
 
+
+static int s3jni_progress_handler_impl(void *pP){
+  PerDbStateJni * const ps = (PerDbStateJni *)pP;
+  JNIEnv * const env = ps->env;
+  int rc = (int)(*env)->CallIntMethod(env, ps->progress.jObj,
+                                      ps->progress.midCallback);
+  IFTHREW{
+    EXCEPTION_CLEAR;
+    rc = s3jni_db_error(ps->pDb, SQLITE_ERROR,
+                        "sqlite3_progress_handler() callback threw.");
+  }
+  return rc;
+}
+
+JDECL(void,1progress_1handler)(JENV_JSELF,jobject jDb, jint n, jobject jProgress){
+  sqlite3 * const pDb = PtrGet_sqlite3(jDb);
+  PerDbStateJni * ps = PerDbStateJni_for_db(env, pDb, 1);
+  jclass klazz;
+  if( n<1 || !jProgress ){
+    if(ps){
+      UNREF_G(ps->progress.jObj);
+      memset(&ps->progress, 0, sizeof(ps->progress));
+    }
+    sqlite3_progress_handler(pDb, 0, 0, 0);
+    return;
+  }
+  if(!ps){
+    s3jni_db_error(pDb, SQLITE_NOMEM, 0);
+    return;
+  }
+  klazz = (*env)->GetObjectClass(env, jProgress);
+  ps->progress.midCallback = (*env)->GetMethodID(env, klazz, "xCallback", "()I");
+  IFTHREW {
+    EXCEPTION_CLEAR;
+    s3jni_db_error(pDb, SQLITE_ERROR,
+                   "Cannot not find matching xCallback() on "
+                   "ProgressHandler object.");
+  }else{
+    ps->progress.jObj = REF_G(jProgress);
+    sqlite3_progress_handler(pDb, (int)n, s3jni_progress_handler_impl, ps);
+  }
+}
+
+
 /* sqlite3_result_text/blob() and friends. */
 static void result_blob_text(int asBlob, int as64,
                              int eTextRep/*only for (asBlob=0)*/,
@@ -1945,30 +1989,31 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
   UNREF_L(jX);
   IFTHREW{
     EXCEPTION_CLEAR;
-    return rc ? rc :
-      s3jni_db_error(ps->pDb, SQLITE_ERROR,
-                     "sqlite3_trace_v2() callback threw.");
+    rc = s3jni_db_error(ps->pDb, SQLITE_ERROR,
+                        "sqlite3_trace_v2() callback threw.");
   }
   return rc;
 }
 
 JDECL(jint,1trace_1v2)(JENV_JSELF,jobject jDb, jint traceMask, jobject jTracer){
   sqlite3 * const pDb = PtrGet_sqlite3(jDb);
-  PerDbStateJni * ps;
+  PerDbStateJni * const ps = PerDbStateJni_for_db(env, pDb, 1);
   jclass klazz;
   if( !traceMask || !jTracer ){
+    if(ps){
+      UNREF_G(ps->trace.jObj);
+      memset(&ps->trace, 0, sizeof(ps->trace));
+    }
     return (jint)sqlite3_trace_v2(pDb, 0, 0, 0);
   }
-  ps = PerDbStateJni_for_db(env, pDb, 1);
   if(!ps) return SQLITE_NOMEM;
   klazz = (*env)->GetObjectClass(env, jTracer);
   ps->trace.midCallback = (*env)->GetMethodID(env, klazz, "xCallback",
                                               "(IJLjava/lang/Object;)I");
   IFTHREW {
-    /* Leave ps in place - it might contain other state. */
     EXCEPTION_CLEAR;
     return s3jni_db_error(pDb, SQLITE_ERROR,
-                          "Cannot not find matchin xCallback() on Tracer object.");
+                          "Cannot not find matching xCallback() on Tracer object.");
   }
   ps->trace.jObj = REF_G(jTracer);
   return sqlite3_trace_v2(pDb, (unsigned)traceMask, s3jni_trace_impl, ps);
index 524a9b407549bb0d67b94757a33b4878a2dfc589..739aea7a87d84181c63b9b1e6a8527b41c8b0bf9 100644 (file)
@@ -1195,6 +1195,14 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1prepare_1v2
 JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1prepare_1v3
   (JNIEnv *, jclass, jobject, jbyteArray, jint, jint, jobject, jobject);
 
+/*
+ * Class:     org_sqlite_jni_SQLite3Jni
+ * Method:    sqlite3_progress_handler
+ * Signature: (Lorg/sqlite/jni/sqlite3;ILorg/sqlite/jni/ProgressHandler;)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1progress_1handler
+  (JNIEnv *, jclass, jobject, jint, jobject);
+
 /*
  * Class:     org_sqlite_jni_SQLite3Jni
  * Method:    sqlite3_reset
index b3e8abc0c047a80c498fe5c266ff9aaa2de00a50..8c463fe364dd95a2db3d0bb1d796d1bf172c8eb6 100644 (file)
@@ -18,6 +18,8 @@ package org.sqlite.jni;
 */
 public interface ProgressHandler {
   /**
+     Works as documented for the sqlite3_progress_handler() callback.
+     Must not throw.
   */
   int xCallback();
 }
index eabe1c86097a00fe02dca18270be89a4d5aa8f0d..e3162d7967f6bd989fd8097133d82b123680d9b0 100644 (file)
@@ -394,8 +394,8 @@ public final class SQLite3Jni {
     return sqlite3_prepare_v3(db, utf8, utf8.length, prepFlags, outStmt, null);
   }
 
-
-  //TODO public static native void sqlite3_progress_handler(sqlite3 db, int n, ProgressHandler h);
+  public static native void sqlite3_progress_handler(@NotNull sqlite3 db, int n,
+                                                     @Nullable ProgressHandler h);
 
   public static native int sqlite3_reset(@NotNull sqlite3_stmt stmt);
 
index b2772cc48b0c9dd4042dd022cba37d575cea782e..7cc88154365568a93ba3b265170b53da7a12c945 100644 (file)
@@ -17,6 +17,11 @@ import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 
 public class Tester1 {
+  private static final class Metrics {
+    int dbOpen;
+  }
+
+  static final Metrics metrics = new Metrics();
 
   private static <T> void out(T val){
     System.out.print(val);
@@ -87,9 +92,10 @@ public class Tester1 {
       sqlite3 db = new sqlite3();
       affirm(0 == db.getNativePointer());
       int rc = sqlite3_open(":memory:", db);
+      ++metrics.dbOpen;
       affirm(0 == rc);
       affirm(0 < db.getNativePointer());
-      sqlite3_close(db);
+      sqlite3_close_v2(db);
       affirm(0 == db.getNativePointer());
   }
 
@@ -99,6 +105,7 @@ public class Tester1 {
     int rc = sqlite3_open_v2(":memory:", db,
                              SQLITE_OPEN_READWRITE
                              | SQLITE_OPEN_CREATE, null);
+    ++metrics.dbOpen;
     affirm(0 == rc);
     affirm(0 < db.getNativePointer());
     sqlite3_close_v2(db);
@@ -109,6 +116,7 @@ public class Tester1 {
     sqlite3 db = new sqlite3();
     affirm(0 == db.getNativePointer());
     int rc = sqlite3_open(":memory:", db);
+    ++metrics.dbOpen;
     affirm(0 == rc);
     affirm(0 != db.getNativePointer());
     rc = sqlite3_busy_timeout(db, 2000);
@@ -394,7 +402,7 @@ public class Tester1 {
     affirm(3 == counter);
     sqlite3_finalize(stmt);
     affirm(!xDestroyCalled.value);
-    sqlite3_close(db);
+    sqlite3_close_v2(db);
     affirm(xDestroyCalled.value);
   }
 
@@ -448,7 +456,7 @@ public class Tester1 {
     execSql(db, "SELECT myfunc(1,2,3)");
     affirm(6 == xFuncAccum.value);
     affirm( !xDestroyCalled.value );
-    sqlite3_close(db);
+    sqlite3_close_v2(db);
     affirm( xDestroyCalled.value );
   }
 
@@ -477,7 +485,7 @@ public class Tester1 {
     }
     sqlite3_finalize(stmt);
     affirm( 1 == n );
-    sqlite3_close(db);
+    sqlite3_close_v2(db);
   }
 
   private static void testUdfAggregate(){
@@ -543,7 +551,7 @@ public class Tester1 {
 
     execSql(db, "SELECT myfunc(1) WHERE 0");
     affirm(xFinalNull.value);
-    sqlite3_close(db);
+    sqlite3_close_v2(db);
   }
 
   private static void testUdfWindow(){
@@ -601,7 +609,7 @@ public class Tester1 {
     }
     sqlite3_finalize(stmt);
     affirm( 5 == n );
-    sqlite3_close(db);
+    sqlite3_close_v2(db);
   }
 
   private static void listBoundMethods(){
@@ -664,7 +672,7 @@ public class Tester1 {
       });
     execSql(db, "SELECT 1; SELECT 2");
     affirm( 6 == counter.value );
-    sqlite3_close(db);
+    sqlite3_close_v2(db);
     affirm( 7 == counter.value );
   }
 
@@ -674,9 +682,11 @@ public class Tester1 {
     final sqlite3 db2 = new sqlite3();
 
     int rc = sqlite3_open(dbName, db1);
+    ++metrics.dbOpen;
     affirm( 0 == rc );
     execSql(db1, "CREATE TABLE IF NOT EXISTS t(a)");
     rc = sqlite3_open(dbName, db2);
+    ++metrics.dbOpen;
     affirm( 0 == rc );
 
     final ValueHolder<Boolean> xDestroyed = new ValueHolder<>(false);
@@ -701,9 +711,9 @@ public class Tester1 {
     affirm( SQLITE_BUSY == rc);
     affirm( 3 == xBusyCalled.value );
     sqlite3_finalize(stmt);
-    sqlite3_close(db1);
+    sqlite3_close_v2(db1);
     affirm(!xDestroyed.value);
-    sqlite3_close(db2);
+    sqlite3_close_v2(db2);
     affirm(xDestroyed.value);
     try{
       final java.io.File f = new java.io.File(dbName);
@@ -713,6 +723,24 @@ public class Tester1 {
     }
   }
 
+  private static void testProgress(){
+    final sqlite3 db = createNewDb();
+    final ValueHolder<Integer> counter = new ValueHolder<>(0);
+    sqlite3_progress_handler(db, 1, new ProgressHandler(){
+        public int xCallback(){
+          ++counter.value;
+          return 0;
+        }
+      });
+    execSql(db, "SELECT 1; SELECT 2;");
+    affirm( counter.value > 0 );
+    int nOld = counter.value;
+    sqlite3_progress_handler(db, 0, null);
+    execSql(db, "SELECT 1; SELECT 2;");
+    affirm( nOld == counter.value );
+    sqlite3_close_v2(db);
+  }
+
   private static void testSleep(){
     out("Sleeping briefly... ");
     sqlite3_sleep(600);
@@ -720,6 +748,7 @@ public class Tester1 {
   }
 
   public static void main(String[] args){
+    final long timeStart = System.nanoTime();
     test1();
     if(false) testCompileOption();
     final java.util.List<String> liArgs =
@@ -740,10 +769,16 @@ public class Tester1 {
     testUdfWindow();
     testTrace();
     testBusy();
-    testSleep();
+    testProgress();
+    //testSleep();
     if(liArgs.indexOf("-v")>0){
       listBoundMethods();
     }
-    outln("Tests done. "+affirmCount+" assertion checked.");
+    final long timeEnd = System.nanoTime();
+    outln("Tests done. Metrics:");
+    outln("\tAssertions checked: "+affirmCount);
+    outln("\tDatabases opened: "+metrics.dbOpen);
+    outln("\tTotal time = "
+          +((timeEnd - timeStart)/1000000.0)+"ms");
   }
 }
index 1d9b4e8b269f839f5d813daaf854eb370fcb82b1..0ccad35a874d2c9171b415ad378b02c993bd2d2b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Internal\sJNI\sbinding\sdocs.
-D 2023-07-28T18:44:11.596
+C Bind\ssqlite3_progress_handler()\sto\sJNI.\sAdd\ssome\smetrics\sto\sTester1.java.
+D 2023-07-30T04:31:56.673
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -232,16 +232,16 @@ F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
 F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
 F ext/jni/GNUmakefile 56a014dbff9516774d895ec1ae9df0ed442765b556f79a0fc0b5bc438217200d
 F ext/jni/README.md b62f1f0e67a6295e9a0283d4dffad6ed30ec50352aa36b3bd323a26593606c0f
-F ext/jni/src/c/sqlite3-jni.c f7f4934cb2698c674842974c1b47d0cba0927ebc5781b0c15304b7ed6c46b743
-F ext/jni/src/c/sqlite3-jni.h c9bb150a38dce09cc2794d5aac8fa097288d9946fbb15250fd0a23c31957f506
+F ext/jni/src/c/sqlite3-jni.c 53fa705d417ab61f4879566352bd1b3e31996aa01d657d6beca597734bff1d0e
+F ext/jni/src/c/sqlite3-jni.h 212c3aede7c9ca8b1116a5d822cb89b95b3d7912452dbe778a9fd6cb869607e3
 F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c
 F ext/jni/src/org/sqlite/jni/Collation.java 8dffbb00938007ad0967b2ab424d3c908413af1bbd3d212b9c9899910f1218d1
 F ext/jni/src/org/sqlite/jni/NativePointerHolder.java 70dc7bc41f80352ff3d4331e2e24f45fcd23353b3641e2f68a81bd8262215861
 F ext/jni/src/org/sqlite/jni/OutputPointer.java 08a752b58a33696c5eaf0eb9361a0966b188dec40f4a3613eb133123951f6c5f
-F ext/jni/src/org/sqlite/jni/ProgressHandler.java 5a1d7b2607eb2ef596fcf4492a49d1b3a5bdea3af9918e11716831ffd2f02284
+F ext/jni/src/org/sqlite/jni/ProgressHandler.java 5979450e996416d28543f1d42634d308439565a99332a8bd84e424af667116cc
 F ext/jni/src/org/sqlite/jni/SQLFunction.java 663a4e479ec65bfbf893586439e12d30b8237898064a22ab64f5658b57315f37
-F ext/jni/src/org/sqlite/jni/SQLite3Jni.java f7939d75d26481d02ea3418fa24bb6f6ba89b98a3e10ac4ab67b7186f9cb4fda
-F ext/jni/src/org/sqlite/jni/Tester1.java 6c819172137bf06d76f26df20c4c846abc82523db62c51cc043ac66031298103
+F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 5d57e46e9d2a1c50d20cbe890908026252068a67ce61dfbb55f23d867dc1d827
+F ext/jni/src/org/sqlite/jni/Tester1.java 69035e38d68ae18d6cc179a82094d9450e6175c973c19969264d48c0e75d6951
 F ext/jni/src/org/sqlite/jni/Tracer.java c2fe1eba4a76581b93b375a7b95ab1919e5ae60accfb06d6beb067b033e9bae1
 F ext/jni/src/org/sqlite/jni/ValueHolder.java f022873abaabf64f3dd71ab0d6037c6e71cece3b8819fa10bf26a5461dc973ee
 F ext/jni/src/org/sqlite/jni/sqlite3.java c7d0500c7269882243aafb41425928d094b2fcbdbc2fd1caffc276871cd3fae3
@@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P bcefa2df563260933c7ab5df90872580f71010c11419f6b1de7b1e2747237ff8
-R 934bdd7c3796e2624766f5d43e958073
+P 991c66197e4dc7297fce3b20a1b4846873bcd4ce8add36aac71bd2e0e73c207b
+R 3db7b0c753b00fafc33e16210b0ec893
 U stephan
-Z 1f7372379f92cca45c2da16bb8bc1a04
+Z b93e8aa0e181c83baf410d69abe8fc02
 # Remove this line to create a well-formed Fossil manifest.
index edc4bc0e92ee80483a050877477f2eee25879d12..2fd5dd978abb8579dafc46606db7d1b8a9ac71a0 100644 (file)
@@ -1 +1 @@
-991c66197e4dc7297fce3b20a1b4846873bcd4ce8add36aac71bd2e0e73c207b
\ No newline at end of file
+437ecfe8abf8d294d429d191d811da6148e0b2ebb74cf66998480bfc8ef58bdf
\ No newline at end of file