From: stephan Date: Fri, 1 Sep 2023 13:27:59 +0000 (+0000) Subject: Make JNI interfaces of sqlite3_column/value_text() match the C ones better. Internal... X-Git-Tag: version-3.44.0~216^2~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d086065644de5b90c40693d6823ad3cc518c5c76;p=thirdparty%2Fsqlite.git Make JNI interfaces of sqlite3_column/value_text() match the C ones better. Internal JNI cleanups and simplifications. FossilOrigin-Name: eb24f97253d9c8e7c728c2ac67a0824b10ca67362ac4f8abb94d5d3c54c58c5b --- diff --git a/ext/jni/GNUmakefile b/ext/jni/GNUmakefile index 3e4d54fb05..ae0c53f902 100644 --- a/ext/jni/GNUmakefile +++ b/ext/jni/GNUmakefile @@ -176,6 +176,7 @@ $(sqlite3.c): $(sqlite3.h) opt.threadsafe ?= 1 opt.fatal-oom ?= 1 +opt.debug ?= 1 SQLITE_OPT = \ -DSQLITE_ENABLE_RTREE \ -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ @@ -193,10 +194,13 @@ SQLITE_OPT = \ -DSQLITE_TEMP_STORE=2 \ -DSQLITE_USE_URI=1 \ -DSQLITE_C=$(sqlite3.c) \ - -DSQLITE_JNI_FATAL_OOM=$(opt.fatal-oom) \ - -DSQLITE_DEBUG + -DSQLITE_JNI_FATAL_OOM=$(opt.fatal-oom) -SQLITE_OPT += -g -DDEBUG -UNDEBUG +ifeq (1,$(opt.debug)) + SQLITE_OPT += -DSQLITE_DEBUG -g -DDEBUG -UNDEBUG +else + SQLITE_OPT += -O2 +endif ifeq (1,$(enable.fts5)) SQLITE_OPT += -DSQLITE_ENABLE_FTS5 @@ -318,16 +322,21 @@ endif tester-ext: tester-local tester: tester-ext tests: tester - ######################################################################## # Build each SQLITE_THREADMODE variant and run all tests against them. multitest: clean - $(MAKE) opt.threadsafe=0 opt.oom=1 tests clean - $(MAKE) opt.threadsafe=0 opt.oom=0 tests clean - $(MAKE) opt.threadsafe=1 opt.oom=1 tests clean - $(MAKE) opt.threadsafe=1 opt.oom=0 tests clean - $(MAKE) opt.threadsafe=2 opt.oom=1 tests clean - $(MAKE) opt.threadsafe=2 opt.oom=0 tests clean +define MULTIOPT +multitest: multitest-$(1) +multitest-$(1): + $$(MAKE) opt.debug=$$(opt.debug) $(patsubst %,opt.%,$(2)) tests clean +endef + +$(eval $(call MULTIOPT,01,threadsafe=0 oom=1)) +$(eval $(call MULTIOPT,00,threadsafe=0 oom=0)) +$(eval $(call MULTIOPT,11,threadsafe=1 oom=1)) +$(eval $(call MULTIOPT,10,threadsafe=1 oom=0)) +$(eval $(call MULTIOPT,21,threadsafe=2 oom=1)) +$(eval $(call MULTIOPT,20,threadsafe=2 oom=0)) ######################################################################## diff --git a/ext/jni/src/c/sqlite3-jni.c b/ext/jni/src/c/sqlite3-jni.c index 553886df6b..831a4d8001 100644 --- a/ext/jni/src/c/sqlite3-jni.c +++ b/ext/jni/src/c/sqlite3-jni.c @@ -170,7 +170,8 @@ ** S3JniApi's intent is that CFunc be the C API func(s) the ** being-declared JNI function is wrapping, making it easier to find ** that function's JNI-side entry point. The other args are for JniDecl. - */ +** See the many examples in this file. +*/ #define S3JniApi(CFunc,ReturnType,Suffix) JniDecl(ReturnType,Suffix) /* @@ -302,10 +303,10 @@ struct S3JniNphRef { }; /* -** Cache keys for each concrete NativePointerHolder subclass and -** OutputPointer.T type. The members are to be used with -** s3jni_nph() and friends, and each one's member->index -** corresponds to its index in the S3JniGlobal.nph[] array. +** Cache keys for each concrete NativePointerHolder subclasses and +** OutputPointer.T types. The members are to be used with s3jni_nph() +** and friends, and each one's member->index corresponds to its index +** in the S3JniGlobal.nph[] array. */ static const struct { const S3JniNphRef sqlite3; @@ -361,6 +362,8 @@ static const struct { #undef RefO }; +#define S3JniNph(T) &S3JniNphRefs.T + enum { /* ** Size of the NativePointerHolder cache. Need enough space for @@ -380,10 +383,24 @@ enum { */ typedef struct S3JniNphClass S3JniNphClass; struct S3JniNphClass { - volatile const S3JniNphRef * pRef /* Entry from S3JniNphRefs. */; - jclass klazz /* global ref to the concrete - ** NativePointerHolder subclass - ** represented by zClassName */; + volatile const S3JniNphRef * pRef /* Entry from S3JniNphRefs */; + /* + ** klazz is a global ref to the class represented by pRef. + ** + ** According to: + ** + ** https://developer.ibm.com/articles/j-jni/ + ** + ** > ... the IDs returned for a given class don't change for the + ** lifetime of the JVM process. But the call to get the field or + ** method can require significant work in the JVM, because fields + ** and methods might have been inherited from superclasses, making + ** the JVM walk up the class hierarchy to find them. Because the + ** IDs are the same for a given class, you should look them up + ** once and then reuse them. Similarly, looking up class objects + ** can be expensive, so they should be cached as well. + */ + jclass klazz; volatile jmethodID midCtor /* klazz's no-arg constructor. Used by ** new_NativePointerHolder_object(). */; volatile jfieldID fidValue /* NativePointerHolder.nativePointer or @@ -465,7 +482,7 @@ static const char * const S3JniDb_clientdata_key = "S3JniDb"; */ typedef struct S3JniEnv S3JniEnv; struct S3JniEnv { - JNIEnv *env /* env in which this cache entry was created */; + JNIEnv *env /* JNIEnv in which this cache entry was created */; /* ** pdbOpening is used to coordinate the Java/DB connection of a ** being-open()'d db in the face of auto-extensions. @@ -561,7 +578,6 @@ struct S3JniGlobalType { ** threads. Caching a copy of the JavaVM object enables any thread ** with access to the cached object to get access to its own ** JNIEnv when necessary. - ** */ JavaVM * jvm; /* Global mutex. */ @@ -577,9 +593,8 @@ struct S3JniGlobalType { struct { S3JniEnv * aHead /* Linked list of in-use instances */; S3JniEnv * aFree /* Linked list of free instances */; - sqlite3_mutex * mutex /* mutex for aHead and aFree, first-time - inits of nph[] entries, and - NativePointerHolder_get/set(). */; + sqlite3_mutex * mutex /* mutex for aHead and aFree, and first-time + inits of nph[] entries. */; void const * locker /* env mutex is held on this object's behalf. Used only for sanity checking. */; } envCache; @@ -1040,7 +1055,7 @@ static char * s3jni_exception_error_msg(JNIEnv * const env, jthrowable jx){ ** Returns errCode unless it is 0, in which case SQLITE_ERROR is ** returned. */ -static int s3jni__db_exception(JNIEnv * const env, S3JniDb * const ps, +static int s3jni__db_exception(JNIEnv * const env, sqlite3 * const pDb, int errCode, const char *zDfltMsg){ jthrowable const ex = (*env)->ExceptionOccurred(env); @@ -1048,17 +1063,17 @@ static int s3jni__db_exception(JNIEnv * const env, S3JniDb * const ps, if( ex ){ char * zMsg; S3JniExceptionClear; - S3JniDb_mutex_enter; zMsg = s3jni_exception_error_msg(env, ex); - s3jni_db_error(ps->pDb, errCode, zMsg ? zMsg : zDfltMsg); + s3jni_db_error(pDb, errCode, zMsg ? zMsg : zDfltMsg); sqlite3_free(zMsg); S3JniUnrefLocal(ex); - S3JniDb_mutex_leave; + }else if( zDfltMsg ){ + s3jni_db_error(pDb, errCode, zDfltMsg); } return errCode; } -#define s3jni_db_exception(JniDb,ERRCODE,DFLTMSG) \ - s3jni__db_exception(env, (JniDb), (ERRCODE), (DFLTMSG) ) +#define s3jni_db_exception(pDb,ERRCODE,DFLTMSG) \ + s3jni__db_exception(env, (pDb), (ERRCODE), (DFLTMSG) ) /* ** Extracts the (void xDestroy()) method from jObj and applies it to @@ -1140,8 +1155,7 @@ static void S3JniHook__unref(JNIEnv * const env, S3JniHook * const s){ } *s = S3JniHook_empty; } -#define S3JniHook_unref(hook) \ - S3JniHook__unref(env, (hook)) +#define S3JniHook_unref(hook) S3JniHook__unref(env, (hook)) /* ** Allocates one blank S3JniHook object from the recycling bin, if @@ -1260,6 +1274,7 @@ static void S3JniDb__set_aside(JNIEnv * const env, S3JniDb * const s){ static int S3JniEnv_uncache(JNIEnv * const env){ struct S3JniEnv * row; struct S3JniEnv * pPrev = 0; + S3JniEnv_mutex_assertLocked; row = SJG.envCache.aHead; for( ; row; pPrev = row, row = row->pNext ){ @@ -1296,26 +1311,13 @@ static int S3JniEnv_uncache(JNIEnv * const env){ ** (2023-07-31) tests. */ static S3JniNphClass * s3jni__nph(JNIEnv * const env, S3JniNphRef const* pRef){ - /** - According to: - - https://developer.ibm.com/articles/j-jni/ - - > ... the IDs returned for a given class don't change for the - lifetime of the JVM process. But the call to get the field or - method can require significant work in the JVM, because - fields and methods might have been inherited from - superclasses, making the JVM walk up the class hierarchy to - find them. Because the IDs are the same for a given class, - you should look them up once and then reuse them. Similarly, - looking up class objects can be expensive, so they should be - cached as well. - */ S3JniNphClass * const pNC = &SJG.nph[pRef->index]; + assert( (void*)pRef>=(void*)&S3JniNphRefs && (void*)pRef<(void*)(&S3JniNphRefs + 1) - && "pRef is out of range." ); + && "pRef is out of range" ); assert( pRef->index>=0 - && (pRef->index < (sizeof(S3JniNphRefs) / sizeof(S3JniNphRef))) ); + && (pRef->index < (sizeof(S3JniNphRefs) / sizeof(S3JniNphRef))) + && "pRef->index is out of range" ); if( !pNC->pRef ){ S3JniNph_mutex_enter; if( !pNC->pRef ){ @@ -1410,7 +1412,7 @@ static void * NativePointerHolder__get(JNIEnv * env, jobject pObj, ** argument is a Java sqlite3 object, as this operation only has void ** pointers to work with. */ -#define PtrGet_T(T,OBJ) NativePointerHolder_get(OBJ, &S3JniNphRefs.T) +#define PtrGet_T(T,OBJ) NativePointerHolder_get(OBJ, S3JniNph(T)) #define PtrGet_sqlite3(OBJ) PtrGet_T(sqlite3, OBJ) #define PtrGet_sqlite3_stmt(OBJ) PtrGet_T(sqlite3_stmt, OBJ) #define PtrGet_sqlite3_value(OBJ) PtrGet_T(sqlite3_value, OBJ) @@ -1528,7 +1530,7 @@ static int S3JniAutoExtension_init(JNIEnv *const env, static void OutputPointer_set_Bool(JNIEnv * const env, jobject const jOut, int v){ (*env)->SetBooleanField(env, jOut, s3jni_nphop_field( - env, &S3JniNphRefs.OutputPointer_Bool + env, S3JniNph(OutputPointer_Bool) ), v ? JNI_TRUE : JNI_FALSE ); S3JniExceptionIsFatal("Cannot set OutputPointer.Bool.value"); } @@ -1540,7 +1542,7 @@ static void OutputPointer_set_Bool(JNIEnv * const env, jobject const jOut, static void OutputPointer_set_Int32(JNIEnv * const env, jobject const jOut, int v){ (*env)->SetIntField(env, jOut, s3jni_nphop_field( - env, &S3JniNphRefs.OutputPointer_Int32 + env, S3JniNph(OutputPointer_Int32) ), (jint)v); S3JniExceptionIsFatal("Cannot set OutputPointer.Int32.value"); } @@ -1552,7 +1554,7 @@ static void OutputPointer_set_Int32(JNIEnv * const env, jobject const jOut, static void OutputPointer_set_Int64(JNIEnv * const env, jobject const jOut, jlong v){ (*env)->SetLongField(env, jOut, s3jni_nphop_field( - env, &S3JniNphRefs.OutputPointer_Int64 + env, S3JniNph(OutputPointer_Int64) ), v); S3JniExceptionIsFatal("Cannot set OutputPointer.Int64.value"); } @@ -1575,7 +1577,7 @@ static void OutputPointer_set_obj(JNIEnv * const env, */ static void OutputPointer_set_sqlite3(JNIEnv * const env, jobject const jOut, jobject jDb){ - OutputPointer_set_obj(env, &S3JniNphRefs.OutputPointer_sqlite3, jOut, jDb); + OutputPointer_set_obj(env, S3JniNph(OutputPointer_sqlite3), jOut, jDb); } /* @@ -1584,7 +1586,7 @@ static void OutputPointer_set_sqlite3(JNIEnv * const env, jobject const jOut, */ static void OutputPointer_set_sqlite3_stmt(JNIEnv * const env, jobject const jOut, jobject jStmt){ - OutputPointer_set_obj(env, &S3JniNphRefs.OutputPointer_sqlite3_stmt, jOut, jStmt); + OutputPointer_set_obj(env, S3JniNph(OutputPointer_sqlite3_stmt), jOut, jStmt); } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK @@ -1594,7 +1596,7 @@ static void OutputPointer_set_sqlite3_stmt(JNIEnv * const env, jobject const jOu */ static void OutputPointer_set_sqlite3_value(JNIEnv * const env, jobject const jOut, jobject jValue){ - OutputPointer_set_obj(env, &S3JniNphRefs.OutputPointer_sqlite3_value, jOut, jValue); + OutputPointer_set_obj(env, S3JniNph(OutputPointer_sqlite3_value), jOut, jValue); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ @@ -1606,7 +1608,7 @@ static void OutputPointer_set_sqlite3_value(JNIEnv * const env, jobject const jO */ static void OutputPointer_set_ByteArray(JNIEnv * const env, jobject const jOut, jbyteArray const v){ - OutputPointer_set_obj(env, &S3JniNphRefs.OutputPointer_ByteArray, jOut, v); + OutputPointer_set_obj(env, S3JniNph(OutputPointer_ByteArray), jOut, v); } #endif #endif /* SQLITE_ENABLE_FTS5 */ @@ -1617,7 +1619,7 @@ static void OutputPointer_set_ByteArray(JNIEnv * const env, jobject const jOut, */ static void OutputPointer_set_String(JNIEnv * const env, jobject const jOut, jstring const v){ - OutputPointer_set_obj(env, &S3JniNphRefs.OutputPointer_String, jOut, v); + OutputPointer_set_obj(env, S3JniNph(OutputPointer_String), jOut, v); } /* @@ -1651,15 +1653,15 @@ static void ResultJavaValue_finalizer(void *v){ /* -** Returns a new Java instance of the class named by zClassName, which +** Returns a new Java instance of the class referred to by pRef, which ** MUST be interface-compatible with NativePointerHolder and MUST have ** a no-arg constructor. The NativePointerHolder_set() method is ** passed the new Java object and pNative. Hypothetically returns NULL ** if Java fails to allocate, but the JNI docs are not entirely clear ** on that detail. ** -** Always use a static pointer from the S3JniNphRefs struct for the 2nd -** argument so that we can use pRef->index as an O(1) cache key. +** Always use a static pointer from the S3JniNphRefs struct for the +** 2nd argument. */ static jobject new_NativePointerHolder_object(JNIEnv * const env, S3JniNphRef const * pRef, const void * pNative){ @@ -1681,16 +1683,16 @@ static jobject new_NativePointerHolder_object(JNIEnv * const env, S3JniNphRef co } static inline jobject new_sqlite3_wrapper(JNIEnv * const env, sqlite3 *sv){ - return new_NativePointerHolder_object(env, &S3JniNphRefs.sqlite3, sv); + return new_NativePointerHolder_object(env, S3JniNph(sqlite3), sv); } static inline jobject new_sqlite3_context_wrapper(JNIEnv * const env, sqlite3_context *sv){ - return new_NativePointerHolder_object(env, &S3JniNphRefs.sqlite3_context, sv); + return new_NativePointerHolder_object(env, S3JniNph(sqlite3_context), sv); } static inline jobject new_sqlite3_stmt_wrapper(JNIEnv * const env, sqlite3_stmt *sv){ - return new_NativePointerHolder_object(env, &S3JniNphRefs.sqlite3_stmt, sv); + return new_NativePointerHolder_object(env, S3JniNph(sqlite3_stmt), sv); } static inline jobject new_sqlite3_value_wrapper(JNIEnv * const env, sqlite3_value *sv){ - return new_NativePointerHolder_object(env, &S3JniNphRefs.sqlite3_value, sv); + return new_NativePointerHolder_object(env, S3JniNph(sqlite3_value), sv); } /* Helper typedefs for UDF callback types. */ @@ -1815,7 +1817,7 @@ static int udf_args(JNIEnv *env, *jArgv = 0; if( !jcx ) goto error_oom; ja = (*env)->NewObjectArray( - env, argc, s3jni_nph(&S3JniNphRefs.sqlite3_value)->klazz, + env, argc, s3jni_nph(S3JniNph(sqlite3_value))->klazz, NULL); s3jni_oom_check( ja ); if( !ja ) goto error_oom; @@ -2117,7 +2119,7 @@ static int s3jni_run_java_auto_extensions(sqlite3 *pDb, const char **pzErr, if( rc ){ return rc; } - NativePointerHolder_set(&S3JniNphRefs.sqlite3, ps->jDb, pDb) + NativePointerHolder_set(S3JniNph(sqlite3), ps->jDb, pDb) /* As of here, the Java/C connection is complete except for the (temporary) lack of finalizer for the ps object. */; ps->pDb = pDb; @@ -2156,7 +2158,7 @@ S3JniApi(sqlite3_auto_extension(),jint,1auto_1extension)( JniArgsEnvClass, jobject jAutoExt ){ int i; - S3JniAutoExtension * ax; + S3JniAutoExtension * ax = 0; int rc = 0; if( !jAutoExt ) return SQLITE_MISUSE; @@ -2336,7 +2338,7 @@ static int s3jni_busy_handler(void* pState, int n){ hook.midCallback, (jint)n); S3JniIfThrew{ S3JniExceptionWarnCallbackThrew("sqlite3_busy_handler() callback"); - rc = s3jni_db_exception(ps, SQLITE_ERROR, + rc = s3jni_db_exception(ps->pDb, SQLITE_ERROR, "sqlite3_busy_handler() callback threw."); } S3JniHook_localundup(hook); @@ -2440,7 +2442,7 @@ static jint s3jni_close_db(JNIEnv * const env, jobject jDb, int version){ ? (jint)sqlite3_close(ps->pDb) : (jint)sqlite3_close_v2(ps->pDb); if( 0==rc ){ - NativePointerHolder_set(&S3JniNphRefs.sqlite3, jDb, 0); + NativePointerHolder_set(S3JniNph(sqlite3), jDb, 0); } } return (jint)rc; @@ -2529,7 +2531,7 @@ S3JniApi(sqlite3_collation_needed(),jint,1collation_1needed)( ); S3JniUnrefLocal(klazz); S3JniIfThrew { - rc = s3jni_db_exception(ps, SQLITE_MISUSE, + rc = s3jni_db_exception(ps->pDb, SQLITE_MISUSE, "Cannot not find matching call() in " "CollationNeededCallback object."); }else{ @@ -2574,7 +2576,7 @@ S3JniApi(sqlite3_column_int64(),jlong,1column_1int64)( return (jlong)sqlite3_column_int64(PtrGet_sqlite3_stmt(jpStmt), (int)ndx); } -S3JniApi(sqlite3_column_text(),jbyteArray,1column_1text_1utf8)( +S3JniApi(sqlite3_column_text(),jbyteArray,1column_1text)( JniArgsEnvClass, jobject jpStmt, jint ndx ){ sqlite3_stmt * const stmt = PtrGet_sqlite3_stmt(jpStmt); @@ -2583,6 +2585,9 @@ S3JniApi(sqlite3_column_text(),jbyteArray,1column_1text_1utf8)( return p ? s3jni_new_jbyteArray(p, n) : NULL; } +#if 0 +// this impl might prove useful, but we'd need to publish the +// bytearray-returning impl with a different name. S3JniApi(sqlite3_column_text(),jstring,1column_1text)( JniArgsEnvClass, jobject jpStmt, jint ndx ){ @@ -2591,6 +2596,7 @@ S3JniApi(sqlite3_column_text(),jstring,1column_1text)( const unsigned char * const p = sqlite3_column_text(stmt, (int)ndx); return p ? s3jni_utf8_to_jstring( (const char *)p, n) : 0; } +#endif S3JniApi(sqlite3_column_text16(),jstring,1column_1text16)( JniArgsEnvClass, jobject jpStmt, jint ndx @@ -2610,7 +2616,7 @@ S3JniApi(sqlite3_column_value(),jobject,1column_1value)( } /* -** Impl for both commit hooks (if isCommit is true) or rollback hooks. +** Impl for commit hooks (if isCommit is true) or rollback hooks. */ static int s3jni_commit_rollback_hook_impl(int isCommit, S3JniDb * const ps){ S3JniDeclLocal_env; @@ -2625,8 +2631,7 @@ static int s3jni_commit_rollback_hook_impl(int isCommit, S3JniDb * const ps){ ? (int)(*env)->CallIntMethod(env, hook.jObj, hook.midCallback) : (int)((*env)->CallVoidMethod(env, hook.jObj, hook.midCallback), 0); S3JniIfThrew{ - S3JniExceptionClear; - rc = s3jni_db_error(ps->pDb, SQLITE_ERROR, "hook callback threw."); + rc = s3jni_db_exception(ps->pDb, SQLITE_ERROR, "hook callback threw"); } S3JniHook_localundup(hook); } @@ -3159,7 +3164,7 @@ S3JniApi(sqlite3_finalize(),jint,1finalize)( sqlite3_stmt * const pStmt = PtrGet_sqlite3_stmt(jpStmt); if( pStmt ){ rc = sqlite3_finalize(pStmt); - NativePointerHolder_set(&S3JniNphRefs.sqlite3_stmt, jpStmt, 0); + NativePointerHolder_set(S3JniNph(sqlite3_stmt), jpStmt, 0); } return rc; } @@ -3283,7 +3288,7 @@ static int s3jni_open_post(JNIEnv * const env, S3JniEnv * const jc, assert(ps->jDb); if( 0==ps->pDb ){ ps->pDb = *ppDb; - NativePointerHolder_set(&S3JniNphRefs.sqlite3, ps->jDb, *ppDb); + NativePointerHolder_set(S3JniNph(sqlite3), ps->jDb, *ppDb); }else{ assert( ps->pDb==*ppDb && "Set up via s3jni_run_java_auto_extensions()" ); @@ -3390,7 +3395,7 @@ end: OutputPointer_set_Int32(env, outTail, (int)(zTail ? (zTail - (const char *)pBuf) : 0)); } if( pStmt ){ - NativePointerHolder_set(&S3JniNphRefs.sqlite3_stmt, jStmt, pStmt); + NativePointerHolder_set(S3JniNph(sqlite3_stmt), jStmt, pStmt); }else{ /* Happens for comments and whitespace. */ S3JniUnrefLocal(jStmt); @@ -3473,7 +3478,7 @@ static void s3jni_updatepre_hook_impl(void * pState, sqlite3 *pDb, int opId, (jint)opId, jDbName, jTable, (jlong)iKey1); S3JniIfThrew{ S3JniExceptionWarnCallbackThrew("sqlite3_(pre)update_hook() callback"); - s3jni_db_exception(ps, 0, + s3jni_db_exception(ps->pDb, 0, "sqlite3_(pre)update_hook() callback threw"); } } @@ -3644,7 +3649,7 @@ static int s3jni_progress_handler_impl(void *pP){ if( hook.jObj ){ rc = (int)(*env)->CallIntMethod(env, hook.jObj, hook.midCallback); S3JniIfThrew{ - rc = s3jni_db_exception(ps, rc, + rc = s3jni_db_exception(ps->pDb, rc, "sqlite3_progress_handler() callback threw"); } S3JniHook_localundup(hook); @@ -3940,7 +3945,7 @@ int s3jni_xAuth(void* pState, int op,const char*z0, const char*z1, rc = (*env)->CallIntMethod(env, hook.jObj, hook.midCallback, (jint)op, s0, s1, s3, s3); S3JniIfThrew{ - rc = s3jni_db_exception(ps, rc, "sqlite3_set_authorizer() callback"); + rc = s3jni_db_exception(ps->pDb, rc, "sqlite3_set_authorizer() callback"); } S3JniUnrefLocal(s0); S3JniUnrefLocal(s1); @@ -4215,7 +4220,7 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){ case SQLITE_TRACE_ROW: break; case SQLITE_TRACE_CLOSE: - jP = ps->jDb; + jP = jPUnref = S3JniRefLocal(ps->jDb); break; default: assert(!"cannot happen - unkown trace flag"); @@ -4234,7 +4239,7 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){ rc = (int)(*env)->CallIntMethod(env, hook.jObj, hook.midCallback, (jint)traceflag, jP, jX); S3JniIfThrew{ - rc = s3jni_db_exception(ps, SQLITE_ERROR, + rc = s3jni_db_exception(ps->pDb, SQLITE_ERROR, "sqlite3_trace_v2() callback threw."); } } @@ -4364,7 +4369,7 @@ S3JniApi(sqlite3_value_java_object(),jobject,1value_1java_1object)( ResultJavaValuePtrStr); } -S3JniApi(sqlite3_value_text_utf8(),jbyteArray,1value_1text_1utf8)( +S3JniApi(sqlite3_value_text(),jbyteArray,1value_1text)( JniArgsEnvClass, jobject jpSVal ){ sqlite3_value * const sv = PtrGet_sqlite3_value(jpSVal); @@ -4373,6 +4378,9 @@ S3JniApi(sqlite3_value_text_utf8(),jbyteArray,1value_1text_1utf8)( return p ? s3jni_new_jbyteArray(p, n) : 0; } +#if 0 +// this impl might prove useful, but we'd need to publish the +// bytearray-returning impl with a different name. S3JniApi(sqlite3_value_text(),jstring,1value_1text)( JniArgsEnvClass, jobject jpSVal ){ @@ -4381,6 +4389,7 @@ S3JniApi(sqlite3_value_text(),jstring,1value_1text)( const unsigned char * const p = sqlite3_value_text(sv); return p ? s3jni_utf8_to_jstring( (const char *)p, n) : 0; } +#endif S3JniApi(sqlite3_value_text16(),jstring,1value_1text16)( JniArgsEnvClass, jobject jpSVal @@ -4483,10 +4492,10 @@ JniDecl(void,1jni_1internal_1details)(JniArgsEnvClass){ JNIEXPORT ReturnType JNICALL \ JniFuncNameFtsTok(Suffix) -#define PtrGet_fts5_api(OBJ) NativePointerHolder_get(OBJ,&S3JniNphRefs.fts5_api) -#define PtrGet_fts5_tokenizer(OBJ) NativePointerHolder_get(OBJ,&S3JniNphRefs.fts5_tokenizer) -#define PtrGet_Fts5Context(OBJ) NativePointerHolder_get(OBJ,&S3JniNphRefs.Fts5Context) -#define PtrGet_Fts5Tokenizer(OBJ) NativePointerHolder_get(OBJ,&S3JniNphRefs.Fts5Tokenizer) +#define PtrGet_fts5_api(OBJ) NativePointerHolder_get(OBJ,S3JniNph(fts5_api)) +#define PtrGet_fts5_tokenizer(OBJ) NativePointerHolder_get(OBJ,S3JniNph(fts5_tokenizer)) +#define PtrGet_Fts5Context(OBJ) NativePointerHolder_get(OBJ,S3JniNph(Fts5Context)) +#define PtrGet_Fts5Tokenizer(OBJ) NativePointerHolder_get(OBJ,S3JniNph(Fts5Tokenizer)) #define Fts5ExtDecl Fts5ExtensionApi const * const fext = s3jni_ftsext() /** @@ -4548,10 +4557,10 @@ static inline Fts5ExtensionApi const * s3jni_ftsext(void){ } static inline jobject new_Fts5Context_wrapper(JNIEnv * const env, Fts5Context *sv){ - return new_NativePointerHolder_object(env, &S3JniNphRefs.Fts5Context, 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, &S3JniNphRefs.fts5_api, sv); + return new_NativePointerHolder_object(env, S3JniNph(fts5_api), sv); } /* @@ -4561,7 +4570,7 @@ static inline jobject new_fts5_api_wrapper(JNIEnv * const env, fts5_api *sv){ static jobject s3jni_getFts5ExensionApi(JNIEnv * const env){ if( !SJG.fts5.jFtsExt ){ jobject pNPH = new_NativePointerHolder_object( - env, &S3JniNphRefs.Fts5ExtensionApi, s3jni_ftsext() + env, S3JniNph(Fts5ExtensionApi), s3jni_ftsext() ); S3JniEnv_mutex_enter; if( pNPH ){ @@ -5016,11 +5025,11 @@ static jint s3jni_fts5_xTokenize(JniArgsEnvObj, S3JniNphRef const *pRef, s.tok.jba = S3JniRefLocal(jbaText); s.tok.zPrev = (const char *)pText; s.tok.nPrev = (int)nText; - if( pRef == &S3JniNphRefs.Fts5ExtensionApi ){ + if( pRef == S3JniNph(Fts5ExtensionApi) ){ rc = fext->xTokenize(PtrGet_Fts5Context(jFcx), (const char *)pText, (int)nText, &s, s3jni_xTokenize_xToken); - }else if( pRef == &S3JniNphRefs.fts5_tokenizer ){ + }else if( pRef == S3JniNph(fts5_tokenizer) ){ fts5_tokenizer * const pTok = PtrGet_fts5_tokenizer(jSelf); rc = pTok->xTokenize(PtrGet_Fts5Tokenizer(jFcx), &s, tokFlags, (const char *)pText, (int)nText, @@ -5038,13 +5047,13 @@ static jint s3jni_fts5_xTokenize(JniArgsEnvObj, S3JniNphRef const *pRef, JniDeclFtsXA(jint,xTokenize)(JniArgsEnvObj,jobject jFcx, jbyteArray jbaText, jobject jCallback){ - return s3jni_fts5_xTokenize(env, jSelf, &S3JniNphRefs.Fts5ExtensionApi, + return s3jni_fts5_xTokenize(env, jSelf, S3JniNph(Fts5ExtensionApi), 0, jFcx, jbaText, jCallback); } JniDeclFtsTok(jint,xTokenize)(JniArgsEnvObj,jobject jFcx, jint tokFlags, jbyteArray jbaText, jobject jCallback){ - return s3jni_fts5_xTokenize(env, jSelf, &S3JniNphRefs.Fts5Tokenizer, + return s3jni_fts5_xTokenize(env, jSelf, S3JniNph(Fts5Tokenizer), tokFlags, jFcx, jbaText, jCallback); } @@ -5337,5 +5346,5 @@ Java_org_sqlite_jni_SQLite3Jni_init(JniArgsEnvClass){ sqlite3_shutdown() /* So that it becomes legal for Java-level code to call - ** sqlite3_config(), if it's ever implemented. */; + ** sqlite3_config(). */; } diff --git a/ext/jni/src/c/sqlite3-jni.h b/ext/jni/src/c/sqlite3-jni.h index 1c9e4a641c..754d57063f 100644 --- a/ext/jni/src/c/sqlite3-jni.h +++ b/ext/jni/src/c/sqlite3-jni.h @@ -1059,20 +1059,12 @@ JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1origin JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1table_1name (JNIEnv *, jclass, jobject, jint); -/* - * Class: org_sqlite_jni_SQLite3Jni - * Method: sqlite3_column_text_utf8 - * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)[B - */ -JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1text_1utf8 - (JNIEnv *, jclass, jobject, jint); - /* * Class: org_sqlite_jni_SQLite3Jni * Method: sqlite3_column_text - * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)Ljava/lang/String; + * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)[B */ -JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1text +JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1text (JNIEnv *, jclass, jobject, jint); /* @@ -1851,20 +1843,12 @@ JNIEXPORT jlong JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1int64 JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1java_1object (JNIEnv *, jclass, jobject); -/* - * Class: org_sqlite_jni_SQLite3Jni - * Method: sqlite3_value_text_utf8 - * Signature: (Lorg/sqlite/jni/sqlite3_value;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1text_1utf8 - (JNIEnv *, jclass, jobject); - /* * Class: org_sqlite_jni_SQLite3Jni * Method: sqlite3_value_text - * Signature: (Lorg/sqlite/jni/sqlite3_value;)Ljava/lang/String; + * Signature: (Lorg/sqlite/jni/sqlite3_value;)[B */ -JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1text +JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1text (JNIEnv *, jclass, jobject); /* diff --git a/ext/jni/src/org/sqlite/jni/SQLite3Jni.java b/ext/jni/src/org/sqlite/jni/SQLite3Jni.java index e6eafa0bef..9225e48281 100644 --- a/ext/jni/src/org/sqlite/jni/SQLite3Jni.java +++ b/ext/jni/src/org/sqlite/jni/SQLite3Jni.java @@ -416,24 +416,13 @@ public final class SQLite3Jni { ); /** - Returns the given column's contents as UTF-8-encoded (not MUTF-8) - text. Returns null if the C-level sqlite3_column_text() returns - NULL. - - @see #sqlite3_column_text - */ - @Canonical(cname="sqlite3_column_text") - public static native byte[] sqlite3_column_text_utf8( - @NotNull sqlite3_stmt stmt, int ndx - ); - - /** - Provides the same feature as the same-named C API but returns the - text in Java-native encoding rather than the C API's UTF-8. - - @see #sqlite3_column_text16 + Functions identially to the C API, and this note is just to + stress that the returned bytes are encoded as UTF-8. It returns + null if the underlying C-level sqlite3_column_text() returns NULL + or on allocation error. */ - public static native String sqlite3_column_text( + @Canonical + public static native byte[] sqlite3_column_text( @NotNull sqlite3_stmt stmt, int ndx ); @@ -471,7 +460,7 @@ public final class SQLite3Jni { // } // case SQLITE_FLOAT: rv = new Double(sqlite3_value_double(v)); break; // case SQLITE_BLOB: rv = sqlite3_value_blob(v); break; - // case SQLITE_TEXT: rv = sqlite3_value_text(v); break; + // case SQLITE_TEXT: rv = sqlite3_value_text16(v); break; // default: break; // } // } @@ -1172,6 +1161,10 @@ public final class SQLite3Jni { @NotNull sqlite3_context cx, long n ); + /** + This overload is private because its final parameter is arguably + unnecessary in Java. + */ @Canonical private static native void sqlite3_result_blob( @NotNull sqlite3_context cx, @Nullable byte[] blob, int maxLen @@ -1195,8 +1188,11 @@ public final class SQLite3Jni { - If @param maxLen is larger than blob.length, it is truncated to - that value. If it is negative, results are undefined. +

