1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Further JNI cleanups.

FossilOrigin-Name: 30e38173c3ece0c9f8e7a9710f46cb5e8e8ef101c04531318a7adb070242f5dd
This commit is contained in:
stephan
2023-09-02 08:51:14 +00:00
parent 49a40ef6d2
commit 63f4a9c4db
10 changed files with 262 additions and 204 deletions

View File

@@ -110,7 +110,6 @@ ifeq (1,$(enable.fts5))
Fts5.java \ Fts5.java \
Fts5Context.java \ Fts5Context.java \
Fts5ExtensionApi.java \ Fts5ExtensionApi.java \
Fts5Function.java \
Fts5PhraseIter.java \ Fts5PhraseIter.java \
Fts5Tokenizer.java \ Fts5Tokenizer.java \
TesterFts5.java \ TesterFts5.java \

View File

@@ -269,6 +269,8 @@ static void * s3jni_realloc_or_die(JNIEnv * const env, void * p, size_t n){
#endif #endif
//#define S3JniDb_oom(pDb,EXPR) ((EXPR) ? sqlite3OomFault(pDb) : 0) //#define S3JniDb_oom(pDb,EXPR) ((EXPR) ? sqlite3OomFault(pDb) : 0)
#define s3jni_db_oom(pDb) (void)((pDb) ? ((pDb)->mallocFailed=1) : 0)
/* Helpers for Java value reference management. */ /* Helpers for Java value reference management. */
static jobject s3jni_ref_global(JNIEnv * const env, jobject const v){ static jobject s3jni_ref_global(JNIEnv * const env, jobject const v){
jobject const rv = v ? (*env)->NewGlobalRef(env, v) : NULL; jobject const rv = v ? (*env)->NewGlobalRef(env, v) : NULL;
@@ -402,7 +404,7 @@ struct S3JniNphClass {
*/ */
jclass klazz; jclass klazz;
volatile jmethodID midCtor /* klazz's no-arg constructor. Used by volatile jmethodID midCtor /* klazz's no-arg constructor. Used by
** new_NativePointerHolder_object(). */; ** NativePointerHolder_new(). */;
volatile jfieldID fidValue /* NativePointerHolder.nativePointer or volatile jfieldID fidValue /* NativePointerHolder.nativePointer or
** OutputPointer.T.value */; ** OutputPointer.T.value */;
volatile jfieldID fidAggCtx /* sqlite3_context.aggregateContext, used only volatile jfieldID fidAggCtx /* sqlite3_context.aggregateContext, used only
@@ -464,7 +466,10 @@ struct S3JniDb {
#endif #endif
} hooks; } hooks;
#ifdef SQLITE_ENABLE_FTS5 #ifdef SQLITE_ENABLE_FTS5
jobject jFtsApi /* global ref to s3jni_fts5_api_from_db() */; /* FTS5-specific state */
struct {
jobject jApi /* global ref to s3jni_fts5_api_from_db() */;
} fts;
#endif #endif
S3JniDb * pNext /* Next entry in SJG.perDb.aFree */; S3JniDb * pNext /* Next entry in SJG.perDb.aFree */;
}; };
@@ -581,18 +586,22 @@ struct S3JniGlobalType {
/* Global mutex. */ /* Global mutex. */
sqlite3_mutex * mutex; sqlite3_mutex * mutex;
/* /*
** Cache of Java refs and method IDs for NativePointerHolder ** Cache of references to Java classes and method IDs for
** subclasses and OutputPointer.T types. ** NativePointerHolder subclasses and OutputPointer.T types.
*/ */
S3JniNphClass nph[S3Jni_NphCache_size]; struct {
S3JniNphClass list[S3Jni_NphCache_size];
sqlite3_mutex * mutex; /* mutex for this->list */
void const * locker; /* sanity-checking-only context object
for this->mutex */
} nph;
/* /*
** Cache of per-thread state. ** Cache of per-thread state.
*/ */
struct { struct {
S3JniEnv * aHead /* Linked list of in-use instances */; S3JniEnv * aHead /* Linked list of in-use instances */;
S3JniEnv * aFree /* Linked list of free instances */; S3JniEnv * aFree /* Linked list of free instances */;
sqlite3_mutex * mutex /* mutex for aHead and aFree, and first-time sqlite3_mutex * mutex /* mutex for aHead and aFree. */;
inits of nph[] entries. */;
void const * locker /* env mutex is held on this object's behalf. void const * locker /* env mutex is held on this object's behalf.
Used only for sanity checking. */; Used only for sanity checking. */;
} envCache; } envCache;
@@ -642,7 +651,7 @@ struct S3JniGlobalType {
} autoExt; } autoExt;
#ifdef SQLITE_ENABLE_FTS5 #ifdef SQLITE_ENABLE_FTS5
struct { struct {
volatile jobject jFtsExt /* Global ref to Java singleton for the volatile jobject jExt /* Global ref to Java singleton for the
Fts5ExtensionApi instance. */; Fts5ExtensionApi instance. */;
struct { struct {
jfieldID fidA /* Fts5Phrase::a member */; jfieldID fidA /* Fts5Phrase::a member */;
@@ -665,7 +674,7 @@ struct S3JniGlobalType {
volatile unsigned nEnvAlloc; volatile unsigned nEnvAlloc;
volatile unsigned nMutexEnv /* number of times envCache.mutex was entered for volatile unsigned nMutexEnv /* number of times envCache.mutex was entered for
a S3JniEnv operation. */; a S3JniEnv operation. */;
volatile unsigned nMutexEnv2 /* number of times envCache.mutex was entered */; volatile unsigned nMutexNph /* number of times SJG.mutex was entered for NPH init */;
volatile unsigned nMutexPerDb /* number of times perDb.mutex was entered */; volatile unsigned nMutexPerDb /* number of times perDb.mutex was entered */;
volatile unsigned nMutexAutoExt /* number of times autoExt.mutex was entered */; volatile unsigned nMutexAutoExt /* number of times autoExt.mutex was entered */;
volatile unsigned nMutexGlobal /* number of times global mutex was entered. */; volatile unsigned nMutexGlobal /* number of times global mutex was entered. */;
@@ -743,18 +752,17 @@ static void s3jni_incr( volatile unsigned int * const p ){
#define S3JniGlobal_mutex_enter \ #define S3JniGlobal_mutex_enter \
sqlite3_mutex_enter( SJG.mutex ); \ sqlite3_mutex_enter( SJG.mutex ); \
s3jni_incr(&SJG.metrics.nMutexGlobal); s3jni_incr(&SJG.metrics.nMutexGlobal);
#define S3JniGlobal_mutex_leave \ #define S3JniGlobal_mutex_leave sqlite3_mutex_leave( SJG.mutex )
sqlite3_mutex_leave( SJG.mutex )
#define S3JniNph_mutex_enter \ #define S3JniNph_mutex_enter \
S3JniEnv_mutex_assertNotLocker; \ sqlite3_mutex_enter( SJG.nph.mutex ); \
sqlite3_mutex_enter( SJG.envCache.mutex ); \ assert( !SJG.nph.locker && "Misuse of S3JniGlobal.nph.mutex" ); \
s3jni_incr( &SJG.metrics.nMutexEnv2 ); \ s3jni_incr( &SJG.metrics.nMutexNph ); \
SJG.envCache.locker = env SJG.nph.locker = env
#define S3JniNph_mutex_leave \ #define S3JniNph_mutex_leave \
S3JniEnv_mutex_assertLocker; \ assert( (env) == SJG.nph.locker && "Misuse of S3JniGlobal.nph.mutex" ); \
SJG.envCache.locker = 0; \ SJG.nph.locker = 0; \
sqlite3_mutex_leave( SJG.envCache.mutex ) sqlite3_mutex_leave( SJG.nph.mutex )
#define S3JniDb_mutex_assertLocker \ #define S3JniDb_mutex_assertLocker \
assert( (env) == SJG.perDb.locker && "Misuse of S3JniGlobal.perDb.mutex" ) assert( (env) == SJG.perDb.locker && "Misuse of S3JniGlobal.perDb.mutex" )
@@ -1120,12 +1128,12 @@ static void s3jni__call_xDestroy(JNIEnv * const env, jobject jObj){
*/ */
static void S3JniHook__localdup( JNIEnv * const env, S3JniHook const * const src, static void S3JniHook__localdup( JNIEnv * const env, S3JniHook const * const src,
S3JniHook * const dest ){ S3JniHook * const dest ){
S3JniDb_mutex_enter; S3JniGlobal_mutex_enter;
*dest = *src; *dest = *src;
if(src->jObj) dest->jObj = S3JniRefLocal(src->jObj); if(src->jObj) dest->jObj = S3JniRefLocal(src->jObj);
if(src->jExtra) dest->jExtra = S3JniRefLocal(src->jExtra); if(src->jExtra) dest->jExtra = S3JniRefLocal(src->jExtra);
dest->doXDestroy = 0; dest->doXDestroy = 0;
S3JniDb_mutex_leave; S3JniGlobal_mutex_leave;
} }
#define S3JniHook_localdup(src,dest) S3JniHook__localdup(env,src,dest) #define S3JniHook_localdup(src,dest) S3JniHook__localdup(env,src,dest)
@@ -1309,7 +1317,7 @@ static int S3JniEnv_uncache(JNIEnv * const env){
** (2023-07-31) tests. ** (2023-07-31) tests.
*/ */
static S3JniNphClass * s3jni__nph(JNIEnv * const env, S3JniNphRef const* pRef){ static S3JniNphClass * s3jni__nph(JNIEnv * const env, S3JniNphRef const* pRef){
S3JniNphClass * const pNC = &SJG.nph[pRef->index]; S3JniNphClass * const pNC = &SJG.nph.list[pRef->index];
assert( (void*)pRef>=(void*)&S3JniNphRefs && (void*)pRef<(void*)(&S3JniNphRefs + 1) assert( (void*)pRef>=(void*)&S3JniNphRefs && (void*)pRef<(void*)(&S3JniNphRefs + 1)
&& "pRef is out of range" ); && "pRef is out of range" );
@@ -1341,7 +1349,7 @@ static S3JniNphClass * s3jni__nph(JNIEnv * const env, S3JniNphRef const* pRef){
** that requirement). If necessary, this fetches the jfieldID for ** that requirement). If necessary, this fetches the jfieldID for
** jOut's pRef->zMember, which must be of the type represented by the ** jOut's pRef->zMember, which must be of the type represented by the
** JNI type signature pRef->zTypeSig, and stores it in ** JNI type signature pRef->zTypeSig, and stores it in
** S3JniGlobal.nph[pRef->index]. Fails fatally if the pRef->zMember ** S3JniGlobal.nph.list[pRef->index]. Fails fatally if the pRef->zMember
** property is not found, as that presents a serious internal misuse. ** property is not found, as that presents a serious internal misuse.
** **
** Property lookups are cached on a per-pRef basis. ** Property lookups are cached on a per-pRef basis.
@@ -1661,7 +1669,8 @@ static void ResultJavaValue_finalizer(void *v){
** Always use a static pointer from the S3JniNphRefs struct for the ** Always use a static pointer from the S3JniNphRefs struct for the
** 2nd argument. ** 2nd argument.
*/ */
static jobject new_NativePointerHolder_object(JNIEnv * const env, S3JniNphRef const * pRef, static jobject NativePointerHolder_new(JNIEnv * const env,
S3JniNphRef const * pRef,
const void * pNative){ const void * pNative){
jobject rv = 0; jobject rv = 0;
S3JniNphClass * const pNC = s3jni_nph(pRef); S3JniNphClass * const pNC = s3jni_nph(pRef);
@@ -1680,17 +1689,17 @@ static jobject new_NativePointerHolder_object(JNIEnv * const env, S3JniNphRef co
return rv; return rv;
} }
static inline jobject new_sqlite3_wrapper(JNIEnv * const env, sqlite3 *sv){ static inline jobject new_java_sqlite3(JNIEnv * const env, sqlite3 *sv){
return new_NativePointerHolder_object(env, S3JniNph(sqlite3), sv); return NativePointerHolder_new(env, S3JniNph(sqlite3), sv);
} }
static inline jobject new_sqlite3_context_wrapper(JNIEnv * const env, sqlite3_context *sv){ static inline jobject new_java_sqlite3_context(JNIEnv * const env, sqlite3_context *sv){
return new_NativePointerHolder_object(env, S3JniNph(sqlite3_context), sv); return NativePointerHolder_new(env, S3JniNph(sqlite3_context), sv);
} }
static inline jobject new_sqlite3_stmt_wrapper(JNIEnv * const env, sqlite3_stmt *sv){ static inline jobject new_java_sqlite3_stmt(JNIEnv * const env, sqlite3_stmt *sv){
return new_NativePointerHolder_object(env, S3JniNph(sqlite3_stmt), sv); return NativePointerHolder_new(env, S3JniNph(sqlite3_stmt), sv);
} }
static inline jobject new_sqlite3_value_wrapper(JNIEnv * const env, sqlite3_value *sv){ static inline jobject new_java_sqlite3_value(JNIEnv * const env, sqlite3_value *sv){
return new_NativePointerHolder_object(env, S3JniNph(sqlite3_value), sv); return NativePointerHolder_new(env, S3JniNph(sqlite3_value), sv);
} }
/* Helper typedefs for UDF callback types. */ /* Helper typedefs for UDF callback types. */
@@ -1811,7 +1820,7 @@ static int udf_args(JNIEnv *env,
int argc, sqlite3_value**argv, int argc, sqlite3_value**argv,
jobject * jCx, jobjectArray *jArgv){ jobject * jCx, jobjectArray *jArgv){
jobjectArray ja = 0; jobjectArray ja = 0;
jobject jcx = new_sqlite3_context_wrapper(env, cx); jobject jcx = new_java_sqlite3_context(env, cx);
jint i; jint i;
*jCx = 0; *jCx = 0;
*jArgv = 0; *jArgv = 0;
@@ -1822,7 +1831,7 @@ static int udf_args(JNIEnv *env,
s3jni_oom_check( ja ); s3jni_oom_check( ja );
if( !ja ) goto error_oom; if( !ja ) goto error_oom;
for(i = 0; i < argc; ++i){ for(i = 0; i < argc; ++i){
jobject jsv = new_sqlite3_value_wrapper(env, argv[i]); jobject jsv = new_java_sqlite3_value(env, argv[i]);
if( !jsv ) goto error_oom; if( !jsv ) goto error_oom;
(*env)->SetObjectArrayElement(env, ja, i, jsv); (*env)->SetObjectArrayElement(env, ja, i, jsv);
S3JniUnrefLocal(jsv)/*ja has a ref*/; S3JniUnrefLocal(jsv)/*ja has a ref*/;
@@ -1909,7 +1918,7 @@ static int udf_xFV(sqlite3_context* cx, S3JniUdf * s,
jmethodID xMethodID, jmethodID xMethodID,
const char *zFuncType){ const char *zFuncType){
S3JniDeclLocal_env; S3JniDeclLocal_env;
jobject jcx = new_sqlite3_context_wrapper(env, cx); jobject jcx = new_java_sqlite3_context(env, cx);
int rc = 0; int rc = 0;
int const isFinal = 'F'==zFuncType[1]/*xFinal*/; int const isFinal = 'F'==zFuncType[1]/*xFinal*/;
@@ -2104,21 +2113,30 @@ static int s3jni_run_java_auto_extensions(sqlite3 *pDb, const char **pzErr,
if( 0==SJG.autoExt.nExt ) return 0; if( 0==SJG.autoExt.nExt ) return 0;
env = s3jni_env(); env = s3jni_env();
jc = S3JniEnv_get(); jc = S3JniEnv_get();
ps = jc->pdbOpening; S3JniAutoExt_mutex_enter;
ps = jc->pdbOpening ? jc->pdbOpening : S3JniDb_from_c(pDb);
if( !ps ){ if( !ps ){
*pzErr = sqlite3_mprintf("Unexpected arrival of null S3JniDb in " *pzErr = sqlite3_mprintf("Unexpected arrival of null S3JniDb in "
"auto-extension runner."); "auto-extension runner.");
S3JniAutoExt_mutex_leave;
return SQLITE_ERROR; return SQLITE_ERROR;
} }
jc->pdbOpening = 0;
assert( !ps->pDb && "it's still being opened" );
assert( ps->jDb ); assert( ps->jDb );
if( !ps->pDb ){
assert( jc->pdbOpening == ps );
rc = sqlite3_set_clientdata(pDb, S3JniDb_clientdata_key, rc = sqlite3_set_clientdata(pDb, S3JniDb_clientdata_key,
ps, 0/* we'll re-set this after open() ps, 0/* we'll re-set this after open()
completes. */); completes. */);
if( rc ){ if( rc ){
S3JniAutoExt_mutex_leave;
return rc; return rc;
} }
}
else{
assert( ps == jc->pdbOpening );
jc->pdbOpening = 0;
}
S3JniAutoExt_mutex_leave;
NativePointerHolder_set(S3JniNph(sqlite3), ps->jDb, pDb) NativePointerHolder_set(S3JniNph(sqlite3), ps->jDb, pDb)
/* As of here, the Java/C connection is complete except for the /* As of here, the Java/C connection is complete except for the
(temporary) lack of finalizer for the ps object. */; (temporary) lack of finalizer for the ps object. */;
@@ -2534,7 +2552,8 @@ S3JniApi(sqlite3_collation_needed(),jint,1collation_1needed)(
"Cannot not find matching call() in " "Cannot not find matching call() in "
"CollationNeededCallback object."); "CollationNeededCallback object.");
}else{ }else{
rc = sqlite3_collation_needed16(ps->pDb, pHook, s3jni_collation_needed_impl16); rc = sqlite3_collation_needed16(ps->pDb, pHook,
s3jni_collation_needed_impl16);
if( 0==rc ){ if( 0==rc ){
S3JniHook_unref(pHook); S3JniHook_unref(pHook);
pHook->midCallback = xCallback; pHook->midCallback = xCallback;
@@ -2610,7 +2629,7 @@ S3JniApi(sqlite3_column_value(),jobject,1column_1value)(
){ ){
sqlite3_value * const sv = sqlite3_value * const sv =
sqlite3_column_value(PtrGet_sqlite3_stmt(jpStmt), (int)ndx); sqlite3_column_value(PtrGet_sqlite3_stmt(jpStmt), (int)ndx);
return new_sqlite3_value_wrapper(env, sv); return new_java_sqlite3_value(env, sv);
} }
/* /*
@@ -2896,7 +2915,7 @@ S3JniApi(sqlite3_create_collation() sqlite3_create_collation_v2(),
"Could not get call() method from " "Could not get call() method from "
"CollationCallback object."); "CollationCallback object.");
}else{ }else{
char * const zName = s3jni_jstring_to_utf8( name, 0); char * const zName = s3jni_jstring_to_utf8(name, 0);
S3JniCollationCallback * const pCC = S3JniCollationCallback * const pCC =
zName ? S3JniHook_alloc() : 0; zName ? S3JniHook_alloc() : 0;
if( pCC ){ if( pCC ){
@@ -3253,7 +3272,7 @@ static int s3jni_open_pre(JNIEnv * const env, S3JniEnv **jc,
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
goto end; goto end;
} }
jDb = new_sqlite3_wrapper(env, 0); jDb = new_java_sqlite3(env, 0);
if( !jDb ){ if( !jDb ){
sqlite3_free(*zDbName); sqlite3_free(*zDbName);
*zDbName = 0; *zDbName = 0;
@@ -3371,7 +3390,7 @@ jint sqlite3_jni_prepare_v123( int prepVersion, JNIEnv * const env, jclass self,
rc = baSql ? SQLITE_NOMEM : SQLITE_MISUSE; rc = baSql ? SQLITE_NOMEM : SQLITE_MISUSE;
goto end; goto end;
} }
jStmt = new_sqlite3_stmt_wrapper(env, 0); jStmt = new_java_sqlite3_stmt(env, 0);
if( !jStmt ){ if( !jStmt ){
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
goto end; goto end;
@@ -3616,7 +3635,7 @@ static int s3jni_preupdate_newold(JNIEnv * const env, int isNew, jobject jDb,
isNew ? sqlite3_preupdate_new : sqlite3_preupdate_old; isNew ? sqlite3_preupdate_new : sqlite3_preupdate_old;
rc = fOrig(pDb, (int)iCol, &pOut); rc = fOrig(pDb, (int)iCol, &pOut);
if( 0==rc ){ if( 0==rc ){
jobject pWrap = new_sqlite3_value_wrapper(env, pOut); jobject pWrap = new_java_sqlite3_value(env, pOut);
if( pWrap ){ if( pWrap ){
OutputPointer_set_sqlite3_value(env, jOut, pWrap); OutputPointer_set_sqlite3_value(env, jOut, pWrap);
S3JniUnrefLocal(pWrap); S3JniUnrefLocal(pWrap);
@@ -4235,7 +4254,7 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
if( 0==rc ){ if( 0==rc ){
if( !jP ){ if( !jP ){
/* Create a new temporary sqlite3_stmt wrapper */ /* Create a new temporary sqlite3_stmt wrapper */
jP = jPUnref = new_sqlite3_stmt_wrapper(env, pP); jP = jPUnref = new_java_sqlite3_stmt(env, pP);
if( !jP ){ if( !jP ){
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
} }
@@ -4347,7 +4366,7 @@ S3JniApi(sqlite3_value_dup(),jobject,1value_1dup)(
JniArgsEnvClass, jobject jpSVal JniArgsEnvClass, jobject jpSVal
){ ){
sqlite3_value * const sv = sqlite3_value_dup(PtrGet_sqlite3_value(jpSVal)); sqlite3_value * const sv = sqlite3_value_dup(PtrGet_sqlite3_value(jpSVal));
return sv ? new_sqlite3_value_wrapper(env, sv) : 0; return sv ? new_java_sqlite3_value(env, sv) : 0;
} }
S3JniApi(sqlite3_value_free(),void,1value_1free)( S3JniApi(sqlite3_value_free(),void,1value_1free)(
@@ -4444,7 +4463,7 @@ JniDecl(void,1jni_1internal_1details)(JniArgsEnvClass){
"\n\tS3JniUdf = %u (free-list)" "\n\tS3JniUdf = %u (free-list)"
"\n\tmetrics = %u\n", "\n\tmetrics = %u\n",
SJG.metrics.nMutexGlobal, SJG.metrics.nMutexEnv, SJG.metrics.nMutexGlobal, SJG.metrics.nMutexEnv,
SJG.metrics.nMutexEnv2, SJG.metrics.nMutexPerDb, SJG.metrics.nMutexNph, SJG.metrics.nMutexPerDb,
SJG.metrics.nMutexAutoExt, SJG.metrics.nMutexUdf, SJG.metrics.nMutexAutoExt, SJG.metrics.nMutexUdf,
SJG.metrics.nMetrics); SJG.metrics.nMetrics);
puts("Allocs:"); puts("Allocs:");
@@ -4501,7 +4520,8 @@ JniDecl(void,1jni_1internal_1details)(JniArgsEnvClass){
#define PtrGet_fts5_tokenizer(OBJ) NativePointerHolder_get(OBJ,S3JniNph(fts5_tokenizer)) #define PtrGet_fts5_tokenizer(OBJ) NativePointerHolder_get(OBJ,S3JniNph(fts5_tokenizer))
#define PtrGet_Fts5Context(OBJ) NativePointerHolder_get(OBJ,S3JniNph(Fts5Context)) #define PtrGet_Fts5Context(OBJ) NativePointerHolder_get(OBJ,S3JniNph(Fts5Context))
#define PtrGet_Fts5Tokenizer(OBJ) NativePointerHolder_get(OBJ,S3JniNph(Fts5Tokenizer)) #define PtrGet_Fts5Tokenizer(OBJ) NativePointerHolder_get(OBJ,S3JniNph(Fts5Tokenizer))
#define Fts5ExtDecl Fts5ExtensionApi const * const fext = s3jni_ftsext() #define s3jni_ftsext() &sFts5Api/*singleton from sqlite3.c*/
#define Fts5ExtDecl Fts5ExtensionApi const * const ext = s3jni_ftsext()
/** /**
State for binding Java-side FTS5 auxiliary functions. State for binding Java-side FTS5 auxiliary functions.
@@ -4541,7 +4561,7 @@ static Fts5JniAux * Fts5JniAux_alloc(JNIEnv * const env, jobject jObj){
memset(s, 0, sizeof(Fts5JniAux)); memset(s, 0, sizeof(Fts5JniAux));
s->jObj = S3JniRefGlobal(jObj); s->jObj = S3JniRefGlobal(jObj);
klazz = (*env)->GetObjectClass(env, jObj); klazz = (*env)->GetObjectClass(env, jObj);
s->jmid = (*env)->GetMethodID(env, klazz, "xFunction", s->jmid = (*env)->GetMethodID(env, klazz, "call",
"(Lorg/sqlite/jni/Fts5ExtensionApi;" "(Lorg/sqlite/jni/Fts5ExtensionApi;"
"Lorg/sqlite/jni/Fts5Context;" "Lorg/sqlite/jni/Fts5Context;"
"Lorg/sqlite/jni/sqlite3_context;" "Lorg/sqlite/jni/sqlite3_context;"
@@ -4557,15 +4577,11 @@ static Fts5JniAux * Fts5JniAux_alloc(JNIEnv * const env, jobject jObj){
return s; return s;
} }
static inline Fts5ExtensionApi const * s3jni_ftsext(void){ static inline jobject new_java_Fts5Context(JNIEnv * const env, Fts5Context *sv){
return &sFts5Api/*singleton from sqlite3.c*/; return NativePointerHolder_new(env, S3JniNph(Fts5Context), sv);
} }
static inline jobject new_java_fts5_api(JNIEnv * const env, fts5_api *sv){
static inline jobject new_Fts5Context_wrapper(JNIEnv * const env, Fts5Context *sv){ return NativePointerHolder_new(env, S3JniNph(fts5_api), sv);
return new_NativePointerHolder_object(env, S3JniNph(Fts5Context), sv);
}
static inline jobject new_fts5_api_wrapper(JNIEnv * const env, fts5_api *sv){
return new_NativePointerHolder_object(env, S3JniNph(fts5_api), sv);
} }
/* /*
@@ -4573,20 +4589,20 @@ static inline jobject new_fts5_api_wrapper(JNIEnv * const env, fts5_api *sv){
** instance, or NULL on OOM. ** instance, or NULL on OOM.
*/ */
static jobject s3jni_getFts5ExensionApi(JNIEnv * const env){ static jobject s3jni_getFts5ExensionApi(JNIEnv * const env){
if( !SJG.fts5.jFtsExt ){ if( !SJG.fts5.jExt ){
jobject pNPH = new_NativePointerHolder_object( S3JniGlobal_mutex_enter;
if( !SJG.fts5.jExt ){
jobject const pNPH = NativePointerHolder_new(
env, S3JniNph(Fts5ExtensionApi), s3jni_ftsext() env, S3JniNph(Fts5ExtensionApi), s3jni_ftsext()
); );
S3JniEnv_mutex_enter;
if( pNPH ){ if( pNPH ){
if( !SJG.fts5.jFtsExt ){ SJG.fts5.jExt = S3JniRefGlobal(pNPH);
SJG.fts5.jFtsExt = S3JniRefGlobal(pNPH);
}
S3JniUnrefLocal(pNPH); S3JniUnrefLocal(pNPH);
} }
S3JniEnv_mutex_leave;
} }
return SJG.fts5.jFtsExt; S3JniGlobal_mutex_leave;
}
return SJG.fts5.jExt;
} }
/* /*
@@ -4607,18 +4623,33 @@ static fts5_api *s3jni_fts5_api_from_db(sqlite3 *db){
JniDeclFtsApi(jobject,getInstanceForDb)(JniArgsEnvClass,jobject jDb){ JniDeclFtsApi(jobject,getInstanceForDb)(JniArgsEnvClass,jobject jDb){
S3JniDb * const ps = S3JniDb_from_java(jDb); S3JniDb * const ps = S3JniDb_from_java(jDb);
#if 0
jobject rv = 0; jobject rv = 0;
if( !ps ) return 0; if( !ps ) return 0;
else if( ps->jFtsApi ){ else if( ps->fts.jApi ){
rv = ps->jFtsApi; rv = ps->fts.jApi;
}else{ }else{
fts5_api * const pApi = s3jni_fts5_api_from_db(ps->pDb); fts5_api * const pApi = s3jni_fts5_api_from_db(ps->pDb);
if( pApi ){ if( pApi ){
rv = new_fts5_api_wrapper(env, pApi); rv = new_java_fts5_api(env, pApi);
ps->jFtsApi = rv ? S3JniRefGlobal(rv) : 0; ps->fts.jApi = rv ? S3JniRefGlobal(rv) : 0;
} }
} }
return rv; return rv;
#else
if( ps && !ps->fts.jApi ){
S3JniDb_mutex_enter;
if( !ps->fts.jApi ){
fts5_api * const pApi = s3jni_fts5_api_from_db(ps->pDb);
if( pApi ){
jobject const rv = new_java_fts5_api(env, pApi);
ps->fts.jApi = rv ? S3JniRefGlobal(rv) : 0;
}
}
S3JniDb_mutex_leave;
}
return ps ? ps->fts.jApi : 0;
#endif
} }
@@ -4628,13 +4659,13 @@ JniDeclFtsXA(jobject,getInstance)(JniArgsEnvClass){
JniDeclFtsXA(jint,xColumnCount)(JniArgsEnvObj,jobject jCtx){ JniDeclFtsXA(jint,xColumnCount)(JniArgsEnvObj,jobject jCtx){
Fts5ExtDecl; Fts5ExtDecl;
return (jint)fext->xColumnCount(PtrGet_Fts5Context(jCtx)); return (jint)ext->xColumnCount(PtrGet_Fts5Context(jCtx));
} }
JniDeclFtsXA(jint,xColumnSize)(JniArgsEnvObj,jobject jCtx, jint iIdx, jobject jOut32){ JniDeclFtsXA(jint,xColumnSize)(JniArgsEnvObj,jobject jCtx, jint iIdx, jobject jOut32){
Fts5ExtDecl; Fts5ExtDecl;
int n1 = 0; int n1 = 0;
int const rc = fext->xColumnSize(PtrGet_Fts5Context(jCtx), (int)iIdx, &n1); int const rc = ext->xColumnSize(PtrGet_Fts5Context(jCtx), (int)iIdx, &n1);
if( 0==rc ) OutputPointer_set_Int32(env, jOut32, n1); if( 0==rc ) OutputPointer_set_Int32(env, jOut32, n1);
return rc; return rc;
} }
@@ -4644,7 +4675,7 @@ JniDeclFtsXA(jint,xColumnText)(JniArgsEnvObj,jobject jCtx, jint iCol,
Fts5ExtDecl; Fts5ExtDecl;
const char *pz = 0; const char *pz = 0;
int pn = 0; int pn = 0;
int rc = fext->xColumnText(PtrGet_Fts5Context(jCtx), (int)iCol, int rc = ext->xColumnText(PtrGet_Fts5Context(jCtx), (int)iCol,
&pz, &pn); &pz, &pn);
if( 0==rc ){ if( 0==rc ){
jstring jstr = pz ? s3jni_utf8_to_jstring( pz, pn) : 0; jstring jstr = pz ? s3jni_utf8_to_jstring( pz, pn) : 0;
@@ -4663,7 +4694,7 @@ JniDeclFtsXA(jint,xColumnText)(JniArgsEnvObj,jobject jCtx, jint iCol,
JniDeclFtsXA(jint,xColumnTotalSize)(JniArgsEnvObj,jobject jCtx, jint iCol, jobject jOut64){ JniDeclFtsXA(jint,xColumnTotalSize)(JniArgsEnvObj,jobject jCtx, jint iCol, jobject jOut64){
Fts5ExtDecl; Fts5ExtDecl;
sqlite3_int64 nOut = 0; sqlite3_int64 nOut = 0;
int const rc = fext->xColumnTotalSize(PtrGet_Fts5Context(jCtx), (int)iCol, &nOut); int const rc = ext->xColumnTotalSize(PtrGet_Fts5Context(jCtx), (int)iCol, &nOut);
if( 0==rc && jOut64 ) OutputPointer_set_Int64(env, jOut64, (jlong)nOut); if( 0==rc && jOut64 ) OutputPointer_set_Int64(env, jOut64, (jlong)nOut);
return (jint)rc; return (jint)rc;
} }
@@ -4688,20 +4719,21 @@ static void s3jni_fts5_extension_function(Fts5ExtensionApi const *pApi,
assert(pAux); assert(pAux);
jFXA = s3jni_getFts5ExensionApi(env); jFXA = s3jni_getFts5ExensionApi(env);
if( !jFXA ) goto error_oom; if( !jFXA ) goto error_oom;
jpFts = new_Fts5Context_wrapper(env, pFts); jpFts = new_java_Fts5Context(env, pFts);
if( !jpFts ) goto error_oom; if( !jpFts ) goto error_oom;
rc = udf_args(env, pCx, argc, argv, &jpCx, &jArgv); rc = udf_args(env, pCx, argc, argv, &jpCx, &jArgv);
if( rc ) goto error_oom; if( rc ) goto error_oom;
(*env)->CallVoidMethod(env, pAux->jObj, pAux->jmid, (*env)->CallVoidMethod(env, pAux->jObj, pAux->jmid,
jFXA, jpFts, jpCx, jArgv); jFXA, jpFts, jpCx, jArgv);
S3JniIfThrew{ S3JniIfThrew{
udf_report_exception(env, 1, pCx, pAux->zFuncName, "xFunction"); udf_report_exception(env, 1, pCx, pAux->zFuncName, "call");
} }
S3JniUnrefLocal(jpFts); S3JniUnrefLocal(jpFts);
S3JniUnrefLocal(jpCx); S3JniUnrefLocal(jpCx);
S3JniUnrefLocal(jArgv); S3JniUnrefLocal(jArgv);
return; return;
error_oom: error_oom:
s3jni_db_oom( sqlite3_context_db_handle(pCx) );
assert( !jArgv ); assert( !jArgv );
assert( !jpCx ); assert( !jpCx );
S3JniUnrefLocal(jpFts); S3JniUnrefLocal(jpFts);
@@ -4761,7 +4793,7 @@ static void S3JniFts5AuxData_xDestroy(void *x){
JniDeclFtsXA(jobject,xGetAuxdata)(JniArgsEnvObj,jobject jCtx, jboolean bClear){ JniDeclFtsXA(jobject,xGetAuxdata)(JniArgsEnvObj,jobject jCtx, jboolean bClear){
Fts5ExtDecl; Fts5ExtDecl;
jobject rv = 0; jobject rv = 0;
S3JniFts5AuxData * const pAux = fext->xGetAuxdata(PtrGet_Fts5Context(jCtx), bClear); S3JniFts5AuxData * const pAux = ext->xGetAuxdata(PtrGet_Fts5Context(jCtx), bClear);
if( pAux ){ if( pAux ){
if( bClear ){ if( bClear ){
if( pAux->jObj ){ if( pAux->jObj ){
@@ -4781,7 +4813,7 @@ JniDeclFtsXA(jint,xInst)(JniArgsEnvObj,jobject jCtx, jint iIdx, jobject jOutPhra
jobject jOutCol, jobject jOutOff){ jobject jOutCol, jobject jOutOff){
Fts5ExtDecl; Fts5ExtDecl;
int n1 = 0, n2 = 2, n3 = 0; int n1 = 0, n2 = 2, n3 = 0;
int const rc = fext->xInst(PtrGet_Fts5Context(jCtx), (int)iIdx, &n1, &n2, &n3); int const rc = ext->xInst(PtrGet_Fts5Context(jCtx), (int)iIdx, &n1, &n2, &n3);
if( 0==rc ){ if( 0==rc ){
OutputPointer_set_Int32(env, jOutPhrase, n1); OutputPointer_set_Int32(env, jOutPhrase, n1);
OutputPointer_set_Int32(env, jOutCol, n2); OutputPointer_set_Int32(env, jOutCol, n2);
@@ -4793,14 +4825,14 @@ JniDeclFtsXA(jint,xInst)(JniArgsEnvObj,jobject jCtx, jint iIdx, jobject jOutPhra
JniDeclFtsXA(jint,xInstCount)(JniArgsEnvObj,jobject jCtx, jobject jOut32){ JniDeclFtsXA(jint,xInstCount)(JniArgsEnvObj,jobject jCtx, jobject jOut32){
Fts5ExtDecl; Fts5ExtDecl;
int nOut = 0; int nOut = 0;
int const rc = fext->xInstCount(PtrGet_Fts5Context(jCtx), &nOut); int const rc = ext->xInstCount(PtrGet_Fts5Context(jCtx), &nOut);
if( 0==rc && jOut32 ) OutputPointer_set_Int32(env, jOut32, nOut); if( 0==rc && jOut32 ) OutputPointer_set_Int32(env, jOut32, nOut);
return (jint)rc; return (jint)rc;
} }
JniDeclFtsXA(jint,xPhraseCount)(JniArgsEnvObj,jobject jCtx){ JniDeclFtsXA(jint,xPhraseCount)(JniArgsEnvObj,jobject jCtx){
Fts5ExtDecl; Fts5ExtDecl;
return (jint)fext->xPhraseCount(PtrGet_Fts5Context(jCtx)); return (jint)ext->xPhraseCount(PtrGet_Fts5Context(jCtx));
} }
/* Copy the 'a' and 'b' fields from pSrc to Fts5PhraseIter object jIter. */ /* Copy the 'a' and 'b' fields from pSrc to Fts5PhraseIter object jIter. */
@@ -4834,7 +4866,7 @@ JniDeclFtsXA(jint,xPhraseFirst)(JniArgsEnvObj,jobject jCtx, jint iPhrase,
Fts5ExtDecl; Fts5ExtDecl;
Fts5PhraseIter iter; Fts5PhraseIter iter;
int rc, iCol = 0, iOff = 0; int rc, iCol = 0, iOff = 0;
rc = fext->xPhraseFirst(PtrGet_Fts5Context(jCtx), (int)iPhrase, rc = ext->xPhraseFirst(PtrGet_Fts5Context(jCtx), (int)iPhrase,
&iter, &iCol, &iOff); &iter, &iCol, &iOff);
if( 0==rc ){ if( 0==rc ){
OutputPointer_set_Int32(env, jOutCol, iCol); OutputPointer_set_Int32(env, jOutCol, iCol);
@@ -4849,7 +4881,7 @@ JniDeclFtsXA(jint,xPhraseFirstColumn)(JniArgsEnvObj,jobject jCtx, jint iPhrase,
Fts5ExtDecl; Fts5ExtDecl;
Fts5PhraseIter iter; Fts5PhraseIter iter;
int rc, iCol = 0; int rc, iCol = 0;
rc = fext->xPhraseFirstColumn(PtrGet_Fts5Context(jCtx), (int)iPhrase, rc = ext->xPhraseFirstColumn(PtrGet_Fts5Context(jCtx), (int)iPhrase,
&iter, &iCol); &iter, &iCol);
if( 0==rc ){ if( 0==rc ){
OutputPointer_set_Int32(env, jOutCol, iCol); OutputPointer_set_Int32(env, jOutCol, iCol);
@@ -4864,7 +4896,7 @@ JniDeclFtsXA(void,xPhraseNext)(JniArgsEnvObj,jobject jCtx, jobject jIter,
Fts5PhraseIter iter; Fts5PhraseIter iter;
int iCol = 0, iOff = 0; int iCol = 0, iOff = 0;
s3jni_phraseIter_JToN(env, jIter, &iter); s3jni_phraseIter_JToN(env, jIter, &iter);
fext->xPhraseNext(PtrGet_Fts5Context(jCtx), &iter, &iCol, &iOff); ext->xPhraseNext(PtrGet_Fts5Context(jCtx), &iter, &iCol, &iOff);
OutputPointer_set_Int32(env, jOutCol, iCol); OutputPointer_set_Int32(env, jOutCol, iCol);
OutputPointer_set_Int32(env, jOutOff, iOff); OutputPointer_set_Int32(env, jOutOff, iOff);
s3jni_phraseIter_NToJ(env, &iter, jIter); s3jni_phraseIter_NToJ(env, &iter, jIter);
@@ -4876,7 +4908,7 @@ JniDeclFtsXA(void,xPhraseNextColumn)(JniArgsEnvObj,jobject jCtx, jobject jIter,
Fts5PhraseIter iter; Fts5PhraseIter iter;
int iCol = 0; int iCol = 0;
s3jni_phraseIter_JToN(env, jIter, &iter); s3jni_phraseIter_JToN(env, jIter, &iter);
fext->xPhraseNextColumn(PtrGet_Fts5Context(jCtx), &iter, &iCol); ext->xPhraseNextColumn(PtrGet_Fts5Context(jCtx), &iter, &iCol);
OutputPointer_set_Int32(env, jOutCol, iCol); OutputPointer_set_Int32(env, jOutCol, iCol);
s3jni_phraseIter_NToJ(env, &iter, jIter); s3jni_phraseIter_NToJ(env, &iter, jIter);
} }
@@ -4884,12 +4916,12 @@ JniDeclFtsXA(void,xPhraseNextColumn)(JniArgsEnvObj,jobject jCtx, jobject jIter,
JniDeclFtsXA(jint,xPhraseSize)(JniArgsEnvObj,jobject jCtx, jint iPhrase){ JniDeclFtsXA(jint,xPhraseSize)(JniArgsEnvObj,jobject jCtx, jint iPhrase){
Fts5ExtDecl; Fts5ExtDecl;
return (jint)fext->xPhraseSize(PtrGet_Fts5Context(jCtx), (int)iPhrase); return (jint)ext->xPhraseSize(PtrGet_Fts5Context(jCtx), (int)iPhrase);
} }
/* State for use with xQueryPhrase() and xTokenize(). */ /* State for use with xQueryPhrase() and xTokenize(). */
struct s3jni_xQueryPhraseState { struct s3jni_xQueryPhraseState {
Fts5ExtensionApi const * fext; Fts5ExtensionApi const * ext;
S3JniEnv const * jc; S3JniEnv const * jc;
jmethodID midCallback; jmethodID midCallback;
jobject jCallback; jobject jCallback;
@@ -4910,7 +4942,7 @@ static int s3jni_xQueryPhrase(const Fts5ExtensionApi *xapi,
struct s3jni_xQueryPhraseState const * s = pData; struct s3jni_xQueryPhraseState const * s = pData;
S3JniDeclLocal_env; S3JniDeclLocal_env;
int rc = (int)(*env)->CallIntMethod(env, s->jCallback, s->midCallback, int rc = (int)(*env)->CallIntMethod(env, s->jCallback, s->midCallback,
SJG.fts5.jFtsExt, s->jFcx); SJG.fts5.jExt, s->jFcx);
S3JniIfThrew{ S3JniIfThrew{
S3JniExceptionWarnCallbackThrew("xQueryPhrase() callback"); S3JniExceptionWarnCallbackThrew("xQueryPhrase() callback");
S3JniExceptionClear; S3JniExceptionClear;
@@ -4930,13 +4962,13 @@ JniDeclFtsXA(jint,xQueryPhrase)(JniArgsEnvObj,jobject jFcx, jint iPhrase,
s.jc = jc; s.jc = jc;
s.jCallback = jCallback; s.jCallback = jCallback;
s.jFcx = jFcx; s.jFcx = jFcx;
s.fext = fext; s.ext = ext;
s.midCallback = (*env)->GetMethodID(env, klazz, "xCallback", s.midCallback = (*env)->GetMethodID(env, klazz, "call",
"(Lorg.sqlite.jni.Fts5ExtensionApi;" "(Lorg.sqlite.jni.Fts5ExtensionApi;"
"Lorg.sqlite.jni.Fts5Context;)I"); "Lorg.sqlite.jni.Fts5Context;)I");
S3JniUnrefLocal(klazz); S3JniUnrefLocal(klazz);
S3JniExceptionIsFatal("Could not extract xQueryPhraseCallback.xCallback method."); S3JniExceptionIsFatal("Could not extract xQueryPhraseCallback.call() method.");
return (jint)fext->xQueryPhrase(PtrGet_Fts5Context(jFcx), iPhrase, &s, return (jint)ext->xQueryPhrase(PtrGet_Fts5Context(jFcx), iPhrase, &s,
s3jni_xQueryPhrase); s3jni_xQueryPhrase);
} }
@@ -4944,14 +4976,14 @@ JniDeclFtsXA(jint,xQueryPhrase)(JniArgsEnvObj,jobject jFcx, jint iPhrase,
JniDeclFtsXA(jint,xRowCount)(JniArgsEnvObj,jobject jCtx, jobject jOut64){ JniDeclFtsXA(jint,xRowCount)(JniArgsEnvObj,jobject jCtx, jobject jOut64){
Fts5ExtDecl; Fts5ExtDecl;
sqlite3_int64 nOut = 0; sqlite3_int64 nOut = 0;
int const rc = fext->xRowCount(PtrGet_Fts5Context(jCtx), &nOut); int const rc = ext->xRowCount(PtrGet_Fts5Context(jCtx), &nOut);
if( 0==rc && jOut64 ) OutputPointer_set_Int64(env, jOut64, (jlong)nOut); if( 0==rc && jOut64 ) OutputPointer_set_Int64(env, jOut64, (jlong)nOut);
return (jint)rc; return (jint)rc;
} }
JniDeclFtsXA(jlong,xRowid)(JniArgsEnvObj,jobject jCtx){ JniDeclFtsXA(jlong,xRowid)(JniArgsEnvObj,jobject jCtx){
Fts5ExtDecl; Fts5ExtDecl;
return (jlong)fext->xRowid(PtrGet_Fts5Context(jCtx)); return (jlong)ext->xRowid(PtrGet_Fts5Context(jCtx));
} }
JniDeclFtsXA(int,xSetAuxdata)(JniArgsEnvObj,jobject jCtx, jobject jAux){ JniDeclFtsXA(int,xSetAuxdata)(JniArgsEnvObj,jobject jCtx, jobject jAux){
@@ -4969,7 +5001,7 @@ JniDeclFtsXA(int,xSetAuxdata)(JniArgsEnvObj,jobject jCtx, jobject jAux){
return SQLITE_NOMEM; return SQLITE_NOMEM;
} }
pAux->jObj = S3JniRefGlobal(jAux); pAux->jObj = S3JniRefGlobal(jAux);
rc = fext->xSetAuxdata(PtrGet_Fts5Context(jCtx), pAux, rc = ext->xSetAuxdata(PtrGet_Fts5Context(jCtx), pAux,
S3JniFts5AuxData_xDestroy); S3JniFts5AuxData_xDestroy);
return rc; return rc;
} }
@@ -5018,7 +5050,7 @@ static jint s3jni_fts5_xTokenize(JniArgsEnvObj, S3JniNphRef const *pRef,
s.jc = jc; s.jc = jc;
s.jCallback = jCallback; s.jCallback = jCallback;
s.jFcx = jFcx; s.jFcx = jFcx;
s.fext = fext; s.ext = ext;
s.midCallback = (*env)->GetMethodID(env, klazz, "call", "(I[BII)I"); s.midCallback = (*env)->GetMethodID(env, klazz, "call", "(I[BII)I");
S3JniUnrefLocal(klazz); S3JniUnrefLocal(klazz);
S3JniIfThrew { S3JniIfThrew {
@@ -5031,7 +5063,7 @@ static jint s3jni_fts5_xTokenize(JniArgsEnvObj, S3JniNphRef const *pRef,
s.tok.zPrev = (const char *)pText; s.tok.zPrev = (const char *)pText;
s.tok.nPrev = (int)nText; s.tok.nPrev = (int)nText;
if( pRef == S3JniNph(Fts5ExtensionApi) ){ if( pRef == S3JniNph(Fts5ExtensionApi) ){
rc = fext->xTokenize(PtrGet_Fts5Context(jFcx), rc = ext->xTokenize(PtrGet_Fts5Context(jFcx),
(const char *)pText, (int)nText, (const char *)pText, (int)nText,
&s, s3jni_xTokenize_xToken); &s, s3jni_xTokenize_xToken);
}else if( pRef == S3JniNph(fts5_tokenizer) ){ }else if( pRef == S3JniNph(fts5_tokenizer) ){
@@ -5065,7 +5097,7 @@ JniDeclFtsTok(jint,xTokenize)(JniArgsEnvObj,jobject jFcx, jint tokFlags,
JniDeclFtsXA(jobject,xUserData)(JniArgsEnvObj,jobject jFcx){ JniDeclFtsXA(jobject,xUserData)(JniArgsEnvObj,jobject jFcx){
Fts5ExtDecl; Fts5ExtDecl;
Fts5JniAux * const pAux = fext->xUserData(PtrGet_Fts5Context(jFcx)); Fts5JniAux * const pAux = ext->xUserData(PtrGet_Fts5Context(jFcx));
return pAux ? pAux->jUserData : 0; return pAux ? pAux->jUserData : 0;
} }
@@ -5337,6 +5369,8 @@ Java_org_sqlite_jni_SQLite3Jni_init(JniArgsEnvClass){
SJG.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); SJG.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
s3jni_oom_fatal( SJG.mutex ); s3jni_oom_fatal( SJG.mutex );
SJG.nph.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
s3jni_oom_fatal( SJG.nph.mutex );
SJG.envCache.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); SJG.envCache.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
s3jni_oom_fatal( SJG.envCache.mutex ); s3jni_oom_fatal( SJG.envCache.mutex );
SJG.perDb.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); SJG.perDb.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);

View File

@@ -28,7 +28,7 @@ public final class Fts5ExtensionApi extends NativePointerHolder<Fts5ExtensionApi
/* Callback type for used by xQueryPhrase(). */ /* Callback type for used by xQueryPhrase(). */
public static interface xQueryPhraseCallback { public static interface xQueryPhraseCallback {
int xCallback(Fts5ExtensionApi fapi, Fts5Context cx); int call(Fts5ExtensionApi fapi, Fts5Context cx);
} }
/** /**
@@ -36,40 +36,67 @@ public final class Fts5ExtensionApi extends NativePointerHolder<Fts5ExtensionApi
*/ */
public static native Fts5ExtensionApi getInstance(); public static native Fts5ExtensionApi getInstance();
@Canonical
public native int xColumnCount(@NotNull Fts5Context fcx); public native int xColumnCount(@NotNull Fts5Context fcx);
@Canonical
public native int xColumnSize(@NotNull Fts5Context cx, int iCol, public native int xColumnSize(@NotNull Fts5Context cx, int iCol,
@NotNull OutputPointer.Int32 pnToken); @NotNull OutputPointer.Int32 pnToken);
@Canonical
public native int xColumnText(@NotNull Fts5Context cx, int iCol, public native int xColumnText(@NotNull Fts5Context cx, int iCol,
@NotNull OutputPointer.String txt); @NotNull OutputPointer.String txt);
@Canonical
public native int xColumnTotalSize(@NotNull Fts5Context fcx, int iCol, public native int xColumnTotalSize(@NotNull Fts5Context fcx, int iCol,
@NotNull OutputPointer.Int64 pnToken); @NotNull OutputPointer.Int64 pnToken);
@Canonical
public native Object xGetAuxdata(@NotNull Fts5Context cx, boolean clearIt); public native Object xGetAuxdata(@NotNull Fts5Context cx, boolean clearIt);
@Canonical
public native int xInst(@NotNull Fts5Context cx, int iIdx, public native int xInst(@NotNull Fts5Context cx, int iIdx,
@NotNull OutputPointer.Int32 piPhrase, @NotNull OutputPointer.Int32 piPhrase,
@NotNull OutputPointer.Int32 piCol, @NotNull OutputPointer.Int32 piCol,
@NotNull OutputPointer.Int32 piOff); @NotNull OutputPointer.Int32 piOff);
@Canonical
public native int xInstCount(@NotNull Fts5Context fcx, public native int xInstCount(@NotNull Fts5Context fcx,
@NotNull OutputPointer.Int32 pnInst); @NotNull OutputPointer.Int32 pnInst);
@Canonical
public native int xPhraseCount(@NotNull Fts5Context fcx); public native int xPhraseCount(@NotNull Fts5Context fcx);
@Canonical
public native int xPhraseFirst(@NotNull Fts5Context cx, int iPhrase, public native int xPhraseFirst(@NotNull Fts5Context cx, int iPhrase,
@NotNull Fts5PhraseIter iter, @NotNull Fts5PhraseIter iter,
@NotNull OutputPointer.Int32 iCol, @NotNull OutputPointer.Int32 iCol,
@NotNull OutputPointer.Int32 iOff); @NotNull OutputPointer.Int32 iOff);
@Canonical
public native int xPhraseFirstColumn(@NotNull Fts5Context cx, int iPhrase, public native int xPhraseFirstColumn(@NotNull Fts5Context cx, int iPhrase,
@NotNull Fts5PhraseIter iter, @NotNull Fts5PhraseIter iter,
@NotNull OutputPointer.Int32 iCol); @NotNull OutputPointer.Int32 iCol);
@Canonical
public native void xPhraseNext(@NotNull Fts5Context cx, public native void xPhraseNext(@NotNull Fts5Context cx,
@NotNull Fts5PhraseIter iter, @NotNull Fts5PhraseIter iter,
@NotNull OutputPointer.Int32 iCol, @NotNull OutputPointer.Int32 iCol,
@NotNull OutputPointer.Int32 iOff); @NotNull OutputPointer.Int32 iOff);
@Canonical
public native void xPhraseNextColumn(@NotNull Fts5Context cx, public native void xPhraseNextColumn(@NotNull Fts5Context cx,
@NotNull Fts5PhraseIter iter, @NotNull Fts5PhraseIter iter,
@NotNull OutputPointer.Int32 iCol); @NotNull OutputPointer.Int32 iCol);
@Canonical
public native int xPhraseSize(@NotNull Fts5Context fcx, int iPhrase); public native int xPhraseSize(@NotNull Fts5Context fcx, int iPhrase);
@Canonical
public native int xQueryPhrase(@NotNull Fts5Context cx, int iPhrase, public native int xQueryPhrase(@NotNull Fts5Context cx, int iPhrase,
@NotNull xQueryPhraseCallback callback); @NotNull xQueryPhraseCallback callback);
@Canonical
public native int xRowCount(@NotNull Fts5Context fcx, public native int xRowCount(@NotNull Fts5Context fcx,
@NotNull OutputPointer.Int64 nRow); @NotNull OutputPointer.Int64 nRow);
@Canonical
public native long xRowid(@NotNull Fts5Context cx); public native long xRowid(@NotNull Fts5Context cx);
/* Note that the JNI binding lacks the C version's xDelete() /* Note that the JNI binding lacks the C version's xDelete()
callback argument. Instead, if pAux has an xDestroy() method, it callback argument. Instead, if pAux has an xDestroy() method, it
@@ -77,10 +104,15 @@ public final class Fts5ExtensionApi extends NativePointerHolder<Fts5ExtensionApi
allocation of storage for the auxdata fails). Any reference to allocation of storage for the auxdata fails). Any reference to
pAux held by the JNI layer will be relinquished regardless of pAux held by the JNI layer will be relinquished regardless of
whether pAux has an xDestroy() method. */ whether pAux has an xDestroy() method. */
@Canonical
public native int xSetAuxdata(@NotNull Fts5Context cx, @Nullable Object pAux); public native int xSetAuxdata(@NotNull Fts5Context cx, @Nullable Object pAux);
@Canonical
public native int xTokenize(@NotNull Fts5Context cx, @NotNull byte[] pText, public native int xTokenize(@NotNull Fts5Context cx, @NotNull byte[] pText,
@NotNull Fts5.xTokenize_callback callback); @NotNull Fts5.xTokenize_callback callback);
@Canonical
public native Object xUserData(Fts5Context cx); public native Object xUserData(Fts5Context cx);
//^^^ returns the pointer passed as the 3rd arg to the C-level //^^^ returns the pointer passed as the 3rd arg to the C-level
// fts5_api::xCreateFunction(). // fts5_api::xCreateFunction().

View File

@@ -1,27 +0,0 @@
/*
** 2023-08-04
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni;
/**
Fts5Function is used in conjunction with the
sqlite3_create_fts_function() JNI-bound API to give that native code
access to the callback functions needed in order to implement
FTS5 auxiliary functions in Java.
*/
public abstract class Fts5Function {
public abstract void xFunction(Fts5ExtensionApi pApi, Fts5Context pFts,
sqlite3_context pCtx, sqlite3_value argv[]);
public void xDestroy() {}
}

View File

@@ -1311,7 +1311,7 @@ public class Tester1 implements Runnable {
final ValueHolder<Integer> val = new ValueHolder<>(0); final ValueHolder<Integer> val = new ValueHolder<>(0);
final ValueHolder<String> toss = new ValueHolder<>(null); final ValueHolder<String> toss = new ValueHolder<>(null);
final AutoExtensionCallback ax = new AutoExtensionCallback(){ final AutoExtensionCallback ax = new AutoExtensionCallback(){
@Override public synchronized int call(sqlite3 db){ @Override public int call(sqlite3 db){
++val.value; ++val.value;
if( null!=toss.value ){ if( null!=toss.value ){
throw new RuntimeException(toss.value); throw new RuntimeException(toss.value);
@@ -1650,7 +1650,7 @@ public class Tester1 implements Runnable {
{ {
// Build list of tests to run from the methods named test*(). // Build list of tests to run from the methods named test*().
testMethods = new ArrayList<>(); testMethods = new ArrayList<>();
out("Skipping tests in multi-thread mode:"); int nSkipped = 0;
for(final java.lang.reflect.Method m : Tester1.class.getDeclaredMethods()){ for(final java.lang.reflect.Method m : Tester1.class.getDeclaredMethods()){
final String name = m.getName(); final String name = m.getName();
if( name.equals("testFail") ){ if( name.equals("testFail") ){
@@ -1659,13 +1659,16 @@ public class Tester1 implements Runnable {
} }
}else if( !m.isAnnotationPresent( ManualTest.class ) ){ }else if( !m.isAnnotationPresent( ManualTest.class ) ){
if( nThread>1 && m.isAnnotationPresent( SingleThreadOnly.class ) ){ if( nThread>1 && m.isAnnotationPresent( SingleThreadOnly.class ) ){
if( 0==nSkipped++ ){
out("Skipping tests in multi-thread mode:");
}
out(" "+name+"()"); out(" "+name+"()");
}else if( name.startsWith("test") ){ }else if( name.startsWith("test") ){
testMethods.add(m); testMethods.add(m);
} }
} }
} }
out("\n"); if( nSkipped>0 ) out("\n");
} }
final long timeStart = System.currentTimeMillis(); final long timeStart = System.currentTimeMillis();

View File

@@ -18,7 +18,7 @@ import static org.sqlite.jni.Tester1.*;
public class TesterFts5 { public class TesterFts5 {
private static void test1(){ private static void test1(){
Fts5ExtensionApi fea = Fts5ExtensionApi.getInstance(); final Fts5ExtensionApi fea = Fts5ExtensionApi.getInstance();
affirm( null != fea ); affirm( null != fea );
affirm( fea.getNativePointer() != 0 ); affirm( fea.getNativePointer() != 0 );
affirm( fea == Fts5ExtensionApi.getInstance() )/*singleton*/; affirm( fea == Fts5ExtensionApi.getInstance() )/*singleton*/;
@@ -38,21 +38,18 @@ public class TesterFts5 {
ValueHolder<Boolean> xDestroyCalled = new ValueHolder<>(false); ValueHolder<Boolean> xDestroyCalled = new ValueHolder<>(false);
ValueHolder<Integer> xFuncCount = new ValueHolder<>(0); ValueHolder<Integer> xFuncCount = new ValueHolder<>(0);
final fts5_extension_function func = new fts5_extension_function(){ final fts5_extension_function func = new fts5_extension_function(){
public void xFunction(Fts5ExtensionApi ext, Fts5Context fCx, @Override public void call(Fts5ExtensionApi ext, Fts5Context fCx,
sqlite3_context pCx, sqlite3_value argv[]){ sqlite3_context pCx, sqlite3_value argv[]){
int nCols = ext.xColumnCount(fCx); int nCols = ext.xColumnCount(fCx);
affirm( 2 == nCols ); affirm( 2 == nCols );
affirm( nCols == argv.length ); affirm( nCols == argv.length );
affirm( ext.xUserData(fCx) == pUserData ); affirm( ext.xUserData(fCx) == pUserData );
if(true){ final OutputPointer.String op = new OutputPointer.String();
OutputPointer.String op = new OutputPointer.String();
for(int i = 0; i < nCols; ++i ){ for(int i = 0; i < nCols; ++i ){
int rc = ext.xColumnText(fCx, i, op); int rc = ext.xColumnText(fCx, i, op);
affirm( 0 == rc ); affirm( 0 == rc );
final String val = op.value; final String val = op.value;
affirm( val.equals(sqlite3_value_text16(argv[i])) ); affirm( val.equals(sqlite3_value_text16(argv[i])) );
//outln("xFunction col "+i+": "+val);
}
} }
++xFuncCount.value; ++xFuncCount.value;
} }
@@ -72,18 +69,24 @@ public class TesterFts5 {
affirm( xDestroyCalled.value ); affirm( xDestroyCalled.value );
} }
private void runTests(){
test1();
}
public TesterFts5(boolean verbose){ public TesterFts5(boolean verbose){
if(verbose){ if(verbose){
synchronized(Tester1.class) {
final long timeStart = System.currentTimeMillis(); final long timeStart = System.currentTimeMillis();
final int oldAffirmCount = Tester1.affirmCount; final int oldAffirmCount = Tester1.affirmCount;
test1(); runTests();
final int affirmCount = Tester1.affirmCount - oldAffirmCount; final int affirmCount = Tester1.affirmCount - oldAffirmCount;
final long timeEnd = System.currentTimeMillis(); final long timeEnd = System.currentTimeMillis();
outln("FTS5 Tests done. Assertions checked = ",affirmCount, outln("FTS5 Tests done. Assertions checked = ",affirmCount,
", Total time = ",(timeEnd - timeStart),"ms"); ", Total time = ",(timeEnd - timeStart),"ms");
}
}else{ }else{
test1(); runTests();
} }
} }
public TesterFts5(){ this(false); } public TesterFts5(){ this(true); }
} }

View File

@@ -33,6 +33,31 @@ public final class fts5_api extends NativePointerHolder<fts5_api> {
*/ */
public static synchronized native fts5_api getInstanceForDb(@NotNull sqlite3 db); public static synchronized native fts5_api getInstanceForDb(@NotNull sqlite3 db);
@Canonical
public synchronized native int xCreateFunction(@NotNull String name,
@Nullable Object userData,
@NotNull fts5_extension_function xFunction);
/**
Convenience overload which passes null as the 2nd argument to the
3-parameter form.
*/
public int xCreateFunction(@NotNull String name,
@NotNull fts5_extension_function xFunction){
return xCreateFunction(name, null, xFunction);
}
// /* Create a new auxiliary function */
// int (*xCreateFunction)(
// fts5_api *pApi,
// const char *zName,
// void *pContext,
// fts5_extension_function xFunction,
// void (*xDestroy)(void*)
// );
// Still potentially todo:
// int (*xCreateTokenizer)( // int (*xCreateTokenizer)(
// fts5_api *pApi, // fts5_api *pApi,
// const char *zName, // const char *zName,
@@ -49,22 +74,4 @@ public final class fts5_api extends NativePointerHolder<fts5_api> {
// fts5_tokenizer *pTokenizer // fts5_tokenizer *pTokenizer
// ); // );
// /* Create a new auxiliary function */
// int (*xCreateFunction)(
// fts5_api *pApi,
// const char *zName,
// void *pContext,
// fts5_extension_function xFunction,
// void (*xDestroy)(void*)
// );
public synchronized native int xCreateFunction(@NotNull String name,
@Nullable Object userData,
@NotNull fts5_extension_function xFunction);
public int xCreateFunction(@NotNull String name,
@NotNull fts5_extension_function xFunction){
return xCreateFunction(name, null, xFunction);
}
} }

View File

@@ -15,9 +15,8 @@ package org.sqlite.jni;
/** /**
JNI-level wrapper for C's fts5_extension_function type. JNI-level wrapper for C's fts5_extension_function type.
*/ */
public abstract class fts5_extension_function { public interface fts5_extension_function {
// typedef void (*fts5_extension_function)( // typedef void (*fts5_extension_function)(
// const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ // const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
// Fts5Context *pFts, /* First arg to pass to pApi functions */ // Fts5Context *pFts, /* First arg to pass to pApi functions */
@@ -30,8 +29,17 @@ public abstract class fts5_extension_function {
The callback implementation, corresponding to the xFunction The callback implementation, corresponding to the xFunction
argument of C's fts5_api::xCreateFunction(). argument of C's fts5_api::xCreateFunction().
*/ */
public abstract void xFunction(Fts5ExtensionApi ext, Fts5Context fCx, void call(Fts5ExtensionApi ext, Fts5Context fCx,
sqlite3_context pCx, sqlite3_value argv[]); sqlite3_context pCx, sqlite3_value argv[]);
//! Optionally override /**
public void xDestroy(){} Is called when this function is destroyed by sqlite3. Typically
this function will be empty.
*/
void xDestroy();
public static abstract class Abstract implements fts5_extension_function {
@Override public abstract void call(Fts5ExtensionApi ext, Fts5Context fCx,
sqlite3_context pCx, sqlite3_value argv[]);
@Override public void xDestroy(){}
}
} }

View File

@@ -1,5 +1,5 @@
C Add\sa\stimer\sto\sthe\sJS\sSQLTester\sapp\sto\swarn\sif\sit\sappears\sthat\sloading\sthe\smodule\shas\sfailed,\swhich\sis\scommonly\scaused\sby\sthe\stest\sscripts\snot\sbeing\scompiled. C Further\sJNI\scleanups.
D 2023-09-01T17:51:09.091 D 2023-09-02T08:51:14.022
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
@@ -234,10 +234,10 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9 F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
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 3e0e28c1c451eab31dd4fa9d262951ef67ed3ece3270a2efc8ec66ec57068547 F ext/jni/GNUmakefile dc6e78f9717470d262b4b3ec17c337834295f9df81717c1539da84106324fd1e
F ext/jni/README.md 1332b1fa27918bd5d9ca2d0d4f3ac3a6ab86b9e3699dc5bfe32904a027f3d2a9 F ext/jni/README.md 1332b1fa27918bd5d9ca2d0d4f3ac3a6ab86b9e3699dc5bfe32904a027f3d2a9
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
F ext/jni/src/c/sqlite3-jni.c 00469db3f64a7f53bc1ecb60749260b937f8892ddc56d4c61d5f427f6e6758a7 F ext/jni/src/c/sqlite3-jni.c d98030bb7f502b42990eeb0f2bd103af0b1f1312ba82892949c5ced85262e036
F ext/jni/src/c/sqlite3-jni.h c22f0189254abe26fad3ba132b484785b19a1aa96d34d30d7d8c5ffe6a9b25d1 F ext/jni/src/c/sqlite3-jni.h c22f0189254abe26fad3ba132b484785b19a1aa96d34d30d7d8c5ffe6a9b25d1
F ext/jni/src/org/sqlite/jni/AbstractCollationCallback.java 95e88ba04f4aac51ffec65693e878e234088b2f21b387f4e4285c8b72b33e436 F ext/jni/src/org/sqlite/jni/AbstractCollationCallback.java 95e88ba04f4aac51ffec65693e878e234088b2f21b387f4e4285c8b72b33e436
F ext/jni/src/org/sqlite/jni/AggregateFunction.java 7312486bc65fecdb91753c0a4515799194e031f45edbe16a6373cea18f404dc4 F ext/jni/src/org/sqlite/jni/AggregateFunction.java 7312486bc65fecdb91753c0a4515799194e031f45edbe16a6373cea18f404dc4
@@ -251,8 +251,7 @@ F ext/jni/src/org/sqlite/jni/CommitHookCallback.java 77cf8bb4f5548113e9792978f3f
F ext/jni/src/org/sqlite/jni/ConfigSqllogCallback.java e3656909eab7ed0f7e457c5b82df160ca22dd5e954c0a306ec1fca61b0d266b4 F ext/jni/src/org/sqlite/jni/ConfigSqllogCallback.java e3656909eab7ed0f7e457c5b82df160ca22dd5e954c0a306ec1fca61b0d266b4
F ext/jni/src/org/sqlite/jni/Fts5.java 3ebfbd5b95fdb9d7bc40306f2e682abd12e247d9224e92510b8dd103b4f96fe8 F ext/jni/src/org/sqlite/jni/Fts5.java 3ebfbd5b95fdb9d7bc40306f2e682abd12e247d9224e92510b8dd103b4f96fe8
F ext/jni/src/org/sqlite/jni/Fts5Context.java 0a5a02047a6a1dd3e4a38b0e542a8dd2de365033ba30e6ae019a676305959890 F ext/jni/src/org/sqlite/jni/Fts5Context.java 0a5a02047a6a1dd3e4a38b0e542a8dd2de365033ba30e6ae019a676305959890
F ext/jni/src/org/sqlite/jni/Fts5ExtensionApi.java 2fd11abb7c5403318181d69bb7b702a79cba7ab460105140f5161bea9bc505d1 F ext/jni/src/org/sqlite/jni/Fts5ExtensionApi.java 6ac342951c5805b48ba1e46dd41dff3b74c609dc5bf1c26fca5738db36493031
F ext/jni/src/org/sqlite/jni/Fts5Function.java 65cde7151e441fee012250a5e03277de7babcd11a0c308a832b7940574259bcc
F ext/jni/src/org/sqlite/jni/Fts5PhraseIter.java 6642beda341c0b1b46af4e2d7f6f9ab03a7aede43277b2c92859176d6bce3be9 F ext/jni/src/org/sqlite/jni/Fts5PhraseIter.java 6642beda341c0b1b46af4e2d7f6f9ab03a7aede43277b2c92859176d6bce3be9
F ext/jni/src/org/sqlite/jni/Fts5Tokenizer.java 91489893596b6528c0df5cd7180bd5b55809c26e2b797fb321dfcdbc1298c060 F ext/jni/src/org/sqlite/jni/Fts5Tokenizer.java 91489893596b6528c0df5cd7180bd5b55809c26e2b797fb321dfcdbc1298c060
F ext/jni/src/org/sqlite/jni/NativePointerHolder.java 564087036449a16df148dcf0a067408bd251170bf23286c655f46b5f973e8b2d F ext/jni/src/org/sqlite/jni/NativePointerHolder.java 564087036449a16df148dcf0a067408bd251170bf23286c655f46b5f973e8b2d
@@ -265,8 +264,8 @@ F ext/jni/src/org/sqlite/jni/SQLFunction.java 544a875d33fd160467d82e2397ac33157b
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 98f8d62492e2d6693336dd42c12267ea7f21eefe219aa85b8dd399bd6b0732bd F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 98f8d62492e2d6693336dd42c12267ea7f21eefe219aa85b8dd399bd6b0732bd
F ext/jni/src/org/sqlite/jni/ScalarFunction.java 6d387bb499fbe3bc13c53315335233dbf6a0c711e8fa7c521683219b041c614c F ext/jni/src/org/sqlite/jni/ScalarFunction.java 6d387bb499fbe3bc13c53315335233dbf6a0c711e8fa7c521683219b041c614c
F ext/jni/src/org/sqlite/jni/TableColumnMetadata.java 54511b4297fa28dcb3f49b24035e34ced10e3fd44fd0e458e784f4d6b0096dab F ext/jni/src/org/sqlite/jni/TableColumnMetadata.java 54511b4297fa28dcb3f49b24035e34ced10e3fd44fd0e458e784f4d6b0096dab
F ext/jni/src/org/sqlite/jni/Tester1.java 2a6ef03fca523280731a88f697cdc8ece9548cd4cbe7e1cc90823e5bb5998e27 F ext/jni/src/org/sqlite/jni/Tester1.java 93e89c4f72065bf28625cf435c47ed2bd3d937fe5c2431e6e7c3407f09f3f9bc
F ext/jni/src/org/sqlite/jni/TesterFts5.java 02b59ea7d75666fd565d90bb8dc7b0c09441bb9d1af091fad9f6d7377297a474 F ext/jni/src/org/sqlite/jni/TesterFts5.java 2b2d6f3cc9f508358c103b774aee296c0f3d8c2f387d6abae9b8b9055f62c800
F ext/jni/src/org/sqlite/jni/TraceV2Callback.java beb0b064c1a5f8bfe585a324ed39a4e33edbe379a3fc60f1401661620d3ca7c0 F ext/jni/src/org/sqlite/jni/TraceV2Callback.java beb0b064c1a5f8bfe585a324ed39a4e33edbe379a3fc60f1401661620d3ca7c0
F ext/jni/src/org/sqlite/jni/UpdateHookCallback.java 8376f4a931f2d5612b295c003c9515ba933ee76d8f95610e89c339727376e36c F ext/jni/src/org/sqlite/jni/UpdateHookCallback.java 8376f4a931f2d5612b295c003c9515ba933ee76d8f95610e89c339727376e36c
F ext/jni/src/org/sqlite/jni/ValueHolder.java f022873abaabf64f3dd71ab0d6037c6e71cece3b8819fa10bf26a5461dc973ee F ext/jni/src/org/sqlite/jni/ValueHolder.java f022873abaabf64f3dd71ab0d6037c6e71cece3b8819fa10bf26a5461dc973ee
@@ -276,8 +275,8 @@ F ext/jni/src/org/sqlite/jni/annotation/Canonical.java d9ff79f1bf9d063d0c3e3b768
F ext/jni/src/org/sqlite/jni/annotation/NotNull.java d48ebd7ae6bbb78bd47d54431c85e1521c89b1d3864a2b6eafd9c0e1b2341457 F ext/jni/src/org/sqlite/jni/annotation/NotNull.java d48ebd7ae6bbb78bd47d54431c85e1521c89b1d3864a2b6eafd9c0e1b2341457
F ext/jni/src/org/sqlite/jni/annotation/Nullable.java 6f962a98c9a5c6e9d21c50ae8716b16bdfdc934a191608cbb7e12ea588ddb6af F ext/jni/src/org/sqlite/jni/annotation/Nullable.java 6f962a98c9a5c6e9d21c50ae8716b16bdfdc934a191608cbb7e12ea588ddb6af
F ext/jni/src/org/sqlite/jni/annotation/package-info.java f66bfb621c6494e67c03ed38a9e26a3bd6af99b9f9f6ef79556bcec30a025a22 F ext/jni/src/org/sqlite/jni/annotation/package-info.java f66bfb621c6494e67c03ed38a9e26a3bd6af99b9f9f6ef79556bcec30a025a22
F ext/jni/src/org/sqlite/jni/fts5_api.java ee47f1837d32968f7bb62278c7504c0fb572a68ec107371b714578312e9f734b F ext/jni/src/org/sqlite/jni/fts5_api.java bf7009a7fd2d11a77280380e6e2c7f98e377494b3f265e50fc44cbb9a24275d9
F ext/jni/src/org/sqlite/jni/fts5_extension_function.java ac825035d7d83fc7fd960347abfa6803e1614334a21533302041823ad5fc894c F ext/jni/src/org/sqlite/jni/fts5_extension_function.java bec9f17a7e784d57eca99d812a65ecc9dd74c8df62d6d90cc1ecb3e37de14d47
F ext/jni/src/org/sqlite/jni/fts5_tokenizer.java a92c2e55bda492e4c76d48ddc73369bcc0d5e8727940840f9339e3292ea58fa7 F ext/jni/src/org/sqlite/jni/fts5_tokenizer.java a92c2e55bda492e4c76d48ddc73369bcc0d5e8727940840f9339e3292ea58fa7
F ext/jni/src/org/sqlite/jni/package-info.java a3946db2504de747a1993c4f6e8ce604bec5a8e5a134b292c3b07527bc321a99 F ext/jni/src/org/sqlite/jni/package-info.java a3946db2504de747a1993c4f6e8ce604bec5a8e5a134b292c3b07527bc321a99
F ext/jni/src/org/sqlite/jni/sqlite3.java 62b1b81935ccf3393472d17cb883dc5ff39c388ec3bc1de547f098a0217158fc F ext/jni/src/org/sqlite/jni/sqlite3.java 62b1b81935ccf3393472d17cb883dc5ff39c388ec3bc1de547f098a0217158fc
@@ -2116,8 +2115,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 016bbdadbf9f95cef185d2606c23e3b3c724586fcca470e11e6fbdbaefd75c79 P f9c1f9cad1ad22f689a4afa13d59bf9969ddaed6624cbc16cb1bf5d1fd0c8a5b
R 4133358901b76bfadefddc6665a81e23 R 215167a378a1f1105562740ffd0f1842
U stephan U stephan
Z eab9aeb866f5eecf9b7d34e391979f20 Z 15dc34b47fe3ed21ed7cc58408f87312
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
f9c1f9cad1ad22f689a4afa13d59bf9969ddaed6624cbc16cb1bf5d1fd0c8a5b 30e38173c3ece0c9f8e7a9710f46cb5e8e8ef101c04531318a7adb070242f5dd