ConfigSqllogCallback.java \
NativePointerHolder.java \
OutputPointer.java \
+ PrepareMultiCallback.java \
PreupdateHookCallback.java \
ProgressHandlerCallback.java \
ResultCode.java \
--- /dev/null
+/*
+** 2023-09-13
+**
+** 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 JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+ Callback for use with {@link SQLite3Jni#sqlite3_prepare_multi}.
+*/
+public interface PrepareMultiCallback extends CallbackProxy {
+
+ /**
+ Gets passed a which it may handle in arbitrary
+ ways, transfering ownership of it to this function.
+
+ sqlite3_prepare_multi() will _not_ finalize st - it is up
+ to the call() implementation how st is handled.
+
+ Must return 0 on success or an SQLITE_... code on error.
+
+ See the {@link Finalize} class for a wrapper which finalizes the
+ statement after calling a proxy PrepareMultiCallback.
+ */
+ int call(sqlite3_stmt st);
+
+ /**
+ A PrepareMultiCallback impl which wraps a separate impl and finalizes
+ any sqlite3_stmt passed to its callback.
+ */
+ public static final class Finalize implements PrepareMultiCallback {
+ private PrepareMultiCallback p;
+ public Finalize( PrepareMultiCallback p ){
+ this.p = p;
+ }
+ /**
+ Calls the call() method of the proxied callback and either returns its
+ result or propagates an exception. Either way, it passes its argument to
+ sqlite3_finalize().
+ */
+ @Override public int call(sqlite3_stmt st){
+ try {
+ return this.p.call(st);
+ }finally{
+ SQLite3Jni.sqlite3_finalize(st);
+ }
+ }
+ }
+
+ /**
+ A PrepareMultiCallback impl which steps entirely through a result set,
+ ignoring all non-error results.
+ */
+ public static final class StepAll implements PrepareMultiCallback {
+ public StepAll(){}
+ /**
+ Calls sqlite3_step() on st until it returns something other than
+ SQLITE_ROW. If the final result is SQLITE_DONE then 0 is returned,
+ else the result of the final step is returned.
+ */
+ @Override public int call(sqlite3_stmt st){
+ int rc = SQLite3Jni.SQLITE_DONE;
+ while( SQLite3Jni.SQLITE_ROW == (rc = SQLite3Jni.sqlite3_step(st)) ){}
+ return SQLite3Jni.SQLITE_DONE==rc ? 0 : rc;
+ }
+ }
+}
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import org.sqlite.jni.annotation.*;
+import java.util.Arrays;
/**
This class contains the entire C-style sqlite3 JNI API binding,
sqlite3_prepare(db, sql, out);
return out.take();
}
-
/**
@see #sqlite3_prepare
*/
return out.take();
}
+ /**
+ A convenience wrapper around sqlite3_prepare_v3() which accepts
+ an arbitrary amount of input provided as a UTF-8-encoded byte
+ array. It loops over the input bytes looking for
+ statements. Each one it finds is passed to p.call(), passing
+ ownership of it to that function. If p.call() returns 0, looping
+ continues, else the loop stops.
+
+ If p.call() throws, the exception is propagated.
+
+ How each statement is handled, including whether it is finalized
+ or not, is up to the callback object. e.g. the callback might
+ collect them for later use. If it does not collect them then it
+ must finalize them. See PrepareMultiCallback.Finalize for a
+ simple proxy which does that.
+ */
+ public static int sqlite3_prepare_multi(
+ @NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
+ int preFlags,
+ @NotNull PrepareMultiCallback p){
+ final OutputPointer.Int32 oTail = new OutputPointer.Int32();
+ int pos = 0, n = 1;
+ byte[] sqlChunk = sqlUtf8;
+ int rc = 0;
+ final OutputPointer.sqlite3_stmt outStmt = new OutputPointer.sqlite3_stmt();
+ while(0==rc && pos<sqlChunk.length){
+ sqlite3_stmt stmt = null;
+ if(pos > 0){
+ sqlChunk = Arrays.copyOfRange(sqlChunk, pos,
+ sqlChunk.length);
+ }
+ if( 0==sqlChunk.length ) break;
+ rc = sqlite3_prepare_v3(db, sqlChunk, preFlags, outStmt, oTail);
+ if( 0!=rc ) break;
+ pos = oTail.value;
+ stmt = outStmt.take();
+ if( null == stmt ){
+ // empty statement was parsed.
+ continue;
+ }
+ rc = p.call(stmt);
+ }
+ return rc;
+ }
+
+ /**
+ Convenience overload which accepts its SQL as a String and uses
+ no statement-preparation flags.
+ */
+ public static int sqlite3_prepare_multi(
+ @NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
+ @NotNull PrepareMultiCallback p){
+ return sqlite3_prepare_multi(db, sqlUtf8, 0, p);
+ }
+
+ /**
+ Convenience overload which accepts its SQL as a String.
+ */
+ public static int sqlite3_prepare_multi(
+ @NotNull sqlite3 db, @NotNull String sql, int prepFlags,
+ @NotNull PrepareMultiCallback p){
+ return sqlite3_prepare_multi(
+ db, sql.getBytes(StandardCharsets.UTF_8), prepFlags, p
+ );
+ }
+
+ /**
+ Convenience overload which accepts its SQL as a String and uses
+ no statement-preparation flags.
+ */
+ public static int sqlite3_prepare_multi(
+ @NotNull sqlite3 db, @NotNull String sql,
+ @NotNull PrepareMultiCallback p){
+ return sqlite3_prepare_multi(db, sql, 0, p);
+ }
+
+ /**
+ Convenience overload which accepts its SQL as a String
+ array. They will be concatenated together as-is, with no
+ separator, and passed on to one of the other overloads.
+ */
+ public static int sqlite3_prepare_multi(
+ @NotNull sqlite3 db, @NotNull String[] sql, int prepFlags,
+ @NotNull PrepareMultiCallback p){
+ return sqlite3_prepare_multi(db, String.join("",sql), prepFlags, p);
+ }
+
+ /**
+ Convenience overload which uses no statement-preparation flags.
+ */
+ public static int sqlite3_prepare_multi(
+ @NotNull sqlite3 db, @NotNull String[] sql,
+ @NotNull PrepareMultiCallback p){
+ return sqlite3_prepare_multi(db, sql, 0, p);
+ }
+
+
/**
If the C API was built with SQLITE_ENABLE_PREUPDATE_HOOK defined, this
acts as a proxy for C's sqlite3_preupdate_blobwrite(), else it returns
sqlite3_close_v2(db);
}
+ private void testPrepareMulti(){
+ final sqlite3 db = createNewDb();
+ final String[] sql = {
+ "create table t(a);",
+ "insert into t(a) values(1),(2),(3);",
+ "select a from t;"
+ };
+ final List<sqlite3_stmt> liStmt = new ArrayList<sqlite3_stmt>();
+ final PrepareMultiCallback proxy = new PrepareMultiCallback.StepAll();
+ PrepareMultiCallback m = new PrepareMultiCallback() {
+ @Override public int call(sqlite3_stmt st){
+ liStmt.add(st);
+ return proxy.call(st);
+ }
+ };
+ int rc = sqlite3_prepare_multi(db, sql, m);
+ affirm( 0==rc );
+ affirm( liStmt.size() == 3 );
+ for( sqlite3_stmt st : liStmt ){
+ sqlite3_finalize(st);
+ }
+ sqlite3_close_v2(db);
+ }
+
/* Copy/paste/rename this to add new tests. */
private void _testTemplate(){
final sqlite3 db = createNewDb();
sqlite3_stmt stmt = prepare(db,"SELECT 1");
-
sqlite3_finalize(stmt);
sqlite3_close_v2(db);
}
-C Replace\san\sif()\scondition\sin\sfts5\sthat\sis\salways\strue\swith\san\sassert().
-D 2023-09-13T11:24:58.386
+C Add\sJNI\ssqlite3_prepare_multi(),\sbased\son\sfeedback.
+D 2023-09-13T17:11:32.386
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
-F ext/jni/GNUmakefile 3c82b1333ab4c8224787a490e80ea000a8f97bcb53bf9c9d11e095da1ae862f0
+F ext/jni/GNUmakefile 3a235b7bc27d238c826d0e67b389c5307dc6688a289d792d86ee46d7c4bd7754
F ext/jni/README.md 9fceaeb17cecdc5d699dfc83c0cbc3a03fdb3b86bf676381894166c73375ee75
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
F ext/jni/src/c/sqlite3-jni.c 24b620de024b1763c094dcfef978c78a1b417cb90210f6fe51b04b45e492496b
F ext/jni/src/org/sqlite/jni/ConfigSqllogCallback.java e3656909eab7ed0f7e457c5b82df160ca22dd5e954c0a306ec1fca61b0d266b4
F ext/jni/src/org/sqlite/jni/NativePointerHolder.java 564087036449a16df148dcf0a067408bd251170bf23286c655f46b5f973e8b2d
F ext/jni/src/org/sqlite/jni/OutputPointer.java 2f57c05672ddc9b38e3f8eed11759896cf0bf01107ffd24d5182b99f6e7254b6
+F ext/jni/src/org/sqlite/jni/PrepareMultiCallback.java f522dd31dc76a09d033967658072c2a7aba1488e41c4d1798637c3bf1ff3f390
F ext/jni/src/org/sqlite/jni/PreupdateHookCallback.java eccaed8dc9c6289f07ef3fc109891c6be1e7cc6c88723d90174b68706fc21cda
F ext/jni/src/org/sqlite/jni/ProgressHandlerCallback.java 7b9ff2218129ece98ba60c57eeedcd8447e9e3b6e5d0f5e5d3eb0f0c5037d48d
F ext/jni/src/org/sqlite/jni/ResultCode.java ba701f20213a5f259e94cfbfdd36eb7ac7ce7797f2c6c7fca2004ff12ce20f86
F ext/jni/src/org/sqlite/jni/RollbackHookCallback.java d12352c0e22840de484ffa9b11ed5058bb0daca2e9f218055d3c54c947a273c4
F ext/jni/src/org/sqlite/jni/SQLFunction.java 544a875d33fd160467d82e2397ac33157b29971d715a821a4fad3c899113ee8c
-F ext/jni/src/org/sqlite/jni/SQLite3Jni.java dab91a2a6f718476b3b3df646f9953a9314738937cc05caaa7298b9079a43006
+F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 62d2c4d537a08e57cf7520faf470767fa5482882ed87600ce2e4517f411c78e3
F ext/jni/src/org/sqlite/jni/ScalarFunction.java 6d387bb499fbe3bc13c53315335233dbf6a0c711e8fa7c521683219b041c614c
F ext/jni/src/org/sqlite/jni/TableColumnMetadata.java 54511b4297fa28dcb3f49b24035e34ced10e3fd44fd0e458e784f4d6b0096dab
-F ext/jni/src/org/sqlite/jni/Tester1.java ac20af46f909b454a0bd9dad19a212823f84ec8f8deeb53d09ef8a07583eeb2b
+F ext/jni/src/org/sqlite/jni/Tester1.java fb6edb189c2644b29806ba48825e6c816c17476bf2a4150cb7e4aee4c7978c34
F ext/jni/src/org/sqlite/jni/TraceV2Callback.java beb0b064c1a5f8bfe585a324ed39a4e33edbe379a3fc60f1401661620d3ca7c0
F ext/jni/src/org/sqlite/jni/UpdateHookCallback.java 8376f4a931f2d5612b295c003c9515ba933ee76d8f95610e89c339727376e36c
F ext/jni/src/org/sqlite/jni/WindowFunction.java 488980f4dbb6bdd7067d6cb9c43e4075475e51c54d9b74a5834422654b126246
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 6f7842f577a28df1f809cd4bae9e8eafa26f2b54a25a1362ebbdebf5026be57c
-R f3b4c841c08d4c6a9c1041284895fe73
-U dan
-Z 604f49d2d8fa4165afb87849a7893996
+P 2170312c8d7f076cbb8319227de3fac981432dae186bc1928cd217e41119b580
+R 3a804bafc3d00c98885f9a7a6ae4ef32
+U stephan
+Z 0f956dfaa1fe15e925b383a970a358db
# Remove this line to create a well-formed Fossil manifest.
-2170312c8d7f076cbb8319227de3fac981432dae186bc1928cd217e41119b580
\ No newline at end of file
+fa1c1534724b03debc83ae35c2fadab83faf4b4e62b91981fed103888de41396
\ No newline at end of file