1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Internal JNI refacoring to support the pending sqlite3_collation_needed() callback. Correct a bug in the linked-list handling of PerDbStateJni which triggered an assert().

FossilOrigin-Name: 7ac6614e69b03304d09745619ed83f12c7eb775aaf4a636a79289b01642ddd14
This commit is contained in:
stephan
2023-07-30 10:47:38 +00:00
parent 9c113744d1
commit 45fe10d02b
3 changed files with 113 additions and 80 deletions

View File

@ -366,7 +366,8 @@ typedef struct PerDbStateJni PerDbStateJni;
struct PerDbStateJni { struct PerDbStateJni {
JNIEnv *env; JNIEnv *env;
sqlite3 * pDb; sqlite3 * pDb;
jobject jDb /* the object which was passed to sqlite3_open(_v2)() */; jobject jDb /* a global ref of the object which was passed to
sqlite3_open(_v2)() */;
PerDbStateJni * pNext; PerDbStateJni * pNext;
PerDbStateJni * pPrev; PerDbStateJni * pPrev;
JniHookState trace; JniHookState trace;
@ -644,22 +645,29 @@ static void * getNativePointer(JNIEnv * env, jobject pObj, const char *zClassNam
/** /**
Extracts the new PerDbStateJni instance from the free-list, or Extracts the new PerDbStateJni instance from the free-list, or
allocates one if needed, associats it with pDb, and returns. allocates one if needed, associats it with pDb, and returns.
Returns NULL on OOM. Returns NULL on OOM. pDb MUST be associated with jDb via
setNativePointer().
*/ */
static PerDbStateJni * PerDbStateJni_alloc(JNIEnv *env, sqlite3 *pDb){ static PerDbStateJni * PerDbStateJni_alloc(JNIEnv *env, sqlite3 *pDb, jobject jDb){
PerDbStateJni * rv; PerDbStateJni * rv;
assert( pDb ); assert( pDb );
if(S3Global.perDb.aFree){ if(S3Global.perDb.aFree){
rv = S3Global.perDb.aFree; rv = S3Global.perDb.aFree;
//MARKER(("state@%p for db allocating for db@%p from free-list\n", rv, pDb));
//MARKER(("%p->pPrev@%p, pNext@%p\n", rv, rv->pPrev, rv->pNext));
S3Global.perDb.aFree = rv->pNext; S3Global.perDb.aFree = rv->pNext;
assert(rv->pNext != rv);
assert(rv->pPrev != rv);
assert(rv->pPrev ? (rv->pPrev!=rv->pNext) : 1);
if(rv->pNext){ if(rv->pNext){
assert(rv->pNext->pPrev == rv); assert(rv->pNext->pPrev == rv);
assert(rv->pNext == rv->pNext->pPrev); assert(rv->pPrev ? (rv->pNext == rv->pPrev->pNext) : 1);
rv->pNext->pPrev = 0; rv->pNext->pPrev = 0;
rv->pNext = 0; rv->pNext = 0;
} }
}else{ }else{
rv = s3jni_malloc(env, sizeof(PerDbStateJni)); rv = s3jni_malloc(env, sizeof(PerDbStateJni));
//MARKER(("state@%p for db allocating for db@%p from heap\n", rv, pDb));
if(rv){ if(rv){
memset(rv, 0, sizeof(PerDbStateJni)); memset(rv, 0, sizeof(PerDbStateJni));
} }
@ -671,6 +679,7 @@ static PerDbStateJni * PerDbStateJni_alloc(JNIEnv *env, sqlite3 *pDb){
assert(!rv->pNext->pPrev); assert(!rv->pNext->pPrev);
rv->pNext->pPrev = rv; rv->pNext->pPrev = rv;
} }
rv->jDb = REF_G(jDb);
rv->pDb = pDb; rv->pDb = pDb;
rv->env = env; rv->env = env;
} }
@ -685,6 +694,10 @@ static void PerDbStateJni_set_aside(PerDbStateJni * const s){
if(s){ if(s){
JNIEnv * const env = s->env; JNIEnv * const env = s->env;
assert(s->pDb && "Else this object is already in the free-list."); assert(s->pDb && "Else this object is already in the free-list.");
//MARKER(("state@%p for db@%p setting aside\n", s, s->pDb));
assert(s->pPrev != s);
assert(s->pNext != s);
assert(s->pPrev ? (s->pPrev!=s->pNext) : 1);
if(s->pNext) s->pNext->pPrev = s->pPrev; if(s->pNext) s->pNext->pPrev = s->pPrev;
if(s->pPrev) s->pPrev->pNext = s->pNext; if(s->pPrev) s->pPrev->pNext = s->pNext;
else if(S3Global.perDb.aUsed == s){ else if(S3Global.perDb.aUsed == s){
@ -699,7 +712,10 @@ static void PerDbStateJni_set_aside(PerDbStateJni * const s){
BusyHandlerJni_clear(&s->busyHandler); BusyHandlerJni_clear(&s->busyHandler);
memset(s, 0, sizeof(PerDbStateJni)); memset(s, 0, sizeof(PerDbStateJni));
s->pNext = S3Global.perDb.aFree; s->pNext = S3Global.perDb.aFree;
if(s->pNext) s->pNext->pPrev = s;
S3Global.perDb.aFree = s; S3Global.perDb.aFree = s;
//MARKER(("%p->pPrev@%p, pNext@%p\n", s, s->pPrev, s->pNext));
//if(s->pNext) MARKER(("next: %p->pPrev@%p\n", s->pNext, s->pNext->pPrev));
} }
} }
@ -720,14 +736,24 @@ static void PerDbStateJni_dump(PerDbStateJni *s){
true then a new instance will be allocated if no mapping currently true then a new instance will be allocated if no mapping currently
exists, else NULL is returned if no mapping is found. exists, else NULL is returned if no mapping is found.
The 3rd and 4th args should only be non-0 for
sqlite3_open(_v2)(). For all other cases, they must be 0, in which
case the db handle will be fished out of the jDb object and NULL is
returned if jDb does not have any associated PerDbStateJni.
*/ */
FIXME_THREADING FIXME_THREADING
static PerDbStateJni * PerDbStateJni_for_db(JNIEnv *env, sqlite3 *pDb, int allocIfNeeded){ static PerDbStateJni * PerDbStateJni_for_db(JNIEnv *env, jobject jDb, sqlite3 *pDb, int allocIfNeeded){
PerDbStateJni * s = S3Global.perDb.aUsed; PerDbStateJni * s = S3Global.perDb.aUsed;
for( ; s; s = s->pNext){ assert(allocIfNeeded ? !!pDb : 1);
if(!allocIfNeeded && !pDb){
pDb = PtrGet_sqlite3_value(jDb);
}
for( ; pDb && s; s = s->pNext){
if(s->pDb == pDb) return s; if(s->pDb == pDb) return s;
} }
if(allocIfNeeded) s = PerDbStateJni_alloc(env, pDb); if(allocIfNeeded){
s = PerDbStateJni_alloc(env, pDb, jDb);
}
return s; return s;
} }
@ -736,19 +762,19 @@ static PerDbStateJni * PerDbStateJni_for_db(JNIEnv *env, sqlite3 *pDb, int alloc
*/ */
FIXME_THREADING FIXME_THREADING
static void PerDbStateJni_free_all(void){ static void PerDbStateJni_free_all(void){
PerDbStateJni * pS = S3Global.perDb.aUsed; PerDbStateJni * ps = S3Global.perDb.aUsed;
PerDbStateJni * pSNext = 0; PerDbStateJni * pSNext = 0;
for( ; pS; pS = pSNext ){ for( ; ps; ps = pSNext ){
pSNext = pS->pNext; pSNext = ps->pNext;
PerDbStateJni_set_aside(pS); PerDbStateJni_set_aside(ps);
assert(pSNext ? !pSNext->pPrev : 1); assert(pSNext ? !pSNext->pPrev : 1);
} }
assert( 0==S3Global.perDb.aUsed ); assert( 0==S3Global.perDb.aUsed );
pS = S3Global.perDb.aFree; ps = S3Global.perDb.aFree;
S3Global.perDb.aFree = 0; S3Global.perDb.aFree = 0;
pSNext = 0; pSNext = 0;
for( ; pS; pS = pSNext ){ for( ; ps; ps = pSNext ){
pSNext = pS->pNext; pSNext = ps->pNext;
s3jni_free(pSNext); s3jni_free(pSNext);
} }
} }
@ -1358,59 +1384,59 @@ JDECL(jint,1bind_1zeroblob64)(JENV_JSELF, jobject jpStmt,
} }
static int s3jni_busy_handler(void* pState, int n){ static int s3jni_busy_handler(void* pState, int n){
PerDbStateJni * const pS = (PerDbStateJni *)pState; PerDbStateJni * const ps = (PerDbStateJni *)pState;
int rc = 0; int rc = 0;
if( pS->busyHandler.jObj ){ if( ps->busyHandler.jObj ){
JNIEnv * const env = pS->env; JNIEnv * const env = ps->env;
rc = (*env)->CallIntMethod(env, pS->busyHandler.jObj, rc = (*env)->CallIntMethod(env, ps->busyHandler.jObj,
pS->busyHandler.jmidxCallback, (jint)n); ps->busyHandler.jmidxCallback, (jint)n);
IFTHREW_CLEAR; IFTHREW_CLEAR;
} }
return rc; return rc;
} }
JDECL(jint,1busy_1handler)(JENV_JSELF, jobject jDb, jobject jBusy){ JDECL(jint,1busy_1handler)(JENV_JSELF, jobject jDb, jobject jBusy){
sqlite3 * const pDb = PtrGet_sqlite3(jDb); PerDbStateJni * const ps = PerDbStateJni_for_db(env, jDb, 0, 0);
PerDbStateJni * const pS = PerDbStateJni_for_db(env, pDb, 1);
int rc; int rc;
if(!pS) return (jint)SQLITE_NOMEM; if(!ps) return (jint)SQLITE_NOMEM;
if(jBusy){ if(jBusy){
if(pS->busyHandler.jObj && if(ps->busyHandler.jObj &&
(*env)->IsSameObject(env, pS->busyHandler.jObj, jBusy)){ (*env)->IsSameObject(env, ps->busyHandler.jObj, jBusy)){
/* Same object - this is a no-op. */ /* Same object - this is a no-op. */
return 0; return 0;
} }
rc = BusyHandlerJni_init(env, &pS->busyHandler, jBusy); rc = BusyHandlerJni_init(env, &ps->busyHandler, jBusy);
if(rc){ if(rc){
assert(!pS->busyHandler.jObj); assert(!ps->busyHandler.jObj);
return (jint)rc; return (jint)rc;
} }
assert(pS->busyHandler.jObj && pS->busyHandler.klazz); assert(ps->busyHandler.jObj && ps->busyHandler.klazz);
assert( (*env)->IsSameObject(env, pS->busyHandler.jObj, jBusy) ); assert( (*env)->IsSameObject(env, ps->busyHandler.jObj, jBusy) );
}else{ }else{
BusyHandlerJni_clear(&pS->busyHandler); BusyHandlerJni_clear(&ps->busyHandler);
} }
return jBusy return jBusy
? sqlite3_busy_handler(pDb, s3jni_busy_handler, pS) ? sqlite3_busy_handler(ps->pDb, s3jni_busy_handler, ps)
: sqlite3_busy_handler(pDb, 0, 0); : sqlite3_busy_handler(ps->pDb, 0, 0);
} }
JDECL(jint,1busy_1timeout)(JENV_JSELF, jobject jDb, jint ms){ JDECL(jint,1busy_1timeout)(JENV_JSELF, jobject jDb, jint ms){
sqlite3* const pDb = PtrGet_sqlite3(jDb); PerDbStateJni * const ps = PerDbStateJni_for_db(env, jDb, 0, 0);
PerDbStateJni * const pS = PerDbStateJni_for_db(env, pDb, 0); if( ps ){
if( pS && pS->busyHandler.jObj ){ if( ps->busyHandler.jObj ){
BusyHandlerJni_clear(&pS->busyHandler); BusyHandlerJni_clear(&ps->busyHandler);
} }
return sqlite3_busy_timeout(pDb, (int)ms); return sqlite3_busy_timeout(ps->pDb, (int)ms);
}
return SQLITE_MISUSE;
} }
/** /**
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 *env, jobject jDb, int version){
sqlite3 * pDb;
int rc = 0; int rc = 0;
PerDbStateJni * pS = 0; PerDbStateJni * ps = 0;
assert(version == 1 || version == 2); assert(version == 1 || version == 2);
if(0){ if(0){
PerDbStateJni * s = S3Global.perDb.aUsed; PerDbStateJni * s = S3Global.perDb.aUsed;
@ -1418,12 +1444,11 @@ static jint s3jni_close_db(JNIEnv *env, jobject jDb, int version){
PerDbStateJni_dump(s); PerDbStateJni_dump(s);
} }
} }
pDb = PtrGet_sqlite3(jDb); ps = PerDbStateJni_for_db(env, jDb, 0, 0);
if(!pDb) return rc; if(!ps) return rc;
pS = PerDbStateJni_for_db(env, pDb, 0); rc = 1==version ? (jint)sqlite3_close(ps->pDb) : (jint)sqlite3_close_v2(ps->pDb);
rc = 1==version ? (jint)sqlite3_close(pDb) : (jint)sqlite3_close_v2(pDb); if(ps) PerDbStateJni_set_aside(ps)
if(pS) PerDbStateJni_set_aside(pS) /* MUST come after close() because of ps->trace. */;
/* MUST come after close() because of pS->trace. */;
setNativePointer(env, jDb, 0, ClassNames.sqlite3); setNativePointer(env, jDb, 0, ClassNames.sqlite3);
return (jint)rc; return (jint)rc;
} }
@ -1536,14 +1561,13 @@ static void s3jni_rollback_hook_impl(void *pP){
static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv *env,jobject jDb, static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv *env,jobject jDb,
jobject jHook){ jobject jHook){
sqlite3 * const pDb = PtrGet_sqlite3(jDb); PerDbStateJni * const ps = PerDbStateJni_for_db(env, jDb, 0, 0);
PerDbStateJni * const ps = PerDbStateJni_for_db(env, pDb, 1);
jclass klazz; jclass klazz;
jobject pOld = 0; jobject pOld = 0;
jmethodID xCallback; jmethodID xCallback;
JniHookState * const pHook = isCommit ? &ps->commitHook : &ps->rollbackHook; JniHookState * const pHook = isCommit ? &ps->commitHook : &ps->rollbackHook;
if(!ps){ if(!ps){
s3jni_db_error(pDb, SQLITE_NOMEM, 0); s3jni_db_error(ps->pDb, SQLITE_NOMEM, 0);
return 0; return 0;
} }
pOld = pHook->jObj; pOld = pHook->jObj;
@ -1558,8 +1582,8 @@ static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv *env,jobject jDb,
pOld = tmp; pOld = tmp;
} }
memset(pHook, 0, sizeof(JniHookState)); memset(pHook, 0, sizeof(JniHookState));
if( isCommit ) sqlite3_commit_hook(pDb, 0, 0); if( isCommit ) sqlite3_commit_hook(ps->pDb, 0, 0);
else sqlite3_rollback_hook(pDb, 0, 0); else sqlite3_rollback_hook(ps->pDb, 0, 0);
return pOld; return pOld;
} }
klazz = (*env)->GetObjectClass(env, jHook); klazz = (*env)->GetObjectClass(env, jHook);
@ -1569,14 +1593,14 @@ static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv *env,jobject jDb,
IFTHREW { IFTHREW {
EXCEPTION_REPORT; EXCEPTION_REPORT;
EXCEPTION_CLEAR; EXCEPTION_CLEAR;
s3jni_db_error(pDb, SQLITE_ERROR, s3jni_db_error(ps->pDb, SQLITE_ERROR,
"Cannot not find matching callback on " "Cannot not find matching callback on "
"hook object."); "hook object.");
}else{ }else{
pHook->midCallback = xCallback; pHook->midCallback = xCallback;
pHook->jObj = REF_G(jHook); pHook->jObj = REF_G(jHook);
if( isCommit ) sqlite3_commit_hook(pDb, s3jni_commit_hook_impl, ps); if( isCommit ) sqlite3_commit_hook(ps->pDb, s3jni_commit_hook_impl, ps);
else sqlite3_rollback_hook(pDb, s3jni_rollback_hook_impl, ps); else sqlite3_rollback_hook(ps->pDb, s3jni_rollback_hook_impl, ps);
if(pOld){ if(pOld){
jobject tmp = REF_L(pOld); jobject tmp = REF_L(pOld);
UNREF_G(pOld); UNREF_G(pOld);
@ -1729,27 +1753,39 @@ JDECL(jlong,1last_1insert_1rowid)(JENV_JSELF, jobject jpDb){
return (jlong)sqlite3_last_insert_rowid(PtrGet_sqlite3(jpDb)); return (jlong)sqlite3_last_insert_rowid(PtrGet_sqlite3(jpDb));
} }
static int s3jni_open_post(JNIEnv *env, sqlite3 **ppDb, jobject jDb, int theRc){
if(1 && *ppDb){
PerDbStateJni * const s = PerDbStateJni_for_db(env, jDb, *ppDb, 1);
if(!s && 0==theRc){
sqlite3_close(*ppDb);
*ppDb = 0;
theRc = SQLITE_NOMEM;
}
}
setNativePointer(env, jDb, *ppDb, ClassNames.sqlite3);
return theRc;
}
JDECL(jint,1open)(JENV_JSELF, jstring strName, jobject ppOut){ JDECL(jint,1open)(JENV_JSELF, jstring strName, jobject jOut){
sqlite3 * pOut = 0; sqlite3 * pOut = 0;
const char *zName = strName ? JSTR_TOC(strName) : 0; const char *zName = strName ? JSTR_TOC(strName) : 0;
int nrc = sqlite3_open(zName, &pOut); int nrc = sqlite3_open(zName, &pOut);
//MARKER(("env=%p, *env=%p\n", env, *env)); //MARKER(("env=%p, *env=%p\n", env, *env));
setNativePointer(env, ppOut, pOut, ClassNames.sqlite3); nrc = s3jni_open_post(env, &pOut, jOut, nrc);
assert(nrc==0 ? pOut!=0 : 1); assert(nrc==0 ? pOut!=0 : 1);
JSTR_RELEASE(strName, zName); JSTR_RELEASE(strName, zName);
return (jint)nrc; return (jint)nrc;
} }
JDECL(jint,1open_1v2)(JENV_JSELF, jstring strName, JDECL(jint,1open_1v2)(JENV_JSELF, jstring strName,
jobject ppOut, jint flags, jstring strVfs){ jobject jOut, jint flags, jstring strVfs){
sqlite3 * pOut = 0; sqlite3 * pOut = 0;
const char *zName = strName ? JSTR_TOC(strName) : 0; const char *zName = strName ? JSTR_TOC(strName) : 0;
const char *zVfs = strVfs ? JSTR_TOC(strVfs) : 0; const char *zVfs = strVfs ? JSTR_TOC(strVfs) : 0;
int nrc = sqlite3_open_v2(zName, &pOut, (int)flags, zVfs); int nrc = sqlite3_open_v2(zName, &pOut, (int)flags, zVfs);
/*MARKER(("zName=%s, zVfs=%s, pOut=%p, flags=%d, nrc=%d\n", /*MARKER(("zName=%s, zVfs=%s, pOut=%p, flags=%d, nrc=%d\n",
zName, zVfs, pOut, (int)flags, nrc));*/ zName, zVfs, pOut, (int)flags, nrc));*/
setNativePointer(env, ppOut, pOut, ClassNames.sqlite3); nrc = s3jni_open_post(env, &pOut, jOut, nrc);
assert(nrc==0 ? pOut!=0 : 1); assert(nrc==0 ? pOut!=0 : 1);
JSTR_RELEASE(strName, zName); JSTR_RELEASE(strName, zName);
JSTR_RELEASE(strVfs, zVfs); JSTR_RELEASE(strVfs, zVfs);
@ -1820,8 +1856,7 @@ static int s3jni_progress_handler_impl(void *pP){
} }
JDECL(void,1progress_1handler)(JENV_JSELF,jobject jDb, jint n, jobject jProgress){ JDECL(void,1progress_1handler)(JENV_JSELF,jobject jDb, jint n, jobject jProgress){
sqlite3 * const pDb = PtrGet_sqlite3(jDb); PerDbStateJni * ps = PerDbStateJni_for_db(env, jDb, 0, 0);
PerDbStateJni * ps = PerDbStateJni_for_db(env, pDb, 1);
jclass klazz; jclass klazz;
jmethodID xCallback; jmethodID xCallback;
if( n<1 || !jProgress ){ if( n<1 || !jProgress ){
@ -1829,25 +1864,25 @@ JDECL(void,1progress_1handler)(JENV_JSELF,jobject jDb, jint n, jobject jProgress
UNREF_G(ps->progress.jObj); UNREF_G(ps->progress.jObj);
memset(&ps->progress, 0, sizeof(ps->progress)); memset(&ps->progress, 0, sizeof(ps->progress));
} }
sqlite3_progress_handler(pDb, 0, 0, 0); sqlite3_progress_handler(ps->pDb, 0, 0, 0);
return; return;
} }
if(!ps){ if(!ps){
s3jni_db_error(pDb, SQLITE_NOMEM, 0); s3jni_db_error(ps->pDb, SQLITE_NOMEM, 0);
return; return;
} }
klazz = (*env)->GetObjectClass(env, jProgress); klazz = (*env)->GetObjectClass(env, jProgress);
xCallback = (*env)->GetMethodID(env, klazz, "xCallback", "()I"); xCallback = (*env)->GetMethodID(env, klazz, "xCallback", "()I");
IFTHREW { IFTHREW {
EXCEPTION_CLEAR; EXCEPTION_CLEAR;
s3jni_db_error(pDb, SQLITE_ERROR, s3jni_db_error(ps->pDb, SQLITE_ERROR,
"Cannot not find matching xCallback() on " "Cannot not find matching xCallback() on "
"ProgressHandler object."); "ProgressHandler object.");
}else{ }else{
UNREF_G(ps->progress.jObj); UNREF_G(ps->progress.jObj);
ps->progress.midCallback = xCallback; ps->progress.midCallback = xCallback;
ps->progress.jObj = REF_G(jProgress); ps->progress.jObj = REF_G(jProgress);
sqlite3_progress_handler(pDb, (int)n, s3jni_progress_handler_impl, ps); sqlite3_progress_handler(ps->pDb, (int)n, s3jni_progress_handler_impl, ps);
} }
} }
@ -2081,15 +2116,14 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
} }
JDECL(jint,1trace_1v2)(JENV_JSELF,jobject jDb, jint traceMask, jobject jTracer){ JDECL(jint,1trace_1v2)(JENV_JSELF,jobject jDb, jint traceMask, jobject jTracer){
sqlite3 * const pDb = PtrGet_sqlite3(jDb); PerDbStateJni * const ps = PerDbStateJni_for_db(env, jDb, 0, 0);
PerDbStateJni * const ps = PerDbStateJni_for_db(env, pDb, 1);
jclass klazz; jclass klazz;
if( !traceMask || !jTracer ){ if( !traceMask || !jTracer ){
if(ps){ if(ps){
UNREF_G(ps->trace.jObj); UNREF_G(ps->trace.jObj);
memset(&ps->trace, 0, sizeof(ps->trace)); memset(&ps->trace, 0, sizeof(ps->trace));
} }
return (jint)sqlite3_trace_v2(pDb, 0, 0, 0); return (jint)sqlite3_trace_v2(ps->pDb, 0, 0, 0);
} }
if(!ps) return SQLITE_NOMEM; if(!ps) return SQLITE_NOMEM;
klazz = (*env)->GetObjectClass(env, jTracer); klazz = (*env)->GetObjectClass(env, jTracer);
@ -2097,11 +2131,11 @@ JDECL(jint,1trace_1v2)(JENV_JSELF,jobject jDb, jint traceMask, jobject jTracer){
"(IJLjava/lang/Object;)I"); "(IJLjava/lang/Object;)I");
IFTHREW { IFTHREW {
EXCEPTION_CLEAR; EXCEPTION_CLEAR;
return s3jni_db_error(pDb, SQLITE_ERROR, return s3jni_db_error(ps->pDb, SQLITE_ERROR,
"Cannot not find matching xCallback() on Tracer object."); "Cannot not find matching xCallback() on Tracer object.");
} }
ps->trace.jObj = REF_G(jTracer); ps->trace.jObj = REF_G(jTracer);
return sqlite3_trace_v2(pDb, (unsigned)traceMask, s3jni_trace_impl, ps); return sqlite3_trace_v2(ps->pDb, (unsigned)traceMask, s3jni_trace_impl, ps);
} }
static void s3jni_update_hook_impl(void * pState, int opId, const char *zDb, static void s3jni_update_hook_impl(void * pState, int opId, const char *zDb,
@ -2133,14 +2167,13 @@ static void s3jni_update_hook_impl(void * pState, int opId, const char *zDb,
JDECL(jobject,1update_1hook)(JENV_JSELF, jobject jDb, jobject jHook){ JDECL(jobject,1update_1hook)(JENV_JSELF, jobject jDb, jobject jHook){
sqlite3 * const pDb = PtrGet_sqlite3(jDb); PerDbStateJni * const ps = PerDbStateJni_for_db(env, jDb, 0, 0);
PerDbStateJni * const ps = PerDbStateJni_for_db(env, pDb, 1);
jclass klazz; jclass klazz;
jobject pOld = 0; jobject pOld = 0;
jmethodID xCallback; jmethodID xCallback;
JniHookState * const pHook = &ps->updateHook; JniHookState * const pHook = &ps->updateHook;
if(!ps){ if(!ps){
s3jni_db_error(pDb, SQLITE_NOMEM, 0); s3jni_db_error(ps->pDb, SQLITE_NOMEM, 0);
return 0; return 0;
} }
pOld = pHook->jObj; pOld = pHook->jObj;
@ -2155,7 +2188,7 @@ JDECL(jobject,1update_1hook)(JENV_JSELF, jobject jDb, jobject jHook){
pOld = tmp; pOld = tmp;
} }
memset(pHook, 0, sizeof(JniHookState)); memset(pHook, 0, sizeof(JniHookState));
sqlite3_update_hook(pDb, 0, 0); sqlite3_update_hook(ps->pDb, 0, 0);
return pOld; return pOld;
} }
klazz = (*env)->GetObjectClass(env, jHook); klazz = (*env)->GetObjectClass(env, jHook);
@ -2163,13 +2196,13 @@ JDECL(jobject,1update_1hook)(JENV_JSELF, jobject jDb, jobject jHook){
"(ILjava/lang/String;Ljava/lang/String;J)V"); "(ILjava/lang/String;Ljava/lang/String;J)V");
IFTHREW { IFTHREW {
EXCEPTION_CLEAR; EXCEPTION_CLEAR;
s3jni_db_error(pDb, SQLITE_ERROR, s3jni_db_error(ps->pDb, SQLITE_ERROR,
"Cannot not find matching callback on " "Cannot not find matching callback on "
"update hook object."); "update hook object.");
}else{ }else{
pHook->midCallback = xCallback; pHook->midCallback = xCallback;
pHook->jObj = REF_G(jHook); pHook->jObj = REF_G(jHook);
sqlite3_update_hook(pDb, s3jni_update_hook_impl, ps); sqlite3_update_hook(ps->pDb, s3jni_update_hook_impl, ps);
if(pOld){ if(pOld){
jobject tmp = REF_L(pOld); jobject tmp = REF_L(pOld);
UNREF_G(pOld); UNREF_G(pOld);

View File

@ -1,5 +1,5 @@
C Incremental\scheckin\sto\sminimize\sthe\sdiff\swhile\snarrowing\sin\son\san\sassertion\scaused\sby\srefactoring. C Internal\sJNI\srefacoring\sto\ssupport\sthe\spending\ssqlite3_collation_needed()\scallback.\sCorrect\sa\sbug\sin\sthe\slinked-list\shandling\sof\sPerDbStateJni\swhich\striggered\san\sassert().
D 2023-07-30T09:45:54.025 D 2023-07-30T10:47:38.755
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
@ -232,7 +232,7 @@ F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8 F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
F ext/jni/GNUmakefile 56a014dbff9516774d895ec1ae9df0ed442765b556f79a0fc0b5bc438217200d F ext/jni/GNUmakefile 56a014dbff9516774d895ec1ae9df0ed442765b556f79a0fc0b5bc438217200d
F ext/jni/README.md c0e6e80935e7761acead89b69c87765b23a6bcb2858c321c3d05681fd338292a F ext/jni/README.md c0e6e80935e7761acead89b69c87765b23a6bcb2858c321c3d05681fd338292a
F ext/jni/src/c/sqlite3-jni.c 5b5631520dd2e3ae6890bcbbee2aad3d7b5c404e96ae826b661e1105d2d2a69d F ext/jni/src/c/sqlite3-jni.c 57db39bd2443435764777a1e43e2f8e356b8c411ee2649ad08df4b32087cbe80
F ext/jni/src/c/sqlite3-jni.h 85345dd3c970b539f1de4e6ad59c245fa6e80ca775a498ab1ed3d67f8615ce34 F ext/jni/src/c/sqlite3-jni.h 85345dd3c970b539f1de4e6ad59c245fa6e80ca775a498ab1ed3d67f8615ce34
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 5e592ed2dfc89225fff3a1c76509adc799a238282413984e0c4b32af18525d18 P 2d7a91b1396d87852f1153ab7af7385514a9537cb64ba3bbd0faba2d28704214
R a4ee8dd84c4c810bd2a0b503fc8278d5 R 5bff367529a1829789141e745a6b193a
U stephan U stephan
Z f4150e59d6c4033aef1bd32347c40f57 Z a4b019fdb819701e83942a71127183e7
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
2d7a91b1396d87852f1153ab7af7385514a9537cb64ba3bbd0faba2d28704214 7ac6614e69b03304d09745619ed83f12c7eb775aaf4a636a79289b01642ddd14