------------------------------------------------------------------------
JNI bindings which accept client-defined functions _must never throw
-exceptions_. There are _no exceptions_ to this rule. Exceptions are
-reserved for higher-level bindings which are constructed to
-specifically deal with them and ensure that they do not leak C-level
-resources. Some of the JNI bindings are provided as Java functions
-which expect this rule to always hold.
+exceptions_ unless _very explicitly documented_ as being
+throw-safe. Exceptions are generally reserved for higher-level
+bindings which are constructed to specifically deal with them and
+ensure that they do not leak C-level resources. Some of the JNI
+bindings are provided as Java functions which expect this rule to
+always hold.
UTF-8(-ish)
------------------------------------------------------------------------
memset(p, 0, sizeof(NphCacheLine));
}
+#define S3JNI_ENABLE_AUTOEXT 0
+#if S3JNI_ENABLE_AUTOEXT
+/*
+ Whether auto extensions are feasible here is currently unknown due
+ to...
+
+ 1) JNIEnv/threading issues. A db instance is mapped to a specific
+ JNIEnv object but auto extensions may be added from any thread. In
+ such contexts, which JNIEnv do we use for the JNI APIs?
+
+ 2) a chicken/egg problem involving the Java/C mapping of the db:
+ when auto extensions are run, the db has not yet been connected to
+ Java. If we do that during the auto-ext, sqlite3_open(_v2)() will not behave
+ properly because they have a different jobject and the API
+ guarantees the user that _that_ object is the one the API will bind
+ the native to.
+
+ If we change the open(_v2()) interfaces to use OutputPointer.sqlite3
+ instead of the client passing in an instance, we could work around
+ (2).
+*/
+typedef struct S3JniAutoExtension S3JniAutoExtension;
+typedef void (*S3JniAutoExtension_xEntryPoint)(sqlite3*);
+struct S3JniAutoExtension {
+ JNIEnv * env;
+ jobject jObj;
+ jmethodID midFunc;
+ S3JniAutoExtension_xEntryPoint xEntryPoint;
+ S3JniAutoExtension *pNext /* next linked-list entry */;
+ S3JniAutoExtension *pPrev /* previous linked-list entry */;
+};
+#endif
+
/** State for various hook callbacks. */
typedef struct JniHookState JniHookState;
struct JniHookState{
unsigned nInverse;
} udf;
} metrics;
+#if S3JNI_ENABLE_AUTOEXT
+ struct {
+ S3JniAutoExtension *pHead;
+ int isRunning;
+ } autoExt;
+#endif
} S3Global;
/**
return s;
}
+#if 0
+/**
+ An alternative form which searches for the PerDbStateJni instance for
+ pDb with no JNIEnv-specific info. This can be (but _should_ it be?)
+ called from the context of a separate JNIEnv than the one mapped
+ to in the returned object. Returns 0 if no match is found.
+*/
+FIXME_THREADING
+static PerDbStateJni * PerDbStateJni_for_db2(sqlite3 *pDb){
+ PerDbStateJni * s = S3Global.perDb.aUsed;
+ for( ; pDb && s; s = s->pNext){
+ if(s->pDb == pDb) return s;
+ }
+ return 0;
+}
+#endif
/**
Requires that jCx be a Java-side sqlite3_context wrapper for pCx.
WRAP_INT_SVALUE(1value_1subtype, sqlite3_value_subtype)
WRAP_INT_SVALUE(1value_1type, sqlite3_value_type)
+#if S3JNI_ENABLE_AUTOEXT
+/* auto-extension is very incomplete */
+static inline jobject new_sqlite3_wrapper(JNIEnv * const env, sqlite3 *sv){
+ return new_NativePointerHolder_object(env, S3ClassNames.sqlite3, sv);
+}
+/*static*/ int s3jni_auto_extension(sqlite3 *pDb, const char **pzErr,
+ const struct sqlite3_api_routines *pThunk){
+ S3JniAutoExtension const * pAX = S3Global.autoExt.pHead;
+ jobject jDb;
+ int rc;
+ JNIEnv * env = 0;
+ if(S3Global.autoExt.isRunning){
+ *pzErr = sqlite3_mprintf("Auto-extensions must not be triggered while "
+ "auto-extensions are running.");
+ return SQLITE_MISUSE;
+ }
+ if( S3Global.jvm->GetEnv(S3Global.jvm, (void **)&env, JNI_VERSION_1_8) ){
+ *pzErr = sqlite3_mprintf("Could not get current JNIEnv.");
+ return SQLITE_ERROR;
+ }
+ S3Global.autoExt.isRunning = 1;
+ jDb = new_sqlite3_wrapper( env, pDb );
+ EXCEPTION_IS_FATAL("Cannot create sqlite3 wrapper object.");
+ // Now we need PerDbStateJni_for_db(env, jDb, pDb, 1)
+ // and rewire sqlite3_open(_v2()) to use OutputPointer.sqlite3
+ // so that they can have this same jobject.
+ for( ; pAX; pAX = pAX->pNext ){
+ JNIEnv * const env = pAX->env
+ /* ^^^ is this correct, or must we use the JavaVM::GetEnv()'s env
+ instead? */;
+ rc = (*env)->CallVoidMethod(env, pAX->jObj, pAX->midFunc, jDb);
+ IFTHREW {
+ *pzErr = sqlite3_mprintf("auto-extension threw. TODO: extract error message.");
+ rc = SQLITE_ERROR;
+ break;
+ }
+ }
+ UNREF_L(jDb);
+ S3Global.autoExt.isRunning = 0;
+ return rc;
+}
+JDECL(jint,1auto_1extension)(JENV_OSELF, jobject jAutoExt){}
+#endif /* S3JNI_ENABLE_AUTOEXT */
+
JDECL(jint,1bind_1blob)(JENV_CSELF, jobject jpStmt,
jint ndx, jbyteArray baData, jint nMax){
int rc;
* Method: sqlite3_db_config
* Signature: (Lorg/sqlite/jni/sqlite3;ILorg/sqlite/jni/OutputPointer/Int32;)I
*/
-JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1db_1config__Lorg_sqlite_jni_sqlite3_2ILorg_sqlite_jni_OutputPointer_Int32_2
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1db_1config__Lorg_sqlite_jni_sqlite3_2ILorg_sqlite_jni_OutputPointer_00024Int32_2
(JNIEnv *, jclass, jobject, jint, jobject);
/*
package org.sqlite.jni;
/**
- A wrapper for use with sqlite3_set_authorizer().
+ A callback for use with sqlite3_set_authorizer().
*/
public interface Authorizer {
/**
public native int xRowCount(@NotNull Fts5Context fcx,
@NotNull OutputPointer.Int64 nRow);
public native long xRowid(@NotNull Fts5Context cx);
- /* Note that this impl lacks the xDelete() callback
- argument. Instead, if pAux has an xDestroy() method, it is called
- if the FTS5 API finalizes the aux state (including if allocation
- of storage for the auxdata fails). Any reference to pAux held by
- the JNI layer will be relinquished regardless of whther pAux has
- an xDestroy() method. */
+ /* Note that the JNI binding lacks the C version's xDelete()
+ callback argument. Instead, if pAux has an xDestroy() method, it
+ is called if the FTS5 API finalizes the aux state (including if
+ allocation of storage for the auxdata fails). Any reference to
+ pAux held by the JNI layer will be relinquished regardless of
+ whether pAux has an xDestroy() method. */
public native int xSetAuxdata(@NotNull Fts5Context cx, @Nullable Object pAux);
public native int xTokenize(@NotNull Fts5Context cx, @NotNull byte pText[],
@NotNull Fts5.xTokenizeCallback callback);
// alphabetized. The SQLITE_... values. on the other hand, are
// grouped by category.
+
+ // Auto-extensions cannot currently work properly in our setup
+ // for reasons explained in sqlite3-jni.c.
+ //
+ // /**
+ // Functions almost as documented for the C API, with these
+ // exceptions:
+ //
+ // - The callback interface is more limited because of
+ // cross-language differences.
+ //
+ // - All of the auto-extension routines will fail without side
+ // effects if invoked from within the execution of an
+ // auto-extension.
+ //
+ // See the AutoExtension class docs for more information.
+ // */
+ // private static native int sqlite3_auto_extension(@NotNull AutoExtension callback);
+
+
public static int sqlite3_bind_blob(@NotNull sqlite3_stmt stmt, int ndx,
@Nullable byte[] data){
return (null == data)
to hook in arbitrary C-side code during development and testing
of this library.
*/
- public static native void sqlite3_do_something_for_developer();
+ static native void sqlite3_do_something_for_developer();
//////////////////////////////////////////////////////////////////////
// SQLITE_... constants follow...
-C Doc\scleanups.
-D 2023-08-06T15:01:38.351
+C Start\sadding\sJNI-side\ssupport\sfor\sauto\sextensions,\sbut\shit\sa\sbrick\swall\swhich\srequires\sslightly\sawkward\ssemantics\schanges\sin\sthe\sJNI\sbindings\sfor\ssqlite3_open(_v2)()\sto\sresolve,\sso\sstash\sthis\s#if'd\sout\sfor\sthe\stime\sbeing.
+D 2023-08-06T20:01:30.439
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
F ext/jni/GNUmakefile 61d9bbc179a49523a142928455b3297779b9c40f25783ecf1538279e426cbc99
-F ext/jni/README.md 6ff7e1f4100dee980434a6ee37a199b653bceec62e233a6e2ccde6e7ae0c58bf
-F ext/jni/src/c/sqlite3-jni.c ec7de3a37d7a62598179bc602c2f81f28434264e9d2d62d894c8c4eb41098291
-F ext/jni/src/c/sqlite3-jni.h 58678453c1b6cccb8d728a60f59b2b0819226658376c0b36e025ce8b0fea75c3
-F ext/jni/src/org/sqlite/jni/Authorizer.java 8dde03bbe50896d2f426240a4af4dcb6d98b655af84fe6ed86e637f5d5ac1fc8
+F ext/jni/README.md e965674505e105626127ad45e628e4d19fcd379cdafc4d23c814c1ac2c55681d
+F ext/jni/src/c/sqlite3-jni.c e335541e3eac0e337cc22f0b78a040e73c477d41128845ffe4ba8029fc077994
+F ext/jni/src/c/sqlite3-jni.h 2ef601ab7cef00047ef0907e873f8f7bc4bfa6ee510b0435e070eb8ee7b6c6f0
+F ext/jni/src/org/sqlite/jni/Authorizer.java 1308988f7f40579ea0e4deeaec3c6be971630566bd021c31367fe3f5140db892
F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c
F ext/jni/src/org/sqlite/jni/Collation.java 8dffbb00938007ad0967b2ab424d3c908413af1bbd3d212b9c9899910f1218d1
F ext/jni/src/org/sqlite/jni/CollationNeeded.java ebc7cd96d46a70daa76016a308e80f70a3f21d3282787c8d139aa840fdcb1bd7
F ext/jni/src/org/sqlite/jni/CommitHook.java 87c6a8e5138c61a8eeff018fe16d23f29219150239746032687f245938baca1a
F ext/jni/src/org/sqlite/jni/Fts5.java 13844685231e8b4840a706db3bed84d5dfcf15be0ae7e809eac40420dba24901
F ext/jni/src/org/sqlite/jni/Fts5Context.java 0a5a02047a6a1dd3e4a38b0e542a8dd2de365033ba30e6ae019a676305959890
-F ext/jni/src/org/sqlite/jni/Fts5ExtensionApi.java 9798c6288097f4619ded680fe0961132a3f3d3cbffd7ce22096159f114f28c61
+F ext/jni/src/org/sqlite/jni/Fts5ExtensionApi.java c908e5fdf6f5d15e388144fcd8160a3f46c18dade749f1b747122d2d37f2e726
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/Fts5Tokenizer.java 91489893596b6528c0df5cd7180bd5b55809c26e2b797fb321dfcdbc1298c060
F ext/jni/src/org/sqlite/jni/ProgressHandler.java 5979450e996416d28543f1d42634d308439565a99332a8bd84e424af667116cc
F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f69df0ba909e49ba18d73f4268d92564
F ext/jni/src/org/sqlite/jni/SQLFunction.java 09ce81c1c637e31c3a830d4c859cce95d65f5e02ff45f8bd1985b3479381bc46
-F ext/jni/src/org/sqlite/jni/SQLite3Jni.java eb49c9e5424e80ed1465c184086b3895155eee0828fc1992bfee24b741735638
+F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 2ee2d3522ab6bec9337653233f5fb50619120cc5b12ce5deb59035ca2502cdcd
F ext/jni/src/org/sqlite/jni/Tester1.java 04c43f3ec93b362fc1c66430a3125067285259cd4fa5afccdb2fa66b691db8d0
F ext/jni/src/org/sqlite/jni/TesterFts5.java cf2d687baafffdeba219b77cf611fd47a0556248820ea794ae3e8259bfbdc5ee
F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 6119289da85ac0c83e2a7236d24bbfff22334d6cf1d852756dc658ad6a75dfec
-R 48b7c494d85b3192affc08b2af78551a
+P 5f56b007704f2aad4cbc6f0ccd1e1f1c974865971f99451352714ee7e077c284
+R 55ff516d4ad7789048494bf17442d9b9
U stephan
-Z a195dbc9574f42748d3f2a6c1a7b8425
+Z 7da38e0ddc75e18237df446c4596f88f
# Remove this line to create a well-formed Fossil manifest.
-5f56b007704f2aad4cbc6f0ccd1e1f1c974865971f99451352714ee7e077c284
\ No newline at end of file
+77a32d238e80fe1d237768d88780043a7bd2b3543e6672536254782cbea0039c
\ No newline at end of file