If @param maxLen is larger than blob.length, it is truncated + to that value. If it is negative, results are undefined.

+ +

This overload is private because its final parameter is + arguably unnecessary in Java.

*/ @Canonical private static native void sqlite3_result_blob64( @@ -1209,6 +1205,10 @@ public final class SQLite3Jni { sqlite3_result_blob64(cx, blob, (long)(null==blob ? 0 : blob.length)); } + /** + This overload is private because its final parameter is + arguably unnecessary in Java. + */ @Canonical private static native void sqlite3_result_text( @NotNull sqlite3_context cx, @Nullable byte[] utf8, int maxLen @@ -1249,6 +1249,9 @@ public final class SQLite3Jni { text.length, it is silently truncated to text.length. If it is negative, results are undefined. If text is null, the subsequent arguments are ignored. + + This overload is private because its maxLength parameter is + arguably unnecessary in Java. */ @Canonical private static native void sqlite3_result_text64( @@ -1342,6 +1345,13 @@ public final class SQLite3Jni { /** Internal impl of the public sqlite3_strglob() method. Neither argument may be NULL and both MUST be NUL-terminated UTF-8. + + This overload is private because: (A) to keep users from + inadvertently passing non-NUL-terminated byte arrays (an easy + thing to do). (B) it is cheaper to NUL-terminate the + String-to-byte-array conversion in the Java implementation + (sqlite3_strglob(String,String)) than to do that in C, so that + signature is the public-facing one. */ @Canonical private static native int sqlite3_strglob( @@ -1358,8 +1368,7 @@ public final class SQLite3Jni { } /** - Internal impl of the public sqlite3_strlike() method. Neither - argument may be NULL and both MUST be NUL-terminated UTF-8. + The LIKE counterpart of the private sqlite3_strglob() method. */ @Canonical private static native int sqlite3_strlike( @@ -1502,30 +1511,14 @@ public final class SQLite3Jni { } /** - Returns the given value as UTF-8-encoded bytes, or null if the - underlying C-level sqlite3_value_text() returns NULL. + Functions identially to the C API, and this note is just to + stress that the returned bytes are encoded as UTF-8. It returns + null if the underlying C-level sqlite3_value_text() returns NULL + or on allocation error. */ - @Canonical(cname="sqlite3_value_text", - comment="Renamed because its String-returning overload would "+ - "otherwise be ambiguous.") - public static native byte[] sqlite3_value_text_utf8(@NotNull sqlite3_value v); - - /** - Provides the same feature as the same-named C API but returns the - text in Java-native encoding rather than the C API's UTF-8. - - @see #sqlite3_value_text16 - */ - public static native String sqlite3_value_text(@NotNull sqlite3_value v); + @Canonical + public static native byte[] sqlite3_value_text(@NotNull sqlite3_value v); - /** - In the Java layer, sqlite3_value_text() and - sqlite3_value_text16() are functionally equivalent, the - difference being only where the encoding to UTF-16 (if necessary) - takes place. This function does it via SQLite and - sqlite3_value_text() fetches UTF-8 (SQLite's default encoding) - and converts it to UTF-16 in Java. - */ @Canonical public static native String sqlite3_value_text16(@NotNull sqlite3_value v); diff --git a/ext/jni/src/org/sqlite/jni/Tester1.java b/ext/jni/src/org/sqlite/jni/Tester1.java index 5d3623f677..ce8eb6bd23 100644 --- a/ext/jni/src/org/sqlite/jni/Tester1.java +++ b/ext/jni/src/org/sqlite/jni/Tester1.java @@ -453,9 +453,14 @@ public class Tester1 implements Runnable { final sqlite3_value sv = sqlite3_value_dup(sqlite3_column_value(stmt,0)); final String txt = sqlite3_column_text16(stmt, 0); sbuf.append( txt ); - affirm( txt.equals(sqlite3_column_text(stmt, 0)) ); + affirm( txt.equals(new String( + sqlite3_column_text(stmt, 0), + StandardCharsets.UTF_8 + )) ); affirm( txt.length() < sqlite3_value_bytes(sv) ); - affirm( txt.equals(sqlite3_value_text(sv)) ); + affirm( txt.equals(new String( + sqlite3_value_text(sv), + StandardCharsets.UTF_8)) ); affirm( txt.length() == sqlite3_value_bytes16(sv)/2 ); affirm( txt.equals(sqlite3_value_text16(sv)) ); sqlite3_value_free(sv); @@ -464,6 +469,20 @@ public class Tester1 implements Runnable { sqlite3_finalize(stmt); affirm(3 == n); affirm("w😃rldhell🤩!🤩".equals(sbuf.toString())); + + stmt = prepare(db, "SELECT ?, ?"); + rc = sqlite3_bind_text(stmt, 1, ""); + affirm( 0==rc ); + rc = sqlite3_bind_text(stmt, 2, (String)null); + affirm( 0==rc ); + rc = sqlite3_step(stmt); + affirm( SQLITE_ROW==rc ); + byte[] colBa = sqlite3_column_text(stmt, 0); + affirm( 0==colBa.length ); + colBa = sqlite3_column_text(stmt, 1); + affirm( null==colBa ); + sqlite3_finalize(stmt); + sqlite3_close_v2(db); } diff --git a/ext/jni/src/org/sqlite/jni/TesterFts5.java b/ext/jni/src/org/sqlite/jni/TesterFts5.java index feb6d6303d..70c8e255d2 100644 --- a/ext/jni/src/org/sqlite/jni/TesterFts5.java +++ b/ext/jni/src/org/sqlite/jni/TesterFts5.java @@ -50,7 +50,7 @@ public class TesterFts5 { int rc = ext.xColumnText(fCx, i, op); affirm( 0 == rc ); final String val = op.value; - affirm( val.equals(sqlite3_value_text(argv[i])) ); + affirm( val.equals(sqlite3_value_text16(argv[i])) ); //outln("xFunction col "+i+": "+val); } } diff --git a/ext/jni/src/org/sqlite/jni/annotation/Canonical.java b/ext/jni/src/org/sqlite/jni/annotation/Canonical.java index 80164a4dda..24b0f82d4c 100644 --- a/ext/jni/src/org/sqlite/jni/annotation/Canonical.java +++ b/ext/jni/src/org/sqlite/jni/annotation/Canonical.java @@ -7,35 +7,22 @@ package org.sqlite.jni.annotation; the Java API.

Canonical functions, unless specifically documented, have the - same semantics as their counterparts in - the C API documentation, - despite their signatures perhaps differing. The Java API adds a - number of overloads to simplify use, as well as a few Java-specific - functions, and those are never flagged as @Canonical. + same semantics as their counterparts in the C API + documentation, despite their signatures perhaps differing + slightly. The Java API adds a number of overloads to simplify use, + as well as a few Java-specific functions, and those are never + flagged as @Canonical.

In some cases, the canonical version of a function is private and exposed to Java via public overloads. -

In rare cases, the Java interface for a canonical function has a - different name than its C counterpart. For such cases, - (cname=the-C-side-name) is passed to this annotation and a - Java-side implementation with a slightly different signature is - added with the canonical name. As of this writing, that applies - only to {@link org.sqlite.jni.SQLite3Jni#sqlite3_value_text_utf8} - and {@link org.sqlite.jni.SQLite3Jni#sqlite3_column_text_utf8}. -

The comment property can be used to add a comment. */ @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface Canonical{ - /** - Java functions which directly map to a canonical function but - change its name for some reason should not the original name - in this property. - */ - String cname() default ""/*doesn't allow null*/; /** Brief comments about the binding, e.g. noting any major semantic differences. diff --git a/manifest b/manifest index 85245e43d1..e8040dc975 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\ssome\snewly-dead\scode. -D 2023-09-01T10:37:15.903 +C Make\sJNI\sinterfaces\sof\ssqlite3_column/value_text()\smatch\sthe\sC\sones\sbetter.\sInternal\sJNI\scleanups\sand\ssimplifications. +D 2023-09-01T13:27:59.308 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -234,11 +234,11 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9 F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282 F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8 -F ext/jni/GNUmakefile 591d05030e7fa787615d88fb5b7e8377e1e777612fce4d4eed9b595843f1d014 +F ext/jni/GNUmakefile bcf386da9510e45034d90b2f7b91ab51adcd2db9e080f3900a1e63caf5999659 F ext/jni/README.md 1332b1fa27918bd5d9ca2d0d4f3ac3a6ab86b9e3699dc5bfe32904a027f3d2a9 F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa -F ext/jni/src/c/sqlite3-jni.c 69a78f7f7b94b58e272184d005813322bad24ed78ea392563b657faa3cc56218 -F ext/jni/src/c/sqlite3-jni.h 383a357c8920e05ea2b6ca7f9548ee04a263319f018ef3daeeaa719727be8b72 +F ext/jni/src/c/sqlite3-jni.c 2da08d92d1cd858353071a2559a260333425e87a79f3da09d85f07f35930a573 +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/AggregateFunction.java 7312486bc65fecdb91753c0a4515799194e031f45edbe16a6373cea18f404dc4 F ext/jni/src/org/sqlite/jni/AuthorizerCallback.java e6135be32f12bf140bffa39be7fd1a45ad83b2661ed49c08dbde04c8485feb38 @@ -262,17 +262,17 @@ F ext/jni/src/org/sqlite/jni/ProgressHandlerCallback.java 7b9ff2218129ece98ba60c F ext/jni/src/org/sqlite/jni/ResultCode.java ba701f20213a5f259e94cfbfdd36eb7ac7ce7797f2c6c7fca2004ff12ce20f86 F ext/jni/src/org/sqlite/jni/RollbackHookCallback.java d12352c0e22840de484ffa9b11ed5058bb0daca2e9f218055d3c54c947a273c4 F ext/jni/src/org/sqlite/jni/SQLFunction.java 544a875d33fd160467d82e2397ac33157b29971d715a821a4fad3c899113ee8c -F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 5a05c67b994d3f431d61203ab1de842d49491714e78cf99ccd5aa5257b66e9ff +F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 35ead9802bf3b16f9afba663ac73f629b3ebdc5cacad151f38403daee9f1e6b0 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/Tester1.java 95fd3d3c0068cd7ebf2e89bb7db16fba541e6cf872f64f08c1e1350f6585682b -F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629 +F ext/jni/src/org/sqlite/jni/Tester1.java d4ab6f3f83cbb96e763dd4feb6e5527864d9957eb5e79259bfbe57dcf6d0103e +F ext/jni/src/org/sqlite/jni/TesterFts5.java 02b59ea7d75666fd565d90bb8dc7b0c09441bb9d1af091fad9f6d7377297a474 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/ValueHolder.java f022873abaabf64f3dd71ab0d6037c6e71cece3b8819fa10bf26a5461dc973ee F ext/jni/src/org/sqlite/jni/WindowFunction.java 488980f4dbb6bdd7067d6cb9c43e4075475e51c54d9b74a5834422654b126246 F ext/jni/src/org/sqlite/jni/XDestroyCallback.java 50c5ca124ef6c6b735a7e136e7a23a557be367e61b56d4aab5777a614ab46cc2 -F ext/jni/src/org/sqlite/jni/annotation/Canonical.java ff9fc59004303d8ef89c516ede9ef5f51c881e9c9ba982f0ebb1bdd9a18550bc +F ext/jni/src/org/sqlite/jni/annotation/Canonical.java d9ff79f1bf9d063d0c3e3b768ec7df15f51e4ca51a5bb291d33b7a6ea9a24f3a 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/package-info.java f66bfb621c6494e67c03ed38a9e26a3bd6af99b9f9f6ef79556bcec30a025a22 @@ -2116,8 +2116,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5fe5b0a585dbfa06cfca1fea40aea5ea3ccfe8295f41306ad2d5b851ace27203 -R e68a872b68a0b0146fb6e1b06b988d94 +P dc0fa76b395c5e352116dc33cc1b455e5e9c9f01c285af52ccba4d37e4453b87 +R 8eeecadbd0aad723daa22691fc77aaf3 U stephan -Z 2904ef85d8a184bf73f88a40f15d384b +Z 2c93c72b42f574b692bce8cc766cb46c # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 1740a09513..f6e2e419ea 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dc0fa76b395c5e352116dc33cc1b455e5e9c9f01c285af52ccba4d37e4453b87 \ No newline at end of file +eb24f97253d9c8e7c728c2ac67a0824b10ca67362ac4f8abb94d5d3c54c58c5b \ No newline at end of file