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

More work towards the new pointer-passing mechanism in JNI, and code-adjacent cleanups.

FossilOrigin-Name: 6c63987e893357dc8b10decaa96c30fb37b75481640a303e77a0d8224354491e
This commit is contained in:
stephan
2023-09-30 09:41:58 +00:00
parent 83f62816f8
commit ebce46f02f
5 changed files with 113 additions and 64 deletions

View File

@ -811,13 +811,13 @@ static void s3jni_incr( volatile unsigned int * const p ){
#endif
/* Helpers for jstring and jbyteArray. */
static const char * s3jni__jstring_to_mutf8_bytes(JNIEnv * const env, jstring v ){
static const char * s3jni__jstring_to_mutf8(JNIEnv * const env, jstring v ){
const char *z = v ? (*env)->GetStringUTFChars(env, v, NULL) : 0;
s3jni_oom_check( v ? !!z : !z );
return z;
}
#define s3jni_jstring_to_mutf8(ARG) s3jni__jstring_to_mutf8_bytes(env, (ARG))
#define s3jni_jstring_to_mutf8(ARG) s3jni__jstring_to_mutf8(env, (ARG))
#define s3jni_mutf8_release(ARG,VAR) if( VAR ) (*env)->ReleaseStringUTFChars(env, ARG, VAR)
static jbyte * s3jni__jbyteArray_bytes(JNIEnv * const env, jbyteArray jBA ){
@ -1515,6 +1515,8 @@ static void S3JniDb_xDestroy(void *p){
*/
#define S3JniDb_from_c(sqlite3Ptr) \
((sqlite3Ptr) ? S3JniDb_from_clientdata(sqlite3Ptr) : 0)
#define S3JniDb_from_jlong(sqlite3PtrAsLong) \
S3JniDb_from_c(S3JniLongPtr_T(sqlite3,sqlite3PtrAsLong))
/*
** Unref any Java-side state in (S3JniAutoExtension*) AX and zero out
@ -2520,7 +2522,7 @@ static int s3jni_busy_handler(void* pState, int n){
S3JniApi(sqlite3_busy_handler(),jint,1busy_1handler)(
JniArgsEnvClass, jlong jpDb, jobject jBusy
){
S3JniDb * const ps = S3JniDb_from_c(S3JniLongPtr_sqlite3(jpDb));
S3JniDb * const ps = S3JniDb_from_jlong(jpDb);
S3JniHook * const pHook = ps ? &ps->hooks.busyHandler : 0;
S3JniHook hook = S3JniHook_empty;
int rc = 0;
@ -2565,7 +2567,7 @@ S3JniApi(sqlite3_busy_handler(),jint,1busy_1handler)(
S3JniApi(sqlite3_busy_timeout(),jint,1busy_1timeout)(
JniArgsEnvClass, jlong jpDb, jint ms
){
S3JniDb * const ps = S3JniDb_from_c(S3JniLongPtr_sqlite3(jpDb));
S3JniDb * const ps = S3JniDb_from_jlong(jpDb);
int rc = SQLITE_MISUSE;
if( ps ){
S3JniDb_mutex_enter;
@ -2604,7 +2606,7 @@ S3JniApi(sqlite3_cancel_auto_extension(),jboolean,1cancel_1auto_1extension)(
/* Wrapper for sqlite3_close(_v2)(). */
static jint s3jni_close_db(JNIEnv * const env, jlong jpDb, int version){
int rc = 0;
S3JniDb * const ps = S3JniDb_from_c(S3JniLongPtr_sqlite3(jpDb));
S3JniDb * const ps = S3JniDb_from_jlong(jpDb);
assert(version == 1 || version == 2);
if( ps ){
@ -2666,14 +2668,14 @@ static void s3jni_collation_needed_impl16(void *pState, sqlite3 *pDb,
}
S3JniApi(sqlite3_collation_needed(),jint,1collation_1needed)(
JniArgsEnvClass, jobject jDb, jobject jHook
JniArgsEnvClass, jlong jpDb, jobject jHook
){
S3JniDb * ps;
S3JniCollationNeeded * pHook;
int rc = 0;
S3JniDb_mutex_enter;
ps = S3JniDb_from_java(jDb);
ps = S3JniDb_from_jlong(jpDb);
if( !ps ){
S3JniDb_mutex_leave;
return SQLITE_MISUSE;
@ -2816,13 +2818,13 @@ static void s3jni_rollback_hook_impl(void *pP){
** sqlite3_rollback_hook().
*/
static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv * const env,
jobject jDb, jobject jHook){
jlong jpDb, jobject jHook){
S3JniDb * ps;
jobject pOld = 0; /* previous hoook */
S3JniHook * pHook; /* ps->hooks.commit|rollback */
S3JniDb_mutex_enter;
ps = S3JniDb_from_java(jDb);
ps = S3JniDb_from_jlong(jpDb);
if( !ps ){
s3jni_db_error(ps->pDb, SQLITE_NOMEM, 0);
S3JniDb_mutex_leave;
@ -2870,9 +2872,9 @@ static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv * const env,
}
S3JniApi(sqlite3_commit_hook(),jobject,1commit_1hook)(
JniArgsEnvClass,jobject jDb, jobject jHook
JniArgsEnvClass, jlong jpDb, jobject jHook
){
return s3jni_commit_rollback_hook(1, env, jDb, jHook);
return s3jni_commit_rollback_hook(1, env, jpDb, jHook);
}
S3JniApi(sqlite3_compileoption_get(),jstring,1compileoption_1get)(
@ -2904,12 +2906,17 @@ S3JniApi(sqlite3_complete(),int,1complete)(
S3JniApi(sqlite3_compileoption_used(),jboolean,1compileoption_1used)(
JniArgsEnvClass, jstring name
){
const char *zUtf8 = s3jni_jstring_to_mutf8(name)
/* We know these to be ASCII, so MUTF-8 is fine. */;
const jboolean rc =
0==sqlite3_compileoption_used(zUtf8) ? JNI_FALSE : JNI_TRUE;
s3jni_mutf8_release(name, zUtf8);
return rc;
if( name ){
const char *zUtf8 = s3jni_jstring_to_mutf8(name)
/* We know these to be ASCII, so MUTF-8 is fine (and
hypothetically faster to convert). */;
const jboolean rc =
0==sqlite3_compileoption_used(zUtf8) ? JNI_FALSE : JNI_TRUE;
s3jni_mutf8_release(name, zUtf8);
return rc;
}else{
return JNI_FALSE;
}
}
S3JniApi(sqlite3_config() /*for a small subset of options.*/,
@ -3118,7 +3125,7 @@ S3JniApi(sqlite3_create_collation() sqlite3_create_collation_v2(),
S3JniDb_mutex_enter;
ps = S3JniDb_from_java(jDb);
if( !ps ){
if( !ps || !name ){
rc = SQLITE_MISUSE;
}else{
jclass const klazz = (*env)->GetObjectClass(env, oCollation);
@ -3164,7 +3171,9 @@ S3JniApi(sqlite3_create_function() sqlite3_create_function_v2()
sqlite3 * const pDb = PtrGet_sqlite3(jDb);
char * zFuncName = 0;
if( !encodingTypeIsValid(eTextRep) ){
if( !pDb || !jFuncName ){
return SQLITE_MISUSE;
}else if( !encodingTypeIsValid(eTextRep) ){
return s3jni_db_error(pDb, SQLITE_FORMAT,
"Invalid function encoding option.");
}
@ -3793,7 +3802,7 @@ S3JniApi(sqlite3_preupdate_depth(),int,1preupdate_1depth)(
** sqlite3_preupdate_hook() (if isPre is true).
*/
static jobject s3jni_updatepre_hook(JNIEnv * env, int isPre, jlong jpDb, jobject jHook){
S3JniDb * const ps = S3JniDb_from_c(S3JniLongPtr_sqlite3(jpDb));
S3JniDb * const ps = S3JniDb_from_jlong(jpDb);
jclass klazz;
jobject pOld = 0;
jmethodID xCallback;
@ -4211,9 +4220,9 @@ S3JniApi(sqlite3_result_zeroblob64(),jint,1result_1zeroblob64)(
}
S3JniApi(sqlite3_rollback_hook(),jobject,1rollback_1hook)(
JniArgsEnvClass, jobject jDb, jobject jHook
JniArgsEnvClass, jlong jpDb, jobject jHook
){
return s3jni_commit_rollback_hook(0, env, jDb, jHook);
return s3jni_commit_rollback_hook(0, env, jpDb, jHook);
}
/* Callback for sqlite3_set_authorizer(). */

View File

@ -1198,18 +1198,18 @@ JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1value
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_collation_needed
* Signature: (Lorg/sqlite/jni/sqlite3;Lorg/sqlite/jni/CollationNeededCallback;)I
* Signature: (JLorg/sqlite/jni/CollationNeededCallback;)I
*/
JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1collation_1needed
(JNIEnv *, jclass, jobject, jobject);
(JNIEnv *, jclass, jlong, jobject);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_commit_hook
* Signature: (Lorg/sqlite/jni/sqlite3;Lorg/sqlite/jni/CommitHookCallback;)Lorg/sqlite/jni/CommitHookCallback;
* Signature: (JLorg/sqlite/jni/CommitHookCallback;)Lorg/sqlite/jni/CommitHookCallback;
*/
JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1commit_1hook
(JNIEnv *, jclass, jobject, jobject);
(JNIEnv *, jclass, jlong, jobject);
/*
* Class: org_sqlite_jni_SQLite3Jni
@ -1758,10 +1758,10 @@ JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1text64
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_rollback_hook
* Signature: (Lorg/sqlite/jni/sqlite3;Lorg/sqlite/jni/RollbackHookCallback;)Lorg/sqlite/jni/RollbackHookCallback;
* Signature: (JLorg/sqlite/jni/RollbackHookCallback;)Lorg/sqlite/jni/RollbackHookCallback;
*/
JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1rollback_1hook
(JNIEnv *, jclass, jobject, jobject);
(JNIEnv *, jclass, jlong, jobject);
/*
* Class: org_sqlite_jni_SQLite3Jni

View File

@ -92,6 +92,14 @@ public final class SQLite3Jni {
//! Called from static init code.
private static native void init();
/**
Returns a nul-terminated copy of s as a byte array, or null if s
is null.
*/
private static byte[] nulTerminateUtf8(String s){
return null==s ? null : (s+"\0").getBytes(StandardCharsets.UTF_8);
}
/**
Each thread which uses the SQLite3 JNI APIs should call
sqlite3_jni_uncache_thread() when it is done with the library -
@ -315,8 +323,8 @@ public final class SQLite3Jni {
public static int sqlite3_bind_parameter_index(
@NotNull sqlite3_stmt stmt, @NotNull String paramName
){
final byte[] utf8 = (paramName+"\0").getBytes(StandardCharsets.UTF_8);
return sqlite3_bind_parameter_index(stmt.getNativePointer(), utf8);
final byte[] utf8 = nulTerminateUtf8(paramName);
return null==utf8 ? 0 : sqlite3_bind_parameter_index(stmt.getNativePointer(), utf8);
}
@Canonical
@ -742,29 +750,43 @@ public final class SQLite3Jni {
@NotNull sqlite3_stmt stmt, int ndx
);
@Canonical
static native int sqlite3_collation_needed(
@NotNull long ptrToDb, @Nullable CollationNeededCallback callback
);
/**
This functions like C's sqlite3_collation_needed16() because
Java's string type is inherently compatible with that interface.
*/
@Canonical
public static native int sqlite3_collation_needed(
public static int sqlite3_collation_needed(
@NotNull sqlite3 db, @Nullable CollationNeededCallback callback
){
return sqlite3_collation_needed(db.getNativePointer(), callback);
}
@Canonical
static native CommitHookCallback sqlite3_commit_hook(
@NotNull long ptrToDb, @Nullable CommitHookCallback hook
);
@Canonical
public static native CommitHookCallback sqlite3_commit_hook(
public static CommitHookCallback sqlite3_commit_hook(
@NotNull sqlite3 db, @Nullable CommitHookCallback hook
);
){
return sqlite3_commit_hook(db.getNativePointer(), hook);
}
@Canonical
public static native String sqlite3_compileoption_get(
int n
);
public static native String sqlite3_compileoption_get(int n);
/**
Unlike the C API, returns false if its argument is NULL (as
opposed to invoking UB).
*/
@Canonical
public static native boolean sqlite3_compileoption_used(
@NotNull String optName
);
public static native boolean sqlite3_compileoption_used(String optName);
/**
This implementation is private because it's too easy to pass it
@ -775,12 +797,13 @@ public final class SQLite3Jni {
@NotNull byte[] nulTerminatedUtf8Sql
);
/**
Unlike this C API, this returns SQLITE_MISUSE if its argument is
null (as opposed to invoking UB).
*/
@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) );
public static int sqlite3_complete(String sql){
return null==sql ? SQLITE_MISUSE : sqlite3_complete( nulTerminateUtf8(sql) );
}
@ -828,11 +851,19 @@ public final class SQLite3Jni {
@Canonical(comment="Option subset: SQLITE_CONFIG_LOG")
public static native int sqlite3_config( @Nullable ConfigLogCallback logger );
/**
Unlike this C API, this returns null if its argument is
null (as opposed to invoking UB).
*/
@Canonical
public static native sqlite3 sqlite3_context_db_handle(
@NotNull sqlite3_context cx
);
/**
Unlike this C API, this returns SQLITE_MISUSE if its db or name
arguments are null (as opposed to invoking UB).
*/
@Canonical
public static native int sqlite3_create_collation(
@NotNull sqlite3 db, @NotNull String name, int eTextRep,
@ -846,6 +877,9 @@ public final class SQLite3Jni {
depends on which methods the final argument implements. See
SQLFunction's subclasses (ScalarFunction, AggregateFunction<T>,
and WindowFunction<T>) for details.
Unlike this C API, this returns SQLITE_MISUSE null if its db or
functionName arguments are null (as opposed to invoking UB).
*/
@Canonical
public static native int sqlite3_create_function(
@ -865,6 +899,9 @@ public final class SQLite3Jni {
Overload for sqlite3_db_config() calls which take (int,int*)
variadic arguments. Returns SQLITE_MISUSE if op is not one of the
SQLITE_DBCONFIG_... options which uses this call form.
Unlike this C API, this returns SQLITE_MISUSE if its db argument
are null (as opposed to invoking UB).
*/
@Canonical
public static native int sqlite3_db_config(
@ -1771,10 +1808,17 @@ public final class SQLite3Jni {
}
@Canonical
public static native RollbackHookCallback sqlite3_rollback_hook(
@NotNull sqlite3 db, @Nullable RollbackHookCallback hook
static native RollbackHookCallback sqlite3_rollback_hook(
@NotNull long ptrToDb, @Nullable RollbackHookCallback hook
);
@Canonical
public static RollbackHookCallback sqlite3_rollback_hook(
@NotNull sqlite3 db, @Nullable RollbackHookCallback hook
){
return sqlite3_rollback_hook(db.getNativePointer(), hook);
}
@Canonical
public static native int sqlite3_set_authorizer(
@NotNull sqlite3 db, @Nullable AuthorizerCallback auth
@ -1876,10 +1920,8 @@ public final class SQLite3Jni {
public static int sqlite3_strglob(
@NotNull String glob, @NotNull String txt
){
return sqlite3_strglob(
(glob+"\0").getBytes(StandardCharsets.UTF_8),
(txt+"\0").getBytes(StandardCharsets.UTF_8)
);
return sqlite3_strglob(nulTerminateUtf8(glob),
nulTerminateUtf8(txt));
}
/**
@ -1895,11 +1937,9 @@ public final class SQLite3Jni {
public static int sqlite3_strlike(
@NotNull String glob, @NotNull String txt, char escChar
){
return sqlite3_strlike(
(glob+"\0").getBytes(StandardCharsets.UTF_8),
(txt+"\0").getBytes(StandardCharsets.UTF_8),
(int)escChar
);
return sqlite3_strlike(nulTerminateUtf8(glob),
nulTerminateUtf8(txt),
(int)escChar);
}
@Canonical