-DSQLITE_TEMP_STORE=2 \
-DSQLITE_USE_URI=1 \
-DSQLITE_C=$(sqlite3.c) \
+ -DSQLITE_JNI_FATAL_OOM=0 \
-DSQLITE_DEBUG
SQLITE_OPT += -g -DDEBUG -UNDEBUG
javadoc: $(doc.index)
# Force rebild of docs
redoc:
- @rm -f $(doc.index)/index.html
+ @rm -f $(doc.index)
@$(MAKE) doc
docserve: $(doc.index)
cd $(dir.doc) && althttpd -max-age 1 -page index.html
//# define SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
//#endif
+/**********************************************************************/
+/* SQLITE_J... */
+#ifdef SQLITE_JNI_FATAL_OOM
+#if !SQLITE_JNI_FATAL_OOM
+#undef SQLITE_JNI_FATAL_OOM
+#endif
+#endif
+
/**********************************************************************/
/* SQLITE_M... */
#ifndef SQLITE_MAX_ALLOCATION_SIZE
** sqlite3_malloc() proxy which fails fatally on OOM. This should
** only be used for routines which manage global state and have no
** recovery strategy for OOM. For sqlite3 API which can reasonably
-** return SQLITE_NOMEM, sqlite3_malloc() should be used instead.
+** return SQLITE_NOMEM, s3jni_malloc() should be used instead.
+*/
+static void * s3jni_malloc_or_die(JNIEnv * const env, size_t n){
+ void * const rv = sqlite3_malloc(n);
+ if( n && !rv ) s3jni_oom(env);
+ return rv;
+}
+
+/*
+** Works like sqlite3_malloc() unless built with SQLITE_JNI_FATAL_OOM,
+** in which case it calls s3jni_oom() on OOM.
*/
static void * s3jni_malloc(JNIEnv * const env, size_t n){
void * const rv = sqlite3_malloc(n);
+#ifdef SQLITE_JNI_FATAL_OOM
if( n && !rv ) s3jni_oom(env);
+#endif
return rv;
}
+/*
+** Works like sqlite3_realloc() unless built with SQLITE_JNI_FATAL_OOM,
+** in which case it calls s3jni_oom() on OOM.
+*/
+static void * s3jni_realloc(JNIEnv * const env, void * p, size_t n){
+ void * const rv = sqlite3_realloc(p, (int)n);
+#ifdef SQLITE_JNI_FATAL_OOM
+ if( n && !rv ) s3jni_oom(env);
+#endif
+ return rv;
+}
+
+
/*
** Returns the current JNIEnv object. Fails fatally if it cannot find
** the object.
SJG.envCache.aFree = row->pNext;
if( row->pNext ) row->pNext->pPrev = 0;
}else{
- row = s3jni_malloc(env, sizeof(S3JniEnv));
+ row = s3jni_malloc_or_die(env, sizeof(*row));
s3jni_incr( &SJG.metrics.envCacheAllocs );
}
memset(row, 0, sizeof(*row));
}
nBa = (*env)->GetArrayLength(env, jba);
if( nLen ) *nLen = (int)nBa;
- rv = sqlite3_malloc( nBa + 1 );
+ rv = s3jni_malloc( env, nBa + 1 );
if( rv ){
(*env)->GetByteArrayRegion(env, jba, 0, nBa, (jbyte*)rv);
rv[nBa] = 0;
** to ResultJavaVal_finalizer().
*/
static ResultJavaVal * ResultJavaVal_alloc(JNIEnv * const env, jobject jObj){
- ResultJavaVal * rv = sqlite3_malloc(sizeof(ResultJavaVal));
+ ResultJavaVal * const rv = s3jni_malloc(env, sizeof(ResultJavaVal));
if( rv ){
rv->jObj = jObj ? S3JniRefGlobal(jObj) : 0;
}
}
S3JniMutex_Global_leave;
if( !s ){
- s = sqlite3_malloc(sizeof(*s));
+ s = s3jni_malloc(env, sizeof(*s));
s3jni_incr(&SJG.metrics.nUdfAlloc);
}
if( s ){
if( SJG.autoExt.nExt == SJG.autoExt.nAlloc ){
unsigned n = 1 + SJG.autoExt.nAlloc;
S3JniAutoExtension * const aNew =
- sqlite3_realloc( SJG.autoExt.pExt,
- n * sizeof(S3JniAutoExtension) );
+ s3jni_realloc( env, SJG.autoExt.pExt, n * sizeof(*ax) );
if( !aNew ){
rc = SQLITE_NOMEM;
}else{
}
/* Impl for sqlite3_result_text/blob() and friends. */
-static void result_blob_text(int as64,
- int eTextRep/*only for (asBlob=0)*/,
+static void result_blob_text(int as64 /* true for text64/blob64() mode */,
+ int eTextRep /* 0 for blobs, else SQLITE_UTF... */,
JNIEnv * const env, sqlite3_context *pCx,
jbyteArray jBa, jlong nMax){
int const asBlob = 0==eTextRep;
}
if( as64 ){ /* 64-bit... */
static const jsize nLimit64 =
- SQLITE_MAX_ALLOCATION_SIZE/*only _kinda_ arbitrary!*/
- /* jsize is int32, not int64! */;
+ SQLITE_MAX_ALLOCATION_SIZE/*only _kinda_ arbitrary*/;
if( nBa > nLimit64 ){
sqlite3_result_error_toobig(pCx);
}else if( asBlob ){
return rc;
}
-S3JniApi(sqlite3_strglob(),jint,1strglob)(
- JniArgsEnvClass, jbyteArray baG, jbyteArray baT
-){
- return s3jni_strlike_glob(0, env, baG, baT, 0);
-}
-
-S3JniApi(sqlite3_strlike(),jint,1strlike)(
- JniArgsEnvClass, jbyteArray baG, jbyteArray baT, jint escChar
-){
- return s3jni_strlike_glob(1, env, baG, baT, escChar);
-}
-
S3JniApi(sqlite3_shutdown(),jint,1shutdown)(
JniArgsEnvClass
){
return sqlite3_shutdown();
}
+S3JniApi(sqlite3_strglob(),jint,1strglob)(
+ JniArgsEnvClass, jbyteArray baG, jbyteArray baT
+){
+ return s3jni_strlike_glob(0, env, baG, baT, 0);
+}
+
+S3JniApi(sqlite3_strlike(),jint,1strlike)(
+ JniArgsEnvClass, jbyteArray baG, jbyteArray baT, jint escChar
+){
+ return s3jni_strlike_glob(1, env, baG, baT, escChar);
+}
+
S3JniApi(sqlite3_sql(),jstring,1sql)(
JniArgsEnvClass, jobject jpStmt
){
}
static Fts5JniAux * Fts5JniAux_alloc(JNIEnv * const env, jobject jObj){
- Fts5JniAux * s = sqlite3_malloc(sizeof(Fts5JniAux));
+ Fts5JniAux * s = s3jni_malloc(env, sizeof(Fts5JniAux));
+
if( s ){
jclass klazz;
memset(s, 0, sizeof(Fts5JniAux));
return new_NativePointerHolder_object(env, &S3NphRefs.fts5_api, sv);
}
-/**
- Returns a per-JNIEnv global ref to the Fts5ExtensionApi singleton
- instance, or NULL on OOM.
+/*
+** Returns a per-JNIEnv global ref to the Fts5ExtensionApi singleton
+** instance, or NULL on OOM.
*/
static jobject s3jni_getFts5ExensionApi(JNIEnv * const env){
if( !SJG.fts5.jFtsExt ){
}
/*
-** Return a pointer to the fts5_api instance for database connection
-** db. If an error occurs, return NULL and leave an error in the
+** Returns a pointer to the fts5_api instance for database connection
+** db. If an error occurs, returns NULL and leaves an error in the
** database handle (accessible using sqlite3_errcode()/errmsg()).
*/
static fts5_api *s3jni_fts5_api_from_db(sqlite3 *db){
Fts5ExtDecl;
int rc;
S3JniFts5AuxData * pAux;
- pAux = sqlite3_malloc(sizeof(*pAux));
+
+ pAux = s3jni_malloc(env, sizeof(*pAux));
if( !pAux ){
if( jAux ){
/* Emulate how xSetAuxdata() behaves when it cannot alloc
char *z;
int n = sqlite3_value_bytes(argv[0]);
SQLTesterJni * const p = (SQLTesterJni *)sqlite3_user_data(context);
+ S3JniDeclLocal_env;
++p->nDup;
- if( n>0 && (pOut = sqlite3_malloc( (n+16)&~7 ))!=0 ){
+ if( n>0 && (pOut = s3jni_malloc( env, (n+16)&~7 ))!=0 ){
pOut[0] = 0x2bbf4b7c;
z = (char*)&pOut[1];
memcpy(z, sqlite3_value_text(argv[0]), n);
JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1text64
(JNIEnv *, jclass, jobject, jbyteArray, jlong, jint);
-/*
- * Class: org_sqlite_jni_SQLite3Jni
- * Method: sqlite3_shutdown
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1shutdown
- (JNIEnv *, jclass);
-
-/*
- * Class: org_sqlite_jni_SQLite3Jni
- * Method: sqlite3_status
- * Signature: (ILorg/sqlite/jni/OutputPointer/Int32;Lorg/sqlite/jni/OutputPointer/Int32;Z)I
- */
-JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1status
- (JNIEnv *, jclass, jint, jobject, jobject, jboolean);
-
-/*
- * Class: org_sqlite_jni_SQLite3Jni
- * Method: sqlite3_status64
- * Signature: (ILorg/sqlite/jni/OutputPointer/Int64;Lorg/sqlite/jni/OutputPointer/Int64;Z)I
- */
-JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1status64
- (JNIEnv *, jclass, jint, jobject, jobject, jboolean);
-
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_rollback_hook
JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1set_1last_1insert_1rowid
(JNIEnv *, jclass, jobject, jlong);
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_shutdown
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1shutdown
+ (JNIEnv *, jclass);
+
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_sleep
JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1sql
(JNIEnv *, jclass, jobject);
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_status
+ * Signature: (ILorg/sqlite/jni/OutputPointer/Int32;Lorg/sqlite/jni/OutputPointer/Int32;Z)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1status
+ (JNIEnv *, jclass, jint, jobject, jobject, jboolean);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_status64
+ * Signature: (ILorg/sqlite/jni/OutputPointer/Int64;Lorg/sqlite/jni/OutputPointer/Int64;Z)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1status64
+ (JNIEnv *, jclass, jint, jobject, jobject, jboolean);
+
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_step
argument, the context is set to the given initial value. On all other
calls, the 2nd argument is ignored.
- @see SQLFunction.PerContextState#getAggregateState()
+ @see SQLFunction.PerContextState#getAggregateState
*/
protected final ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
return map.getAggregateState(cx, initialValue);
To be called from the implementation's xFinal() method to fetch
the final state of the UDF and remove its mapping.
- see SQLFunction.PerContextState#takeAggregateState()
+ see SQLFunction.PerContextState#takeAggregateState
*/
protected final T takeAggregateState(sqlite3_context cx){
return map.takeAggregateState(cx);
a complaint about the invalid argument.
*/
private static native void sqlite3_result_error(
- @NotNull sqlite3_context cx, @NotNull byte[] msg,
- int eTextRep
+ @NotNull sqlite3_context cx, @NotNull byte[] msg, int eTextRep
);
public static void sqlite3_result_error(
public static void sqlite3_result_error16(
@NotNull sqlite3_context cx, @NotNull String msg
){
- final byte[] utf8 = msg.getBytes(StandardCharsets.UTF_16);
- sqlite3_result_error(cx, utf8, SQLITE_UTF16);
+ final byte[] utf16 = msg.getBytes(StandardCharsets.UTF_16);
+ sqlite3_result_error(cx, utf16, SQLITE_UTF16);
}
+ /**
+ Equivalent to passing e.getMessage() to
+ sqlite3_result_error(db,String).
+ */
public static void sqlite3_result_error(
@NotNull sqlite3_context cx, @NotNull Exception e
){
sqlite3_result_error(cx, e.getMessage());
}
- public static void sqlite3_result_error16(
- @NotNull sqlite3_context cx, @NotNull Exception e
- ){
- sqlite3_result_error16(cx, e.getMessage());
- }
-
public static native void sqlite3_result_error_toobig(
@NotNull sqlite3_context cx
);
/**
Binds the SQL result to the given object, or
- {@link #sqlite3_result_null(sqlite3_context) sqlite3_result_null()} if {@code o} is null. Use
+ {@link #sqlite3_result_null} if {@code o} is null. Use
{@link #sqlite3_value_java_object(sqlite3_value) sqlite3_value_java_object()} or
{@link #sqlite3_column_java_object(sqlite3_stmt,int) sqlite3_column_java_object()} to
fetch it.
}
private static native void sqlite3_result_text(
- @NotNull sqlite3_context cx, @Nullable byte[] text, int maxLen
+ @NotNull sqlite3_context cx, @Nullable byte[] utf8, int maxLen
);
public static void sqlite3_result_text(
- @NotNull sqlite3_context cx, @Nullable byte[] text
+ @NotNull sqlite3_context cx, @Nullable byte[] utf8
){
- sqlite3_result_text(cx, text, null==text ? 0 : text.length);
+ sqlite3_result_text(cx, utf8, null==utf8 ? 0 : utf8.length);
}
public static void sqlite3_result_text(
long maxLength, int encoding
);
- /**
- Cleans up all stale per-thread state managed by the library, as
- well as any registered auto-extensions, then calls the C-native
- sqlite3_shutdown(). Calling this while database handles or
- prepared statements are still active will leak resources. Trying
- to use those objects after this routine is called invoked
- undefined behavior.
- */
- public static synchronized native int sqlite3_shutdown();
-
- public static native int sqlite3_status(
- int op, @NotNull OutputPointer.Int32 pCurrent,
- @NotNull OutputPointer.Int32 pHighwater, boolean reset
- );
-
- public static native int sqlite3_status64(
- int op, @NotNull OutputPointer.Int64 pCurrent,
- @NotNull OutputPointer.Int64 pHighwater, boolean reset
- );
-
/**
Sets the current UDF result to the given bytes, which are assumed
be encoded in UTF-16 using the platform's byte order.
*/
public static void sqlite3_result_text16(
- @NotNull sqlite3_context cx, @Nullable byte[] text
+ @NotNull sqlite3_context cx, @Nullable byte[] utf16
){
- sqlite3_result_text64(cx, text, text.length, SQLITE_UTF16);
+ sqlite3_result_text64(cx, utf16, utf16.length, SQLITE_UTF16);
}
public static void sqlite3_result_text16(
@NotNull sqlite3 db, long rowid
);
+
+ /**
+ Cleans up all stale per-thread state managed by the library, as
+ well as any registered auto-extensions, then calls the C-native
+ sqlite3_shutdown(). Calling this while database handles or
+ prepared statements are still active will leak resources. Trying
+ to use those objects after this routine is called invoked
+ undefined behavior.
+ */
+ public static synchronized native int sqlite3_shutdown();
+
public static native int sqlite3_sleep(int ms);
public static native String sqlite3_sourceid();
public static native String sqlite3_sql(@NotNull sqlite3_stmt stmt);
+
+ public static native int sqlite3_status(
+ int op, @NotNull OutputPointer.Int32 pCurrent,
+ @NotNull OutputPointer.Int32 pHighwater, boolean reset
+ );
+
+ public static native int sqlite3_status64(
+ int op, @NotNull OutputPointer.Int64 pCurrent,
+ @NotNull OutputPointer.Int64 pHighwater, boolean reset
+ );
+
public static native int sqlite3_step(@NotNull sqlite3_stmt stmt);
/**
-C Correct\sa\sstring\slength\smisuse\sin\sJNI\ssqlite3_result_error()\sin\san\sOOM\scase.\sUnrelated\sminor\sJNI\scleanups.
-D 2023-08-26T19:34:49.574
+C Whether\sor\snot\sOOM\sis\salways\sfatal\sin\sJNI\sis\snow\sa\scompile-time\soption.
+D 2023-08-26T21:02:50.002
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
-F ext/jni/GNUmakefile d9244b5addf58868343a74a94faa71f829e7f40c163486d053f4b4bbea173703
+F ext/jni/GNUmakefile 4e60cdca419ac6783719da98379480b6f04d5d1b5fa1408c46fcb0c32565c571
F ext/jni/README.md 1332b1fa27918bd5d9ca2d0d4f3ac3a6ab86b9e3699dc5bfe32904a027f3d2a9
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
-F ext/jni/src/c/sqlite3-jni.c 14ac371890c91b15eb0f996fe5bcc9f30dde996983845a5e32a147826b81f72d
-F ext/jni/src/c/sqlite3-jni.h 22c6c760a31ebfc3fe13d45d2a3a4dd7c8f9c6207aeba3fdc38137452cbf3a04
-F ext/jni/src/org/sqlite/jni/AggregateFunction.java e0aac6ccae05702f8ee779820570866a2760aaa57a73135c57c8d3580bef52d5
+F ext/jni/src/c/sqlite3-jni.c d6665b309171af316f83a422b0a1c360f760493d9d8cfe239c8f38b639daac47
+F ext/jni/src/c/sqlite3-jni.h a410d05ca47a676b75ff7b8980e75ad604ea15f3c29965f88989703abc2eeaf6
+F ext/jni/src/org/sqlite/jni/AggregateFunction.java 0a5a74bea5ee12a99407e9432d0ca393525af912c2b0ca55c7ee5dbd019c00ef
F ext/jni/src/org/sqlite/jni/AuthorizerCallback.java c374bb76409cce7a0bdba94877706b59ac6127fa5d9e6af3e8058c99ce99c030
F ext/jni/src/org/sqlite/jni/AutoExtensionCallback.java 4290d8b0937b07d466b50e6ca4136cec037f3ce658277af0d0c2d371e5f4b459
F ext/jni/src/org/sqlite/jni/BusyHandlerCallback.java efef1892e404f5780d81c46a7997cab874aff5db5131985dd3af319fc5e3adc7
F ext/jni/src/org/sqlite/jni/RollbackHookCallback.java be7f7a26d1102fb514d835e11198d51302af8053d97188bfb2e34c2133208568
F ext/jni/src/org/sqlite/jni/SQLFunction.java d060f302b2cc4cf7a4f5a6b2d36458a2e6fc9648374b5d09c36a43665af41207
F ext/jni/src/org/sqlite/jni/SQLite3CallbackProxy.java 13c4ea6f35871261eba63fa4117715515e0beecbdebfb879ec5b1f340ed36904
-F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 77a8f965c87af3913839ee12666f6feed6c97fd981c55dadcad8f069aad89c00
+F ext/jni/src/org/sqlite/jni/SQLite3Jni.java d640493f52c04e03f9c0525f16dcec6b718638ace22101c0ccfc014883a15b0b
F ext/jni/src/org/sqlite/jni/ScalarFunction.java 21301a947e49f0dd9c682dfe2cc8a6518226c837253dd791cd512f847eeca52c
F ext/jni/src/org/sqlite/jni/Tester1.java 37b46dc15ac8fbeb916dcf1f7771023d2be025d05422d725d5891935eda506ac
F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P b49488481e2952294960bb0ee971f6eca126c19d68ef92152894aa28393e6865
-R 9cb44f7d9077da136013e6794a7e1baf
+P 4252f56f3d8574b7b43306440726daf3b5f5500d5d9105784b2f82753e7c71dd
+R 73a65c0a564c2b6325f39c30c9023371
U stephan
-Z b123384a6d9af143d63c67db0e5f0b49
+Z c1a9d88eb5b30bcb5f8055b2c7e2b244
# Remove this line to create a well-formed Fossil manifest.
-4252f56f3d8574b7b43306440726daf3b5f5500d5d9105784b2f82753e7c71dd
\ No newline at end of file
+320a34c080d8bc1feae1578697923dfa7c4144b78de36f704c24cc4a4ce9d535
\ No newline at end of file