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:
@ -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
|
||||
){
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
){
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user