]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add JNI wrapper1.SqliteStmt.bindXyz() APIs.
authorstephan <stephan@noemail.net>
Sun, 22 Oct 2023 12:43:30 +0000 (12:43 +0000)
committerstephan <stephan@noemail.net>
Sun, 22 Oct 2023 12:43:30 +0000 (12:43 +0000)
FossilOrigin-Name: 54fce9bf04a7517cdc8e96fe2efec66f03b0d03983c3a45d0ae7e1f16aa5a6c9

ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java
ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java
manifest
manifest.uuid

index bcf97b23946abff5ce7095c44bfac2fac015aed7..4cf06d355c7953b081ba1e85c6b349597c83a8c8 100644 (file)
@@ -77,7 +77,7 @@ public final class Sqlite implements AutoCloseable  {
   */
   sqlite3 nativeHandle(){ return this.db; }
 
-  private sqlite3 affirmOpen(){
+  private sqlite3 thisDb(){
     if( null==db || 0==db.getNativePointer() ){
       throw new IllegalArgumentException("This database instance is closed.");
     }
@@ -88,12 +88,58 @@ public final class Sqlite implements AutoCloseable  {
   //   return s==null ? null : s.getBytes(StandardCharsets.UTF_8);
   // }
 
+  /**
+     If rc!=0, throws an SqliteException. If this db is currently
+     opened, the error state is extracted from it, else only the
+     string form of rc is used.
+  */
   private void affirmRcOk(int rc){
     if( 0!=rc ){
-      throw new SqliteException(db);
+      if( null==db ) throw new SqliteException(rc);
+      else throw new SqliteException(db);
     }
   }
 
+  /**
+     prepare() TODOs include:
+
+     - overloads taking byte[] and ByteBuffer.
+
+     - multi-statement processing, like CApi.sqlite3_prepare_multi()
+     but using a callback specific to the higher-level Stmt class
+     rather than the sqlite3_stmt class.
+  */
+  public Stmt prepare(String sql, int prepFlags){
+    final OutputPointer.sqlite3_stmt out = new OutputPointer.sqlite3_stmt();
+    final int rc = sqlite3_prepare_v3(thisDb(), sql, prepFlags, out);
+    affirmRcOk(rc);
+    return new Stmt(this, out.take());
+  }
+
+  public Stmt prepare(String sql){
+    return prepare(sql, 0);
+  }
+
+  public void createFunction(String name, int nArg, int eTextRep, ScalarFunction f ){
+    int rc = CApi.sqlite3_create_function(thisDb(), name, nArg, eTextRep,
+                                           new SqlFunction.ScalarAdapter(f));
+    if( 0!=rc ) throw new SqliteException(db);
+  }
+
+  public void createFunction(String name, int nArg, ScalarFunction f){
+    this.createFunction(name, nArg, CApi.SQLITE_UTF8, f);
+  }
+
+  public void createFunction(String name, int nArg, int eTextRep, AggregateFunction f ){
+    int rc = CApi.sqlite3_create_function(thisDb(), name, nArg, eTextRep,
+                                           new SqlFunction.AggregateAdapter(f));
+    if( 0!=rc ) throw new SqliteException(db);
+  }
+
+  public void createFunction(String name, int nArg, AggregateFunction f){
+    this.createFunction(name, nArg, CApi.SQLITE_UTF8, f);
+  }
+
   /**
      Corresponds to the sqlite3_stmt class. Use Sqlite.prepare() to
      create new instances.
@@ -111,7 +157,11 @@ public final class Sqlite implements AutoCloseable  {
       return stmt;
     }
 
-    private sqlite3_stmt affirmOpen(){
+    /**
+       If this statement is still opened, its low-level handle is
+       returned, eelse an IllegalArgumentException is thrown.
+    */
+    private sqlite3_stmt thisStmt(){
       if( null==stmt || 0==stmt.getNativePointer() ){
         throw new IllegalArgumentException("This Stmt has been finalized.");
       }
@@ -140,7 +190,9 @@ public final class Sqlite implements AutoCloseable  {
 
     /**
        Throws if rc is any value other than 0, SQLITE_ROW, or
-       SQLITE_DONE, else returns rc.
+       SQLITE_DONE, else returns rc. Error state for the exception is
+       extracted from this statement object (if it's opened) or the
+       string form of rc.
     */
     private int checkRc(int rc){
       switch(rc){
@@ -148,7 +200,8 @@ public final class Sqlite implements AutoCloseable  {
         case SQLITE_ROW:
         case SQLITE_DONE: return rc;
         default:
-          throw new SqliteException(this);
+          if( null==stmt ) throw new SqliteException(rc);
+          else throw new SqliteException(this);
       }
     }
 
@@ -157,7 +210,7 @@ public final class Sqlite implements AutoCloseable  {
        result other than 0, SQLITE_ROW, or SQLITE_DONE.
     */
     public int step(){
-      return checkRc(sqlite3_step(affirmOpen()));
+      return checkRc(sqlite3_step(thisStmt()));
     }
 
     public Sqlite db(){ return this._db; }
@@ -166,53 +219,55 @@ public final class Sqlite implements AutoCloseable  {
        Works like sqlite3_reset() but throws on error.
     */
     public void reset(){
-      checkRc(sqlite3_reset(affirmOpen()));
+      checkRc(CApi.sqlite3_reset(thisStmt()));
     }
 
     public void clearBindings(){
-      sqlite3_clear_bindings( affirmOpen() );
+      CApi.sqlite3_clear_bindings( thisStmt() );
+    }
+    public void bindInt(int ndx, int val){
+      checkRc(CApi.sqlite3_bind_int(thisStmt(), ndx, val));
+    }
+    public void bindInt64(int ndx, long val){
+      checkRc(CApi.sqlite3_bind_int64(thisStmt(), ndx, val));
+    }
+    public void bindDouble(int ndx, double val){
+      checkRc(CApi.sqlite3_bind_double(thisStmt(), ndx, val));
+    }
+    public void bindObject(int ndx, Object o){
+      checkRc(CApi.sqlite3_bind_java_object(thisStmt(), ndx, o));
+    }
+    public void bindNull(int ndx){
+      checkRc(CApi.sqlite3_bind_null(thisStmt(), ndx));
+    }
+    public int bindParameterCount(){
+      return CApi.sqlite3_bind_parameter_count(thisStmt());
+    }
+    public int bindParameterIndex(String paramName){
+      return CApi.sqlite3_bind_parameter_index(thisStmt(), paramName);
+    }
+    public String bindParameterName(int ndx){
+      return CApi.sqlite3_bind_parameter_name(thisStmt(), ndx);
+    }
+    public void bindText(int ndx, byte[] utf8){
+      checkRc(CApi.sqlite3_bind_text(thisStmt(), ndx, utf8));
+    }
+    public void bindText(int ndx, String asUtf8){
+      checkRc(CApi.sqlite3_bind_text(thisStmt(), ndx, asUtf8));
+    }
+    public void bindText16(int ndx, byte[] utf16){
+      checkRc(CApi.sqlite3_bind_text16(thisStmt(), ndx, utf16));
+    }
+    public void bindText16(int ndx, String txt){
+      checkRc(CApi.sqlite3_bind_text16(thisStmt(), ndx, txt));
+    }
+    public void bindZeroBlob(int ndx, int n){
+      checkRc(CApi.sqlite3_bind_zeroblob(thisStmt(), ndx, n));
+    }
+    public void bindBlob(int ndx, byte[] bytes){
+      checkRc(CApi.sqlite3_bind_blob(thisStmt(), ndx, bytes));
     }
-  }
-
-
-  /**
-     prepare() TODOs include:
-
-     - overloads taking byte[] and ByteBuffer.
-
-     - multi-statement processing, like CApi.sqlite3_prepare_multi()
-     but using a callback specific to the higher-level Stmt class
-     rather than the sqlite3_stmt class.
-  */
-  public Stmt prepare(String sql, int prepFlags){
-    final OutputPointer.sqlite3_stmt out = new OutputPointer.sqlite3_stmt();
-    final int rc = sqlite3_prepare_v3(affirmOpen(), sql, prepFlags, out);
-    affirmRcOk(rc);
-    return new Stmt(this, out.take());
-  }
-
-  public Stmt prepare(String sql){
-    return prepare(sql, 0);
-  }
-
-  public void createFunction(String name, int nArg, int eTextRep, ScalarFunction f ){
-    int rc = CApi.sqlite3_create_function(affirmOpen(), name, nArg, eTextRep,
-                                           new SqlFunction.ScalarAdapter(f));
-    if( 0!=rc ) throw new SqliteException(db);
-  }
-
-  public void createFunction(String name, int nArg, ScalarFunction f){
-    this.createFunction(name, nArg, CApi.SQLITE_UTF8, f);
-  }
-
-  public void createFunction(String name, int nArg, int eTextRep, AggregateFunction f ){
-    int rc = CApi.sqlite3_create_function(affirmOpen(), name, nArg, eTextRep,
-                                           new SqlFunction.AggregateAdapter(f));
-    if( 0!=rc ) throw new SqliteException(db);
-  }
 
-  public void createFunction(String name, int nArg, AggregateFunction f){
-    this.createFunction(name, nArg, CApi.SQLITE_UTF8, f);
-  }
+  } /* Stmt class */
 
 }
index f5fd5f84e60e6b01680a539dc89ea3daabf9633c..cf3364bc16156469d53ea1944881e88b2d96c8ed 100644 (file)
@@ -224,8 +224,26 @@ public class Tester2 implements Runnable {
 
   void testPrepare1(){
     try (Sqlite db = openDb()) {
-      Sqlite.Stmt stmt = db.prepare("SELECT 1");
+      Sqlite.Stmt stmt = db.prepare("SELECT ?1");
+      Exception e = null;
       affirm( null!=stmt.nativeHandle() );
+      affirm( 1==stmt.bindParameterCount() );
+      affirm( "?1".equals(stmt.bindParameterName(1)) );
+      affirm( null==stmt.bindParameterName(2) );
+      stmt.bindInt(1, 1);
+      stmt.bindInt64(1, 1);
+      stmt.bindDouble(1, 1.1);
+      stmt.bindObject(1, db);
+      stmt.bindNull(1);
+      stmt.bindText(1, new byte[] {32,32,32});
+      stmt.bindText(1, "123");
+      stmt.bindText16(1, "123".getBytes(StandardCharsets.UTF_16));
+      stmt.bindText16(1, "123");
+      stmt.bindZeroBlob(1, 8);
+      stmt.bindBlob(1, new byte[] {1,2,3,4});
+      try{ stmt.bindInt(2,1); }
+      catch(Exception ex){ e = ex; }
+      affirm( null!=e );
       affirm( CApi.SQLITE_ROW == stmt.step() );
       affirm( CApi.SQLITE_DONE == stmt.step() );
       stmt.reset();
@@ -269,6 +287,10 @@ public class Tester2 implements Runnable {
   }
 
   void testUdfAggregate(){
+    /* FIXME/TODO: once we've added the stmt bind/step/fetch
+       capabilities, go back and extend these tests to correspond to
+       the aggregate UDF tests in ext/wasm/tester1.c-pp.js. We first
+       require the ability to bind/step/fetch, however. */
     final ValueHolder<Integer> xDestroyCalled = new ValueHolder<>(0);
     final ValueHolder<Integer> vh = new ValueHolder<>(0);
     try (Sqlite db = openDb()) {
index 16ecd5eb71ef8c3a0f9ea6046a825e80ca08edc5..3110770045ed7cd593370e705145aa679b46eb65 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C JNI:\simprove\sUB\sprotections\sin\ssqlite3_bind_blob/text/text16().
-D 2023-10-22T12:33:05.772
+C Add\sJNI\swrapper1.SqliteStmt.bindXyz()\sAPIs.
+D 2023-10-22T12:43:30.072
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -294,9 +294,9 @@ F ext/jni/src/org/sqlite/jni/test-script-interpreter.md f9f25126127045d051e918fe
 F ext/jni/src/org/sqlite/jni/wrapper1/AggregateFunction.java 5ad99bd74c85f56bbef324d9ec29b4048f4620547c9a80093d8586c3557f9f9a
 F ext/jni/src/org/sqlite/jni/wrapper1/ScalarFunction.java 43c43adfb7866098aadaaca1620028a6ec82d5193149970019b1cce9eb59fb03
 F ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java 004394eeb944baa56e36cd7ae69ba6d4a52b52db3c49439db16e98270b861421
-F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java a9ddc6a9e8c113168cc67592ae24c0e56d30dd06226eeab012f2761a0889d7bb
+F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java 25e4e65ba434d0e110e4adb6782e20cd374d83b7fe00ba5ca48a1dadd2fdd7dd
 F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 1386f7b753134fc12253ce2fbbc448ba8c970567fac01a3356cb672e14408d73
-F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java c24b510ebe801c30533cc62efdf69a4a5e2da9ec4b49f8d403f2060693f060a0
+F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java 65437e09115bfef4445957db61fcf6dac9aad37ac00edb445c3de812e9750d6e
 F ext/jni/src/org/sqlite/jni/wrapper1/ValueHolder.java 7b89a7391f771692c5b83b0a5b86266abe8d59f1c77d7a0eccc9b79f259d79af
 F ext/jni/src/tests/000-000-sanity.test c3427a0e0ac84d7cbe4c95fdc1cd4b61f9ddcf43443408f3000139478c4dc745
 F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
@@ -2136,8 +2136,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P b8258103fb433d9f5cfa15661b5edf4e60128fb4161d8a18e5cc3253e5aed72b
-R 10dd3eddc3858c0c90f96d7af2dd213f
+P 5c8383210a87d7f9d37a27053b5b1b6f41794fa8612826c68c1ca49c495cbd97
+R 186cd14750afba6ac11c0a47787c2fc3
+T *branch * jni-post-3.44
+T *sym-jni-post-3.44 *
+T -sym-trunk * Cancelled\sby\sbranch.
 U stephan
-Z 39a3acd541e66480809465cadb3002fa
+Z dc6c06549901a63430a6e90b2648f01f
 # Remove this line to create a well-formed Fossil manifest.
index bcfb4efa9576b161c8fd810f851a153d18c803ff..166d31ff93cd4b438bcda300f00b5088a6f7da0d 100644 (file)
@@ -1 +1 @@
-5c8383210a87d7f9d37a27053b5b1b6f41794fa8612826c68c1ca49c495cbd97
\ No newline at end of file
+54fce9bf04a7517cdc8e96fe2efec66f03b0d03983c3a45d0ae7e1f16aa5a6c9
\ No newline at end of file