** May you share freely, never taking more than you give.
**
*************************************************************************
-** This file holds utility code for the sqlite3 JNI bindings.
+** This file contains the ValueHolder utility class for the sqlite3
+** JNI bindings.
*/
package org.sqlite.jni.capi;
PrepareMultiFinalize offers a proxy which finalizes each
statement after it is passed to another client-defined visitor.
+
+ Be aware that certain legal SQL constructs may fail in the
+ preparation phase, before the corresponding statement can be
+ stepped. Most notably, authorizer checks which disallow access to
+ something in a statement behave that way.
*/
public void prepareMulti(byte sqlUtf8[], int prepFlags, PrepareMulti visitor){
int pos = 0, n = 1;
Executes all SQL statements in the given string. If throwOnError
is true then it will throw for any prepare/step errors, else it
will return the corresponding non-0 result code.
-
- TODO: reimplement this in the high-level API once it has the
- multi-prepare capability.
*/
public static int execSql(Sqlite dbw, boolean throwOnError, String sql){
- final sqlite3 db = dbw.nativeHandle();
- OutputPointer.Int32 oTail = new OutputPointer.Int32();
- final byte[] sqlUtf8 = sql.getBytes(StandardCharsets.UTF_8);
- int pos = 0, n = 1;
- byte[] sqlChunk = sqlUtf8;
- int rc = 0;
- sqlite3_stmt stmt = null;
- final OutputPointer.sqlite3_stmt outStmt = new OutputPointer.sqlite3_stmt();
- while(pos < sqlChunk.length){
- if(pos > 0){
- sqlChunk = Arrays.copyOfRange(sqlChunk, pos,
- sqlChunk.length);
- }
- if( 0==sqlChunk.length ) break;
- rc = CApi.sqlite3_prepare_v2(db, sqlChunk, outStmt, oTail);
- if( throwOnError ) affirm(0 == rc);
- else if( 0!=rc ) break;
- pos = oTail.value;
- stmt = outStmt.take();
- if( null == stmt ){
- // empty statement was parsed.
- continue;
- }
- affirm(0 != stmt.getNativePointer());
- while( CApi.SQLITE_ROW == (rc = CApi.sqlite3_step(stmt)) ){
- }
- CApi.sqlite3_finalize(stmt);
- affirm(0 == stmt.getNativePointer());
- if(Sqlite.DONE!=rc){
- break;
+ final ValueHolder<Integer> rv = new ValueHolder<>(0);
+ final Sqlite.PrepareMulti pm = new Sqlite.PrepareMulti(){
+ @Override public void call(Sqlite.Stmt stmt){
+ try{
+ while( Sqlite.ROW == (rv.value = stmt.step(throwOnError)) ){}
+ }
+ finally{ stmt.finalizeStmt(); }
+ }
+ };
+ try {
+ dbw.prepareMulti(sql, pm);
+ }catch(SqliteException se){
+ if( throwOnError ){
+ throw se;
+ }else{
+ /* This error (likely) happened in the prepare() phase and we
+ need to preempt it. */
+ rv.value = se.errcode();
}
}
- CApi.sqlite3_finalize(stmt);
- if(CApi.SQLITE_ROW==rc || CApi.SQLITE_DONE==rc) rc = 0;
- if( 0!=rc && throwOnError){
- throw new SqliteException(db);
- }
- return rc;
+ return (rv.value==Sqlite.DONE) ? 0 : rv.value;
}
static void execSql(Sqlite db, String sql){
** May you share freely, never taking more than you give.
**
*************************************************************************
-** This file contains a set of tests for the sqlite3 JNI bindings.
+** This file contains the ValueHolder utility class.
*/
package org.sqlite.jni.wrapper1;
/**
A helper class which simply holds a single value. Its primary use
- is for communicating values out of anonymous classes, as doing so
+ is for communicating values out of anonymous callbacks, as doing so
requires a "final" reference.
*/
public class ValueHolder<T> {
-C Fix\sanother\sobscure\sproblem\swith\snested\saggregates.\sdbsqlfuzz\s04408efc51.
-D 2023-11-14T14:50:34.938
+C JNI:\sreimplement\sTester2.execSql()\susing\sthe\shigh-level\sAPI.
+D 2023-11-14T14:59:41.697
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/jni/src/org/sqlite/jni/capi/Tester1.java dcaa283a27aecb25dfd8f1a610885fb95d24945235b51ea13a1143585922de04
F ext/jni/src/org/sqlite/jni/capi/TraceV2Callback.java 0a25e117a0daae3394a77f24713e36d7b44c67d6e6d30e9e1d56a63442eef723
F ext/jni/src/org/sqlite/jni/capi/UpdateHookCallback.java c8bdf7848e6599115d601bcc9427ff902cb33129b9be32870ac6808e04b6ae56
-F ext/jni/src/org/sqlite/jni/capi/ValueHolder.java 22d365746a78c5cd7ae10c39444eb7bbf1a819aad4bb7eb77b1edc47773a3950
+F ext/jni/src/org/sqlite/jni/capi/ValueHolder.java 2ce069f3e007fdbbe1f4e507a5a407fc9679da31a0aa40985e6317ed4d5ec7b5
F ext/jni/src/org/sqlite/jni/capi/WindowFunction.java caf4396f91b2567904cf94bc538a069fd62260d975bd037d15a02a890ed1ef9e
F ext/jni/src/org/sqlite/jni/capi/XDestroyCallback.java f3abb8dd7381f53ebba909437090caf68200f06717b8a7d6aa96fa3e8133117d
F ext/jni/src/org/sqlite/jni/capi/package-info.java 08ff986a65d2be9162442c82d28a65ce431d826f188520717c2ecb1484d0a50e
F ext/jni/src/org/sqlite/jni/wrapper1/AggregateFunction.java d5c108b02afd3c63c9e5e53f71f85273c1bfdc461ae526e0a0bb2b25e4df6483
F ext/jni/src/org/sqlite/jni/wrapper1/ScalarFunction.java 43c43adfb7866098aadaaca1620028a6ec82d5193149970019b1cce9eb59fb03
F ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java 27b141f5914c7cb0e40e90a301d5e05b77f3bd42236834a68031b7086381fafd
-F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java 408f3a2170a483a49443b21d9bd65c3be0c393c8bbdee432c615f9e37e05b466
+F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java 1d8ee109710fd41ba05c17b584f89fe6fcbb53ec1c305dc9686fc7a81fadd6f2
F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 982538ddb4c0719ef87dfa664cd137b09890b546029a7477810bd64d4c47ee35
-F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java 952d9b8707d3d1d7adb548fff18ceff81d5fe2a20d6470c4cf7c359a2b047d60
-F ext/jni/src/org/sqlite/jni/wrapper1/ValueHolder.java 7b89a7391f771692c5b83b0a5b86266abe8d59f1c77d7a0eccc9b79f259d79af
+F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java a9235aa3695e5ad2fca47d43d35a77220b1244d77e43dab1fa3f56555bfc3733
+F ext/jni/src/org/sqlite/jni/wrapper1/ValueHolder.java a84e90c43724a69c2ecebd601bc8e5139f869b7d08cb705c77ef757dacdd0593
F ext/jni/src/org/sqlite/jni/wrapper1/WindowFunction.java c7d1452f9ff26175b3c19bbf273116cc2846610af68e01756d755f037fe7319f
F ext/jni/src/tests/000-000-sanity.test c3427a0e0ac84d7cbe4c95fdc1cd4b61f9ddcf43443408f3000139478c4dc745
F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P f4f1cc201a7dc618a66617778ecf58ba60461ae700cb41f5c4abfa26dd0c0ed4
-R 94985542eb4157d1c2f915c1f903ad50
-U dan
-Z 2996a0d39c504eb56fd5f0fd9881439a
+P 6f9eed826f5b3d1cb08402925b406a7fe9b54259af1ba5eba92d4d37fbad628a
+R feb9a566cf38692cf88b194dedd844a6
+U stephan
+Z 3ab4c39a2f231e26a5c50b57bdfcf5f5
# Remove this line to create a well-formed Fossil manifest.
-6f9eed826f5b3d1cb08402925b406a7fe9b54259af1ba5eba92d4d37fbad628a
\ No newline at end of file
+3a69679e41d23a760df349b2471a1ed306c087f9a7a7a2e2cba3723071dee6b2
\ No newline at end of file