/** 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;
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;
"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",
#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
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;
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);
}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);
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);
}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);
rv = (void*)(*env)->GetLongField(env, pObj, getter);
IFTHREW_REPORT;
return rv;
+ }else{
+ return 0;
}
}
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;
}
/**
- 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
/* 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);
#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",
#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,
/**
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.
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,
#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;
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;
}
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;
}
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;
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;
}
/* 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);
}
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:
// 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:
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()
/**
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;
}
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;
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;
}
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;
}
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;
}
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;
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;
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);
}
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);
}
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;
}
* 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);
/*
/*
* 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);
/*
* 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);
/*
* 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);
/*
* 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);
/*
* 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);
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);}
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);
/**
*/
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);
}
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);
}
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);
}
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);
}
}
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);
}
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 );
}
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());
}
}
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());
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);
}
//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),
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() );
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);
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);
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);
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;
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);
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;
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) ){
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);
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) ){
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) ){
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);
}
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);
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) );
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;
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);
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);
"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) ){
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:
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) );
// 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);
and C via JNI.
*/
public final class sqlite3 extends NativePointerHolder<sqlite3> {
+ // Only invoked from JNI
+ private sqlite3(){}
}
package org.sqlite.jni;
public final class sqlite3_value extends NativePointerHolder<sqlite3_value> {
+ //! Invoked only from JNI.
+ private sqlite3_value(){}
}
-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
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
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
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
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.
-77a32d238e80fe1d237768d88780043a7bd2b3543e6672536254782cbea0039c
\ No newline at end of file
+644999caff9db79562d45520d94aaa24ee88c65e397b6fb9c20a4f0e7f84e1a5
\ No newline at end of file