Correct JNI layer's misuse of an sqlite3-internal error-reporting API (no mutex held). Style cleanups. Eliminate lookups of per-thread state by approximately 85% across the test suite.

FossilOrigin-Name: 1f46ba8d3bc61af771c1e33d09ad25f0da4fc4f915f7a9f6223ebfd99526d81d
This commit is contained in:
stephan 2023-08-24 14:31:36 +00:00
parent bfdc7ab5a7
commit e7a4685837
4 changed files with 92 additions and 99 deletions

View File

@ -303,7 +303,7 @@ static const struct {
/** Create a trivial JNI wrapper for (jstring CName(sqlite3_stmt*,int)). */
#define WRAP_STR_STMT_INT(JniNameSuffix,CName) \
JDECL(jstring,JniNameSuffix)(JENV_CSELF, jobject pStmt, jint ndx){ \
return s3jni_utf8_to_jstring(S3JniGlobal_env_cache(env), \
return s3jni_utf8_to_jstring(env, \
CName(PtrGet_sqlite3_stmt(pStmt), (int)ndx), \
-1); \
}
@ -324,10 +324,10 @@ static const struct {
}
/* Helpers for jstring and jbyteArray. */
#define JSTR_TOC(ARG) (*env)->GetStringUTFChars(env, ARG, NULL)
#define JSTR_RELEASE(ARG,VAR) if(VAR) (*env)->ReleaseStringUTFChars(env, ARG, VAR)
#define JBA_TOC(ARG) (*env)->GetByteArrayElements(env,ARG, NULL)
#define JBA_RELEASE(ARG,VAR) if(VAR) (*env)->ReleaseByteArrayElements(env, ARG, VAR, JNI_ABORT)
#define s3jni_jstring_to_mutf8(ARG) (*env)->GetStringUTFChars(env, ARG, NULL)
#define s3jni_mutf8_release(ARG,VAR) if(VAR) (*env)->ReleaseStringUTFChars(env, ARG, VAR)
#define s3jni_jbytearray_bytes(ARG) (*env)->GetByteArrayElements(env,ARG, NULL)
#define s3jni_jbytearray_release(ARG,VAR) if(VAR) (*env)->ReleaseByteArrayElements(env, ARG, VAR, JNI_ABORT)
enum {
/*
@ -423,9 +423,7 @@ struct S3JniEnv {
**
** - In the JNI side of sqlite3_open(), allocate the Java side of
** that connection and set pdbOpening to point to that
** object. Note that it's per-thread, and we remain in that
** thread until after the auto-extensions are run, so we don't
** need to mutex-lock this.
** object.
**
** - Call sqlite3_open(), which triggers the auto-extension
** handler. That handler uses pdbOpening to connect the native
@ -631,7 +629,7 @@ static void s3jni_incr( volatile unsigned int * const p ){
SJG.perDb.locker = 0; \
sqlite3_mutex_leave( SJG.perDb.mutex )
#define OOM_CHECK(VAR) if(!(VAR)) s3jni_oom(env)
#define s3jni_oom_check(VAR) if(!(VAR)) s3jni_oom(env)
static inline void s3jni_oom(JNIEnv * const env){
(*env)->FatalError(env, "Out of memory.") /* does not return */;
}
@ -706,7 +704,9 @@ static int s3jni_db_error(sqlite3* const db, int err_code,
sqlite3Error(db, err_code);
}else{
const int nMsg = sqlite3Strlen30(zMsg);
sqlite3_mutex_enter(sqlite3_db_mutex(db));
sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg);
sqlite3_mutex_leave(sqlite3_db_mutex(db));
}
}
return err_code;
@ -753,10 +753,9 @@ static JNIEnv * s3jni_get_env(void){
** standard UTF-8 to a Java string, but JNI offers only algorithms for
** working with MUTF-8, not UTF-8.
*/
static jstring s3jni_utf8_to_jstring(S3JniEnv * const jc,
static jstring s3jni_utf8_to_jstring(JNIEnv * const env,
const char * const z, int n){
jstring rv = NULL;
LocalJniGetEnv;
if( 0==n || (n<0 && z && !z[0]) ){
/* Fast-track the empty-string case via the MUTF-8 API. We could
hypothetically do this for any strings where n<4 and z is
@ -790,9 +789,8 @@ static jstring s3jni_utf8_to_jstring(S3JniEnv * const jc,
** The returned memory is allocated from sqlite3_malloc() and
** ownership is transferred to the caller.
*/
static char * s3jni_jstring_to_utf8(S3JniEnv * const jc,
static char * s3jni_jstring_to_utf8(JNIEnv * const env,
jstring jstr, int *nLen){
LocalJniGetEnv;
jbyteArray jba;
jsize nBa;
char *rv;
@ -844,7 +842,6 @@ static jstring s3jni_text16_to_jstring(JNIEnv * const env, const void * const p,
** System.out.println(e.getMessage()); // Hi
*/
static char * s3jni_exception_error_msg(JNIEnv * const env, jthrowable jx ){
S3JniEnv * const jc = S3JniGlobal_env_cache(env);
jmethodID mid;
jstring msg;
char * zMsg;
@ -862,7 +859,7 @@ static char * s3jni_exception_error_msg(JNIEnv * const env, jthrowable jx ){
EXCEPTION_CLEAR;
return 0;
}
zMsg = s3jni_jstring_to_utf8(jc, msg, 0);
zMsg = s3jni_jstring_to_utf8(env, msg, 0);
UNREF_L(msg);
return zMsg;
}
@ -1484,7 +1481,7 @@ static jobject new_NativePointerHolder_object(JNIEnv * const env, S3NphRef const
}
rv = (*env)->NewObject(env, pNC->klazz, pNC->midCtor);
EXCEPTION_IS_FATAL("No-arg constructor threw.");
OOM_CHECK(rv);
s3jni_oom_check(rv);
if(rv) NativePointerHolder_set(env, rv, pNative, pRef);
return rv;
}
@ -1807,6 +1804,16 @@ WRAP_INT_SVALUE(1value_1numeric_1type, sqlite3_value_numeric_type)
WRAP_INT_SVALUE(1value_1subtype, sqlite3_value_subtype)
WRAP_INT_SVALUE(1value_1type, sqlite3_value_type)
#undef WRAP_INT64_DB
#undef WRAP_INT_DB
#undef WRAP_INT_INT
#undef WRAP_INT_STMT
#undef WRAP_INT_STMT_INT
#undef WRAP_INT_SVALUE
#undef WRAP_INT_VOID
#undef WRAP_MUTF8_VOID
#undef WRAP_STR_STMT_INT
/* Central auto-extension handler. */
static int s3jni_run_java_auto_extensions(sqlite3 *pDb, const char **pzErr,
const struct sqlite3_api_routines *ignored){
@ -1915,10 +1922,10 @@ JDECL(jint,1auto_1extension)(JENV_CSELF, jobject jAutoExt){
JDECL(jint,1bind_1blob)(JENV_CSELF, jobject jpStmt,
jint ndx, jbyteArray baData, jint nMax){
jbyte * const pBuf = baData ? JBA_TOC(baData) : 0;
jbyte * const pBuf = baData ? s3jni_jbytearray_bytes(baData) : 0;
int const rc = sqlite3_bind_blob(PtrGet_sqlite3_stmt(jpStmt), (int)ndx,
pBuf, (int)nMax, SQLITE_TRANSIENT);
JBA_RELEASE(baData,pBuf);
s3jni_jbytearray_release(baData,pBuf);
return (jint)rc;
}
@ -1944,31 +1951,31 @@ JDECL(jint,1bind_1null)(JENV_CSELF, jobject jpStmt,
JDECL(jint,1bind_1parameter_1index)(JENV_CSELF, jobject jpStmt, jbyteArray jName){
int rc = 0;
jbyte * const pBuf = JBA_TOC(jName);
jbyte * const pBuf = s3jni_jbytearray_bytes(jName);
if(pBuf){
rc = sqlite3_bind_parameter_index(PtrGet_sqlite3_stmt(jpStmt),
(const char *)pBuf);
JBA_RELEASE(jName, pBuf);
s3jni_jbytearray_release(jName, pBuf);
}
return rc;
}
JDECL(jint,1bind_1text)(JENV_CSELF, jobject jpStmt,
jint ndx, jbyteArray baData, jint nMax){
jbyte * const pBuf = baData ? JBA_TOC(baData) : 0;
jbyte * const pBuf = baData ? s3jni_jbytearray_bytes(baData) : 0;
int const rc = sqlite3_bind_text(PtrGet_sqlite3_stmt(jpStmt), (int)ndx,
(const char *)pBuf,
(int)nMax, SQLITE_TRANSIENT);
JBA_RELEASE(baData, pBuf);
s3jni_jbytearray_release(baData, pBuf);
return (jint)rc;
}
JDECL(jint,1bind_1text16)(JENV_CSELF, jobject jpStmt,
jint ndx, jbyteArray baData, jint nMax){
jbyte * const pBuf = baData ? JBA_TOC(baData) : 0;
jbyte * const pBuf = baData ? s3jni_jbytearray_bytes(baData) : 0;
int const rc = sqlite3_bind_text16(PtrGet_sqlite3_stmt(jpStmt), (int)ndx,
pBuf, (int)nMax, SQLITE_TRANSIENT);
JBA_RELEASE(baData, pBuf);
s3jni_jbytearray_release(baData, pBuf);
return (jint)rc;
}
@ -2295,10 +2302,10 @@ JDECL(jstring,1compileoption_1get)(JENV_CSELF, jint n){
}
JDECL(jboolean,1compileoption_1used)(JENV_CSELF, jstring name){
const char *zUtf8 = JSTR_TOC(name);
const char *zUtf8 = s3jni_jstring_to_mutf8(name);
const jboolean rc =
0==sqlite3_compileoption_used(zUtf8) ? JNI_FALSE : JNI_TRUE;
JSTR_RELEASE(name, zUtf8);
s3jni_mutf8_release(name, zUtf8);
return rc;
}
@ -2323,7 +2330,6 @@ static void s3jni_config_sqllog(void *ignored, sqlite3 *pDb, const char *z, int
jobject jArg0 = 0;
jstring jArg1 = 0;
LocalJniGetEnv;
S3JniEnv * const jc = S3JniGlobal_env_cache(env);
S3JniDb * const ps = S3JniDb_for_db(env, 0, pDb);
S3JniHook * const hook = &SJG.hooks.sqllog;
@ -2332,7 +2338,7 @@ static void s3jni_config_sqllog(void *ignored, sqlite3 *pDb, const char *z, int
switch(op){
case 0: /* db opened */
case 1: /* SQL executed */
jArg1 = s3jni_utf8_to_jstring(jc, z, -1);
jArg1 = s3jni_utf8_to_jstring(env, z, -1);
break;
case 2: /* db closed */
break;
@ -2420,11 +2426,11 @@ JDECL(jint,1create_1collation)(JENV_CSELF, jobject jDb,
return s3jni_db_error(ps->pDb, SQLITE_ERROR,
"Could not get xCompare() method for object.");
}
zName = JSTR_TOC(name);
zName = s3jni_jstring_to_mutf8(name);
rc = sqlite3_create_collation_v2(ps->pDb, zName, (int)eTextRep,
ps, CollationState_xCompare,
CollationState_xDestroy);
JSTR_RELEASE(name, zName);
s3jni_mutf8_release(name, zName);
if( 0==rc ){
pHook->jObj = REF_G(oCollation);
}else{
@ -2438,7 +2444,7 @@ JDECL(jint,1create_1function)(JENV_CSELF, jobject jDb, jstring jFuncName,
S3JniUdf * s = 0;
int rc;
sqlite3 * const pDb = PtrGet_sqlite3(jDb);
const char * zFuncName = 0;
char * zFuncName = 0;
if( !encodingTypeIsValid(eTextRep) ){
return s3jni_db_error(pDb, SQLITE_FORMAT,
@ -2452,7 +2458,7 @@ JDECL(jint,1create_1function)(JENV_CSELF, jobject jDb, jstring jFuncName,
S3JniUdf_free(s);
goto error_cleanup;
}
zFuncName = JSTR_TOC(jFuncName);
zFuncName = s3jni_jstring_to_utf8(env,jFuncName,0);
if(!zFuncName){
rc = SQLITE_NOMEM;
S3JniUdf_free(s);
@ -2476,14 +2482,8 @@ JDECL(jint,1create_1function)(JENV_CSELF, jobject jDb, jstring jFuncName,
rc = sqlite3_create_function_v2(pDb, zFuncName, nArg, eTextRep, s,
xFunc, xStep, xFinal, S3JniUdf_finalizer);
}
if( 0==rc ){
s->zFuncName = sqlite3_mprintf("%s", zFuncName)
/* OOM here is non-fatal. Ignore it. Handling it would require
** re-calling the appropriate create_function() func with 0
** for all xAbc args so that s would be finalized. */;
}
error_cleanup:
JSTR_RELEASE(jFuncName, zFuncName);
sqlite3_free(zFuncName);
/* on sqlite3_create_function() error, s will be destroyed via
** create_function(), so we're not leaking s. */
return (jint)rc;
@ -2499,7 +2499,7 @@ JDECL(int,1db_1config__Lorg_sqlite_jni_sqlite3_2ILjava_lang_String_2)(
switch( (ps && jStr) ? op : 0 ){
case SQLITE_DBCONFIG_MAINDBNAME:
zStr = s3jni_jstring_to_utf8(S3JniGlobal_env_cache(env), jStr, 0);
zStr = s3jni_jstring_to_utf8(env, jStr, 0);
if( zStr ){
rc = sqlite3_db_config(ps->pDb, (int)op, zStr);
if( rc ){
@ -2577,7 +2577,6 @@ JDECL(jint,1db_1config__Lorg_sqlite_jni_sqlite3_2IILorg_sqlite_jni_OutputPointer
JDECL(jstring,1db_1filename)(JENV_CSELF, jobject jDb, jstring jDbName){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
S3JniEnv * const jc = ps ? S3JniGlobal_env_cache(env) : 0;
char *zDbName;
jstring jRv = 0;
int nStr = 0;
@ -2585,12 +2584,12 @@ JDECL(jstring,1db_1filename)(JENV_CSELF, jobject jDb, jstring jDbName){
if( !ps || !jDbName ){
return 0;
}
zDbName = s3jni_jstring_to_utf8(jc, jDbName, &nStr);
zDbName = s3jni_jstring_to_utf8(env, jDbName, &nStr);
if( zDbName ){
char const * zRv = sqlite3_db_filename(ps->pDb, zDbName);
sqlite3_free(zDbName);
if( zRv ){
jRv = s3jni_utf8_to_jstring(jc, zRv, -1);
jRv = s3jni_utf8_to_jstring(env, zRv, -1);
}
}
return jRv;
@ -2617,8 +2616,7 @@ JDECL(jint,1errcode)(JENV_CSELF, jobject jpDb){
JDECL(jstring,1errmsg)(JENV_CSELF, jobject jpDb){
sqlite3 * const pDb = PtrGet_sqlite3(jpDb);
S3JniEnv * const jc = pDb ? S3JniGlobal_env_cache(env) : 0;
return jc ? s3jni_utf8_to_jstring(jc, sqlite3_errmsg(pDb), -1) : 0;
return pDb ? s3jni_utf8_to_jstring(env, sqlite3_errmsg(pDb), -1) : 0;
}
JDECL(jstring,1errstr)(JENV_CSELF, jint rcCode){
@ -2631,11 +2629,10 @@ JDECL(jstring,1expanded_1sql)(JENV_CSELF, jobject jpStmt){
sqlite3_stmt * const pStmt = PtrGet_sqlite3_stmt(jpStmt);
jstring rv = 0;
if( pStmt ){
S3JniEnv * const jc = S3JniGlobal_env_cache(env);
char * zSql = sqlite3_expanded_sql(pStmt);
OOM_CHECK(zSql);
s3jni_oom_check(zSql);
if( zSql ){
rv = s3jni_utf8_to_jstring(jc, zSql, -1);
rv = s3jni_utf8_to_jstring(env, zSql, -1);
sqlite3_free(zSql);
}
}
@ -2692,7 +2689,7 @@ static int s3jni_open_pre(JNIEnv * const env, S3JniEnv **jc,
rc = SQLITE_NOMEM;
goto end;
}
*zDbName = jDbName ? s3jni_jstring_to_utf8(*jc, jDbName, 0) : 0;
*zDbName = jDbName ? s3jni_jstring_to_utf8(env, jDbName, 0) : 0;
if(jDbName && !*zDbName){
rc = SQLITE_NOMEM;
goto end;
@ -2771,7 +2768,7 @@ JDECL(jint,1open_1v2)(JENV_CSELF, jstring strName,
char *zVfs = 0;
int rc = s3jni_open_pre(env, &jc, strName, &zName, &ps);
if( 0==rc && strVfs ){
zVfs = s3jni_jstring_to_utf8(jc, strVfs, 0);
zVfs = s3jni_jstring_to_utf8(env, strVfs, 0);
if( !zVfs ){
rc = SQLITE_NOMEM;
}
@ -2794,7 +2791,7 @@ static jint sqlite3_jni_prepare_v123(int prepVersion, JNIEnv * const env, jclass
sqlite3_stmt * pStmt = 0;
jobject jStmt = 0;
const char * zTail = 0;
jbyte * const pBuf = JBA_TOC(baSql);
jbyte * const pBuf = s3jni_jbytearray_bytes(baSql);
int rc = SQLITE_ERROR;
assert(prepVersion==1 || prepVersion==2 || prepVersion==3);
if( !pBuf ){
@ -2821,7 +2818,7 @@ static jint sqlite3_jni_prepare_v123(int prepVersion, JNIEnv * const env, jclass
assert(0 && "Invalid prepare() version");
}
end:
JBA_RELEASE(baSql,pBuf);
s3jni_jbytearray_release(baSql,pBuf);
if( 0==rc ){
if( 0!=outTail ){
/* Noting that pBuf is deallocated now but its address is all we need for
@ -2879,7 +2876,6 @@ static void s3jni_updatepre_hook_impl(void * pState, sqlite3 *pDb, int opId,
sqlite3_int64 iKey1, sqlite3_int64 iKey2){
S3JniDb * const ps = pState;
LocalJniGetEnv;
S3JniEnv * const jc = S3JniGlobal_env_cache(env);
jstring jDbName;
jstring jTable;
S3JniHook * pHook;
@ -2894,8 +2890,8 @@ static void s3jni_updatepre_hook_impl(void * pState, sqlite3 *pDb, int opId,
: &ps->hooks.update;
assert( pHook );
jDbName = s3jni_utf8_to_jstring(jc, zDb, -1);
jTable = jDbName ? s3jni_utf8_to_jstring(jc, zTable, -1) : 0;
jDbName = s3jni_utf8_to_jstring(env, zDb, -1);
jTable = jDbName ? s3jni_utf8_to_jstring(env, zTable, -1) : 0;
IFTHREW {
EXCEPTION_CLEAR;
s3jni_db_error(ps->pDb, SQLITE_NOMEM, 0);
@ -3131,7 +3127,7 @@ static void result_blob_text(int asBlob, int as64,
JNIEnv * const env, sqlite3_context *pCx,
jbyteArray jBa, jlong nMax){
if(jBa){
jbyte * const pBuf = JBA_TOC(jBa);
jbyte * const pBuf = s3jni_jbytearray_bytes(jBa);
jsize nBa = (*env)->GetArrayLength(env, jBa);
if( nMax>=0 && nBa>(jsize)nMax ){
nBa = (jsize)nMax;
@ -3196,7 +3192,7 @@ static void result_blob_text(int asBlob, int as64,
break;
}
}
JBA_RELEASE(jBa, pBuf);
s3jni_jbytearray_release(jBa, pBuf);
}
}else{
sqlite3_result_null(pCx);
@ -3219,7 +3215,7 @@ JDECL(void,1result_1error)(JENV_CSELF, jobject jpCx, jbyteArray baMsg,
int eTextRep){
const char * zUnspecified = "Unspecified error.";
jsize const baLen = (*env)->GetArrayLength(env, baMsg);
jbyte * const pjBuf = baMsg ? JBA_TOC(baMsg) : NULL;
jbyte * const pjBuf = baMsg ? s3jni_jbytearray_bytes(baMsg) : NULL;
switch(pjBuf ? eTextRep : SQLITE_UTF8){
case SQLITE_UTF8: {
const char *zMsg = pjBuf ? (const char *)pjBuf : zUnspecified;
@ -3238,7 +3234,7 @@ JDECL(void,1result_1error)(JENV_CSELF, jobject jpCx, jbyteArray baMsg,
"to sqlite3_result_error().", -1);
break;
}
JBA_RELEASE(baMsg,pjBuf);
s3jni_jbytearray_release(baMsg,pjBuf);
}
JDECL(void,1result_1error_1code)(JENV_CSELF, jobject jpCx, jint v){
@ -3313,12 +3309,11 @@ static int s3jni_xAuth(void* pState, int op,const char*z0, const char*z1,
const char*z2,const char*z3){
S3JniDb * const ps = pState;
LocalJniGetEnv;
S3JniEnv * const jc = S3JniGlobal_env_cache(env);
S3JniHook const * const pHook = &ps->hooks.auth;
jstring const s0 = z0 ? s3jni_utf8_to_jstring(jc, z0, -1) : 0;
jstring const s1 = z1 ? s3jni_utf8_to_jstring(jc, z1, -1) : 0;
jstring const s2 = z2 ? s3jni_utf8_to_jstring(jc, z2, -1) : 0;
jstring const s3 = z3 ? s3jni_utf8_to_jstring(jc, z3, -1) : 0;
jstring const s0 = z0 ? s3jni_utf8_to_jstring(env, z0, -1) : 0;
jstring const s1 = z1 ? s3jni_utf8_to_jstring(env, z1, -1) : 0;
jstring const s2 = z2 ? s3jni_utf8_to_jstring(env, z2, -1) : 0;
jstring const s3 = z3 ? s3jni_utf8_to_jstring(env, z3, -1) : 0;
int rc;
assert( pHook->jObj );
@ -3405,18 +3400,18 @@ JDECL(jint,1status64)(JENV_CSELF, jint op, jobject jOutCurrent, jobject jOutHigh
static int s3jni_strlike_glob(int isLike, JNIEnv *const env,
jbyteArray baG, jbyteArray baT, jint escLike){
int rc = 0;
jbyte * const pG = JBA_TOC(baG);
jbyte * const pT = pG ? JBA_TOC(baT) : 0;
jbyte * const pG = s3jni_jbytearray_bytes(baG);
jbyte * const pT = pG ? s3jni_jbytearray_bytes(baT) : 0;
OOM_CHECK(pT);
s3jni_oom_check(pT);
/* Note that we're relying on the byte arrays having been
NUL-terminated on the Java side. */
rc = isLike
? sqlite3_strlike((const char *)pG, (const char *)pT,
(unsigned int)escLike)
: sqlite3_strglob((const char *)pG, (const char *)pT);
JBA_RELEASE(baG, pG);
JBA_RELEASE(baT, pT);
s3jni_jbytearray_release(baG, pG);
s3jni_jbytearray_release(baT, pT);
return rc;
}
@ -3445,10 +3440,9 @@ JDECL(jstring,1sql)(JENV_CSELF, jobject jpStmt){
jstring rv = 0;
if( pStmt ){
const char * zSql = 0;
S3JniEnv * const jc = S3JniGlobal_env_cache(env);
zSql = sqlite3_sql(pStmt);
rv = s3jni_utf8_to_jstring(jc, zSql, -1);
OOM_CHECK(rv);
rv = s3jni_utf8_to_jstring(env, zSql, -1);
s3jni_oom_check(rv);
}
return rv;
}
@ -3468,12 +3462,11 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
jobject jX = NULL /* the tracer's X arg */;
jobject jP = NULL /* the tracer's P arg */;
jobject jPUnref = NULL /* potentially a local ref to jP */;
S3JniEnv * const jc = S3JniGlobal_env_cache(env);
int rc;
int createStmt = 0;
switch(traceflag){
case SQLITE_TRACE_STMT:
jX = s3jni_utf8_to_jstring(jc, (const char *)pX, -1);
jX = s3jni_utf8_to_jstring(env, (const char *)pX, -1);
if(!jX) return SQLITE_NOMEM;
/*MARKER(("TRACE_STMT@%p SQL=%p / %s\n", pP, jX, (const char *)pX));*/
createStmt = 1;
@ -3858,8 +3851,7 @@ JDECLFtsXA(jint,xColumnText)(JENV_OSELF,jobject jCtx, jint iCol,
int rc = fext->xColumnText(PtrGet_Fts5Context(jCtx), (int)iCol,
&pz, &pn);
if( 0==rc ){
S3JniEnv * const jc = S3JniGlobal_env_cache(env);
jstring jstr = pz ? s3jni_utf8_to_jstring(jc, pz, pn) : 0;
jstring jstr = pz ? s3jni_utf8_to_jstring(env, pz, pn) : 0;
if( pz ){
if( jstr ){
OutputPointer_set_String(env, jOut, jstr);
@ -3929,7 +3921,7 @@ JDECLFtsApi(jint,xCreateFunction)(JENV_OSELF, jstring jName,
Fts5JniAux * pAux;
assert(pApi);
zName = JSTR_TOC(jName);
zName = s3jni_jstring_to_mutf8(jName);
if(!zName) return SQLITE_NOMEM;
pAux = Fts5JniAux_alloc(env, jFunc);
if( pAux ){
@ -3944,7 +3936,7 @@ JDECLFtsApi(jint,xCreateFunction)(JENV_OSELF, jstring jName,
pAux->zFuncName = sqlite3_mprintf("%s", zName)
/* OOM here is non-fatal. Ignore it. */;
}
JSTR_RELEASE(jName, zName);
s3jni_mutf8_release(jName, zName);
return (jint)rc;
}
@ -4222,7 +4214,7 @@ static jint s3jni_fts5_xTokenize(JENV_OSELF, S3NphRef const *pRef,
S3JniEnv * const jc = S3JniGlobal_env_cache(env);
struct s3jni_xQueryPhraseState s;
int rc = 0;
jbyte * const pText = jCallback ? JBA_TOC(jbaText) : 0;
jbyte * const pText = jCallback ? s3jni_jbytearray_bytes(jbaText) : 0;
jsize nText = pText ? (*env)->GetArrayLength(env, jbaText) : 0;
jclass const klazz = jCallback ? (*env)->GetObjectClass(env, jCallback) : NULL;
@ -4237,7 +4229,7 @@ static jint s3jni_fts5_xTokenize(JENV_OSELF, S3NphRef const *pRef,
IFTHREW {
EXCEPTION_REPORT;
EXCEPTION_CLEAR;
JBA_RELEASE(jbaText, pText);
s3jni_jbytearray_release(jbaText, pText);
return SQLITE_ERROR;
}
s.tok.jba = REF_L(jbaText);
@ -4259,7 +4251,7 @@ static jint s3jni_fts5_xTokenize(JENV_OSELF, S3NphRef const *pRef,
assert( s.tok.zPrev );
UNREF_L(s.tok.jba);
}
JBA_RELEASE(jbaText, pText);
s3jni_jbytearray_release(jbaText, pText);
return (jint)rc;
}
@ -4457,15 +4449,15 @@ Java_org_sqlite_jni_tester_SQLTester_strglob(
JENV_CSELF, jbyteArray baG, jbyteArray baT
){
int rc = 0;
jbyte * const pG = JBA_TOC(baG);
jbyte * const pT = pG ? JBA_TOC(baT) : 0;
jbyte * const pG = s3jni_jbytearray_bytes(baG);
jbyte * const pT = pG ? s3jni_jbytearray_bytes(baT) : 0;
OOM_CHECK(pT);
s3jni_oom_check(pT);
/* Note that we're relying on the byte arrays having been
NUL-terminated on the Java side. */
rc = !SQLTester_strnotglob((const char *)pG, (const char *)pT);
JBA_RELEASE(baG, pG);
JBA_RELEASE(baT, pT);
s3jni_jbytearray_release(baG, pG);
s3jni_jbytearray_release(baT, pT);
return rc;
}
@ -4610,15 +4602,15 @@ Java_org_sqlite_jni_SQLite3Jni_init(JENV_CSELF){
#endif
SJG.envCache.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
OOM_CHECK( SJG.envCache.mutex );
s3jni_oom_check( SJG.envCache.mutex );
SJG.perDb.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
OOM_CHECK( SJG.perDb.mutex );
s3jni_oom_check( SJG.perDb.mutex );
SJG.autoExt.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
OOM_CHECK( SJG.autoExt.mutex );
s3jni_oom_check( SJG.autoExt.mutex );
#if S3JNI_METRICS_MUTEX
SJG.metrics.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
OOM_CHECK( SJG.metrics.mutex );
s3jni_oom_check( SJG.metrics.mutex );
#endif
sqlite3_shutdown()

View File

@ -680,7 +680,8 @@ public class Tester1 implements Runnable {
sqlite3_finalize(stmt);
affirm( 0 != rc );
affirm( sqlite3_errmsg(db).indexOf("an xFunc") > 0 );
rc = sqlite3_create_function(db, "mysca", 1, -1, funcSc);
affirm( SQLITE_FORMAT==rc, "invalid encoding value." );
sqlite3_close_v2(db);
}

View File

@ -1,5 +1,5 @@
C Add\smore\sJNI\sdocs,\stests,\sand\sa\shandful\sof\sJava-side\soverloads.
D 2023-08-24T11:57:51.863
C Correct\sJNI\slayer's\smisuse\sof\san\ssqlite3-internal\serror-reporting\sAPI\s(no\smutex\sheld).\sStyle\scleanups.\sEliminate\slookups\sof\sper-thread\sstate\sby\sapproximately\s85%\sacross\sthe\stest\ssuite.
D 2023-08-24T14:31:36.028
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -235,7 +235,7 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3
F ext/jni/GNUmakefile 0a823c56f081294e7797dae303380ac989ebaa801bba970968342b7358f07aed
F ext/jni/README.md 64bf1da0d562d051207ca1c5cfa52e8b7a69120533cc034a3da7670ef920cbef
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
F ext/jni/src/c/sqlite3-jni.c e1e3cde4d08925282b5bc949f9ed8f613a6a2c6f60d0c697e79d59fb49f9fe4b
F ext/jni/src/c/sqlite3-jni.c d7d6d420f2a13d55828cee19ba17a37c4244532dafbc5822582d7fd52ae2aaf0
F ext/jni/src/c/sqlite3-jni.h cc24d6742b29a52338ffd3b47caf923facb8ae77f9c2fc9c2de82673bf339ea2
F ext/jni/src/org/sqlite/jni/Authorizer.java 1308988f7f40579ea0e4deeaec3c6be971630566bd021c31367fe3f5140db892
F ext/jni/src/org/sqlite/jni/AutoExtension.java bcc1849b2fccbe5e2d7ac9e9ac7f8d05a6d7088a8fedbaad90e39569745a61e6
@ -258,7 +258,7 @@ F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f
F ext/jni/src/org/sqlite/jni/SQLFunction.java f697cf2a81c4119f2baf0682af689686f0466f1dd83dba00885f5603e693fe16
F ext/jni/src/org/sqlite/jni/SQLLog.java c60610b35208416940822e834d61f08fbbe5d6e06b374b541b49e41fd56c9798
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 956063c854c4f662183c41c65d0ab48b5e2127824b8053eeb05b9fc40f0d09e3
F ext/jni/src/org/sqlite/jni/Tester1.java b5a4bb2a969df053d5c138887f04039a79b36170372a2efdf5dfbd6ac90db4c9
F ext/jni/src/org/sqlite/jni/Tester1.java 9b6ec0ae299a56822e82e7dc2cf7ef1031ae87bcb595065bef84b7edac7114f5
F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629
F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d
F ext/jni/src/org/sqlite/jni/UpdateHook.java e58645a1727f8a9bbe72dc072ec5b40d9f9362cb0aa24acfe93f49ff56a9016d
@ -2094,8 +2094,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P a9e6d5158b8a4a6b8554a5f8f0a35785ee450d42ea877275dc27085e89716c18
R cb79df5ad40cc86377d98f5a1329b589
P d19a431facbde6a6b960664674753ee85d2c051a76109ce7db0b079c65fbdea0
R a3460d6a3bf6ffdc6985db3e6bc764fc
U stephan
Z 39e8fbdcbc2ebaa58ed84b96f0374c06
Z 4bd864e1476ea863a52783451fa010a4
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
d19a431facbde6a6b960664674753ee85d2c051a76109ce7db0b079c65fbdea0
1f46ba8d3bc61af771c1e33d09ad25f0da4fc4f915f7a9f6223ebfd99526d81d