]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Completely rework how the JNI sqlite3_open(_v2) and sqlite3_prepare(_vN)() bindings...
authorstephan <stephan@noemail.net>
Sun, 6 Aug 2023 21:29:13 +0000 (21:29 +0000)
committerstephan <stephan@noemail.net>
Sun, 6 Aug 2023 21:29:13 +0000 (21:29 +0000)
FossilOrigin-Name: 644999caff9db79562d45520d94aaa24ee88c65e397b6fb9c20a4f0e7f84e1a5

ext/jni/src/c/sqlite3-jni.c
ext/jni/src/c/sqlite3-jni.h
ext/jni/src/org/sqlite/jni/OutputPointer.java
ext/jni/src/org/sqlite/jni/SQLite3Jni.java
ext/jni/src/org/sqlite/jni/Tester1.java
ext/jni/src/org/sqlite/jni/sqlite3.java
ext/jni/src/org/sqlite/jni/sqlite3_value.java
manifest
manifest.uuid

index 6a490404f7cc61aa32668aee63ae80a7c64b6292..87f530d8a05ea52fac98736086211897bc3f04b1 100644 (file)
 /** Helpers for extracting pointers from jobjects, noting that the
     corresponding Java interfaces have already done the type-checking.
  */
-#define PtrGet_sqlite3(OBJ) getNativePointer(env,OBJ,S3ClassNames.sqlite3)
-#define PtrGet_sqlite3_stmt(OBJ) getNativePointer(env,OBJ,S3ClassNames.sqlite3_stmt)
-#define PtrGet_sqlite3_value(OBJ) getNativePointer(env,OBJ,S3ClassNames.sqlite3_value)
-#define PtrGet_sqlite3_context(OBJ) getNativePointer(env,OBJ,S3ClassNames.sqlite3_context)
+#define PtrGet_sqlite3(OBJ) NativePointerHolder_get(env,OBJ,S3ClassNames.sqlite3)
+#define PtrGet_sqlite3_stmt(OBJ) NativePointerHolder_get(env,OBJ,S3ClassNames.sqlite3_stmt)
+#define PtrGet_sqlite3_value(OBJ) NativePointerHolder_get(env,OBJ,S3ClassNames.sqlite3_value)
+#define PtrGet_sqlite3_context(OBJ) NativePointerHolder_get(env,OBJ,S3ClassNames.sqlite3_context)
 /* Helpers for Java value reference management. */
 static inline jobject new_global_ref(JNIEnv *env, jobject v){
   return v ? (*env)->NewGlobalRef(env, v) : NULL;
@@ -215,6 +215,8 @@ static const struct {
   const char * const OutputPointer_Int64;
   const char * const OutputPointer_String;
   const char * const OutputPointer_ByteArray;
+  const char * const OutputPointer_sqlite3;
+  const char * const OutputPointer_sqlite3_stmt;
 #ifdef SQLITE_ENABLE_FTS5
   const char * const Fts5Context;
   const char * const Fts5ExtensionApi;
@@ -231,6 +233,8 @@ static const struct {
   "org/sqlite/jni/OutputPointer$Int64",
   "org/sqlite/jni/OutputPointer$String",
   "org/sqlite/jni/OutputPointer$ByteArray",
+  "org/sqlite/jni/OutputPointer$sqlite3",
+  "org/sqlite/jni/OutputPointer$sqlite3_stmt",
 #ifdef SQLITE_ENABLE_FTS5
   "org/sqlite/jni/Fts5Context",
   "org/sqlite/jni/Fts5ExtensionApi",
@@ -296,7 +300,7 @@ static const struct {
 #define JSTR_TOC(ARG) (*env)->GetStringUTFChars(env, ARG, NULL)
 #define JSTR_RELEASE(ARG,VAR) if(VAR) (*env)->ReleaseStringUTFChars(env, ARG, VAR)
 #define JBA_TOC(ARG) (*env)->GetByteArrayElements(env,ARG, NULL)
-#define JBA_RELEASE(ARG,VAR) if(ARG) (*env)->ReleaseByteArrayElements(env, ARG, VAR, JNI_ABORT)
+#define JBA_RELEASE(ARG,VAR) if(VAR) (*env)->ReleaseByteArrayElements(env, ARG, VAR, JNI_ABORT)
 
 /* Marker for code which needs(?) to be made thread-safe. */
 #define FIXME_THREADING
@@ -948,7 +952,11 @@ static struct NphCacheLine * S3Global_nph_cache(JNIEnv * const env, const char *
   return freeSlot;
 }
 
-static jfieldID getNativePointerField(JNIEnv * const env, jclass klazz){
+/**
+   Returns the ID of the "nativePointer" field from the given
+   NativePointerHolder<T> class.
+ */
+static jfieldID NativePointerHolder_getField(JNIEnv * const env, jclass klazz){
   jfieldID rv = (*env)->GetFieldID(env, klazz, "nativePointer", "J");
   EXCEPTION_IS_FATAL("Code maintenance required: missing nativePointer field.");
   return rv;
@@ -959,7 +967,7 @@ static jfieldID getNativePointerField(JNIEnv * const env, jclass klazz){
    zClassName must be a static string so we can use its address
    as a cache key.
 */
-static void setNativePointer(JNIEnv * env, jobject ppOut, const void * p,
+static void NativePointerHolder_set(JNIEnv * env, jobject ppOut, const void * p,
                              const char *zClassName){
   jfieldID setter = 0;
   struct NphCacheLine * const cacheLine = S3Global_nph_cache(env, zClassName);
@@ -970,7 +978,7 @@ static void setNativePointer(JNIEnv * env, jobject ppOut, const void * p,
   }else{
     jclass const klazz =
       cacheLine ? cacheLine->klazz : (*env)->GetObjectClass(env, ppOut);
-    setter = getNativePointerField(env, klazz);
+    setter = NativePointerHolder_getField(env, klazz);
     if(cacheLine){
       assert(cacheLine->klazz);
       assert(!cacheLine->fidValue);
@@ -987,9 +995,8 @@ static void setNativePointer(JNIEnv * env, jobject ppOut, const void * p,
    zClassName must be a static string so we can use its address as a
    cache key.
 */
-static void * getNativePointer(JNIEnv * env, jobject pObj, const char *zClassName){
-  if( 0==pObj ) return 0;
-  else{
+static void * NativePointerHolder_get(JNIEnv * env, jobject pObj, const char *zClassName){
+  if( pObj ){
     jfieldID getter = 0;
     void * rv = 0;
     struct NphCacheLine * const cacheLine = S3Global_nph_cache(env, zClassName);
@@ -998,7 +1005,7 @@ static void * getNativePointer(JNIEnv * env, jobject pObj, const char *zClassNam
     }else{
       jclass const klazz =
         cacheLine ? cacheLine->klazz : (*env)->GetObjectClass(env, pObj);
-      getter = getNativePointerField(env, klazz);
+      getter = NativePointerHolder_getField(env, klazz);
       if(cacheLine){
         assert(cacheLine->klazz);
         assert(zClassName == cacheLine->zClassName);
@@ -1008,6 +1015,8 @@ static void * getNativePointer(JNIEnv * env, jobject pObj, const char *zClassNam
     rv = (void*)(*env)->GetLongField(env, pObj, getter);
     IFTHREW_REPORT;
     return rv;
+  }else{
+    return 0;
   }
 }
 
@@ -1015,7 +1024,7 @@ static void * getNativePointer(JNIEnv * env, jobject pObj, const char *zClassNam
    Extracts the new PerDbStateJni instance from the free-list, or
    allocates one if needed, associats it with pDb, and returns.
    Returns NULL on OOM. pDb MUST be associated with jDb via
-   setNativePointer().
+   NativePointerHolder_set().
 */
 static PerDbStateJni * PerDbStateJni_alloc(JNIEnv * const env, sqlite3 *pDb, jobject jDb){
   PerDbStateJni * rv;
@@ -1179,7 +1188,7 @@ static int udf_setAggregateContext(JNIEnv * env, jobject jCx,
 }
 
 /**
-   Common init for setOutputInt32() and friends. zClassName must be a
+   Common init for OutputPointer_set_Int32() and friends. zClassName must be a
    pointer from S3ClassNames. jOut must be an instance of that
    class. Fetches the jfieldID for jOut's [value] property, which must
    be of the type represented by the JNI type signature zTypeSig, and
@@ -1213,17 +1222,35 @@ static void setupOutputPointer(JNIEnv * const env, const char *zClassName,
 
 /* Sets the value property of the OutputPointer.Int32 jOut object
    to v. */
-static void setOutputInt32(JNIEnv * const env, jobject const jOut, int v){
+static void OutputPointer_set_Int32(JNIEnv * const env, jobject const jOut, int v){
   jfieldID setter = 0;
   setupOutputPointer(env, S3ClassNames.OutputPointer_Int32, "I", jOut, &setter);
   (*env)->SetIntField(env, jOut, setter, (jint)v);
   EXCEPTION_IS_FATAL("Cannot set OutputPointer.Int32.value");
 }
 
+static void OutputPointer_set_sqlite3(JNIEnv * const env, jobject const jOut,
+                              jobject jDb){
+  jfieldID setter = 0;
+  setupOutputPointer(env, S3ClassNames.OutputPointer_sqlite3,
+                     "Lorg/sqlite/jni/sqlite3;", jOut, &setter);
+  (*env)->SetObjectField(env, jOut, setter, jDb);
+  EXCEPTION_IS_FATAL("Cannot set OutputPointer.sqlite3.value");
+}
+
+static void OutputPointer_set_sqlite3_stmt(JNIEnv * const env, jobject const jOut,
+                                   jobject jStmt){
+  jfieldID setter = 0;
+  setupOutputPointer(env, S3ClassNames.OutputPointer_sqlite3_stmt,
+                     "Lorg/sqlite/jni/sqlite3_stmt;", jOut, &setter);
+  (*env)->SetObjectField(env, jOut, setter, jStmt);
+  EXCEPTION_IS_FATAL("Cannot set OutputPointer.sqlite3_stmt.value");
+}
+
 #ifdef SQLITE_ENABLE_FTS5
 /* Sets the value property of the OutputPointer.Int64 jOut object
    to v. */
-static void setOutputInt64(JNIEnv * const env, jobject const jOut, jlong v){
+static void OutputPointer_set_Int64(JNIEnv * const env, jobject const jOut, jlong v){
   jfieldID setter = 0;
   setupOutputPointer(env, S3ClassNames.OutputPointer_Int64, "J", jOut, &setter);
   (*env)->SetLongField(env, jOut, setter, v);
@@ -1232,7 +1259,7 @@ static void setOutputInt64(JNIEnv * const env, jobject const jOut, jlong v){
 #if 0
 /* Sets the value property of the OutputPointer.ByteArray jOut object
    to v. */
-static void setOutputByteArray(JNIEnv * const env, jobject const jOut,
+static void OutputPointer_set_ByteArray(JNIEnv * const env, jobject const jOut,
                                jbyteArray const v){
   jfieldID setter = 0;
   setupOutputPointer(env, S3ClassNames.OutputPointer_ByteArray, "[B",
@@ -1243,7 +1270,7 @@ static void setOutputByteArray(JNIEnv * const env, jobject const jOut,
 #endif
 /* Sets the value property of the OutputPointer.String jOut object
    to v. */
-static void setOutputString(JNIEnv * const env, jobject const jOut,
+static void OutputPointer_set_String(JNIEnv * const env, jobject const jOut,
                             jstring const v){
   jfieldID setter = 0;
   setupOutputPointer(env, S3ClassNames.OutputPointer_String,
@@ -1367,7 +1394,7 @@ static void ResultJavaVal_finalizer(void *v){
 /**
    Returns a new Java instance of the class named by zClassName, which
    MUST be interface-compatible with NativePointerHolder and MUST have
-   a no-arg constructor. Its setNativePointer() method is passed
+   a no-arg constructor. Its NativePointerHolder_set() method is passed
    pNative. Hypothetically returns NULL if Java fails to allocate, but
    the JNI docs are not entirely clear on that detail.
 
@@ -1402,21 +1429,22 @@ static jobject new_NativePointerHolder_object(JNIEnv * const env, const char *zC
   assert(ctor);
   rv = (*env)->NewObject(env, klazz, ctor);
   EXCEPTION_IS_FATAL("No-arg constructor threw.");
-  if(rv) setNativePointer(env, rv, pNative, zClassName);
+  if(rv) NativePointerHolder_set(env, rv, pNative, zClassName);
   return rv;
 }
 
-static inline jobject new_sqlite3_value_wrapper(JNIEnv * const env, sqlite3_value *sv){
-  return new_NativePointerHolder_object(env, S3ClassNames.sqlite3_value, sv);
+static inline jobject new_sqlite3_wrapper(JNIEnv * const env, sqlite3 *sv){
+  return new_NativePointerHolder_object(env, S3ClassNames.sqlite3, sv);
 }
-
 static inline jobject new_sqlite3_context_wrapper(JNIEnv * const env, sqlite3_context *sv){
   return new_NativePointerHolder_object(env, S3ClassNames.sqlite3_context, sv);
 }
-
 static inline jobject new_sqlite3_stmt_wrapper(JNIEnv * const env, sqlite3_stmt *sv){
   return new_NativePointerHolder_object(env, S3ClassNames.sqlite3_stmt, sv);
 }
+static inline jobject new_sqlite3_value_wrapper(JNIEnv * const env, sqlite3_value *sv){
+  return new_NativePointerHolder_object(env, S3ClassNames.sqlite3_value, sv);
+}
 
 enum UDFType {
   UDF_SCALAR = 1,
@@ -1690,9 +1718,6 @@ 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;
@@ -1872,7 +1897,7 @@ static jint s3jni_close_db(JNIEnv * const env, jobject jDb, int version){
   rc = 1==version ? (jint)sqlite3_close(ps->pDb) : (jint)sqlite3_close_v2(ps->pDb);
   if(ps) PerDbStateJni_set_aside(ps)
            /* MUST come after close() because of ps->trace. */;
-  setNativePointer(env, jDb, 0, S3ClassNames.sqlite3);
+  NativePointerHolder_set(env, jDb, 0, S3ClassNames.sqlite3);
   return (jint)rc;
 }
 
@@ -2177,7 +2202,7 @@ JDECL(jint,1db_1config__Lorg_sqlite_jni_sqlite3_2ILorg_sqlite_jni_OutputPointer_
       int pOut = 0;
       rc = sqlite3_db_config( ps->pDb, (int)op, &pOut );
       if( 0==rc && jOut ){
-        setOutputInt32(env, jOut, pOut);
+        OutputPointer_set_Int32(env, jOut, pOut);
       }
       break;
     }
@@ -2346,7 +2371,7 @@ JDECL(jint,1finalize)(JENV_CSELF, jobject jpStmt){
     JNIEnvCache * const jc = S3Global_env_cache(env);
     jobject const pPrev = stmt_set_current(jc, jpStmt);
     rc = sqlite3_finalize(pStmt);
-    setNativePointer(env, jpStmt, 0, S3ClassNames.sqlite3_stmt);
+    NativePointerHolder_set(env, jpStmt, 0, S3ClassNames.sqlite3_stmt);
     (void)stmt_set_current(jc, pPrev);
   }
   return rc;
@@ -2367,16 +2392,19 @@ JDECL(jlong,1last_1insert_1rowid)(JENV_CSELF, jobject jpDb){
    is returned, else theRc is returned. In in case, *ppDb is stored in
    jDb's native pointer property (even if it's NULL).
 */
-static int s3jni_open_post(JNIEnv * const env, sqlite3 **ppDb, jobject jDb, int theRc){
+static int s3jni_open_post(JNIEnv * const env, sqlite3 **ppDb, jobject jOut, int theRc){
+  jobject jDb = 0;
   if(*ppDb){
-    PerDbStateJni * const s = PerDbStateJni_for_db(env, jDb, *ppDb, 1);
+    jDb = new_sqlite3_wrapper(env, *ppDb);
+    PerDbStateJni * const s = jDb ? PerDbStateJni_for_db(env, jDb, *ppDb, 1) : 0;
     if(!s && 0==theRc){
+      UNREF_L(jDb);
       sqlite3_close(*ppDb);
       *ppDb = 0;
       theRc = SQLITE_NOMEM;
     }
   }
-  setNativePointer(env, jDb, *ppDb, S3ClassNames.sqlite3);
+  OutputPointer_set_sqlite3(env, jOut, jDb);
   return theRc;
 }
 
@@ -2408,53 +2436,72 @@ JDECL(jint,1open_1v2)(JENV_CSELF, jstring strName,
 
 /* Proxy for the sqlite3_prepare[_v2/3]() family. */
 static jint sqlite3_jni_prepare_v123(int prepVersion, JNIEnv * const env, jclass self,
-                                     jobject jpDb, jbyteArray baSql,
+                                     jobject jDb, jbyteArray baSql,
                                      jint nMax, jint prepFlags,
                                      jobject jOutStmt, jobject outTail){
   sqlite3_stmt * pStmt = 0;
+  jobject jStmt = 0;
   const char * zTail = 0;
   jbyte * const pBuf = JBA_TOC(baSql);
   JNIEnvCache * const jc = S3Global_env_cache(env);
-  jobject const pOldStmt = stmt_set_current(jc, jOutStmt);
+  jobject const pOldStmt = stmt_set_current(jc, 0);
   int rc = SQLITE_ERROR;
   assert(prepVersion==1 || prepVersion==2 || prepVersion==3);
+  if( !pBuf ){
+     rc = baSql ? SQLITE_MISUSE : SQLITE_NOMEM;
+     goto end;
+  }
+  jStmt = new_sqlite3_stmt_wrapper(env, 0);
+  if( !jStmt ){
+    rc = SQLITE_NOMEM;
+    goto end;
+  }
   switch( prepVersion ){
-    case 1: rc = sqlite3_prepare(PtrGet_sqlite3(jpDb), (const char *)pBuf,
+    case 1: rc = sqlite3_prepare(PtrGet_sqlite3(jDb), (const char *)pBuf,
                                  (int)nMax, &pStmt, &zTail);
       break;
-    case 2: rc = sqlite3_prepare_v2(PtrGet_sqlite3(jpDb), (const char *)pBuf,
+    case 2: rc = sqlite3_prepare_v2(PtrGet_sqlite3(jDb), (const char *)pBuf,
                                     (int)nMax, &pStmt, &zTail);
       break;
-    case 3: rc = sqlite3_prepare_v3(PtrGet_sqlite3(jpDb), (const char *)pBuf,
+    case 3: rc = sqlite3_prepare_v3(PtrGet_sqlite3(jDb), (const char *)pBuf,
                                     (int)nMax, (unsigned int)prepFlags,
                                     &pStmt, &zTail);
       break;
     default:
       assert(0 && "Invalid prepare() version");
   }
+end:
   JBA_RELEASE(baSql,pBuf);
-  if( 0!=outTail ){
-    assert(zTail ? ((void*)zTail>=(void*)pBuf) : 1);
-    assert(zTail ? (((int)((void*)zTail - (void*)pBuf)) >= 0) : 1);
-    setOutputInt32(env, outTail, (int)(zTail ? (zTail - (const char *)pBuf) : 0));
+  if( 0==rc ){
+    if( 0!=outTail ){
+      /* Noting that pBuf is deallocated now but its address is all we need. */
+      assert(zTail ? ((void*)zTail>=(void*)pBuf) : 1);
+      assert(zTail ? (((int)((void*)zTail - (void*)pBuf)) >= 0) : 1);
+      OutputPointer_set_Int32(env, outTail, (int)(zTail ? (zTail - (const char *)pBuf) : 0));
+    }
+    NativePointerHolder_set(env, jStmt, pStmt, S3ClassNames.sqlite3_stmt);
+  }else{
+    UNREF_L(jStmt);
+    jStmt = 0;
   }
-  setNativePointer(env, jOutStmt, pStmt, S3ClassNames.sqlite3_stmt);
+  OutputPointer_set_sqlite3_stmt(env, jOutStmt, jStmt);
+  //NativePointerHolder_set(env, jOutStmt, pStmt, S3ClassNames.sqlite3_stmt);
   (void)stmt_set_current(jc, pOldStmt);
   return (jint)rc;
 }
-JDECL(jint,1prepare)(JNIEnv * const env, jclass self, jobject jpDb, jbyteArray baSql,
+JDECL(jint,1prepare)(JNIEnv * const env, jclass self, jobject jDb, jbyteArray baSql,
                      jint nMax, jobject jOutStmt, jobject outTail){
-  return sqlite3_jni_prepare_v123(1, env, self, jpDb, baSql, nMax, 0,
+  return sqlite3_jni_prepare_v123(1, env, self, jDb, baSql, nMax, 0,
                                   jOutStmt, outTail);
 }
-JDECL(jint,1prepare_1v2)(JNIEnv * const env, jclass self, jobject jpDb, jbyteArray baSql,
+JDECL(jint,1prepare_1v2)(JNIEnv * const env, jclass self, jobject jDb, jbyteArray baSql,
                          jint nMax, jobject jOutStmt, jobject outTail){
-  return sqlite3_jni_prepare_v123(2, env, self, jpDb, baSql, nMax, 0,
+  return sqlite3_jni_prepare_v123(2, env, self, jDb, baSql, nMax, 0,
                                   jOutStmt, outTail);
 }
-JDECL(jint,1prepare_1v3)(JNIEnv * const env, jclass self, jobject jpDb, jbyteArray baSql,
+JDECL(jint,1prepare_1v3)(JNIEnv * const env, jclass self, jobject jDb, jbyteArray baSql,
                          jint nMax, jint prepFlags, jobject jOutStmt, jobject outTail){
-  return sqlite3_jni_prepare_v123(3, env, self, jpDb, baSql, nMax,
+  return sqlite3_jni_prepare_v123(3, env, self, jDb, baSql, nMax,
                                   prepFlags, jOutStmt, outTail);
 }
 
@@ -2797,6 +2844,7 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
     case SQLITE_TRACE_STMT:
       jX = s3jni_utf8_to_jstring(jc, (const char *)pX, -1);
       if(!jX) return SQLITE_NOMEM;
+      /*MARKER(("TRACE_STMT@%p SQL=%p / %s\n", pP, jX, (const char *)pX));*/
       jP = jc->currentStmt;
       break;
     case SQLITE_TRACE_PROFILE:
@@ -2806,15 +2854,13 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
       // MARKER(("profile time = %llu\n", *((sqlite3_int64*)pX)));
       jP = jc->currentStmt;
       if(!jP){
+        // This will be the case during prepare() b/c we don't have the
+        // pointer in time to wrap it before tracing is triggered.
         jP = jPUnref = new_sqlite3_stmt_wrapper(env, pP);
         if(!jP){
           UNREF_L(jX);
           return SQLITE_NOMEM;
         }
-        MARKER(("WARNING: created new sqlite3_stmt wrapper for TRACE_PROFILE. stmt@%p\n"
-                "This means we have missed a route into the tracing API and it "
-                "needs the stmt_set_current() treatment which is littered around "
-                "a handful of other functions in this file.\n", pP));
       }
       break;
     case SQLITE_TRACE_ROW:
@@ -3092,10 +3138,10 @@ JDECL(void,1do_1something_1for_1developer)(JENV_CSELF){
   JNIEXPORT ReturnType JNICALL                  \
   JFuncNameFtsTok(Suffix)
 
-#define PtrGet_fts5_api(OBJ) getNativePointer(env,OBJ,S3ClassNames.fts5_api)
-#define PtrGet_fts5_tokenizer(OBJ) getNativePointer(env,OBJ,S3ClassNames.fts5_tokenizer)
-#define PtrGet_Fts5Context(OBJ) getNativePointer(env,OBJ,S3ClassNames.Fts5Context)
-#define PtrGet_Fts5Tokenizer(OBJ) getNativePointer(env,OBJ,S3ClassNames.Fts5Tokenizer)
+#define PtrGet_fts5_api(OBJ) NativePointerHolder_get(env,OBJ,S3ClassNames.fts5_api)
+#define PtrGet_fts5_tokenizer(OBJ) NativePointerHolder_get(env,OBJ,S3ClassNames.fts5_tokenizer)
+#define PtrGet_Fts5Context(OBJ) NativePointerHolder_get(env,OBJ,S3ClassNames.Fts5Context)
+#define PtrGet_Fts5Tokenizer(OBJ) NativePointerHolder_get(env,OBJ,S3ClassNames.Fts5Tokenizer)
 #define Fts5ExtDecl Fts5ExtensionApi const * const fext = s3jni_ftsext()
 
 /**
@@ -3226,7 +3272,7 @@ JDECLFtsXA(jint,xColumnSize)(JENV_OSELF,jobject jCtx, jint iIdx, jobject jOut32)
   Fts5ExtDecl;
   int n1 = 0;
   int const rc = fext->xColumnSize(PtrGet_Fts5Context(jCtx), (int)iIdx, &n1);
-  if( 0==rc ) setOutputInt32(env, jOut32, n1);
+  if( 0==rc ) OutputPointer_set_Int32(env, jOut32, n1);
   return rc;
 }
 
@@ -3242,7 +3288,7 @@ JDECLFtsXA(jint,xColumnText)(JENV_OSELF,jobject jCtx, jint iCol,
     jstring jstr = pz ? s3jni_utf8_to_jstring(jc, pz, pn) : 0;
     if( pz ){
       if( jstr ){
-        setOutputString(env, jOut, jstr);
+        OutputPointer_set_String(env, jOut, jstr);
         UNREF_L(jstr)/*jOut has a reference*/;
       }else{
         rc = SQLITE_NOMEM;
@@ -3256,7 +3302,7 @@ JDECLFtsXA(jint,xColumnTotalSize)(JENV_OSELF,jobject jCtx, jint iCol, jobject jO
   Fts5ExtDecl;
   sqlite3_int64 nOut = 0;
   int const rc = fext->xColumnTotalSize(PtrGet_Fts5Context(jCtx), (int)iCol, &nOut);
-  if( 0==rc && jOut64 ) setOutputInt64(env, jOut64, (jlong)nOut);
+  if( 0==rc && jOut64 ) OutputPointer_set_Int64(env, jOut64, (jlong)nOut);
   return (jint)rc;
 }
 
@@ -3372,9 +3418,9 @@ JDECLFtsXA(jint,xInst)(JENV_OSELF,jobject jCtx, jint iIdx, jobject jOutPhrase,
   int n1 = 0, n2 = 2, n3 = 0;
   int const rc = fext->xInst(PtrGet_Fts5Context(jCtx), (int)iIdx, &n1, &n2, &n3);
   if( 0==rc ){
-    setOutputInt32(env, jOutPhrase, n1);
-    setOutputInt32(env, jOutCol, n2);
-    setOutputInt32(env, jOutOff, n3);
+    OutputPointer_set_Int32(env, jOutPhrase, n1);
+    OutputPointer_set_Int32(env, jOutCol, n2);
+    OutputPointer_set_Int32(env, jOutOff, n3);
   }
   return rc;
 }
@@ -3383,7 +3429,7 @@ JDECLFtsXA(jint,xInstCount)(JENV_OSELF,jobject jCtx, jobject jOut32){
   Fts5ExtDecl;
   int nOut = 0;
   int const rc = fext->xInstCount(PtrGet_Fts5Context(jCtx), &nOut);
-  if( 0==rc && jOut32 ) setOutputInt32(env, jOut32, nOut);
+  if( 0==rc && jOut32 ) OutputPointer_set_Int32(env, jOut32, nOut);
   return (jint)rc;
 }
 
@@ -3442,8 +3488,8 @@ JDECLFtsXA(jint,xPhraseFirst)(JENV_OSELF,jobject jCtx, jint iPhrase,
   rc = fext->xPhraseFirst(PtrGet_Fts5Context(jCtx), (int)iPhrase,
                          &iter, &iCol, &iOff);
   if( 0==rc ){
-    setOutputInt32(env, jOutCol, iCol);
-    setOutputInt32(env, jOutOff, iOff);
+    OutputPointer_set_Int32(env, jOutCol, iCol);
+    OutputPointer_set_Int32(env, jOutOff, iOff);
     s3jni_phraseIter_NToJ(env, jc, &iter, jIter);
   }
   return rc;
@@ -3459,7 +3505,7 @@ JDECLFtsXA(jint,xPhraseFirstColumn)(JENV_OSELF,jobject jCtx, jint iPhrase,
   rc = fext->xPhraseFirstColumn(PtrGet_Fts5Context(jCtx), (int)iPhrase,
                                 &iter, &iCol);
   if( 0==rc ){
-    setOutputInt32(env, jOutCol, iCol);
+    OutputPointer_set_Int32(env, jOutCol, iCol);
     s3jni_phraseIter_NToJ(env, jc, &iter, jIter);
   }
   return rc;
@@ -3475,8 +3521,8 @@ JDECLFtsXA(void,xPhraseNext)(JENV_OSELF,jobject jCtx, jobject jIter,
   s3jni_phraseIter_JToN(env, jc, jIter, &iter);
   fext->xPhraseNext(PtrGet_Fts5Context(jCtx),
                          &iter, &iCol, &iOff);
-  setOutputInt32(env, jOutCol, iCol);
-  setOutputInt32(env, jOutOff, iOff);
+  OutputPointer_set_Int32(env, jOutCol, iCol);
+  OutputPointer_set_Int32(env, jOutOff, iOff);
   s3jni_phraseIter_NToJ(env, jc, &iter, jIter);
 }
 
@@ -3489,7 +3535,7 @@ JDECLFtsXA(void,xPhraseNextColumn)(JENV_OSELF,jobject jCtx, jobject jIter,
   if(!jc->jPhraseIter.klazz) return /*SQLITE_MISUSE*/;
   s3jni_phraseIter_JToN(env, jc, jIter, &iter);
   fext->xPhraseNextColumn(PtrGet_Fts5Context(jCtx), &iter, &iCol);
-  setOutputInt32(env, jOutCol, iCol);
+  OutputPointer_set_Int32(env, jOutCol, iCol);
   s3jni_phraseIter_NToJ(env, jc, &iter, jIter);
 }
 
@@ -3562,7 +3608,7 @@ JDECLFtsXA(jint,xRowCount)(JENV_OSELF,jobject jCtx, jobject jOut64){
   Fts5ExtDecl;
   sqlite3_int64 nOut = 0;
   int const rc = fext->xRowCount(PtrGet_Fts5Context(jCtx), &nOut);
-  if( 0==rc && jOut64 ) setOutputInt64(env, jOut64, (jlong)nOut);
+  if( 0==rc && jOut64 ) OutputPointer_set_Int64(env, jOut64, (jlong)nOut);
   return (jint)rc;
 }
 
index edb75ae04e766dcbdcc9f8e72e3122ea2dddbd01..287df65558b4b1967a331fb3a06946b0a2276844 100644 (file)
@@ -1104,7 +1104,7 @@ JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1db_1filename
  * 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_00024Int32_2
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1db_1config__Lorg_sqlite_jni_sqlite3_2ILorg_sqlite_jni_OutputPointer_Int32_2
   (JNIEnv *, jclass, jobject, jint, jobject);
 
 /*
@@ -1206,7 +1206,7 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1libversion_1numbe
 /*
  * Class:     org_sqlite_jni_SQLite3Jni
  * Method:    sqlite3_open
- * Signature: (Ljava/lang/String;Lorg/sqlite/jni/sqlite3;)I
+ * Signature: (Ljava/lang/String;Lorg/sqlite/jni/OutputPointer/sqlite3;)I
  */
 JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1open
   (JNIEnv *, jclass, jstring, jobject);
@@ -1214,7 +1214,7 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1open
 /*
  * Class:     org_sqlite_jni_SQLite3Jni
  * Method:    sqlite3_open_v2
- * Signature: (Ljava/lang/String;Lorg/sqlite/jni/sqlite3;ILjava/lang/String;)I
+ * Signature: (Ljava/lang/String;Lorg/sqlite/jni/OutputPointer/sqlite3;ILjava/lang/String;)I
  */
 JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1open_1v2
   (JNIEnv *, jclass, jstring, jobject, jint, jstring);
@@ -1222,7 +1222,7 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1open_1v2
 /*
  * Class:     org_sqlite_jni_SQLite3Jni
  * Method:    sqlite3_prepare
- * Signature: (Lorg/sqlite/jni/sqlite3;[BILorg/sqlite/jni/sqlite3_stmt;Lorg/sqlite/jni/OutputPointer/Int32;)I
+ * Signature: (Lorg/sqlite/jni/sqlite3;[BILorg/sqlite/jni/OutputPointer/sqlite3_stmt;Lorg/sqlite/jni/OutputPointer/Int32;)I
  */
 JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1prepare
   (JNIEnv *, jclass, jobject, jbyteArray, jint, jobject, jobject);
@@ -1230,7 +1230,7 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1prepare
 /*
  * Class:     org_sqlite_jni_SQLite3Jni
  * Method:    sqlite3_prepare_v2
- * Signature: (Lorg/sqlite/jni/sqlite3;[BILorg/sqlite/jni/sqlite3_stmt;Lorg/sqlite/jni/OutputPointer/Int32;)I
+ * Signature: (Lorg/sqlite/jni/sqlite3;[BILorg/sqlite/jni/OutputPointer/sqlite3_stmt;Lorg/sqlite/jni/OutputPointer/Int32;)I
  */
 JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1prepare_1v2
   (JNIEnv *, jclass, jobject, jbyteArray, jint, jobject, jobject);
@@ -1238,7 +1238,7 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1prepare_1v2
 /*
  * Class:     org_sqlite_jni_SQLite3Jni
  * Method:    sqlite3_prepare_v3
- * Signature: (Lorg/sqlite/jni/sqlite3;[BIILorg/sqlite/jni/sqlite3_stmt;Lorg/sqlite/jni/OutputPointer/Int32;)I
+ * Signature: (Lorg/sqlite/jni/sqlite3;[BIILorg/sqlite/jni/OutputPointer/sqlite3_stmt;Lorg/sqlite/jni/OutputPointer/Int32;)I
  */
 JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1prepare_1v3
   (JNIEnv *, jclass, jobject, jbyteArray, jint, jint, jobject, jobject);
index c4fbcb116e6f0c29dfe18ca1780f35497d8193de..065e1332023232f3bc5ba54c13cd0dec21569975 100644 (file)
@@ -22,6 +22,20 @@ package org.sqlite.jni;
    autoboxing at that level.
 */
 public final class OutputPointer {
+  public static final class sqlite3 {
+    private org.sqlite.jni.sqlite3 value;
+    public sqlite3(){value = null;}
+    public void clear(){value = null;}
+    public final org.sqlite.jni.sqlite3 getValue(){return value;}
+  }
+
+  public static final class sqlite3_stmt {
+    private org.sqlite.jni.sqlite3_stmt value;
+    public sqlite3_stmt(){value = null;}
+    public void clear(){value = null;}
+    public final org.sqlite.jni.sqlite3_stmt getValue(){return value;}
+  }
+
   public static final class Int32 {
     private int value;
     public Int32(){this(0);}
index d8f67cd1f9c022c112ea6a41576b5acd9212cce5..68bd4e246af7257f2a596902ccd1dca14568733d 100644 (file)
@@ -476,10 +476,10 @@ public final class SQLite3Jni {
      pass to, e.g., the sqlite3_collation_needed() callback.
   */
   public static native int sqlite3_open(@Nullable String filename,
-                                        @NotNull sqlite3 ppDb);
+                                        @NotNull OutputPointer.sqlite3 ppDb);
 
   public static native int sqlite3_open_v2(@Nullable String filename,
-                                           @NotNull sqlite3 ppDb,
+                                           @NotNull OutputPointer.sqlite3 ppDb,
                                            int flags, @Nullable String zVfs);
 
   /**
@@ -503,24 +503,24 @@ public final class SQLite3Jni {
   */
   private static native int sqlite3_prepare(@NotNull sqlite3 db,
                                             @NotNull byte[] sqlUtf8, int maxBytes,
-                                            @NotNull sqlite3_stmt outStmt,
+                                            @NotNull OutputPointer.sqlite3_stmt outStmt,
                                             @Nullable OutputPointer.Int32 pTailOffset);
 
   public static int sqlite3_prepare(@NotNull sqlite3 db,
                                     @NotNull byte[] sqlUtf8,
-                                    @NotNull sqlite3_stmt outStmt,
+                                    @NotNull OutputPointer.sqlite3_stmt outStmt,
                                     @Nullable OutputPointer.Int32 pTailOffset){
     return sqlite3_prepare(db, sqlUtf8, sqlUtf8.length, outStmt, pTailOffset);
   }
 
   public static int sqlite3_prepare(@NotNull sqlite3 db,
                                     @NotNull byte[] sqlUtf8,
-                                    @NotNull sqlite3_stmt outStmt){
+                                    @NotNull OutputPointer.sqlite3_stmt outStmt){
     return sqlite3_prepare(db, sqlUtf8, sqlUtf8.length, outStmt, null);
   }
 
   public static int sqlite3_prepare(@NotNull sqlite3 db, @NotNull String sql,
-                                    @NotNull sqlite3_stmt outStmt){
+                                    @NotNull OutputPointer.sqlite3_stmt outStmt){
     final byte[] utf8 = sql.getBytes(StandardCharsets.UTF_8);
     return sqlite3_prepare(db, utf8, utf8.length, outStmt, null);
   }
@@ -528,24 +528,24 @@ public final class SQLite3Jni {
   private static native int sqlite3_prepare_v2(@NotNull sqlite3 db,
                                                @NotNull byte[] sqlUtf8,
                                                int maxBytes,
-                                               @NotNull sqlite3_stmt outStmt,
+                                               @NotNull OutputPointer.sqlite3_stmt outStmt,
                                                @Nullable OutputPointer.Int32 pTailOffset);
 
   public static int sqlite3_prepare_v2(@NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
-                                       @NotNull sqlite3_stmt outStmt,
+                                       @NotNull OutputPointer.sqlite3_stmt outStmt,
                                        @Nullable OutputPointer.Int32 pTailOffset){
     return sqlite3_prepare_v2(db, sqlUtf8, sqlUtf8.length, outStmt, pTailOffset);
   }
 
   public static int sqlite3_prepare_v2(@NotNull sqlite3 db,
                                        @NotNull byte[] sqlUtf8,
-                                       @NotNull sqlite3_stmt outStmt){
+                                       @NotNull OutputPointer.sqlite3_stmt outStmt){
     return sqlite3_prepare_v2(db, sqlUtf8, sqlUtf8.length, outStmt, null);
   }
 
   public static int sqlite3_prepare_v2(@NotNull sqlite3 db,
                                        @NotNull String sql,
-                                       @NotNull sqlite3_stmt outStmt){
+                                       @NotNull OutputPointer.sqlite3_stmt outStmt){
     final byte[] utf8 = sql.getBytes(StandardCharsets.UTF_8);
     return sqlite3_prepare_v2(db, utf8, utf8.length, outStmt, null);
   }
@@ -553,12 +553,12 @@ public final class SQLite3Jni {
   private static native int sqlite3_prepare_v3(@NotNull sqlite3 db,
                                                @NotNull byte[] sqlUtf8,
                                                int maxBytes, int prepFlags,
-                                               @NotNull sqlite3_stmt outStmt,
+                                               @NotNull OutputPointer.sqlite3_stmt outStmt,
                                                @Nullable OutputPointer.Int32 pTailOffset);
 
   public static int sqlite3_prepare_v3(@NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
                                        int prepFlags,
-                                       @NotNull sqlite3_stmt outStmt,
+                                       @NotNull OutputPointer.sqlite3_stmt outStmt,
                                        @Nullable OutputPointer.Int32 pTailOffset){
     return sqlite3_prepare_v3(db, sqlUtf8, sqlUtf8.length, prepFlags, outStmt, pTailOffset);
   }
@@ -566,12 +566,13 @@ public final class SQLite3Jni {
   public static int sqlite3_prepare_v3(@NotNull sqlite3 db,
                                        @NotNull byte[] sqlUtf8,
                                        int prepFlags,
-                                       @NotNull sqlite3_stmt outStmt){
+                                       @NotNull OutputPointer.sqlite3_stmt outStmt){
     return sqlite3_prepare_v3(db, sqlUtf8, sqlUtf8.length, prepFlags, outStmt, null);
   }
 
   public static int sqlite3_prepare_v3(@NotNull sqlite3 db, @NotNull String sql,
-                                       int prepFlags, @NotNull sqlite3_stmt outStmt){
+                                       int prepFlags,
+                                       @NotNull OutputPointer.sqlite3_stmt outStmt){
     final byte[] utf8 = sql.getBytes(StandardCharsets.UTF_8);
     return sqlite3_prepare_v3(db, utf8, utf8.length, prepFlags, outStmt, null);
   }
index d25d8791737126020f23dd9d681aa6ece11a16f7..e96038d4d8641817c67244972621a75e394f2e72 100644 (file)
@@ -22,6 +22,8 @@ public class Tester1 {
   }
 
   static final Metrics metrics = new Metrics();
+  private static final OutputPointer.sqlite3_stmt outStmt
+    = new OutputPointer.sqlite3_stmt();
 
   public static <T> void out(T val){
     System.out.print(val);
@@ -53,11 +55,11 @@ public class Tester1 {
   }
 
   public static sqlite3 createNewDb(){
-    sqlite3 db = new sqlite3();
-    affirm(0 == db.getNativePointer());
-    int rc = sqlite3_open(":memory:", db);
+    final OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
+    int rc = sqlite3_open(":memory:", out);
     ++metrics.dbOpen;
     affirm(0 == rc);
+    sqlite3 db = out.getValue();
     affirm(0 != db.getNativePointer());
     rc = sqlite3_busy_timeout(db, 2000);
     affirm( 0 == rc );
@@ -69,52 +71,63 @@ public class Tester1 {
   }
 
   public static int execSql(sqlite3 db, boolean throwOnError, String sql){
-      OutputPointer.Int32 oTail = new OutputPointer.Int32();
-      final byte[] sqlUtf8 = sql.getBytes(StandardCharsets.UTF_8);
-      int pos = 0, n = 1;
-      byte[] sqlChunk = sqlUtf8;
-      sqlite3_stmt stmt = new sqlite3_stmt();
-      int rc = 0;
-      while(pos < sqlChunk.length){
-        if(pos > 0){
-          sqlChunk = Arrays.copyOfRange(sqlChunk, pos,
-                                        sqlChunk.length);
-        }
-        if( 0==sqlChunk.length ) break;
-        rc = sqlite3_prepare_v2(db, sqlChunk, stmt, oTail);
-        if(throwOnError) affirm(0 == rc);
-        else if( 0!=rc ) break;
-        pos = oTail.getValue();
-        affirm(0 != stmt.getNativePointer());
-        while( SQLITE_ROW == (rc = sqlite3_step(stmt)) ){
-        }
-        sqlite3_finalize(stmt);
-        affirm(0 == stmt.getNativePointer());
-        if(0!=rc && SQLITE_ROW!=rc && SQLITE_DONE!=rc){
-          if(throwOnError){
-            throw new RuntimeException("db op failed with rc="+rc);
-          }else{
-            break;
-          }
-        }
+    OutputPointer.Int32 oTail = new OutputPointer.Int32();
+    final byte[] sqlUtf8 = sql.getBytes(StandardCharsets.UTF_8);
+    int pos = 0, n = 1;
+    byte[] sqlChunk = sqlUtf8;
+    int rc = 0;
+    sqlite3_stmt stmt = null;
+    while(pos < sqlChunk.length){
+      if(pos > 0){
+        sqlChunk = Arrays.copyOfRange(sqlChunk, pos,
+                                      sqlChunk.length);
+      }
+      if( 0==sqlChunk.length ) break;
+      rc = sqlite3_prepare_v2(db, sqlChunk, outStmt, oTail);
+      if(throwOnError) affirm(0 == rc);
+      else if( 0!=rc ) break;
+      stmt = outStmt.getValue();
+      pos = oTail.getValue();
+      affirm(0 != stmt.getNativePointer());
+      while( SQLITE_ROW == (rc = sqlite3_step(stmt)) ){
       }
       sqlite3_finalize(stmt);
-      if(SQLITE_ROW==rc || SQLITE_DONE==rc) rc = 0;
-      return rc;
+      affirm(0 == stmt.getNativePointer());
+      if(0!=rc && SQLITE_ROW!=rc && SQLITE_DONE!=rc){
+        if(throwOnError){
+          throw new RuntimeException("db op failed with rc="+rc);
+        }else{
+          break;
+        }
+      }
+    }
+    sqlite3_finalize(stmt);
+    if(SQLITE_ROW==rc || SQLITE_DONE==rc) rc = 0;
+    return rc;
   }
 
   public static void execSql(sqlite3 db, String sql){
     execSql(db, true, sql);
   }
 
+  public static sqlite3_stmt prepare(sqlite3 db, String sql){
+    outStmt.clear();
+    int rc = sqlite3_prepare(db, sql, outStmt);
+    affirm( 0 == rc );
+    final sqlite3_stmt rv = outStmt.getValue();
+    outStmt.clear();
+    affirm( 0 != rv.getNativePointer() );
+    return rv;
+  }
+
   private static void testOpenDb1(){
-      sqlite3 db = new sqlite3();
-      affirm(0 == db.getNativePointer());
-      int rc = sqlite3_open(":memory:", db);
-      ++metrics.dbOpen;
-      affirm(0 == rc);
-      affirm(0 < db.getNativePointer());
-      sqlite3_close_v2(db);
+    final OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
+    int rc = sqlite3_open(":memory:", out);
+    ++metrics.dbOpen;
+    sqlite3 db = out.getValue();
+    affirm(0 == rc);
+    affirm(0 < db.getNativePointer());
+    sqlite3_close_v2(db);
       affirm(0 == db.getNativePointer());
   }
 
@@ -130,13 +143,13 @@ public class Tester1 {
   }
 
   private static void testOpenDb2(){
-    sqlite3 db = new sqlite3();
-    affirm(0 == db.getNativePointer());
-    int rc = sqlite3_open_v2(":memory:", db,
+    final OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
+    int rc = sqlite3_open_v2(":memory:", out,
                              SQLITE_OPEN_READWRITE
                              | SQLITE_OPEN_CREATE, null);
     ++metrics.dbOpen;
     affirm(0 == rc);
+    sqlite3 db = out.getValue();
     affirm(0 < db.getNativePointer());
     sqlite3_close_v2(db);
     affirm(0 == db.getNativePointer());
@@ -145,10 +158,9 @@ public class Tester1 {
   private static void testPrepare123(){
     sqlite3 db = createNewDb();
     int rc;
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    affirm(0 == stmt.getNativePointer());
-    rc = sqlite3_prepare(db, "CREATE TABLE t1(a);", stmt);
+    rc = sqlite3_prepare(db, "CREATE TABLE t1(a);", outStmt);
     affirm(0 == rc);
+    sqlite3_stmt stmt = outStmt.getValue();
     affirm(0 != stmt.getNativePointer());
     rc = sqlite3_step(stmt);
     affirm(SQLITE_DONE == rc);
@@ -169,8 +181,9 @@ public class Tester1 {
         }
         //outln("SQL chunk #"+n+" length = "+sqlChunk.length+", pos = "+pos);
         if( 0==sqlChunk.length ) break;
-        rc = sqlite3_prepare_v2(db, sqlChunk, stmt, oTail);
+        rc = sqlite3_prepare_v2(db, sqlChunk, outStmt, oTail);
         affirm(0 == rc);
+        stmt = outStmt.getValue();
         pos = oTail.getValue();
         /*outln("SQL tail pos = "+pos+". Chunk = "+
               (new String(Arrays.copyOfRange(sqlChunk,0,pos),
@@ -192,8 +205,9 @@ public class Tester1 {
 
 
     rc = sqlite3_prepare_v3(db, "INSERT INTO t2(a) VALUES(1),(2),(3)",
-                            SQLITE_PREPARE_NORMALIZE, stmt);
+                            SQLITE_PREPARE_NORMALIZE, outStmt);
     affirm(0 == rc);
+    stmt = outStmt.getValue();
     affirm(0 != stmt.getNativePointer());
     sqlite3_finalize(stmt);
     affirm(0 == stmt.getNativePointer() );
@@ -204,9 +218,7 @@ public class Tester1 {
     sqlite3 db = createNewDb();
     execSql(db, "CREATE TABLE t(a)");
 
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    int rc = sqlite3_prepare(db, "INSERT INTO t(a) VALUES(:a);", stmt);
-    affirm(0 == rc);
+    sqlite3_stmt stmt = prepare(db, "INSERT INTO t(a) VALUES(:a);");
     affirm(1 == sqlite3_bind_parameter_count(stmt));
     final int paramNdx = sqlite3_bind_parameter_index(stmt, ":a");
     affirm(1 == paramNdx);
@@ -216,6 +228,7 @@ public class Tester1 {
     int changesT = sqlite3_total_changes(db);
     long changes64 = sqlite3_changes64(db);
     long changesT64 = sqlite3_total_changes64(db);
+    int rc;
     for(int i = 99; i < 102; ++i ){
       total1 += i;
       rc = sqlite3_bind_int(stmt, paramNdx, i);
@@ -233,8 +246,7 @@ public class Tester1 {
     affirm(sqlite3_total_changes(db) > changesT);
     affirm(sqlite3_changes64(db) > changes64);
     affirm(sqlite3_total_changes64(db) > changesT64);
-    rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
-    affirm(0 == rc);
+    stmt = prepare(db, "SELECT a FROM t ORDER BY a DESC;");
     int total2 = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
       total2 += sqlite3_column_int(stmt, 0);
@@ -252,8 +264,7 @@ public class Tester1 {
   private static void testBindFetchInt64(){
     sqlite3 db = createNewDb();
     execSql(db, "CREATE TABLE t(a)");
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    int rc = sqlite3_prepare(db, "INSERT INTO t(a) VALUES(?);", stmt);
+    sqlite3_stmt stmt = prepare(db, "INSERT INTO t(a) VALUES(?);");
     long total1 = 0;
     for(long i = 0xffffffff; i < 0xffffffff + 3; ++i ){
       total1 += i;
@@ -262,8 +273,7 @@ public class Tester1 {
       sqlite3_reset(stmt);
     }
     sqlite3_finalize(stmt);
-    rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
-    affirm(0 == rc);
+    stmt = prepare(db, "SELECT a FROM t ORDER BY a DESC;");
     long total2 = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
       total2 += sqlite3_column_int64(stmt, 0);
@@ -276,8 +286,7 @@ public class Tester1 {
   private static void testBindFetchDouble(){
     sqlite3 db = createNewDb();
     execSql(db, "CREATE TABLE t(a)");
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    int rc = sqlite3_prepare(db, "INSERT INTO t(a) VALUES(?);", stmt);
+    sqlite3_stmt stmt = prepare(db, "INSERT INTO t(a) VALUES(?);");
     double total1 = 0;
     for(double i = 1.5; i < 5.0; i = i + 1.0 ){
       total1 += i;
@@ -286,8 +295,7 @@ public class Tester1 {
       sqlite3_reset(stmt);
     }
     sqlite3_finalize(stmt);
-    rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
-    affirm(0 == rc);
+    stmt = prepare(db, "SELECT a FROM t ORDER BY a DESC;");
     double total2 = 0;
     int counter = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
@@ -303,9 +311,9 @@ public class Tester1 {
   private static void testBindFetchText(){
     sqlite3 db = createNewDb();
     execSql(db, "CREATE TABLE t(a)");
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    int rc = sqlite3_prepare(db, "INSERT INTO t(a) VALUES(?);", stmt);
+    sqlite3_stmt stmt = prepare(db, "INSERT INTO t(a) VALUES(?);");
     String[] list1 = { "hell🤩", "w😃rld", "!" };
+    int rc;
     for( String e : list1 ){
       rc = sqlite3_bind_text(stmt, 1, e);
       affirm(0 == rc);
@@ -314,8 +322,7 @@ public class Tester1 {
       sqlite3_reset(stmt);
     }
     sqlite3_finalize(stmt);
-    rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
-    affirm(0 == rc);
+    stmt = prepare(db, "SELECT a FROM t ORDER BY a DESC;");
     StringBuilder sbuf = new StringBuilder();
     int n = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
@@ -333,15 +340,14 @@ public class Tester1 {
   private static void testBindFetchBlob(){
     sqlite3 db = createNewDb();
     execSql(db, "CREATE TABLE t(a)");
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    int rc = sqlite3_prepare(db, "INSERT INTO t(a) VALUES(?);", stmt);
+    sqlite3_stmt stmt = prepare(db, "INSERT INTO t(a) VALUES(?);");
     byte[] list1 = { 0x32, 0x33, 0x34 };
-    rc = sqlite3_bind_blob(stmt, 1, list1);
+    int rc = sqlite3_bind_blob(stmt, 1, list1);
+    affirm( 0==rc );
     rc = sqlite3_step(stmt);
     affirm(SQLITE_DONE == rc);
     sqlite3_finalize(stmt);
-    rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
-    affirm(0 == rc);
+    stmt = prepare(db, "SELECT a FROM t ORDER BY a DESC;");
     int n = 0;
     int total = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
@@ -398,9 +404,7 @@ public class Tester1 {
     affirm( 0 == rc );
     rc = sqlite3_collation_needed(db, collLoader);
     affirm( 0 == rc /* Installing the same object again is a no-op */);
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a COLLATE reversi", stmt);
-    affirm( 0 == rc );
+    sqlite3_stmt stmt = prepare(db, "SELECT a FROM t ORDER BY a COLLATE reversi");
     int counter = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
       final String val = sqlite3_column_text(stmt, 0);
@@ -414,7 +418,7 @@ public class Tester1 {
     }
     affirm(3 == counter);
     sqlite3_finalize(stmt);
-    sqlite3_prepare(db, "SELECT a FROM t ORDER BY a", stmt);
+    stmt = prepare(db, "SELECT a FROM t ORDER BY a");
     counter = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
       final String val = sqlite3_column_text(stmt, 0);
@@ -479,9 +483,7 @@ public class Tester1 {
     int rc = sqlite3_create_function(db, "myfunc", -1, SQLITE_UTF8, func);
     affirm(0 == rc);
     affirm(0 == xFuncAccum.value);
-    final sqlite3_stmt stmt = new sqlite3_stmt();
-    rc = sqlite3_prepare(db, "SELECT myfunc(1,2,3)", stmt);
-    affirm( 0==rc );
+    final sqlite3_stmt stmt = prepare(db, "SELECT myfunc(1,2,3)");
     int n = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
       affirm( 6 == sqlite3_column_int(stmt, 0) );
@@ -498,15 +500,14 @@ public class Tester1 {
   private static void testUdfJavaObject(){
     final sqlite3 db = createNewDb();
     final ValueHolder<sqlite3> testResult = new ValueHolder<>(db);
-    SQLFunction func = new SQLFunction.Scalar(){
+    final SQLFunction func = new SQLFunction.Scalar(){
         public void xFunc(sqlite3_context cx, sqlite3_value args[]){
           sqlite3_result_java_object(cx, testResult.value);
         }
       };
     int rc = sqlite3_create_function(db, "myfunc", -1, SQLITE_UTF8, func);
     affirm(0 == rc);
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    sqlite3_prepare(db, "select myfunc()", stmt);
+    final sqlite3_stmt stmt = prepare(db, "select myfunc()");
     affirm( 0 != stmt.getNativePointer() );
     affirm( testResult.value == db );
     int n = 0;
@@ -550,9 +551,7 @@ public class Tester1 {
     execSql(db, "CREATE TABLE t(a); INSERT INTO t(a) VALUES(1),(2),(3)");
     int rc = sqlite3_create_function(db, "myfunc", 1, SQLITE_UTF8, func);
     affirm(0 == rc);
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    sqlite3_prepare(db, "select myfunc(a), myfunc(a+10) from t", stmt);
-    affirm( 0 != stmt.getNativePointer() );
+    sqlite3_stmt stmt = prepare(db, "select myfunc(a), myfunc(a+10) from t");
     int n = 0;
     if( SQLITE_ROW == sqlite3_step(stmt) ){
       final int v = sqlite3_column_int(stmt, 0);
@@ -571,9 +570,7 @@ public class Tester1 {
     sqlite3_finalize(stmt);
     affirm( 1==n );
 
-    rc = sqlite3_prepare(db, "select myfunc(a), myfunc(a+a) from t order by a",
-                         stmt);
-    affirm( 0 == rc );
+    stmt = prepare(db, "select myfunc(a), myfunc(a+a) from t order by a");
     n = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
       final int c0 = sqlite3_column_int(stmt, 0);
@@ -624,12 +621,11 @@ public class Tester1 {
         "CREATE TEMP TABLE twin(x, y); INSERT INTO twin VALUES",
         "('a', 4),('b', 5),('c', 3),('d', 8),('e', 1)"
       });
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    rc = sqlite3_prepare(db,
+    final sqlite3_stmt stmt = prepare(db,
                          "SELECT x, winsumint(y) OVER ("+
                          "ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING"+
                          ") AS sum_y "+
-                         "FROM twin ORDER BY x;", stmt);
+                         "FROM twin ORDER BY x;");
     affirm( 0 == rc );
     int n = 0;
     while( SQLITE_ROW == sqlite3_step(stmt) ){
@@ -693,11 +689,12 @@ public class Tester1 {
       new Tracer(){
         public int xCallback(int traceFlag, Object pNative, Object x){
           ++counter.value;
+          //outln("TRACE "+traceFlag+" pNative = "+pNative.getClass().getName());
           switch(traceFlag){
             case SQLITE_TRACE_STMT:
               affirm(pNative instanceof sqlite3_stmt);
-              affirm(x instanceof String);
               //outln("TRACE_STMT sql = "+x);
+              affirm(x instanceof String);
               affirm( ((String)x).indexOf(nonBmpChar) > 0 );
               break;
             case SQLITE_TRACE_PROFILE:
@@ -730,16 +727,18 @@ public class Tester1 {
 
   private static void testBusy(){
     final String dbName = "_busy-handler.db";
-    final sqlite3 db1 = new sqlite3();
-    final sqlite3 db2 = new sqlite3();
+    final OutputPointer.sqlite3 outDb = new OutputPointer.sqlite3();
 
-    int rc = sqlite3_open(dbName, db1);
+    int rc = sqlite3_open(dbName, outDb);
     ++metrics.dbOpen;
     affirm( 0 == rc );
+    final sqlite3 db1 = outDb.getValue();
     execSql(db1, "CREATE TABLE IF NOT EXISTS t(a)");
-    rc = sqlite3_open(dbName, db2);
+    rc = sqlite3_open(dbName, outDb);
     ++metrics.dbOpen;
     affirm( 0 == rc );
+    affirm( outDb.getValue() != db1 );
+    final sqlite3 db2 = outDb.getValue();
     rc = sqlite3_db_config(db1, SQLITE_DBCONFIG_MAINDBNAME, "foo");
     affirm( sqlite3_db_filename(db1, "foo").endsWith(dbName) );
 
@@ -760,11 +759,10 @@ public class Tester1 {
     // Force a locked condition...
     execSql(db1, "BEGIN EXCLUSIVE");
     affirm(!xDestroyed.value);
-    sqlite3_stmt stmt = new sqlite3_stmt();
-    rc = sqlite3_prepare(db2, "SELECT * from t", stmt);
+    rc = sqlite3_prepare_v2(db2, "SELECT * from t", outStmt);
     affirm( SQLITE_BUSY == rc);
+    assert( null == outStmt.getValue() );
     affirm( 3 == xBusyCalled.value );
-    sqlite3_finalize(stmt);
     sqlite3_close_v2(db1);
     affirm(!xDestroyed.value);
     sqlite3_close_v2(db2);
index 99d06af829f24392b6042aa7efa8772027d9680b..8f4ecb772b0ddf5cb5c33478ded16a40c5248130 100644 (file)
@@ -20,4 +20,6 @@ package org.sqlite.jni;
    and C via JNI.
 */
 public final class sqlite3 extends NativePointerHolder<sqlite3> {
+  // Only invoked from JNI
+  private sqlite3(){}
 }
index 8aa8c77bbdcd274172722201f2734a8a5bbc7dc5..2cfb32ff1a68db4b1dd804aa7b6ad28b5d8245db 100644 (file)
@@ -14,4 +14,6 @@
 package org.sqlite.jni;
 
 public final class sqlite3_value extends NativePointerHolder<sqlite3_value> {
+  //! Invoked only from JNI.
+  private sqlite3_value(){}
 }
index dcdf8f77f92839602f3fcc2d94f8f0b8168dd526..e68cb542c117a9e7e0e99aae8e24825b7af3e8d2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-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
+C Completely\srework\show\sthe\sJNI\ssqlite3_open(_v2)\sand\ssqlite3_prepare(_vN)()\sbindings\sdeal\swith\soutput\spointers\sto\sgive\sthe\sJNI\sside\sfull\scontrol\sover\sthe\sorigin\sof\sdb\sand\sstmt\shandles\s(necessary\sfor\ssolving\schicken/egg\ssituations\sin\sauto-extensions\sand\sprepare-time\strace).\sLots\sof\sadjacent\sinternal\sAPI\srenaming.
+D 2023-08-06T21:29:13.410
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -232,8 +232,8 @@ F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
 F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
 F ext/jni/GNUmakefile 61d9bbc179a49523a142928455b3297779b9c40f25783ecf1538279e426cbc99
 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/c/sqlite3-jni.c 22f463b0bf4e79ccbc0dcd157e8c419e1a6ab1a88afbd565db818aec2802241e
+F ext/jni/src/c/sqlite3-jni.h 2108bb9434fe873e08d6388bce102a474b5c6b00c2ea47d8aee257aca2de2a67
 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
@@ -246,12 +246,12 @@ F ext/jni/src/org/sqlite/jni/Fts5Function.java 65cde7151e441fee012250a5e03277de7
 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/NativePointerHolder.java 9c5d901cce4f7e57c3d623f4e2476f9f79a8eed6e51b2a603f37866018e040ee
-F ext/jni/src/org/sqlite/jni/OutputPointer.java fcece068415b804aa7843534addb39059ea2b923a9f5dbe91f4f78f066c77991
+F ext/jni/src/org/sqlite/jni/OutputPointer.java 053ea7dbc1234dd70b8948009a52a3f1090403a6fe2ab7b7885b6f08ed26deea
 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 2ee2d3522ab6bec9337653233f5fb50619120cc5b12ce5deb59035ca2502cdcd
-F ext/jni/src/org/sqlite/jni/Tester1.java 04c43f3ec93b362fc1c66430a3125067285259cd4fa5afccdb2fa66b691db8d0
+F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 3edf79fb7a3cb5eaeeaaa074f51521d6d9a962b0dd1ca88074be4fd075258fd8
+F ext/jni/src/org/sqlite/jni/Tester1.java 7ea111e9d52042889f2360e7addfefed4174c1a17dfe6efccf64aaa9a65749cf
 F ext/jni/src/org/sqlite/jni/TesterFts5.java cf2d687baafffdeba219b77cf611fd47a0556248820ea794ae3e8259bfbdc5ee
 F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d
 F ext/jni/src/org/sqlite/jni/UpdateHook.java e58645a1727f8a9bbe72dc072ec5b40d9f9362cb0aa24acfe93f49ff56a9016d
@@ -259,10 +259,10 @@ F ext/jni/src/org/sqlite/jni/ValueHolder.java f022873abaabf64f3dd71ab0d6037c6e71
 F ext/jni/src/org/sqlite/jni/fts5_api.java 8c6b32455d7f85ee3f7f3e71c148bb3c2106f1d5484017daddfd560dd69d4f66
 F ext/jni/src/org/sqlite/jni/fts5_extension_function.java ac825035d7d83fc7fd960347abfa6803e1614334a21533302041823ad5fc894c
 F ext/jni/src/org/sqlite/jni/fts5_tokenizer.java e530b36e6437fcc500e95d5d75fbffe272bdea20d2fac6be2e1336c578fba98b
-F ext/jni/src/org/sqlite/jni/sqlite3.java 600c3ddc1ac28ee8f58669fb435fd0d21f2972c652039361fde907d4fe44eb58
+F ext/jni/src/org/sqlite/jni/sqlite3.java ff3729426704626a6019d97bfee512a83f253cf43ffeffbd45b238718154df36
 F ext/jni/src/org/sqlite/jni/sqlite3_context.java d26573fc7b309228cb49786e9078597d96232257defa955a3425d10897bca810
 F ext/jni/src/org/sqlite/jni/sqlite3_stmt.java 72a0698aeb50a183ad146cd29ee04952abb8c36021f6122656aa5ec20469f6f7
-F ext/jni/src/org/sqlite/jni/sqlite3_value.java fd045a09458e0a1b9328b085015b5ca5cc9024e7f91ee299f95da9dfd9a865a7
+F ext/jni/src/org/sqlite/jni/sqlite3_value.java 3d1d4903e267bc0bc81d57d21f5e85978eff389a1a6ed46726dbe75f85e6914a
 F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9
 F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
 F ext/lsm1/lsm-test/README 87ea529d2abe615e856d4714bfe8bb185e6c2771b8612aa6298588b7b43e6f86
@@ -2082,8 +2082,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 5f56b007704f2aad4cbc6f0ccd1e1f1c974865971f99451352714ee7e077c284
-R 55ff516d4ad7789048494bf17442d9b9
+P 77a32d238e80fe1d237768d88780043a7bd2b3543e6672536254782cbea0039c
+R 218b9f82589d0175238ee5cd53ac1842
 U stephan
-Z 7da38e0ddc75e18237df446c4596f88f
+Z f6066ff3c416a47c98afc4ffb5e0f6a5
 # Remove this line to create a well-formed Fossil manifest.
index b8a927308bd0e1c9aee454262d7144b8789fc364..101fba0f15d77465a200f954fa8350b9259d25b6 100644 (file)
@@ -1 +1 @@
-77a32d238e80fe1d237768d88780043a7bd2b3543e6672536254782cbea0039c
\ No newline at end of file
+644999caff9db79562d45520d94aaa24ee88c65e397b6fb9c20a4f0e7f84e1a5
\ No newline at end of file