Add JNI wrapper1.SqliteStmt.bindXyz() APIs.
FossilOrigin-Name: 54fce9bf04a7517cdc8e96fe2efec66f03b0d03983c3a45d0ae7e1f16aa5a6c9
This commit is contained in:
@@ -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 */
|
||||
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
5c8383210a87d7f9d37a27053b5b1b6f41794fa8612826c68c1ca49c495cbd97
|
||||
54fce9bf04a7517cdc8e96fe2efec66f03b0d03983c3a45d0ae7e1f16aa5a6c9
|
||||
Reference in New Issue
Block a user