相关文章推荐
儒雅的饺子  ·  广东省公安厅网站·  1 周前    · 
瘦瘦的企鹅  ·  常见问题·  2 周前    · 
大鼻子的水龙头  ·  Oris·  2 月前    · 
曾深爱过的电池  ·  中共沈阳市委 ...·  5 月前    · 
/* Helpers for jstring and jbyteArray. */ #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(VAR) (*env)->ReleaseByteArrayElements(env, ARG, VAR, JNI_ABORT) /* Marker for code which needs(?) to be made thread-safe. */ #define FIXME_THREADING(REASON) enum { Size of the NativePointerHolder cache. Need enough space for (only) the library's NativePointerHolder types, a fixed count known at build-time. If we add more than this a fatal error will /* Helpers for jstring and jbyteArray. */ #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(VAR) (*env)->ReleaseByteArrayElements(env, ARG, VAR, JNI_ABORT) /* Marker for code which needs(?) to be made thread-safe. REASON is a terse reminder about why that function requires a mutex. #define FIXME_THREADING(REASON) enum { Size of the NativePointerHolder cache. Need enough space for (only) the library's NativePointerHolder types, a fixed count known at build-time. If we add more than this a fatal error will to v. */ static void OutputPointer_set_Int32(JNIEnv * const env, jobject const jOut, int v){ jfieldID setter = 0; setupOutputPointer(env, S3JniClassNames.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, S3JniClassNames.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, S3JniClassNames.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 OutputPointer_set_Int64(JNIEnv * const env, jobject const jOut, jlong v){ jfieldID setter = 0; setupOutputPointer(env, S3JniClassNames.OutputPointer_Int64, "J", jOut, &setter); (*env)->SetLongField(env, jOut, setter, v); EXCEPTION_IS_FATAL("Cannot set OutputPointer.Int64.value"); #if 0 /* Sets the value property of the OutputPointer.ByteArray jOut object to v. */ static void OutputPointer_set_ByteArray(JNIEnv * const env, jobject const jOut, jbyteArray const v){ jfieldID setter = 0; setupOutputPointer(env, S3JniClassNames.OutputPointer_ByteArray, "[B", to v. */ static void OutputPointer_set_Int32(JNIEnv * const env, jobject const jOut, int v){ jfieldID setter = 0; setupOutputPointer(env, S3JniClassNames.OutputPointer_Int32, "I", jOut, &setter); (*env)->SetIntField(env, jOut, setter, (jint)v); EXCEPTION_IS_FATAL("Cannot set OutputPointer.Int32.value"); /* Sets the value property of the OutputPointer.Int64 jOut object to v. */ static void OutputPointer_set_Int64(JNIEnv * const env, jobject const jOut, jlong v){ jfieldID setter = 0; setupOutputPointer(env, S3JniClassNames.OutputPointer_Int64, "J", jOut, &setter); (*env)->SetLongField(env, jOut, setter, v); EXCEPTION_IS_FATAL("Cannot set OutputPointer.Int64.value"); static void OutputPointer_set_sqlite3(JNIEnv * const env, jobject const jOut, jobject jDb){ jfieldID setter = 0; setupOutputPointer(env, S3JniClassNames.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, S3JniClassNames.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.ByteArray jOut object to v. */ static void OutputPointer_set_ByteArray(JNIEnv * const env, jobject const jOut, jbyteArray const v){ jfieldID setter = 0; setupOutputPointer(env, S3JniClassNames.OutputPointer_ByteArray, "[B", JDECL(void,1set_1last_1insert_1rowid)(JENV_CSELF, jobject jpDb, jlong rowId){ sqlite3_set_last_insert_rowid(PtrGet_sqlite3_context(jpDb), (sqlite3_int64)rowId); static int s3jni_strlike_glob(int isLike, JNIEnv *const env, jbyteArray baG, jbyteArray baT, jint escLike){ int rc = 0; jbyte * const pG = JBA_TOC(baG); jbyte * const pT = pG ? JBA_TOC(baT) : 0; OOM_CHECK(pT); JDECL(void,1set_1last_1insert_1rowid)(JENV_CSELF, jobject jpDb, jlong rowId){ sqlite3_set_last_insert_rowid(PtrGet_sqlite3_context(jpDb), (sqlite3_int64)rowId); FIXME_THREADING(nphCache) JDECL(jint,1status)(JENV_CSELF, jint op, jobject jOutCurrent, jobject jOutHigh, jboolean reset ){ int iCur = 0, iHigh = 0; int rc = sqlite3_status( op, &iCur, &iHigh, reset ); if( 0==rc ){ OutputPointer_set_Int32(env, jOutCurrent, iCur); OutputPointer_set_Int32(env, jOutHigh, iHigh); return (jint)rc; FIXME_THREADING(nphCache) JDECL(jint,1status64)(JENV_CSELF, jint op, jobject jOutCurrent, jobject jOutHigh, jboolean reset ){ sqlite3_int64 iCur = 0, iHigh = 0; int rc = sqlite3_status64( op, &iCur, &iHigh, reset ); if( 0==rc ){ OutputPointer_set_Int64(env, jOutCurrent, iCur); OutputPointer_set_Int64(env, jOutHigh, iHigh); return (jint)rc; static int s3jni_strlike_glob(int isLike, JNIEnv *const env, jbyteArray baG, jbyteArray baT, jint escLike){ int rc = 0; jbyte * const pG = JBA_TOC(baG); jbyte * const pT = pG ? JBA_TOC(baT) : 0; OOM_CHECK(pT); Modified ext/jni/src/c/sqlite3-jni.h from [8f9e0301] to [7a51d104] . * Class: org_sqlite_jni_SQLite3Jni * Method: sqlite3_result_text64 * Signature: (Lorg/sqlite/jni/sqlite3_context;[BJI)V JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1text64 (JNIEnv *, jclass, jobject, jbyteArray, jlong, jint); * Class: org_sqlite_jni_SQLite3Jni * Method: sqlite3_rollback_hook * Signature: (Lorg/sqlite/jni/sqlite3;Lorg/sqlite/jni/RollbackHook;)Lorg/sqlite/jni/RollbackHook; JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1rollback_1hook (JNIEnv *, jclass, jobject, jobject); * Class: org_sqlite_jni_SQLite3Jni * Method: sqlite3_result_text64 * Signature: (Lorg/sqlite/jni/sqlite3_context;[BJI)V JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1text64 (JNIEnv *, jclass, jobject, jbyteArray, jlong, jint); * Class: org_sqlite_jni_SQLite3Jni * Method: sqlite3_status * Signature: (ILorg/sqlite/jni/OutputPointer/Int32;Lorg/sqlite/jni/OutputPointer/Int32;Z)I JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1status (JNIEnv *, jclass, jint, jobject, jobject, jboolean); * Class: org_sqlite_jni_SQLite3Jni * Method: sqlite3_status64 * Signature: (ILorg/sqlite/jni/OutputPointer/Int64;Lorg/sqlite/jni/OutputPointer/Int64;Z)I JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1status64 (JNIEnv *, jclass, jint, jobject, jobject, jboolean); * Class: org_sqlite_jni_SQLite3Jni * Method: sqlite3_rollback_hook * Signature: (Lorg/sqlite/jni/sqlite3;Lorg/sqlite/jni/RollbackHook;)Lorg/sqlite/jni/RollbackHook; JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1rollback_1hook (JNIEnv *, jclass, jobject, jobject); Modified ext/jni/src/org/sqlite/jni/SQLite3Jni.java from [23dec2c2] to [21af8894] . private static synchronized native void sqlite3_result_text64( @NotNull sqlite3_context cx, @Nullable byte[] text, long maxLength, int encoding // public static synchronized native int sqlite3_status( // int op, OutputPointer.Int32 pCurrent , OutputPointer.Int32 pHighwater , // boolean reset // ); // public static synchronized native int sqlite3_status64( // int op, OutputPointer.Int64 pCurrent , OutputPointer.Int64 pHighwater , // boolean reset // ); Sets the current UDF result to the given bytes, which are assumed be encoded in UTF-16 using the platform's byte order. public static void sqlite3_result_text16( @NotNull sqlite3_context cx, @Nullable byte[] text private static synchronized native void sqlite3_result_text64( @NotNull sqlite3_context cx, @Nullable byte[] text, long maxLength, int encoding public static synchronized native int sqlite3_status( int op, @NotNull OutputPointer.Int32 pCurrent, @NotNull OutputPointer.Int32 pHighwater, boolean reset public static synchronized native int sqlite3_status64( int op, @NotNull OutputPointer.Int64 pCurrent, @NotNull OutputPointer.Int64 pHighwater, boolean reset Sets the current UDF result to the given bytes, which are assumed be encoded in UTF-16 using the platform's byte order. public static void sqlite3_result_text16( @NotNull sqlite3_context cx, @Nullable byte[] text Modified ext/jni/src/org/sqlite/jni/Tester1.java from [62ba3f54] to [c7bb4747] . 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(){ 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_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, null) /* This function has different mangled names in jdk8 vs jdk19, and this call is here to ensure that the build fails if it cannot find both names. */; sqlite3_close_v2(db); affirm(0 == db.getNativePointer()); private static void testCompileOption(){ int i = 0; String optName; outln("compile options:"); for( ; null != (optName = sqlite3_compileoption_get(i)); ++i){ outln("\t"+optName+"\t (used="+ sqlite3_compileoption_used(optName)+")"); private static void testOpenDb2(){ final OutputPointer.sqlite3 out = new OutputPointer.sqlite3(); int rc = sqlite3_open_v2(":memory:", out, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null); 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 testCompileOption(){ int i = 0; String optName; outln("compile options:"); for( ; null != (optName = sqlite3_compileoption_get(i)); ++i){ outln("\t"+optName+"\t (used="+ sqlite3_compileoption_used(optName)+")"); private static void testOpenDb1(){ 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_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, null) /* This function has different mangled names in jdk8 vs jdk19, and this call is here to ensure that the build fails if it cannot find both names. */; sqlite3_close_v2(db); affirm(0 == db.getNativePointer()); private static void testOpenDb2(){ final OutputPointer.sqlite3 out = new OutputPointer.sqlite3(); int rc = sqlite3_open_v2(":memory:", out, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null); https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html Let's ensure that we can convert to standard UTF-8 in Java code (noting that the JNI native API has no way to do this). final byte[] ba = "a \0 b".getBytes(StandardCharsets.UTF_8); affirm( 5 == ba.length /* as opposed to 6 in modified utf-8 */); private static void testUdf1(){ final sqlite3 db = createNewDb(); // These ValueHolders are just to confirm that the func did what we want... final ValueHolder<Boolean> xDestroyCalled = new ValueHolder<>(false); final ValueHolder<Integer> xFuncAccum = new ValueHolder<>(0); https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html Let's ensure that we can convert to standard UTF-8 in Java code (noting that the JNI native API has no way to do this). final byte[] ba = "a \0 b".getBytes(StandardCharsets.UTF_8); affirm( 5 == ba.length /* as opposed to 6 in modified utf-8 */); private static void testStatus(){ final OutputPointer.Int64 cur64 = new OutputPointer.Int64(); final OutputPointer.Int64 high64 = new OutputPointer.Int64(); final OutputPointer.Int32 cur32 = new OutputPointer.Int32(); final OutputPointer.Int32 high32 = new OutputPointer.Int32(); final sqlite3 db = createNewDb(); execSql(db, "create table t(a)"); sqlite3_close_v2(db); int rc = sqlite3_status(SQLITE_STATUS_MEMORY_USED, cur32, high32, false); affirm( 0 == rc ); affirm( cur32.getValue() > 0 ); affirm( high32.getValue() >= cur32.getValue() ); rc = sqlite3_status64(SQLITE_STATUS_MEMORY_USED, cur64, high64, false); affirm( 0 == rc ); affirm( cur64.getValue() > 0 ); affirm( high64.getValue() >= cur64.getValue() ); private static void testUdf1(){ final sqlite3 db = createNewDb(); // These ValueHolders are just to confirm that the func did what we want... final ValueHolder<Boolean> xDestroyCalled = new ValueHolder<>(false); final ValueHolder<Integer> xFuncAccum = new ValueHolder<>(0); testBindFetchInt64(); testBindFetchDouble(); testBindFetchText(); testBindFetchBlob(); testSql(); testCollation(); testToUtf8(); testUdf1(); testUdfJavaObject(); testUdfAggregate(); testUdfWindow(); testTrace(); testBusy(); testProgress();