1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Expose sqlite3_complete() to JNI. Slightly widen the definition of "canonical" for the purposes of the @Canonical annotation. Add a few new tests.

FossilOrigin-Name: a59fe0cd9552128ca4186f4e66f0d188f2a57c7647f43828e42cb95801f350ce
This commit is contained in:
stephan
2023-09-02 12:53:25 +00:00
parent 216433636d
commit 7d31de600b
8 changed files with 107 additions and 33 deletions

View File

@ -2743,6 +2743,22 @@ S3JniApi(sqlite3_compileoption_get(),jstring,1compileoption_1get)(
return rv;
}
S3JniApi(sqlite3_complete(),int,1complete)(
JniArgsEnvClass, jbyteArray jSql
){
jbyte * const pBuf = s3jni_jbytearray_bytes(jSql);
const jsize nBa = pBuf ? (*env)->GetArrayLength(env, jSql) : 0;
int rc;
assert( (nBa>0 ? 0==pBuf[nBa-1] : (pBuf ? 0==*pBuf : 1))
&& "Byte array is not NUL-terminated." );
rc = (pBuf && 0==pBuf[(nBa ? nBa-1 : 0)])
? sqlite3_complete( (const char *)pBuf )
: (jSql ? SQLITE_NOMEM : SQLITE_ERROR);
s3jni_jbytearray_release(jSql, pBuf);
return rc;
}
S3JniApi(sqlite3_compileoption_used(),jboolean,1compileoption_1used)(
JniArgsEnvClass, jstring name
){

View File

@ -1099,14 +1099,6 @@ JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1value
JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1collation_1needed
(JNIEnv *, jclass, jobject, jobject);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_context_db_handle
* Signature: (Lorg/sqlite/jni/sqlite3_context;)Lorg/sqlite/jni/sqlite3;
*/
JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1context_1db_1handle
(JNIEnv *, jclass, jobject);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_commit_hook
@ -1131,6 +1123,14 @@ JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1compileoption_
JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1compileoption_1used
(JNIEnv *, jclass, jstring);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_complete
* Signature: ([B)I
*/
JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1complete
(JNIEnv *, jclass, jbyteArray);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_config
@ -1147,6 +1147,14 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1config__I
JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1config__Lorg_sqlite_jni_ConfigSqllogCallback_2
(JNIEnv *, jclass, jobject);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_context_db_handle
* Signature: (Lorg/sqlite/jni/sqlite3_context;)Lorg/sqlite/jni/sqlite3;
*/
JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1context_1db_1handle
(JNIEnv *, jclass, jobject);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_create_collation

View File

@ -230,6 +230,7 @@ public final class SQLite3Jni {
@NotNull sqlite3_stmt stmt, @NotNull byte[] paramName
);
@Canonical
public static int sqlite3_bind_parameter_index(
@NotNull sqlite3_stmt stmt, @NotNull String paramName
){
@ -495,11 +496,6 @@ public final class SQLite3Jni {
@NotNull sqlite3 db, @Nullable CollationNeededCallback callback
);
@Canonical
public static native sqlite3 sqlite3_context_db_handle(
@NotNull sqlite3_context cx
);
@Canonical
public static native CommitHookCallback sqlite3_commit_hook(
@NotNull sqlite3 db, @Nullable CommitHookCallback hook
@ -515,6 +511,24 @@ public final class SQLite3Jni {
@NotNull String optName
);
/**
This implementation is private because it's too easy to pass it
non-NUL-terminated arrays.
*/
@Canonical
private static native int sqlite3_complete(
@NotNull byte[] nulTerminatedUtf8Sql
);
@Canonical()
public static int sqlite3_complete(@NotNull String sql){
/* Design note: we don't implement this in native code because we
won't get a NUL-terminated string there unless we make our own
copy to add a terminator. That's much easier to do here. */
return sqlite3_complete( (sql+"\0").getBytes(StandardCharsets.UTF_8) );
}
/**
<p>Works like in the C API with the exception that it only supports
the following subset of configution flags:
@ -554,6 +568,11 @@ public final class SQLite3Jni {
@Canonical(comment="Option subset: SQLITE_CONFIG_SQLLOG")
public static native int sqlite3_config( @Nullable ConfigSqllogCallback logger );
@Canonical
public static native sqlite3 sqlite3_context_db_handle(
@NotNull sqlite3_context cx
);
@Canonical
public static native int sqlite3_create_collation(
@NotNull sqlite3 db, @NotNull String name, int eTextRep,
@ -761,6 +780,7 @@ public final class SQLite3Jni {
<p>Several overloads provided simplified call signatures.
*/
@Canonical
public static int sqlite3_prepare(
@NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
@NotNull OutputPointer.sqlite3_stmt outStmt,
@ -815,6 +835,7 @@ public final class SQLite3Jni {
output paramter is returned as the index offset into the given
byte array at which SQL parsing stopped.
*/
@Canonical
public static int sqlite3_prepare_v2(
@NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
@NotNull OutputPointer.sqlite3_stmt outStmt,
@ -865,6 +886,7 @@ public final class SQLite3Jni {
output paramter is returned as the index offset into the given
byte array at which SQL parsing stopped.
*/
@Canonical
public static int sqlite3_prepare_v3(
@NotNull sqlite3 db, @NotNull byte[] sqlUtf8, int prepFlags,
@NotNull OutputPointer.sqlite3_stmt outStmt,
@ -998,20 +1020,22 @@ public final class SQLite3Jni {
The main sqlite3_result_error() impl of which all others are
proxies. eTextRep must be one of SQLITE_UTF8 or SQLITE_UTF16 and
msg must be encoded correspondingly. Any other eTextRep value
results in the C-level sqlite3_result_error() being called with
a complaint about the invalid argument.
results in the C-level sqlite3_result_error() being called with a
complaint about the invalid argument.
*/
@Canonical
private static native void sqlite3_result_error(
@NotNull sqlite3_context cx, @NotNull byte[] msg, int eTextRep
);
@Canonical
public static void sqlite3_result_error(
@NotNull sqlite3_context cx, @NotNull byte[] utf8
){
sqlite3_result_error(cx, utf8, SQLITE_UTF8);
}
@Canonical
public static void sqlite3_result_error(
@NotNull sqlite3_context cx, @NotNull String msg
){
@ -1178,6 +1202,7 @@ public final class SQLite3Jni {
@NotNull sqlite3_context cx, @Nullable byte[] blob, int maxLen
);
@Canonical
public static void sqlite3_result_blob(
@NotNull sqlite3_context cx, @Nullable byte[] blob
){
@ -1207,6 +1232,7 @@ public final class SQLite3Jni {
@NotNull sqlite3_context cx, @Nullable byte[] blob, long maxLen
);
@Canonical
public static void sqlite3_result_blob64(
@NotNull sqlite3_context cx, @Nullable byte[] blob
){
@ -1222,12 +1248,14 @@ public final class SQLite3Jni {
@NotNull sqlite3_context cx, @Nullable byte[] utf8, int maxLen
);
@Canonical
public static void sqlite3_result_text(
@NotNull sqlite3_context cx, @Nullable byte[] utf8
){
sqlite3_result_text(cx, utf8, null==utf8 ? 0 : utf8.length);
}
@Canonical
public static void sqlite3_result_text(
@NotNull sqlite3_context cx, @Nullable String text
){
@ -1271,12 +1299,14 @@ public final class SQLite3Jni {
Sets the current UDF result to the given bytes, which are assumed
be encoded in UTF-16 using the platform's byte order.
*/
@Canonical
public static void sqlite3_result_text16(
@NotNull sqlite3_context cx, @Nullable byte[] utf16
){
sqlite3_result_text64(cx, utf16, utf16.length, SQLITE_UTF16);
}
@Canonical
public static void sqlite3_result_text16(
@NotNull sqlite3_context cx, @Nullable String text
){
@ -1363,9 +1393,10 @@ public final class SQLite3Jni {
*/
@Canonical
private static native int sqlite3_strglob(
@NotNull byte[] glob, @NotNull byte[] txt
@NotNull byte[] glob, @NotNull byte[] nullTerminatedUtf8
);
@Canonical
public static int sqlite3_strglob(
@NotNull String glob, @NotNull String txt
){
@ -1380,9 +1411,11 @@ public final class SQLite3Jni {
*/
@Canonical
private static native int sqlite3_strlike(
@NotNull byte[] glob, @NotNull byte[] txt, int escChar
@NotNull byte[] glob, @NotNull byte[] nullTerminatedUtf8,
int escChar
);
@Canonical
public static int sqlite3_strlike(
@NotNull String glob, @NotNull String txt, char escChar
){

View File

@ -1472,6 +1472,12 @@ public class Tester1 implements Runnable {
sqlite3_close_v2(db);
}
private void testComplete(){
affirm( 0==sqlite3_complete("select 1") );
affirm( 0!=sqlite3_complete("select 1;") );
affirm( 0!=sqlite3_complete("nope 'nope' 'nope' 1;"), "Yup" );
}
/* Copy/paste/rename this to add new tests. */
private void _testTemplate(){
final sqlite3 db = createNewDb();

View File

@ -40,16 +40,23 @@ public class TesterFts5 {
final fts5_extension_function func = new fts5_extension_function(){
@Override public void call(Fts5ExtensionApi ext, Fts5Context fCx,
sqlite3_context pCx, sqlite3_value argv[]){
int nCols = ext.xColumnCount(fCx);
final int nCols = ext.xColumnCount(fCx);
affirm( 2 == nCols );
affirm( nCols == argv.length );
affirm( ext.xUserData(fCx) == pUserData );
final OutputPointer.String op = new OutputPointer.String();
final OutputPointer.Int32 colsz = new OutputPointer.Int32();
final OutputPointer.Int64 colTotalSz = new OutputPointer.Int64();
for(int i = 0; i < nCols; ++i ){
int rc = ext.xColumnText(fCx, i, op);
affirm( 0 == rc );
final String val = op.value;
affirm( val.equals(sqlite3_value_text16(argv[i])) );
rc = ext.xColumnSize(fCx, i, colsz);
affirm( 0==rc );
affirm( 3==sqlite3_value_bytes(argv[i]) );
rc = ext.xColumnTotalSize(fCx, i, colTotalSz);
affirm( 0==rc );
}
++xFuncCount.value;
}

View File

@ -10,9 +10,13 @@ package org.sqlite.jni.annotation;
same semantics as their counterparts in <a
href="https://sqlite.org/c3ref/intro.html">the C API
documentation</a>, despite their signatures perhaps differing
slightly. The Java API adds a number of overloads to simplify use,
as well as a few Java-specific functions, and those are never
flagged as @Canonical.
slightly. Canonical forms may be native or implemented in Java.
Sometimes multiple overloads are labeled as Canonical because one
or more of them are just type- or encoding-related conversion
wrappers but provide identical semantics (e.g. from a String to a
byte[]). The Java API adds a number of convenience overloads to
simplify use, as well as a few Java-specific functions, and those
are never flagged as @Canonical.
<p>In some cases, the canonical version of a function is private
and exposed to Java via public overloads.