]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
JNI: initial draft (untested - requires more infrastructure first) of a UDF argument...
authorstephan <stephan@noemail.net>
Mon, 16 Oct 2023 13:04:42 +0000 (13:04 +0000)
committerstephan <stephan@noemail.net>
Mon, 16 Oct 2023 13:04:42 +0000 (13:04 +0000)
FossilOrigin-Name: 43b10a5cf9cb8be53d62914f340d533e60a70bf4caa8b9b91c0f867fa0f70493

ext/jni/GNUmakefile
ext/jni/src/org/sqlite/jni/capi/CApi.java
ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java [new file with mode: 0644]
ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java
ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java
manifest
manifest.uuid

index cc53cf8d151d188fdb64a9eeb4b8ee321ee4f347..e7f083a75643ec22663cecc999bddd89d730c2ff 100644 (file)
@@ -113,6 +113,7 @@ JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/annotation/%,\
   sqlite3_stmt.java \
   sqlite3_value.java \
 ) $(patsubst %,$(dir.src.jni)/wrapper1/%,\
+  SqlFunction.java \
   Sqlite.java \
   SqliteException.java \
 )
index 051e28a899508035c9e47f6193c7cfbfc576c39a..a72184474452477e16821111b03a46e026c4a081 100644 (file)
@@ -1635,7 +1635,8 @@ public final class CApi {
   public static void sqlite3_result_text16(
     @NotNull sqlite3_context cx, @Nullable byte[] utf16
   ){
-    sqlite3_result_text64(cx, utf16, utf16.length, SQLITE_UTF16);
+    if(null == utf16) sqlite3_result_null(cx);
+    else sqlite3_result_text64(cx, utf16, utf16.length, SQLITE_UTF16);
   }
 
   public static void sqlite3_result_text16(
diff --git a/ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java b/ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java
new file mode 100644 (file)
index 0000000..4be6dcb
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+** 2023-10-16
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the wrapper1 interface for sqlite3.
+*/
+package org.sqlite.jni.wrapper1;
+import org.sqlite.jni.capi.CApi;
+import org.sqlite.jni.annotation.*;
+import org.sqlite.jni.capi.sqlite3_context;
+import org.sqlite.jni.capi.sqlite3_value;
+
+/**
+   EXPERIMENTAL/INCOMPLETE/UNTESTED
+*/
+public interface SqlFunction  {
+
+  /**
+     EXPERIMENTAL/INCOMPLETE/UNTESTED. An attempt at hiding UDF-side
+     uses of the sqlite3_context and sqlite3_value classes from a
+     high-level wrapper.  This level of indirection requires more than
+     twice as much Java code (in this API, not client-side) as using
+     the lower-level API. Client-side it's roughly the same amount of
+     code.
+  */
+  public final static class Arguments implements Iterable<SqlFunction.Arguments.Arg>{
+    private final sqlite3_context cx;
+    private final sqlite3_value args[];
+
+    /**
+       Must be passed the context and arguments for the UDF call this
+       object is wrapping.
+    */
+    Arguments(@NotNull sqlite3_context cx, @NotNull sqlite3_value args[]){
+      this.cx = cx;
+      this.args = args;
+    }
+
+    /**
+       Wrapper for a single SqlFunction argument. Primarily intended
+       for eventual use with the Arguments class's Iterable interface.
+    */
+    public final static class Arg {
+      private final Arguments a;
+      private final int ndx;
+      /* Only for use by the Arguments class. */
+      private Arg(@NotNull Arguments a, int ndx){
+        this.a = a;
+        this.ndx = ndx;
+      }
+      /** Returns this argument's index in its parent argument list. */
+      public int getIndex(){return ndx;}
+
+      public int getInt(){return a.getInt(ndx);}
+      public long getInt64(){return a.getInt64(ndx);}
+      public double getDouble(){return a.getDouble(ndx);}
+      public byte[] getBlob(){return a.getBlob(ndx);}
+      public byte[] getText(){return a.getText(ndx);}
+      public String getText16(){return a.getText16(ndx);}
+      public int getBytes(){return a.getBytes(ndx);}
+      public int getBytes16(){return a.getBytes16(ndx);}
+      public Object getObject(){return a.getObject(ndx);}
+      public <T> T getObjectCasted(Class<T> type){ return a.getObjectCasted(ndx, type); }
+      public int getType(){return a.getType(ndx);}
+      public Object getAuxData(){return a.getAuxData(ndx);}
+      public void setAuxData(Object o){a.setAuxData(ndx, o);}
+    }
+
+    //! Untested!
+    @Override
+    public java.util.Iterator<SqlFunction.Arguments.Arg> iterator(){
+      Arg[] proxies = new Arg[args.length];
+      for( int i = 0; i < args.length; ++i ){
+        proxies[i] = new Arg(this, i);
+      }
+      return java.util.Arrays.stream(proxies).iterator();
+    }
+
+    /**
+       Returns the sqlite3_value at the given argument index or throws
+       an IllegalArgumentException exception if ndx is out of range.
+    */
+    private sqlite3_value valueAt(int ndx){
+      if(ndx<0 || ndx>=args.length){
+        throw new IllegalArgumentException(
+          "SQL function argument index "+ndx+" is out of range."
+        );
+      }
+      return args[ndx];
+    }
+
+    public int getArgCount(){ return args.length; }
+
+    public int getInt(int arg){return CApi.sqlite3_value_int(valueAt(arg));}
+    public long getInt64(int arg){return CApi.sqlite3_value_int64(valueAt(arg));}
+    public double getDouble(int arg){return CApi.sqlite3_value_double(valueAt(arg));}
+    public byte[] getBlob(int arg){return CApi.sqlite3_value_blob(valueAt(arg));}
+    public byte[] getText(int arg){return CApi.sqlite3_value_text(valueAt(arg));}
+    public String getText16(int arg){return CApi.sqlite3_value_text16(valueAt(arg));}
+    public int getBytes(int arg){return CApi.sqlite3_value_bytes(valueAt(arg));}
+    public int getBytes16(int arg){return CApi.sqlite3_value_bytes16(valueAt(arg));}
+    public Object getObject(int arg){return CApi.sqlite3_value_java_object(valueAt(arg));}
+    public <T> T getObjectCasted(int arg, Class<T> type){
+      return CApi.sqlite3_value_java_casted(valueAt(arg), type);
+    }
+
+    public int getType(int arg){return CApi.sqlite3_value_type(valueAt(arg));}
+
+    public void resultInt(int v){ CApi.sqlite3_result_int(cx, v); }
+    public void resultInt64(long v){ CApi.sqlite3_result_int64(cx, v); }
+    public void resultDouble(double v){ CApi.sqlite3_result_double(cx, v); }
+    public void resultError(String msg){CApi.sqlite3_result_error(cx, msg);}
+    public void resultError(Exception e){CApi.sqlite3_result_error(cx, e);}
+    public void resultErrorTooBig(){CApi.sqlite3_result_error_toobig(cx);}
+    public void resultErrorCode(int rc){CApi.sqlite3_result_error_code(cx, rc);}
+    public void resultObject(Object o){CApi.sqlite3_result_java_object(cx, o);}
+    public void resultArg(int argNdx){CApi.sqlite3_result_value(cx, valueAt(argNdx));}
+    public void resultZeroBlob(long n){
+      // Throw on error? If n is too big,
+      // sqlite3_result_error_toobig() is automatically called.
+      CApi.sqlite3_result_zeroblob64(cx, n);
+    }
+
+    public void resultBlob(byte[] blob){CApi.sqlite3_result_blob(cx, blob);}
+    public void resultText(byte[] utf8){CApi.sqlite3_result_text(cx, utf8);}
+    public void resultText(String txt){CApi.sqlite3_result_text(cx, txt);}
+    public void resultText16(byte[] utf16){CApi.sqlite3_result_text16(cx, utf16);}
+    public void resultText16(String txt){CApi.sqlite3_result_text16(cx, txt);}
+
+    public void setAuxData(int arg, Object o){
+      /* From the API docs: https://www.sqlite.org/c3ref/get_auxdata.html
+
+         The value of the N parameter to these interfaces should be
+         non-negative. Future enhancements may make use of negative N
+         values to define new kinds of function caching behavior.
+      */
+      valueAt(arg);
+      CApi.sqlite3_set_auxdata(cx, arg, o);
+    }
+
+    public Object getAuxData(int arg){
+      valueAt(arg);
+      return CApi.sqlite3_get_auxdata(cx, arg);
+    }
+  }
+}
index aaa1fe67fcda231c972d802067010bda1c0e94a9..b6a4bda108e2aa843166f5a99da42c975d43c191 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This file is part of the JNI bindings for the sqlite3 C API.
+** This file is part of the wrapper1 interface for sqlite3.
 */
 package org.sqlite.jni.wrapper1;
 import java.nio.charset.StandardCharsets;
index 87b0d3737f18c65b7a432a88d5b271d045c2dbae..111f004db44cbc3b158c023309fb18ae8c00d8f9 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This file is part of the JNI bindings for the sqlite3 C API.
+** This file is part of the wrapper1 interface for sqlite3.
 */
 package org.sqlite.jni.wrapper1;
 import static org.sqlite.jni.capi.CApi.*;
@@ -54,7 +54,7 @@ public final class SqliteException extends java.lang.RuntimeException {
      a failed db-open operation, and the place(s) where that can
      happen are inside this library, not client-level code.
   */
-  public SqliteException(sqlite3 db){
+  SqliteException(sqlite3 db){
     super(sqlite3_errmsg(db));
     errCode = sqlite3_errcode(db);
     xerrCode = sqlite3_extended_errcode(db);
@@ -63,8 +63,8 @@ public final class SqliteException extends java.lang.RuntimeException {
   }
 
   /**
-     Records the current error state of db (which must not be null and must
-     refer to an open database) then closes it.
+     Records the current error state of db (which must not be null and
+     must refer to an open database).
   */
   public SqliteException(Sqlite db){
     this(db.nativeHandle());
index 891a5e2aef88d4cdbff14c7148c5ef50f7698e48..978dd1cded6ec208731f1c092cf39a30c59987aa 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C JNI:\scleanups\sin\sTester2\sand\supdate\sthe\sjar\smakefile\starget\sto\saccount\sfor\s[9fcdf96adca2].
-D 2023-10-16T10:38:34.125
+C JNI:\sinitial\sdraft\s(untested\s-\srequires\smore\sinfrastructure\sfirst)\sof\sa\sUDF\sargument/result-handling\sinterface\swhich\scompletely\shides\sthe\sC-style\sAPI\sfrom\sthe\sclient.
+D 2023-10-16T13:04:42.394
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -235,7 +235,7 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
 F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
 F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
 F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
-F ext/jni/GNUmakefile bf7dbc177903a180aaa45540483d49185abb5e032c08773a36eb7983281b7ab0
+F ext/jni/GNUmakefile 069399d471af948a4293e79135907a8d58daa09e59b4cc1b9cc1a5124c87f589
 F ext/jni/README.md ef9ac115e97704ea995d743b4a8334e23c659e5534c3b64065a5405256d5f2f4
 F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
 F ext/jni/src/c/sqlite3-jni.c 8d32ca0598a11370a9e92a6d111f38934c225056b42b13512175acf6e37eed4c
@@ -248,7 +248,7 @@ F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java bc29e986c866c2ddbbb9f93
 F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java 7ed409d5449684616cc924534e22ff6b07d361f12ad904b69ecb10e0568a8013
 F ext/jni/src/org/sqlite/jni/capi/AutoExtensionCallback.java 74cc4998a73d6563542ecb90804a3c4f4e828cb4bd69e61226d1a51f4646e759
 F ext/jni/src/org/sqlite/jni/capi/BusyHandlerCallback.java 7b8e19810c42b0ad21a04b5d8c804b32ee5905d137148703f16a75b612c380ca
-F ext/jni/src/org/sqlite/jni/capi/CApi.java 82993492793fd946e2b9b9a244fe5ac39647292b449cac7453ea49031c00f517
+F ext/jni/src/org/sqlite/jni/capi/CApi.java 5d754b4bb57852d006ad046b2860eb23ba406f800846460b26beee5172df4fc3
 F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 0bfd6e56e8265c2f05c9207665707285534d78f8466ef0e0430c65677f00943d
 F ext/jni/src/org/sqlite/jni/capi/CollationCallback.java e29bcfc540fdd343e2f5cca4d27235113f2886acb13380686756d5cabdfd065a
 F ext/jni/src/org/sqlite/jni/capi/CollationNeededCallback.java f81cf10b79c52f9b2e9247d523d29ae48863935f60420eae35f257c38c80ce95
@@ -289,8 +289,9 @@ F ext/jni/src/org/sqlite/jni/fts5/fts5_api.java a8e88c3783d21cec51b0748568a96653
 F ext/jni/src/org/sqlite/jni/fts5/fts5_extension_function.java 9e2b954d210d572552b28aca523b272fae14bd41e318921b22f65b728d5bf978
 F ext/jni/src/org/sqlite/jni/fts5/fts5_tokenizer.java 92bdaa3893bd684533004d64ade23d329843f809cd0d0f4f1a2856da6e6b4d90
 F ext/jni/src/org/sqlite/jni/test-script-interpreter.md f9f25126127045d051e918fe59004a1485311c50a13edbf18c79a6ff9160030e
-F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java f05ee6c52b039bb5b65e49ac90710f58cbfc95e13e5a8d46a7fe5106d5819dad
-F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 039f6f858cd6a0f59a41f0823d638959d8f47e7098dd469c486988494d651896
+F ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java 40a9f4f8a7a72b90b12baa82d26ba16376a5758009739b069c1863201770e816
+F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java 2bc90edc4c25225e018ed600b5eff43ba0485be85db08f8b6b35246372fdac20
+F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 1386f7b753134fc12253ce2fbbc448ba8c970567fac01a3356cb672e14408d73
 F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java aee8301f92256ab8572043cf5de2a35afda057d2a6ff09970a2f84a90305471e
 F ext/jni/src/tests/000-000-sanity.test c3427a0e0ac84d7cbe4c95fdc1cd4b61f9ddcf43443408f3000139478c4dc745
 F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
@@ -2128,8 +2129,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 9fcdf96adca25cc2d2f4b75ec4eea94254fb9671c5ba63b88213d7f62dedff1b
-R 376c33c5d6d18c40ea3627a195e8192d
+P abc82bf4b800dde1b6e6172c7be816edb391fdbed5dbd2749f54623fdf3bf8e6
+R 287c21329f3772a974832101be3bffee
 U stephan
-Z 0f3f56205e0babb2af321d2f9efdae5a
+Z a4e77b564ffa0b3970c5e65a1253c53d
 # Remove this line to create a well-formed Fossil manifest.
index 11d064f42be3d20c5cc1d3ce637a88b9b1df9637..2eac8e0f45e19c80cec8a423c1f7cf3799b83f22 100644 (file)
@@ -1 +1 @@
-abc82bf4b800dde1b6e6172c7be816edb391fdbed5dbd2749f54623fdf3bf8e6
\ No newline at end of file
+43b10a5cf9cb8be53d62914f340d533e60a70bf4caa8b9b91c0f867fa0f70493
\ No newline at end of file