1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-27 20:41:58 +03:00

Internal exception-handling cleanups in the JNI bindings.

FossilOrigin-Name: 057b1d4f6ffff73c120566895f61ea3fd8118968464d67ec9262096a7aa03f39
This commit is contained in:
stephan
2023-08-01 09:44:26 +00:00
parent 0bc72d2b91
commit e209d144c3
4 changed files with 73 additions and 64 deletions

View File

@ -95,7 +95,10 @@ Known consequences and limitations of this discrepancy include:
- Names of databases, tables, and collations must not contain - Names of databases, tables, and collations must not contain
characters which differ in MUTF-8 and UTF-8, or certain APIs will characters which differ in MUTF-8 and UTF-8, or certain APIs will
mis-translate them on their way between languages. mis-translate them on their way between languages. The
sqlite3_trace_v2() implementation is also currently affected by
this, in that it will necessarily translate traced SQL statements to
MUTF-8.
[modutf8]: https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html#modified-utf-8 [modutf8]: https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html#modified-utf-8

View File

@ -157,25 +157,25 @@
JNIEXPORT ReturnType JNICALL \ JNIEXPORT ReturnType JNICALL \
JFuncName(Suffix) JFuncName(Suffix)
/* First 2 parameters to all JNI bindings. */ /* First 2 parameters to all JNI bindings. */
#define JENV_JSELF JNIEnv * env, jobject jSelf #define JENV_JSELF JNIEnv * const env, jobject jSelf
/* Helpers to squelch -Xcheck:jni warnings about /* Helpers to squelch -Xcheck:jni warnings about
not having checked for exceptions. */ not having checked for exceptions. */
#define IFTHREW if((*env)->ExceptionCheck(env)) #define IFTHREW if((*env)->ExceptionCheck(env))
#define EXCEPTION_IGNORE (void)((*env)->ExceptionCheck(env)) #define EXCEPTION_IGNORE (void)((*env)->ExceptionCheck(env))
#define EXCEPTION_CLEAR (*env)->ExceptionClear(env) #define EXCEPTION_CLEAR (*env)->ExceptionClear(env)
#define EXCEPTION_REPORT (*env)->ExceptionDescribe(env) #define EXCEPTION_REPORT (*env)->ExceptionDescribe(env)
#define EXCEPTION_WARN_CALLBACK_THREW1(STR) \ #define EXCEPTION_WARN_CALLBACK_THREW(STR) \
MARKER(("WARNING: " STR " MUST NOT THROW.\n")); \ MARKER(("WARNING: " STR " MUST NOT THROW.\n")); \
(*env)->ExceptionDescribe(env) (*env)->ExceptionDescribe(env)
#define EXCEPTION_WARN_CALLBACK_THREW \
EXCEPTION_WARN_CALLBACK_THREW1("this routine")
#define IFTHREW_REPORT IFTHREW EXCEPTION_REPORT #define IFTHREW_REPORT IFTHREW EXCEPTION_REPORT
#define IFTHREW_CLEAR IFTHREW EXCEPTION_CLEAR #define IFTHREW_CLEAR IFTHREW EXCEPTION_CLEAR
#define EXCEPTION_CANNOT_HAPPEN IFTHREW{\
EXCEPTION_REPORT; \
(*env)->FatalError(env,"This \"cannot happen\"."); \
}
/** To be used for cases where we're _really_ not expecting an
exception, e.g. looking up well-defined Java class members. */
#define EXCEPTION_IS_FATAL(MSG) IFTHREW {\
EXCEPTION_REPORT; EXCEPTION_CLEAR; \
(*env)->FatalError(env, MSG); \
}
/** Helpers for extracting pointers from jobjects, noting that the /** Helpers for extracting pointers from jobjects, noting that the
corresponding Java interfaces have already done the type-checking. corresponding Java interfaces have already done the type-checking.
@ -327,6 +327,12 @@ struct JNIEnvCacheLine {
accounted for, so it may be best to accounted for, so it may be best to
redefine the tracing API rather than redefine the tracing API rather than
passing through the statement handles. */; passing through the statement handles. */;
#if 0
/* TODO: refactor this cache as a linked list with malloc()'d entries,
rather than a fixed-size array in S3Global.envCache */
JNIEnvCacheLine * pPrev /* Previous entry in the linked list */;
JNIEnvCacheLine * pNext /* Next entry in the linked list */;
#endif
struct NphCacheLine nph[NphCache_SIZE]; struct NphCacheLine nph[NphCache_SIZE];
}; };
typedef struct JNIEnvCache JNIEnvCache; typedef struct JNIEnvCache JNIEnvCache;
@ -335,12 +341,12 @@ struct JNIEnvCache {
unsigned int used; unsigned int used;
}; };
static void NphCacheLine_clear(JNIEnv *env, NphCacheLine * p){ static void NphCacheLine_clear(JNIEnv * const env, NphCacheLine * const p){
UNREF_G(p->klazz); UNREF_G(p->klazz);
memset(p, 0, sizeof(NphCacheLine)); memset(p, 0, sizeof(NphCacheLine));
} }
static void JNIEnvCacheLine_clear(JNIEnvCacheLine * p){ static void JNIEnvCacheLine_clear(JNIEnvCacheLine * const p){
JNIEnv * const env = p->env; JNIEnv * const env = p->env;
int i; int i;
if(env){ if(env){
@ -353,7 +359,7 @@ static void JNIEnvCacheLine_clear(JNIEnvCacheLine * p){
} }
} }
static void JNIEnvCache_clear(JNIEnvCache * p){ static void JNIEnvCache_clear(JNIEnvCache * const p){
unsigned int i = 0; unsigned int i = 0;
for( ; i < p->used; ++i ){ for( ; i < p->used; ++i ){
JNIEnvCacheLine_clear( &p->lines[i] ); JNIEnvCacheLine_clear( &p->lines[i] );
@ -417,16 +423,17 @@ static struct {
JavaVM * jvm; JavaVM * jvm;
struct JNIEnvCache envCache; struct JNIEnvCache envCache;
struct { struct {
PerDbStateJni * aUsed; PerDbStateJni * aUsed /* Linked list of in-use instances */;
PerDbStateJni * aFree; PerDbStateJni * aFree /* Linked list of free instances */;
} perDb; } perDb;
struct { struct {
unsigned nphCacheHits; unsigned nphCacheHits;
unsigned nphCacheMisses; unsigned nphCacheMisses;
unsigned envCacheHits; unsigned envCacheHits;
unsigned envCacheMisses; unsigned envCacheMisses;
unsigned nDestroy; unsigned nDestroy /* xDestroy() calls across all types */;
struct { struct {
/* Number of calls for each type of UDF callback. */
unsigned nFunc; unsigned nFunc;
unsigned nStep; unsigned nStep;
unsigned nFinal; unsigned nFinal;
@ -442,15 +449,15 @@ static struct {
recovery strategy for OOM. For sqlite3 API which can reasonably recovery strategy for OOM. For sqlite3 API which can reasonably
return SQLITE_NOMEM, sqlite3_malloc() should be used instead. return SQLITE_NOMEM, sqlite3_malloc() should be used instead.
*/ */
static void * s3jni_malloc(JNIEnv *env, size_t n){ static void * s3jni_malloc(JNIEnv * const env, size_t n){
void * rv = sqlite3_malloc(n); void * const rv = sqlite3_malloc(n);
if(n && !rv){ if(n && !rv){
(*env)->FatalError(env, "Out of memory.") /* does not return */; (*env)->FatalError(env, "Out of memory.") /* does not return */;
} }
return rv; return rv;
} }
static void s3jni_free(void * p){ static void s3jni_free(void * const p){
if(p) sqlite3_free(p); if(p) sqlite3_free(p);
} }
@ -469,7 +476,7 @@ static void s3jni_free(void * p){
** **
** Returns err_code. ** Returns err_code.
*/ */
static int s3jni_db_error(sqlite3*db, int err_code, const char *zMsg){ static int s3jni_db_error(sqlite3* const db, int err_code, const char * const zMsg){
if( db!=0 ){ if( db!=0 ){
if( 0==zMsg ){ if( 0==zMsg ){
sqlite3Error(db, err_code); sqlite3Error(db, err_code);
@ -488,7 +495,7 @@ static int s3jni_db_error(sqlite3*db, int err_code, const char *zMsg){
is silently ignored and any exceptions thrown by the method trigger is silently ignored and any exceptions thrown by the method trigger
a warning to stdout or stderr and then the exception is suppressed. a warning to stdout or stderr and then the exception is suppressed.
*/ */
static void s3jni_call_xDestroy(JNIEnv *env, jobject jObj, jclass klazz){ static void s3jni_call_xDestroy(JNIEnv * const env, jobject jObj, jclass klazz){
if(jObj){ if(jObj){
jmethodID method; jmethodID method;
if(!klazz){ if(!klazz){
@ -501,7 +508,7 @@ static void s3jni_call_xDestroy(JNIEnv *env, jobject jObj, jclass klazz){
++S3Global.metrics.nDestroy; ++S3Global.metrics.nDestroy;
(*env)->CallVoidMethod(env, jObj, method); (*env)->CallVoidMethod(env, jObj, method);
IFTHREW{ IFTHREW{
EXCEPTION_WARN_CALLBACK_THREW; EXCEPTION_WARN_CALLBACK_THREW("xDestroy() callback");
EXCEPTION_CLEAR; EXCEPTION_CLEAR;
} }
}else{ }else{
@ -561,7 +568,7 @@ static struct JNIEnvCacheLine * S3Global_env_cache(JNIEnv * env){
(2023-07-31) tests. (2023-07-31) tests.
*/ */
FIXME_THREADING FIXME_THREADING
static struct NphCacheLine * S3Global_nph_cache(JNIEnv *env, const char *zClassName){ static struct NphCacheLine * S3Global_nph_cache(JNIEnv * const env, const char *zClassName){
/** /**
According to: According to:
@ -600,8 +607,9 @@ static struct NphCacheLine * S3Global_nph_cache(JNIEnv *env, const char *zClassN
} }
if(freeSlot){ if(freeSlot){
freeSlot->zClassName = zClassName; freeSlot->zClassName = zClassName;
freeSlot->klazz = REF_G((*env)->FindClass(env, zClassName)); freeSlot->klazz = (*env)->FindClass(env, zClassName);
EXCEPTION_CANNOT_HAPPEN; EXCEPTION_IS_FATAL("FindClass() unexpectedly threw");
freeSlot->klazz = REF_G(freeSlot->klazz);
++S3Global.metrics.nphCacheMisses; ++S3Global.metrics.nphCacheMisses;
#if DUMP_NPH_CACHES #if DUMP_NPH_CACHES
static unsigned int cacheMisses = 0; static unsigned int cacheMisses = 0;
@ -616,11 +624,9 @@ static struct NphCacheLine * S3Global_nph_cache(JNIEnv *env, const char *zClassN
return freeSlot; return freeSlot;
} }
static jfieldID getNativePointerField(JNIEnv *env, jclass klazz){ static jfieldID getNativePointerField(JNIEnv * const env, jclass klazz){
jfieldID rv = (*env)->GetFieldID(env, klazz, "nativePointer", "J"); jfieldID rv = (*env)->GetFieldID(env, klazz, "nativePointer", "J");
IFTHREW{ EXCEPTION_IS_FATAL("Code maintenance required: missing nativePointer field.");
(*env)->FatalError(env, "Maintenance required: missing nativePointer field.");
}
return rv; return rv;
} }
@ -687,7 +693,7 @@ static void * getNativePointer(JNIEnv * env, jobject pObj, const char *zClassNam
Returns NULL on OOM. pDb MUST be associated with jDb via Returns NULL on OOM. pDb MUST be associated with jDb via
setNativePointer(). setNativePointer().
*/ */
static PerDbStateJni * PerDbStateJni_alloc(JNIEnv *env, sqlite3 *pDb, jobject jDb){ static PerDbStateJni * PerDbStateJni_alloc(JNIEnv * const env, sqlite3 *pDb, jobject jDb){
PerDbStateJni * rv; PerDbStateJni * rv;
assert( pDb ); assert( pDb );
if(S3Global.perDb.aFree){ if(S3Global.perDb.aFree){
@ -808,7 +814,7 @@ static void PerDbStateJni_dump(PerDbStateJni *s){
return a (sqlite3*) but do not take one as an argument. return a (sqlite3*) but do not take one as an argument.
*/ */
FIXME_THREADING FIXME_THREADING
static PerDbStateJni * PerDbStateJni_for_db(JNIEnv *env, jobject jDb, sqlite3 *pDb, int allocIfNeeded){ static PerDbStateJni * PerDbStateJni_for_db(JNIEnv * const env, jobject jDb, sqlite3 *pDb, int allocIfNeeded){
PerDbStateJni * s = S3Global.perDb.aUsed; PerDbStateJni * s = S3Global.perDb.aUsed;
if(!jDb){ if(!jDb){
if(pDb){ if(pDb){
@ -1017,7 +1023,7 @@ typedef struct {
/* For use with sqlite3_result/value_pointer() */ /* For use with sqlite3_result/value_pointer() */
#define RESULT_JAVA_VAL_STRING "ResultJavaVal" #define RESULT_JAVA_VAL_STRING "ResultJavaVal"
static ResultJavaVal * ResultJavaVal_alloc(JNIEnv *env, jobject jObj){ static ResultJavaVal * ResultJavaVal_alloc(JNIEnv * const env, jobject jObj){
ResultJavaVal * rv = sqlite3_malloc(sizeof(ResultJavaVal)); ResultJavaVal * rv = sqlite3_malloc(sizeof(ResultJavaVal));
if(rv){ if(rv){
rv->env = env; rv->env = env;
@ -1046,7 +1052,7 @@ static void ResultJavaVal_finalizer(void *v){
Always use a string literal for the 2nd argument so that we can use Always use a string literal for the 2nd argument so that we can use
its address as a cache key. its address as a cache key.
*/ */
static jobject new_NativePointerHolder_object(JNIEnv *env, const char *zClassName, static jobject new_NativePointerHolder_object(JNIEnv * const env, const char *zClassName,
void * pNative){ void * pNative){
jobject rv = 0; jobject rv = 0;
jclass klazz = 0; jclass klazz = 0;
@ -1076,15 +1082,15 @@ static jobject new_NativePointerHolder_object(JNIEnv *env, const char *zClassNam
return rv; return rv;
} }
static jobject new_sqlite3_value_wrapper(JNIEnv *env, sqlite3_value *sv){ static jobject new_sqlite3_value_wrapper(JNIEnv * const env, sqlite3_value *sv){
return new_NativePointerHolder_object(env, "org/sqlite/jni/sqlite3_value", sv); return new_NativePointerHolder_object(env, "org/sqlite/jni/sqlite3_value", sv);
} }
static jobject new_sqlite3_context_wrapper(JNIEnv *env, sqlite3_context *sv){ static jobject new_sqlite3_context_wrapper(JNIEnv * const env, sqlite3_context *sv){
return new_NativePointerHolder_object(env, "org/sqlite/jni/sqlite3_context", sv); return new_NativePointerHolder_object(env, "org/sqlite/jni/sqlite3_context", sv);
} }
static jobject new_sqlite3_stmt_wrapper(JNIEnv *env, sqlite3_stmt *sv){ static jobject new_sqlite3_stmt_wrapper(JNIEnv * const env, sqlite3_stmt *sv){
return new_NativePointerHolder_object(env, "org/sqlite/jni/sqlite3_stmt", sv); return new_NativePointerHolder_object(env, "org/sqlite/jni/sqlite3_stmt", sv);
} }
@ -1118,7 +1124,7 @@ typedef struct {
jmethodID jmidxInverse; jmethodID jmidxInverse;
} UDFState; } UDFState;
static UDFState * UDFState_alloc(JNIEnv *env, jobject jObj){ static UDFState * UDFState_alloc(JNIEnv * const env, jobject jObj){
UDFState * const s = sqlite3_malloc(sizeof(UDFState)); UDFState * const s = sqlite3_malloc(sizeof(UDFState));
if(s){ if(s){
const char * zFSI = /* signature for xFunc, xStep, xInverse */ const char * zFSI = /* signature for xFunc, xStep, xInverse */
@ -1428,7 +1434,7 @@ static int s3jni_busy_handler(void* pState, int n){
rc = (*env)->CallIntMethod(env, ps->busyHandler.jObj, rc = (*env)->CallIntMethod(env, ps->busyHandler.jObj,
ps->busyHandler.midCallback, (jint)n); ps->busyHandler.midCallback, (jint)n);
IFTHREW{ IFTHREW{
EXCEPTION_WARN_CALLBACK_THREW; EXCEPTION_WARN_CALLBACK_THREW("busy-handler callback");
EXCEPTION_CLEAR; EXCEPTION_CLEAR;
rc = s3jni_db_error(ps->pDb, SQLITE_ERROR, "busy-handle callback threw."); rc = s3jni_db_error(ps->pDb, SQLITE_ERROR, "busy-handle callback threw.");
} }
@ -1477,7 +1483,7 @@ JDECL(jint,1busy_1timeout)(JENV_JSELF, jobject jDb, jint ms){
/** /**
Wrapper for sqlite3_close(_v2)(). Wrapper for sqlite3_close(_v2)().
*/ */
static jint s3jni_close_db(JNIEnv *env, jobject jDb, int version){ static jint s3jni_close_db(JNIEnv * const env, jobject jDb, int version){
int rc = 0; int rc = 0;
PerDbStateJni * ps = 0; PerDbStateJni * ps = 0;
assert(version == 1 || version == 2); assert(version == 1 || version == 2);
@ -1529,7 +1535,7 @@ static void s3jni_collation_needed_impl16(void *pState, sqlite3 *pDb,
ps->collationNeeded.midCallback, ps->collationNeeded.midCallback,
ps->jDb, (jint)eTextRep, jName); ps->jDb, (jint)eTextRep, jName);
IFTHREW{ IFTHREW{
EXCEPTION_WARN_CALLBACK_THREW; EXCEPTION_WARN_CALLBACK_THREW("collation-needed callback");
EXCEPTION_CLEAR; EXCEPTION_CLEAR;
s3jni_db_error(ps->pDb, SQLITE_ERROR, "collation-needed hook threw."); s3jni_db_error(ps->pDb, SQLITE_ERROR, "collation-needed hook threw.");
} }
@ -1608,7 +1614,7 @@ JDECL(jlong,1column_1int64)(JENV_JSELF, jobject jpStmt,
Java String of exactly half that length, returning NULL if !p or Java String of exactly half that length, returning NULL if !p or
(*env)->NewString() fails. (*env)->NewString() fails.
*/ */
static jstring s3jni_text_to_jstring(JNIEnv *env, const void * const p, int nP){ static jstring s3jni_text_to_jstring(JNIEnv * const env, const void * const p, int nP){
return p return p
? (*env)->NewString(env, (const jchar *)p, (jsize)(nP/2)) ? (*env)->NewString(env, (const jchar *)p, (jsize)(nP/2))
: NULL; : NULL;
@ -1618,7 +1624,7 @@ static jstring s3jni_text_to_jstring(JNIEnv *env, const void * const p, int nP){
Creates a new jByteArray of length nP, copies p's contents into it, and Creates a new jByteArray of length nP, copies p's contents into it, and
returns that byte array. returns that byte array.
*/ */
static jbyteArray s3jni_new_jbyteArray(JNIEnv *env, const unsigned char * const p, int nP){ static jbyteArray s3jni_new_jbyteArray(JNIEnv * const env, const unsigned char * const p, int nP){
jbyteArray jba = (*env)->NewByteArray(env, (jint)nP); jbyteArray jba = (*env)->NewByteArray(env, (jint)nP);
if(jba){ if(jba){
(*env)->SetByteArrayRegion(env, jba, 0, (jint)nP, (const jbyte*)p); (*env)->SetByteArrayRegion(env, jba, 0, (jint)nP, (const jbyte*)p);
@ -1671,7 +1677,7 @@ static void s3jni_rollback_hook_impl(void *pP){
(void)s3jni_commit_rollback_hook_impl(0, pP); (void)s3jni_commit_rollback_hook_impl(0, pP);
} }
static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv *env,jobject jDb, static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv * const env,jobject jDb,
jobject jHook){ jobject jHook){
PerDbStateJni * const ps = PerDbStateJni_for_db(env, jDb, 0, 0); PerDbStateJni * const ps = PerDbStateJni_for_db(env, jDb, 0, 0);
jclass klazz; jclass klazz;
@ -1895,7 +1901,7 @@ JDECL(jlong,1last_1insert_1rowid)(JENV_JSELF, jobject jpDb){
bindings. Allocates the PerDbStateJni for *ppDb if *ppDb is not bindings. Allocates the PerDbStateJni for *ppDb if *ppDb is not
NULL. NULL.
*/ */
static int s3jni_open_post(JNIEnv *env, sqlite3 **ppDb, jobject jDb, int theRc){ static int s3jni_open_post(JNIEnv * const env, sqlite3 **ppDb, jobject jDb, int theRc){
if(1 && *ppDb){ if(1 && *ppDb){
PerDbStateJni * const s = PerDbStateJni_for_db(env, jDb, *ppDb, 1); PerDbStateJni * const s = PerDbStateJni_for_db(env, jDb, *ppDb, 1);
if(!s && 0==theRc){ if(!s && 0==theRc){
@ -1935,7 +1941,7 @@ JDECL(jint,1open_1v2)(JENV_JSELF, jstring strName,
} }
/* Proxy for the sqlite3_prepare[_v2/3]() family. */ /* Proxy for the sqlite3_prepare[_v2/3]() family. */
static jint sqlite3_jni_prepare_v123(int prepVersion, JNIEnv *env, jclass self, static jint sqlite3_jni_prepare_v123(int prepVersion, JNIEnv * const env, jclass self,
jobject jpDb, jbyteArray baSql, jobject jpDb, jbyteArray baSql,
jint nMax, jint prepFlags, jint nMax, jint prepFlags,
jobject jOutStmt, jobject outTail){ jobject jOutStmt, jobject outTail){
@ -1970,17 +1976,17 @@ static jint sqlite3_jni_prepare_v123(int prepVersion, JNIEnv *env, jclass self,
(void)stmt_set_current(jc, pOldStmt); (void)stmt_set_current(jc, pOldStmt);
return (jint)rc; return (jint)rc;
} }
JDECL(jint,1prepare)(JNIEnv *env, jclass self, jobject jpDb, jbyteArray baSql, JDECL(jint,1prepare)(JNIEnv * const env, jclass self, jobject jpDb, jbyteArray baSql,
jint nMax, jobject jOutStmt, jobject outTail){ jint nMax, jobject jOutStmt, jobject outTail){
return sqlite3_jni_prepare_v123(1, env, self, jpDb, baSql, nMax, 0, return sqlite3_jni_prepare_v123(1, env, self, jpDb, baSql, nMax, 0,
jOutStmt, outTail); jOutStmt, outTail);
} }
JDECL(jint,1prepare_1v2)(JNIEnv *env, jclass self, jobject jpDb, jbyteArray baSql, JDECL(jint,1prepare_1v2)(JNIEnv * const env, jclass self, jobject jpDb, jbyteArray baSql,
jint nMax, jobject jOutStmt, jobject outTail){ jint nMax, jobject jOutStmt, jobject outTail){
return sqlite3_jni_prepare_v123(2, env, self, jpDb, baSql, nMax, 0, return sqlite3_jni_prepare_v123(2, env, self, jpDb, baSql, nMax, 0,
jOutStmt, outTail); jOutStmt, outTail);
} }
JDECL(jint,1prepare_1v3)(JNIEnv *env, jclass self, jobject jpDb, jbyteArray baSql, JDECL(jint,1prepare_1v3)(JNIEnv * const env, jclass self, jobject jpDb, jbyteArray baSql,
jint nMax, jint prepFlags, jobject jOutStmt, jobject outTail){ jint nMax, jint prepFlags, jobject jOutStmt, jobject outTail){
return sqlite3_jni_prepare_v123(3, env, self, jpDb, baSql, nMax, return sqlite3_jni_prepare_v123(3, env, self, jpDb, baSql, nMax,
prepFlags, jOutStmt, outTail); prepFlags, jOutStmt, outTail);
@ -2047,7 +2053,7 @@ JDECL(jint,1reset)(JENV_JSELF, jobject jpStmt){
/* sqlite3_result_text/blob() and friends. */ /* sqlite3_result_text/blob() and friends. */
static void result_blob_text(int asBlob, int as64, static void result_blob_text(int asBlob, int as64,
int eTextRep/*only for (asBlob=0)*/, int eTextRep/*only for (asBlob=0)*/,
JNIEnv *env, sqlite3_context *pCx, JNIEnv * const env, sqlite3_context *pCx,
jbyteArray jBa, jlong nMax){ jbyteArray jBa, jlong nMax){
if(jBa){ if(jBa){
jbyte * const pBuf = JBA_TOC(jBa); jbyte * const pBuf = JBA_TOC(jBa);
@ -2278,8 +2284,8 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
} }
MARKER(("WARNING: created new sqlite3_stmt wrapper for TRACE_PROFILE. stmt@%p\n" MARKER(("WARNING: created new sqlite3_stmt wrapper for TRACE_PROFILE. stmt@%p\n"
"This means we have missed a route into the tracing API and it " "This means we have missed a route into the tracing API and it "
"needs the stmt_set_current() treatment littered around a handful " "needs the stmt_set_current() treatment which is littered around "
"of other functions.\n", pP)); "a handful of other functions in this file.\n", pP));
} }
break; break;
case SQLITE_TRACE_ROW: case SQLITE_TRACE_ROW:
@ -2297,7 +2303,7 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
ps->trace.midCallback, ps->trace.midCallback,
(jint)traceflag, jP, jX); (jint)traceflag, jP, jX);
IFTHREW{ IFTHREW{
EXCEPTION_WARN_CALLBACK_THREW1("sqlite3_trace_v2() callback"); EXCEPTION_WARN_CALLBACK_THREW("sqlite3_trace_v2() callback");
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
} }
UNREF_L(jPUnref); UNREF_L(jPUnref);
@ -2346,7 +2352,7 @@ static void s3jni_update_hook_impl(void * pState, int opId, const char *zDb,
ps->updateHook.midCallback, ps->updateHook.midCallback,
(jint)opId, jDbName, jTable, (jlong)nRowid); (jint)opId, jDbName, jTable, (jlong)nRowid);
IFTHREW{ IFTHREW{
EXCEPTION_WARN_CALLBACK_THREW; EXCEPTION_WARN_CALLBACK_THREW("update hook");
EXCEPTION_CLEAR; EXCEPTION_CLEAR;
s3jni_db_error(ps->pDb, SQLITE_ERROR, "update hook callback threw."); s3jni_db_error(ps->pDb, SQLITE_ERROR, "update hook callback threw.");
} }
@ -2458,7 +2464,7 @@ JDECL(jbyteArray,1value_1text_1utf8)(JENV_JSELF, jobject jpSVal){
return s3jni_new_jbyteArray(env, p, n); return s3jni_new_jbyteArray(env, p, n);
} }
static jbyteArray value_text16(int mode, JNIEnv *env, jobject jpSVal){ static jbyteArray value_text16(int mode, JNIEnv * const env, jobject jpSVal){
int const nLen = sqlite3_value_bytes16(PtrGet_sqlite3_value(jpSVal)); int const nLen = sqlite3_value_bytes16(PtrGet_sqlite3_value(jpSVal));
jbyteArray jba; jbyteArray jba;
const jbyte * pBytes; const jbyte * pBytes;
@ -2535,7 +2541,7 @@ JDECL(void,1do_1something_1for_1developer)(JENV_JSELF){
sqlite3.h. sqlite3.h.
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_org_sqlite_jni_SQLite3Jni_init(JNIEnv *env, jclass self, jobject sJni){ Java_org_sqlite_jni_SQLite3Jni_init(JNIEnv * const env, jclass self, jobject sJni){
typedef struct { typedef struct {
const char *zName; const char *zName;
int value; int value;
@ -2582,10 +2588,10 @@ Java_org_sqlite_jni_SQLite3Jni_init(JNIEnv *env, jclass self, jobject sJni){
for( pLimit = &aLimits[0]; pLimit->zName; ++pLimit ){ for( pLimit = &aLimits[0]; pLimit->zName; ++pLimit ){
fieldId = (*env)->GetStaticFieldID(env, klazz, pLimit->zName, "I"); fieldId = (*env)->GetStaticFieldID(env, klazz, pLimit->zName, "I");
EXCEPTION_CANNOT_HAPPEN; EXCEPTION_IS_FATAL("Missing an expected static member of the SQLite3Jni class.");
//MARKER(("Setting %s (field=%p) = %d\n", pLimit->zName, fieldId, pLimit->value)); //MARKER(("Setting %s (field=%p) = %d\n", pLimit->zName, fieldId, pLimit->value));
assert(fieldId); assert(fieldId);
(*env)->SetStaticIntField(env, klazz, fieldId, (jint)pLimit->value); (*env)->SetStaticIntField(env, klazz, fieldId, (jint)pLimit->value);
EXCEPTION_CANNOT_HAPPEN; EXCEPTION_IS_FATAL("Seting a static member of the SQLite3Jni class failed.");
} }
} }

View File

@ -1,5 +1,5 @@
C Minor\sJNI-related\sdoc\stweaks\sand\scode\sre-ordering. C Internal\sexception-handling\scleanups\sin\sthe\sJNI\sbindings.
D 2023-08-01T08:48:13.434 D 2023-08-01T09:44:26.568
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -231,8 +231,8 @@ F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f4
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282 F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8 F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
F ext/jni/GNUmakefile 3d1f106e7a08bb54279c12979b31492b3dea702a732eab445dbc765120995182 F ext/jni/GNUmakefile 3d1f106e7a08bb54279c12979b31492b3dea702a732eab445dbc765120995182
F ext/jni/README.md c0e6e80935e7761acead89b69c87765b23a6bcb2858c321c3d05681fd338292a F ext/jni/README.md d5cfc3037236dee3efa1c5ce62ddee8ad9d6d43c329a10a491888f272e90edc8
F ext/jni/src/c/sqlite3-jni.c c67b9ae6ee3eda2c89523ccddc6fd98bc610c3ac1c55dfdca2971587ff4795ef F ext/jni/src/c/sqlite3-jni.c a2f53b91a905a2ac0cc5a71a9157c6ec684d64a343a59b0c503a61bd12163aa6
F ext/jni/src/c/sqlite3-jni.h 74aaf87e77f99857aa3afc013517c934cbc2c16618c83d8f5d6294351bc8e7b1 F ext/jni/src/c/sqlite3-jni.h 74aaf87e77f99857aa3afc013517c934cbc2c16618c83d8f5d6294351bc8e7b1
F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c
F ext/jni/src/org/sqlite/jni/Collation.java 8dffbb00938007ad0967b2ab424d3c908413af1bbd3d212b9c9899910f1218d1 F ext/jni/src/org/sqlite/jni/Collation.java 8dffbb00938007ad0967b2ab424d3c908413af1bbd3d212b9c9899910f1218d1
@ -2071,8 +2071,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 459db332af6ea358b42bac096b9d26f1045b9ec32fad8463bca06807b2396b2c P b663b27e425966f34fb62482a18048f0e2934380e5c411ae3627f1fe6a765c04
R 2116d1859999fef41708d9f5ffc75a3f R 2f5470dcd701417296bafb0eecce52d9
U stephan U stephan
Z e9112cb724b07771e50f3afa4c070a7b Z 5b2b767d2f48d93a46b3cc4865630bdc
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
b663b27e425966f34fb62482a18048f0e2934380e5c411ae3627f1fe6a765c04 057b1d4f6ffff73c120566895f61ea3fd8118968464d67ec9262096a7aa03f39