--- /dev/null
+# Quick-and-dirty makefile to bootstrap the sqlite3-jni project. This
+# build assumes a Linux-like system.
+default: all
+
+JDK_HOME ?= $(HOME)/jdk/current
+# /usr/lib/jvm/default-javajava-19-openjdk-amd64
+bin.javac := $(JDK_HOME)/bin/javac
+bin.java := $(JDK_HOME)/bin/java
+bin.jar := $(JDK_HOME)/bin/jar
+ifeq (,$(wildcard $(JDK_HOME)))
+$(error set JDK_HOME to the top-most dir of your JDK installation.)
+endif
+MAKEFILE := $(lastword $(MAKEFILE_LIST))
+$(MAKEFILE):
+
+package.version := 0.0.1
+package.jar := sqlite3-jni-$(package.version).jar
+
+dir.top := ../..
+dir.jni := $(patsubst %/,%,$(dir $(MAKEFILE)))
+
+dir.src := $(dir.jni)/src
+dir.src.c := $(dir.src)/c
+dir.bld := $(dir.jni)/bld
+dir.bld.c := $(dir.bld)
+dir.src.jni := $(dir.src)/org/sqlite/jni
+$(dir.bld.c):
+ mkdir -p $@
+
+classpath := $(dir.src)
+CLEAN_FILES := $(package.jar)
+DISTCLEAN_FILES := $(dir.jni)/*~ $(dir.src.c)/*~ $(dir.src.jni)/*~
+
+sqlite3-jni.h := $(dir.src.c)/sqlite3-jni.h
+.NOTPARALLEL: $(sqlite3-jni.h)
+SQLite3Jni.java := src/org/sqlite/jni/SQLite3Jni.java
+SQLite3Jni.class := $(subst .java,.class,$(SQLite3Jni.java))
+#$(sqlite3-jni.h): $(SQLite3Jni.java) $(dir.bld.c)
+# $(bin.javac) -h $(dir $@) $<
+#all: $(sqlite3-jni.h)
+
+JAVA_FILES := $(wildcard $(dir.src.jni)/*.java)
+CLASS_FILES :=
+define DOTCLASS_DEPS
+$(1).class: $(1).java
+all: $(1).class
+CLASS_FILES += $(1).class
+endef
+$(foreach B,$(basename $(JAVA_FILES)),$(eval $(call DOTCLASS_DEPS,$(B))))
+javac.flags ?= -Xlint:unchecked -Xlint:deprecation
+java.flags ?=
+jnicheck ?= 1
+ifeq (1,$(jnicheck))
+ java.flags += -Xcheck:jni
+endif
+$(SQLite3Jni.class): $(JAVA_FILES)
+ $(bin.javac) $(javac.flags) -h $(dir.bld.c) -cp $(classpath) $(JAVA_FILES)
+all: $(SQLite3Jni.class)
+#.PHONY: classfiles
+
+########################################################################
+# Set up sqlite3.c and sqlite3.h...
+#
+# To build with SEE (https://sqlite.org/see), either put sqlite3-see.c
+# in the top of this build tree or pass
+# sqlite3.c=PATH_TO_sqlite3-see.c to the build. Note that only
+# encryption modules with no 3rd-party dependencies will currently
+# work here: AES256-OFB, AES128-OFB, and AES128-CCM. Not
+# coincidentally, those 3 modules are included in the sqlite3-see.c
+# bundle.
+#
+# A custom sqlite3.c must not have any spaces in its name.
+# $(sqlite3.canonical.c) must point to the sqlite3.c in
+# the sqlite3 canonical source tree, as that source file
+# is required for certain utility and test code.
+sqlite3.canonical.c := $(dir.top)/sqlite3.c
+sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c))
+sqlite3.h := $(dir.top)/sqlite3.h
+#ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c) 2>/dev/null))
+# SQLITE_C_IS_SEE := 0
+#else
+# SQLITE_C_IS_SEE := 1
+# $(info This is an SEE build.)
+#endif
+
+.NOTPARALLEL: $(sqlite3.h)
+$(sqlite3.h):
+ $(MAKE) -C $(dir.top) sqlite3.c
+$(sqlite3.c): $(sqlite3.h)
+
+SQLITE_OPT := \
+ -DSQLITE_ENABLE_FTS5 \
+ -DSQLITE_ENABLE_RTREE \
+ -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
+ -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
+ -DSQLITE_ENABLE_STMTVTAB \
+ -DSQLITE_ENABLE_DBPAGE_VTAB \
+ -DSQLITE_ENABLE_DBSTAT_VTAB \
+ -DSQLITE_ENABLE_BYTECODE_VTAB \
+ -DSQLITE_ENABLE_OFFSET_SQL_FUNC \
+ -DSQLITE_OMIT_LOAD_EXTENSION \
+ -DSQLITE_OMIT_DEPRECATED \
+ -DSQLITE_OMIT_SHARED_CACHE \
+ -DSQLITE_OMIT_WAL \
+ -DSQLITE_THREADSAFE=0 \
+ -DSQLITE_TEMP_STORE=2 \
+ -DSQLITE_USE_URI=1 \
+ -DSQLITE_C=$(sqlite3.c) \
+ -DSQLITE_DEBUG
+# -DSQLITE_DEBUG is just to work around a -Wall warning
+# for a var which gets set in all builds but only read
+# via assert().
+
+sqlite3-jni.c := $(dir.src.c)/sqlite3-jni.c
+sqlite3-jni.o := $(dir.bld.c)/sqlite3-jni.o
+sqlite3-jni.h.in := $(dir.bld.c)/org_sqlite_jni_SQLite3Jni.h
+sqlite3-jni.h := $(dir.src.c)/sqlite3-jni.h
+sqlite3-jni.dll := $(dir.bld.c)/libsqlite3-jni.so
+# ------------------------------^^^ lib prefix is requires
+# for java's System.loadLibrary().
+#sqlite3-jni.dll.cfiles := $(dir.src.c)
+sqlite3-jni.dll.cflags := \
+ -fPIC \
+ -I. \
+ -I$(dir $(sqlite3.h)) \
+ -I$(dir.src.c) \
+ -I$(JDK_HOME)/include \
+ $(patsubst %,-I%,$(patsubst %.h,,$(wildcard $(JDK_HOME)/include/*))) \
+ -Wall
+# Using (-Wall -Wextra) triggers an untennable number of
+# gcc warnings from sqlite3.c for mundane things like
+# unused parameters.
+#
+# The gross $(patsubst...) above is to include the platform-specific
+# subdir which lives under $(JDK_HOME)/include and is a required
+# include path for client-level code.
+########################################################################
+
+$(sqlite3-jni.h.in): $(dir.src.jni)/SQLite3Jni.class
+$(sqlite3-jni.h): $(sqlite3-jni.h.in) $(MAKEFILE)
+ cp -p $(sqlite3-jni.h.in) $@
+$(sqlite3-jni.c): $(sqlite3-jni.h) $(sqlite3.c) $(sqlite3.h)
+$(sqlite3-jni.dll): $(dir.bld.c) $(sqlite3-jni.c) $(SQLite3Jni.java) $(MAKEFILE)
+ $(CC) $(sqlite3-jni.dll.cflags) $(SQLITE_OPT) \
+ $(sqlite3-jni.c) -shared -o $@
+all: $(sqlite3-jni.dll)
+
+test: $(SQLite3Jni.class) $(sqlite3-jni.dll)
+ $(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
+ $(java.flags) -cp $(classpath) org.sqlite.jni.Tester1
+
+$(package.jar): $(CLASS_FILES) $(MAKEFILE)
+ rm -f $(dir.src)/c/*~ $(dir.src.jni)/*~
+ $(bin.jar) -cfe $@ org.sqlite.Tester1 -C src org -C src c
+
+jar: $(package.jar)
+
+CLEAN_FILES += $(dir.bld.c)/* \
+ $(dir.src.jni)/*.class \
+ $(sqlite3-jni.dll) \
+ hs_err_pid*.log
+
+.PHONY: clean distclean
+clean:
+ -rm -f $(CLEAN_FILES)
+distclean: clean
+ -rm -f $(DISTCLEAN_FILES)
+ -rm -fr $(dir.bld.c)
--- /dev/null
+SQLite3 via JNI
+========================================================================
+
+This repository houses a Java Native Interface (JNI) binding for the
+sqlite3 API.
+
+> **FOREWARNING:** this project is very much in development and
+ subject to any number of changes. Please do not rely on any
+ information about its API until this disclaimer is removed.
+
+Project goals/requirements:
+
+- A [1-to-1(-ish) mapping of the C API](#1to1ish) to Java via JNI,
+ insofar as cross-language semantics allow for. A closely-related
+ goal is that [the C documentation](www:/c3ref/intro.html)
+ should be usable as-is, insofar as possible, for the JNI binding.
+
+- Support Java as far back as version 8 (2014).
+
+- Environment-independent. Should work everywhere both Java
+ and SQLite3 do.
+
+- No 3rd-party dependencies beyond the JDK. That includes no
+ build-level dependencies for specific IDEs and toolchains. We
+ welcome the addition of build files for arbitrary environments
+ insofar as they do not directly interfere with each other.
+
+Non-goals:
+
+- Creation of high-level OO wrapper APIs. Clients are free to create
+ them off of the C-style API.
+
+
+Significant TODOs
+========================================================================
+
+- LOTS of APIs left to bind.
+
+- Bundling of the resulting class files into a jar. Bundling the DLLs
+ is a much larger problem, as they inherently have platform-specific
+ OS-level dependencies which we obviously cannot bundle.
+
+
+Building
+========================================================================
+
+The canonical builds assumes a Linux-like environment and requires:
+
+- GNU Make
+- A JDK supporting Java 8 or higher
+- A modern C compiler. gcc and clang should both work.
+
+Put simply:
+
+```
+$ export JDK_HOME=/path/to/jdk/root
+$ make
+$ make test
+$ make clean
+```
+
+<a id='1to1ish'></a>
+One-to-One(-ish) Mapping to C
+========================================================================
+
+This JNI binding aims to provide as close to a 1-to-1 experience with
+the C API as cross-language semantics allow. Exceptions are
+necessarily made where cross-language semantics do not allow a 1-to-1,
+and judiciously made where a 1-to-1 mapping would be unduly cumbersome
+to use in Java.
+
+Golden Rule: _Never_ Throw from Callbacks
+------------------------------------------------------------------------
+
+JNI bindings which accept client-defined functions _must never throw
+exceptions_. There are _no exceptions_ to this rule. Exceptions are
+reserved for higher-level bindings which are constructed to
+specifically deal with them and ensure that they do not leak C-level
+resources. Some of the JNI bindings are provided as Java functions
+which expect this rule to always hold.
+
+UTF-8(-ish)
+------------------------------------------------------------------------
+
+SQLite internally uses UTF-8 encoding, whereas Java natively uses
+UTF-16. Java JNI has routines for converting to and from UTF-8, _but_
+Java uses what its docs call "[modified UTF-8][modutf8]." Care must be
+taken when converting Java strings to UFF-8 to ensure that the proper
+conversion is performed. In short,
+`String.getBytes(StandardCharsets.UTF_8)` performs the proper
+conversion in Java, and there is no JNI C API for that conversion
+(JNI's `NewStringUTF()` returns MUTF-8).
+
+[modutf8]: https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html#modified-utf-8
+
+
+Unweildy Constructs are Re-mapped
+------------------------------------------------------------------------
+
+Some constructs, when modelled 1-to-1 from C to Java, are unduly
+clumsy to work with in Java because they try to shoehorn C's way of
+doing certain things into Java's wildly different ways. The following
+subsections cover those, starting with a verbose explanation and
+demonstration of where such changes are "really necessary"...
+
+### Custom Collations
+
+A prime example of where interface changes for Java are necessary for
+usability is [registration of a custom
+collation](www:/c3ref/create_collation.html):
+
+```
+// C:
+int sqlite3_create_collation(sqlite3 * db, const char * name, int eTextRep,
+ void *pUserData,
+ int (*xCompare)(void*,int,void const *,int,void const *));
+
+int sqlite3_create_collation_v2(sqlite3 * db, const char * name, int eTextRep,
+ void *pUserData,
+ int (*xCompare)(void*,int,void const *,int,void const *),
+ void (*xDestroy)(void*));
+```
+
+The `pUserData` object is optional client-defined state for the
+`xCompare()` and/or `xDestroy()` callback functions, both of which are
+passed that object as their first argument. That data is passed around
+"externally" in C because that's how C models the world. If we were to
+bind that part as-is to Java, the result would be awkward to use (^Yes,
+we tried this.):
+
+```
+// Java:
+int sqlite3_create_collation(sqlite3 db, String name, int eTextRep,
+ Object pUserData, xCompareType xCompare);
+
+int sqlite3_create_collation_v2(sqlite3 db, String name, int eTextRep,
+ Object pUserData,
+ xCompareType xCompare, xDestroyType xDestroy);
+```
+
+The awkwardness comes from (A) having two distinctly different objects
+for callbacks and (B) having their internal state provided separately,
+which is ill-fitting in Java. For the sake of usability, C APIs which
+follow that pattern use a slightly different Java interface:
+
+```
+int sqlite3_create_collation(sqlite3 db, String name, int eTextRep,
+ Collation collation);
+```
+
+Where the `Collation` class has an abstract `xCompare()` method and
+no-op `xDestroy()` method which can be overridden if needed, leading to
+a much more Java-esque usage:
+
+```
+int rc = sqlite3_create_collation(db, "mycollation", SQLITE_UTF8, new Collation(){
+ // Required comparison function:
+ @Override public int xCompare(byte[] lhs, byte[] rhs){ ... }
+ // Optional finalizer function:
+ @Override public void xDestroy(){ ... }
+ // Optional local state:
+ private String localState1 =
+ "This is local state. There are many like it, but this one is mine.";
+ private MyStateType localState2 = new MyStateType();
+ ...
+});
+```
+
+Noting that:
+
+- It is still possible to bind in call-scope-local state via closures,
+ but using member data for the Collation object is generally a better
+ fit for Java.
+
+- No capabilities of the C API are lost or unduly obscured via the
+ above API reshaping, so power users need not make any compromises.
+
+- In the specific example above, `sqlite3_create_collation_v2()`
+ becomes superfluous because the provided interface effectively
+ provides both the v1 and v2 interfaces, the difference being that
+ overriding the `xDestroy()` method effectively gives it v2
+ semantics.
+
+### User-defined SQL Functions (a.k.a. UDFs)
+
+The [`sqlite3_create_function()`](www:/c3ref/create_function.html)
+family of APIs make heavy use of function pointers to provide
+client-defined callbacks, necessitating interface changes in the JNI
+binding. The Jav API has only one core function-registration function:
+
+```
+int sqlite3_create_function(sqlite3 db, String funcName, int nArgs,
+ int encoding, SQLFunction func);
+```
+
+`SQLFunction` is not used directly, but is instead instantiated via
+one of its three subclasses:
+
+- `SQLFunction.Scalar` implements simple scalar functions using but a
+ single callback.
+- `SQLFunction.Aggregate` implements aggregate functions using two
+ callbacks.
+- `SQLFunction.Window` implements window functions using four
+ callbacks.
+
+Search [`Tester1.java`](/file/src/org/sqlite/jni/Tester1.java) for
+`SQLFunction` for how it's used.
+
+Reminder: see the disclaimer at the top of this document regarding the
+in-flux nature of this API.
+
+[jsrc]: /file/
+[www]: https://sqlite.org
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements the JNI bindings declared in
+** org.sqlite.jni.SQLiteJni (from which sqlite3-jni.h is generated).
+*/
+
+/*
+** Define any SQLITE_... config defaults we want if they aren't
+** overridden by the builder. Please keep these alphabetized.
+*/
+
+/**********************************************************************/
+/* SQLITE_D... */
+#ifndef SQLITE_DEFAULT_CACHE_SIZE
+# define SQLITE_DEFAULT_CACHE_SIZE -16384
+#endif
+#if !defined(SQLITE_DEFAULT_PAGE_SIZE)
+# define SQLITE_DEFAULT_PAGE_SIZE 8192
+#endif
+#ifndef SQLITE_DEFAULT_UNIX_VFS
+# define SQLITE_DEFAULT_UNIX_VFS "unix"
+#endif
+#undef SQLITE_DQS
+#define SQLITE_DQS 0
+
+/**********************************************************************/
+/* SQLITE_ENABLE_... */
+#ifndef SQLITE_ENABLE_BYTECODE_VTAB
+# define SQLITE_ENABLE_BYTECODE_VTAB 1
+#endif
+#ifndef SQLITE_ENABLE_DBPAGE_VTAB
+# define SQLITE_ENABLE_DBPAGE_VTAB 1
+#endif
+#ifndef SQLITE_ENABLE_DBSTAT_VTAB
+# define SQLITE_ENABLE_DBSTAT_VTAB 1
+#endif
+#ifndef SQLITE_ENABLE_EXPLAIN_COMMENTS
+# define SQLITE_ENABLE_EXPLAIN_COMMENTS 1
+#endif
+#ifndef SQLITE_ENABLE_FTS4
+# define SQLITE_ENABLE_FTS4 1
+#endif
+#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
+# define SQLITE_ENABLE_MATH_FUNCTIONS 1
+#endif
+#ifndef SQLITE_ENABLE_OFFSET_SQL_FUNC
+# define SQLITE_ENABLE_OFFSET_SQL_FUNC 1
+#endif
+#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
+# define SQLITE_ENABLE_PREUPDATE_HOOK 1 /*required by session extension*/
+#endif
+#ifndef SQLITE_ENABLE_RTREE
+# define SQLITE_ENABLE_RTREE 1
+#endif
+#ifndef SQLITE_ENABLE_SESSION
+# define SQLITE_ENABLE_SESSION 1
+#endif
+#ifndef SQLITE_ENABLE_STMTVTAB
+# define SQLITE_ENABLE_STMTVTAB 1
+#endif
+#ifndef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+# define SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+#endif
+
+/**********************************************************************/
+/* SQLITE_M... */
+#ifndef SQLITE_MAX_ALLOCATION_SIZE
+# define SQLITE_MAX_ALLOCATION_SIZE 0x1fffffff
+#endif
+
+/**********************************************************************/
+/* SQLITE_O... */
+#ifndef SQLITE_OMIT_DEPRECATED
+# define SQLITE_OMIT_DEPRECATED 1
+#endif
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+# define SQLITE_OMIT_LOAD_EXTENSION 1
+#endif
+#ifndef SQLITE_OMIT_SHARED_CACHE
+# define SQLITE_OMIT_SHARED_CACHE 1
+#endif
+#ifdef SQLITE_OMIT_UTF16
+/* UTF16 is required for java */
+# undef SQLITE_OMIT_UTF16 1
+#endif
+
+/**********************************************************************/
+/* SQLITE_T... */
+#ifndef SQLITE_TEMP_STORE
+# define SQLITE_TEMP_STORE 2
+#endif
+#ifndef SQLITE_THREADSAFE
+# define SQLITE_THREADSAFE 0
+#endif
+
+/**********************************************************************/
+/* SQLITE_USE_... */
+#ifndef SQLITE_USE_URI
+# define SQLITE_USE_URI 1
+#endif
+
+
+/*
+** Which sqlite3.c we're using needs to be configurable to enable
+** building against a custom copy, e.g. the SEE variant. We have to
+** include sqlite3.c, as opposed to sqlite3.h, in order to get access
+** to SQLITE_MAX_... and friends. This increases the rebuild time
+** considerably but we need this in order to keep the exported values
+** of SQLITE_MAX_... and SQLITE_LIMIT_... in sync with the C build.
+*/
+#ifndef SQLITE_C
+# define SQLITE_C sqlite3.c
+#endif
+#define INC__STRINGIFY_(f) #f
+#define INC__STRINGIFY(f) INC__STRINGIFY_(f)
+#include INC__STRINGIFY(SQLITE_C)
+#undef INC__STRINGIFY_
+#undef INC__STRINGIFY
+#undef SQLITE_C
+
+#include "sqlite3-jni.h"
+#include <stdio.h> /* only for testing/debugging */
+#include <assert.h>
+
+/* Only for debugging */
+#define MARKER(pfexp) \
+ do{ printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); \
+ printf pfexp; \
+ } while(0)
+
+/* Creates a verbose JNI function name. */
+#define JFuncName(Suffix) \
+ Java_org_sqlite_jni_SQLite3Jni_sqlite3_ ## Suffix
+
+/* Prologue for JNI functions. */
+#define JDECL(ReturnType,Suffix) \
+ JNIEXPORT ReturnType JNICALL \
+ JFuncName(Suffix)
+/* First 2 parameters to all JNI bindings. */
+#define JENV_JSELF JNIEnv * env, jobject jSelf
+/* Helper to squelch -Xcheck:jni warnings about
+ not having checked for exceptions. */
+#define IFTHREW if((*env)->ExceptionCheck(env))
+#define EXCEPTION_IGNORE (void)((*env)->ExceptionCheck(env))
+#define EXCEPTION_CLEAR (*env)->ExceptionClear(env)
+#define EXCEPTION_REPORT (*env)->ExceptionDescribe(env)
+#define IFTHREW_REPORT IFTHREW EXCEPTION_REPORT
+
+
+#define PtrGet_sqlite3(OBJ) getNativePointer(env,OBJ,ClassNames.sqlite3)
+#define PtrGet_sqlite3_stmt(OBJ) getNativePointer(env,OBJ,ClassNames.sqlite3_stmt)
+#define PtrGet_sqlite3_value(OBJ) getNativePointer(env,OBJ,ClassNames.sqlite3_value)
+#define PtrGet_sqlite3_context(OBJ) getNativePointer(env,OBJ,ClassNames.sqlite3_context)
+#define REF_G(VAR) (*env)->NewGlobalRef(env, VAR)
+/*#define REF_L(VAR) (*env)->NewLocalRef(env, VAR)*/
+#define UNREF_G(VAR) if(VAR) (*env)->DeleteGlobalRef(env, (VAR))
+#define UNREF_L(VAR) if(VAR) (*env)->DeleteLocalRef(env, (VAR))
+
+/**
+ Constant string class names used as keys for S3Global_nph_cache() and
+ friends.
+*/
+static const struct {
+ const char * const sqlite3;
+ const char * const sqlite3_stmt;
+ const char * const sqlite3_context;
+ const char * const sqlite3_value;
+ const char * const OutputPointer_Int32;
+} ClassNames = {
+ "org/sqlite/jni/sqlite3",
+ "org/sqlite/jni/sqlite3_stmt",
+ "org/sqlite/jni/sqlite3_context",
+ "org/sqlite/jni/sqlite3_value",
+ "org/sqlite/jni/OutputPointer$Int32"
+};
+
+/** Create a trivial JNI wrapper for (int CName(void)). */
+#define WRAP_INT_VOID(JniNameSuffix,CName) \
+ JDECL(jint,JniNameSuffix)(JNIEnv *env, jobject jSelf){ \
+ return (jint)CName(); \
+ }
+
+#define WRAP_INT_INT(JniNameSuffix,CName) \
+ JDECL(jint,JniNameSuffix)(JNIEnv *env, jobject jSelf, jint arg){ \
+ return (jint)CName((int)arg); \
+ }
+
+/** Create a trivial JNI wrapper for (const mutf8_string *
+ CName(void)). This is only value for functions which are known to
+ return ASCII or text compatible with Modified UTF8. */
+#define WRAP_MUTF8_VOID(JniNameSuffix,CName) \
+ JDECL(jstring,JniNameSuffix)(JENV_JSELF){ \
+ return (*env)->NewStringUTF( env, CName() ); \
+ }
+/** Create a trivial JNI wrapper for (int CName(sqlite3_stmt*)). */
+#define WRAP_INT_STMT(JniNameSuffix,CName) \
+ JDECL(jint,JniNameSuffix)(JENV_JSELF, jobject jpStmt){ \
+ jint const rc = (jint)CName(PtrGet_sqlite3_stmt(jpStmt)); \
+ EXCEPTION_IGNORE /* squelch -Xcheck:jni */; \
+ return rc; \
+ }
+/** Create a trivial JNI wrapper for (int CName(sqlite3*)). */
+#define WRAP_INT_DB(JniNameSuffix,CName) \
+ JDECL(jint,JniNameSuffix)(JENV_JSELF, jobject pDb){ \
+ return (jint)CName(PtrGet_sqlite3(pDb)); \
+ }
+/** Create a trivial JNI wrapper for (int64 CName(sqlite3*)). */
+#define WRAP_INT64_DB(JniNameSuffix,CName) \
+ JDECL(jlong,JniNameSuffix)(JENV_JSELF, jobject pDb){ \
+ return (jlong)CName(PtrGet_sqlite3(pDb)); \
+ }
+/** Create a trivial JNI wrapper for (int CName(sqlite3_stmt*,int)). */
+#define WRAP_INT_STMT_INT(JniNameSuffix,CName) \
+ JDECL(jint,JniNameSuffix)(JENV_JSELF, jobject pStmt, jint n){ \
+ return (jint)CName(PtrGet_sqlite3_stmt(pStmt), (int)n); \
+ }
+/** Create a trivial JNI wrapper for (jstring CName(sqlite3_stmt*,int)). */
+#define WRAP_STR_STMT_INT(JniNameSuffix,CName) \
+ JDECL(jstring,JniNameSuffix)(JENV_JSELF, jobject pStmt, jint ndx){ \
+ return (*env)->NewStringUTF(env, CName(PtrGet_sqlite3_stmt(pStmt), (int)ndx)); \
+ }
+/** Create a trivial JNI wrapper for (int CName(sqlite3_value*)). */
+#define WRAP_INT_SVALUE(JniNameSuffix,CName) \
+ JDECL(jint,JniNameSuffix)(JENV_JSELF, jobject jpSValue){ \
+ return (jint)CName(PtrGet_sqlite3_value(jpSValue)); \
+ }
+
+/* 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) (*env)->ReleaseByteArrayElements(env, ARG, VAR, JNI_ABORT)
+
+/* Marker for code which needs(?) to be made thread-safe. */
+#define FIXME_THREADING
+
+enum {
+ /**
+ Size of the per-JNIEnv cache. We have no way of knowing how many
+ distinct JNIEnv's will be used in any given run, but know that it
+ will normally be only 1. Perhaps (just speculating) differen
+ threads use separate JNIEnvs? If that's the case, we don't(?)
+ have enough info to evict from the cache when those JNIEnvs
+ expire.
+
+ If this ever fills up, we can refactor this to dynamically
+ allocate them.
+ */
+ JNIEnvCache_SIZE = 10,
+ /**
+ 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 be triggered with a reminder to increase this.
+ */
+ NphCache_SIZE = 10
+};
+
+/**
+ Cache for NativePointerHolder lookups.
+*/
+typedef struct NphCacheLine NphCacheLine;
+struct NphCacheLine {
+ const char * zClassName /* "full/class/Name" */;
+ jclass klazz /* global ref to concrete NPH class */;
+ jmethodID midSet /* setNativePointer() */;
+ jmethodID midGet /* getNativePointer() */;
+ jmethodID midCtor /* constructor */;
+};
+
+typedef struct JNIEnvCacheLine JNIEnvCacheLine;
+struct JNIEnvCacheLine {
+ JNIEnv *env;
+ jclass globalClassObj /* global ref to java.lang.Object */;
+ jclass globalClassLong /* global ref to java.lang.Long */;
+ jmethodID ctorLong1 /* the Long(long) constructor */;
+ struct NphCacheLine nph[NphCache_SIZE];
+};
+typedef struct JNIEnvCache JNIEnvCache;
+struct JNIEnvCache {
+ struct JNIEnvCacheLine lines[JNIEnvCache_SIZE];
+ unsigned int used;
+};
+
+static void NphCacheLine_clear(JNIEnv *env, NphCacheLine * p){
+ UNREF_G(p->klazz);
+ memset(p, 0, sizeof(NphCacheLine));
+}
+
+static void JNIEnvCacheLine_clear(JNIEnvCacheLine * p){
+ JNIEnv *env = p->env;
+ int i;
+ if(env){
+ UNREF_G(p->globalClassObj);
+ UNREF_G(p->globalClassLong);
+ i = 0;
+ for( ; i < NphCache_SIZE; ++i){
+ NphCacheLine_clear(env, &p->nph[i]);
+ }
+ }
+}
+
+static void JNIEnvCache_clear(JNIEnvCache * p){
+ unsigned int i = 0;
+ for( ; i < p->used; ++i ){
+ JNIEnvCacheLine_clear( &p->lines[i] );
+ }
+ memset(p, 0, sizeof(JNIEnvCache));
+}
+
+/**
+ Per-(sqlite3*) state for bindings which do not have their own
+ finalizer functions, e.g. tracing and commit/rollback hooks. This
+ state is allocated as needed, cleaned up in sqlite3_close(_v2)(),
+ and recycled when possible. It is freed during sqlite3_shutdown().
+
+ Open questions:
+
+ - Do we need to do a (JNIEnv*) for the db and each set of binding
+ data (since they can(?) hypothetically be set via multiple JNIEnv
+ objects)?
+*/
+typedef struct PerDbState PerDbState;
+struct PerDbState {
+ JNIEnv *env;
+ sqlite3 * pDb;
+ PerDbState * pNext;
+ PerDbState * pPrev;
+ struct {
+ jobject jObj;
+ jmethodID midCallback;
+ } trace;
+ struct {
+ jobject jObj;
+ jmethodID midCallback;
+ } progress;
+ struct {
+ jobject jObj;
+ jmethodID midCallback;
+ } commitHook;
+ struct {
+ jobject jObj;
+ jmethodID midCallback;
+ } rollbackHook;
+};
+
+static struct {
+ /**
+ According to: https://developer.ibm.com/articles/j-jni/
+
+ > A thread can get a JNIEnv by calling GetEnv() using the JNI
+ invocation interface through a JavaVM object. The JavaVM object
+ itself can be obtained by calling the JNI GetJavaVM() method
+ using a JNIEnv object and can be cached and shared across
+ threads. Caching a copy of the JavaVM object enables any thread
+ with access to the cached object to get access to its own
+ JNIEnv when necessary.
+ */
+ JavaVM * jvm;
+ struct JNIEnvCache envCache;
+ struct {
+ PerDbState * aUsed;
+ PerDbState * aFree;
+ } perDb;
+} S3Global;
+
+/**
+ sqlite3_malloc() proxy which fails fatally on OOM. This should
+ only be used for routines which manage global state and have no
+ recovery strategy for OOM. For sqlite3 API which can reasonably
+ return SQLITE_NOMEM, sqlite3_malloc() should be used instead.
+*/
+static void * s3jni_malloc(JNIEnv *env, size_t n){
+ void * rv = sqlite3_malloc(n);
+ if(n && !rv){
+ (*env)->FatalError(env, "Out of memory.") /* does not return */;
+ }
+ return rv;
+}
+
+static void s3jni_free(void * p){
+ if(p) sqlite3_free(p);
+}
+/**
+ Extracts the new PerDbState instance from the free-list, or
+ allocates one if needed, associats it with pDb, and returns.
+ Returns NULL on OOM.
+*/
+static PerDbState * PerDbState_alloc(JNIEnv *env, sqlite3 *pDb){
+ PerDbState * rv;
+ assert( pDb );
+ if(S3Global.perDb.aFree){
+ rv = S3Global.perDb.aFree;
+ S3Global.perDb.aFree = rv->pNext;
+ if(rv->pNext){
+ assert(rv->pNext->pPrev == rv);
+ assert(rv->pNext == rv->pNext->pPrev);
+ rv->pNext->pPrev = 0;
+ rv->pNext = 0;
+ }
+ }else{
+ rv = s3jni_malloc(env, sizeof(PerDbState));
+ if(rv){
+ memset(rv, 0, sizeof(PerDbState));
+ rv->pNext = S3Global.perDb.aUsed;
+ S3Global.perDb.aUsed = rv;
+ if(rv->pNext){
+ assert(!rv->pNext->pPrev);
+ rv->pNext->pPrev = rv;
+ }
+ }
+ }
+ if(rv){
+ rv->pDb = pDb;
+ rv->env = env;
+ }
+ return rv;
+}
+
+/**
+ Clears s's state and moves it to the free-list.
+*/
+FIXME_THREADING
+static void PerDbState_set_aside(PerDbState *s){
+ if(s){
+ JNIEnv * const env = s->env;
+ assert(s->pDb && "Else this object is already in the free-list.");
+ if(s->pNext) s->pNext->pPrev = s->pPrev;
+ if(s->pPrev) s->pPrev->pNext = s->pNext;
+ else if(S3Global.perDb.aUsed == s){
+ assert(!s->pPrev);
+ S3Global.perDb.aUsed = s->pNext;
+ }
+ UNREF_G(s->trace.jObj);
+ UNREF_G(s->progress.jObj);
+ UNREF_G(s->commitHook.jObj);
+ UNREF_G(s->rollbackHook.jObj);
+ s->env = 0;
+ s->pDb = 0;
+ s->pPrev = 0;
+ s->pNext = S3Global.perDb.aFree;
+ S3Global.perDb.aFree = s;
+ }
+}
+
+/**
+ Returns the PerDbState object for the given db. If allocIfNeeded is
+ true then a new instance will be allocated if no mapping currently
+ exists, else NULL is returned if no mapping is found.
+
+*/
+FIXME_THREADING
+static PerDbState * PerDbState_for_db(JNIEnv *env, sqlite3 *pDb, int allocIfNeeded){
+ PerDbState * s = S3Global.perDb.aUsed;
+ for( ; s; s = s->pNext){
+ if(s->pDb == pDb) return s;
+ }
+ if(allocIfNeeded) s = PerDbState_alloc(env, pDb);
+ return s;
+}
+
+/**
+ Cleans up and frees all state in S3Global.perDb.
+*/
+FIXME_THREADING
+static void PerDbState_free_all(void){
+ PerDbState * pS = S3Global.perDb.aUsed;
+ PerDbState * pSNext = 0;
+ for( ; pS; pS = pSNext ){
+ pSNext = pS->pNext;
+ PerDbState_set_aside(pS);
+ assert(pSNext ? !pSNext->pPrev : 1);
+ }
+ assert( 0==S3Global.perDb.aUsed );
+ pS = S3Global.perDb.aFree;
+ S3Global.perDb.aFree = 0;
+ pSNext = 0;
+ for( ; pS; pS = pSNext ){
+ pSNext = pS->pNext;
+ s3jni_free(pSNext);
+ }
+}
+
+/**
+ Fetches the S3Global.envCache row for the given env, allocing
+ a row if needed. When a row is allocated, its state is initialized
+ insofar as possible. Calls (*env)->FatalError() if the cache
+ fills up. That's hypothetically possible but "shouldn't happen."
+ If it does, we can dynamically allocate these instead.
+
+*/
+FIXME_THREADING
+static struct JNIEnvCacheLine * S3Global_env_cache(JNIEnv * env){
+ struct JNIEnvCacheLine * row = 0;
+ int i = 0;
+ for( ; i < JNIEnvCache_SIZE; ++i ){
+ row = &S3Global.envCache.lines[i];
+ if(row->env == env) return row;
+ else if(!row->env) break;
+ }
+ if(i == JNIEnvCache_SIZE){
+ (*env)->FatalError(env, "Maintenance required: JNIEnvCache is full.");
+ return NULL;
+ }
+ row->env = env;
+ row->globalClassObj = REF_G((*env)->FindClass(env,"java/lang/Object"));
+ row->globalClassLong = REF_G((*env)->FindClass(env,"java/lang/Long"));
+ row->ctorLong1 = (*env)->GetMethodID(env, row->globalClassLong,
+ "<init>", "(J)V");
+ ++S3Global.envCache.used;
+ //MARKER(("Added S3Global.envCache entry #%d.\n", S3Global.envCache.used));
+ return row;
+}
+
+/**
+ Searches the NativePointerHolder cache for the given combination.
+ If it finds one, it returns it as-is. If it doesn't AND the cache
+ has a free slot, it populates that slot with (env, zClassName,
+ klazz) and returns it. If the cache is full with no match it
+ returns NULL.
+
+ It is up to the caller to populate the other members of the returned
+ object if needed.
+
+ zClassName must be a static string so we can use its address as a
+ cache key.
+
+ This simple cache catches the overwhelming majority of searches
+ (>95%) in the current (2023-07-24) tests.
+*/
+FIXME_THREADING
+static struct NphCacheLine * S3Global_nph_cache(JNIEnv *env, const char *zClassName){
+ /**
+ According to:
+
+ https://developer.ibm.com/articles/j-jni/
+
+ > ... the IDs returned for a given class don't change for the
+ lifetime of the JVM process. But the call to get the field or
+ method can require significant work in the JVM, because
+ fields and methods might have been inherited from
+ superclasses, making the JVM walk up the class hierarchy to
+ find them. Because the IDs are the same for a given class,
+ you should look them up once and then reuse them. Similarly,
+ looking up class objects can be expensive, so they should be
+ cached as well.
+ */
+ struct JNIEnvCacheLine * const envRow = S3Global_env_cache(env);
+ struct NphCacheLine * freeSlot = 0;
+ struct NphCacheLine * cacheLine = 0;
+ int i;
+ assert(envRow);
+ for( i = 0; i < NphCache_SIZE; ++i ){
+ cacheLine = &envRow->nph[i];
+ if(zClassName == cacheLine->zClassName){
+#if 0
+ static unsigned int n = 0;
+ MARKER(("Cache hit #%u %s klazz@%p getter@%p, setter@%p, ctor@%p\n",
+ ++n, zClassName, cacheLine->klazz, cacheLine->midGet,
+ cacheLine->midSet, cacheLine->midCtor));
+#endif
+ assert(cacheLine->klazz);
+ return cacheLine;
+ }else if(!freeSlot && !cacheLine->zClassName){
+ freeSlot = cacheLine;
+ }
+ }
+ if(freeSlot){
+ freeSlot->zClassName = zClassName;
+ freeSlot->klazz = REF_G((*env)->FindClass(env, zClassName));
+#if 0
+ static unsigned int cacheMisses = 0;
+ MARKER(("Cache miss #%u %s klazz@%p getter@%p, setter@%p, ctor@%p\n",
+ ++cacheMisses, zClassName, freeSlot->klazz,
+ freeSlot->midGet, freeSlot->midSet, freeSlot->midCtor));
+#endif
+ }else{
+ (*env)->FatalError(env, "MAINTENANCE REQUIRED: NphCache_SIZE is too low.");
+ }
+ return freeSlot;
+}
+
+/**
+ Sets a native ptr value in NativePointerHolder object ppOut.
+ zClassName must be a static string so we can use its address
+ as a cache key.
+*/
+static void setNativePointer(JNIEnv * env, jobject ppOut, void * p,
+ const char *zClassName){
+ jmethodID setter = 0;
+ struct NphCacheLine * const cacheLine = S3Global_nph_cache(env, zClassName);
+ if(cacheLine && cacheLine->klazz && cacheLine->midSet){
+ assert(zClassName == cacheLine->zClassName);
+ setter = cacheLine->midSet;
+ assert(setter);
+ }else{
+ jclass const klazz =
+ cacheLine ? cacheLine->klazz : (*env)->GetObjectClass(env, ppOut);
+ setter = (*env)->GetMethodID(env, klazz, "setNativePointer", "(J)V");
+ if(cacheLine){
+ assert(cacheLine->klazz);
+ assert(!cacheLine->midSet);
+ assert(zClassName == cacheLine->zClassName);
+ cacheLine->midSet = setter;
+ }
+ }
+ (*env)->CallVoidMethod(env, ppOut, setter, (jlong)p);
+ IFTHREW_REPORT;
+}
+
+/**
+ Fetches a native ptr value from NativePointerHolder object ppOut.
+ 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{
+ jmethodID getter = 0;
+ void * rv = 0;
+ struct NphCacheLine * const cacheLine = S3Global_nph_cache(env, zClassName);
+ if(cacheLine && cacheLine->midGet){
+ getter = cacheLine->midGet;
+ }else{
+ jclass const klazz =
+ cacheLine ? cacheLine->klazz : (*env)->GetObjectClass(env, pObj);
+ getter = (*env)->GetMethodID(env, klazz, "getNativePointer", "()J");
+ if(cacheLine){
+ assert(cacheLine->klazz);
+ assert(zClassName == cacheLine->zClassName);
+ cacheLine->midGet = getter;
+ }
+ }
+ rv = (void*)(*env)->CallLongMethod(env, pObj, getter);
+ IFTHREW_REPORT;
+ return rv;
+ }
+}
+
+/*
+** This function is NOT part of the sqlite3 public API. It is strictly
+** for use by the sqlite project's own Java/JNI bindings.
+**
+** For purposes of certain hand-crafted JNI function bindings, we
+** need a way of reporting errors which is consistent with the rest of
+** the C API, as opposed to throwing JS exceptions. To that end, this
+** internal-use-only function is a thin proxy around
+** sqlite3ErrorWithMessage(). The intent is that it only be used from
+** JNI bindings such as sqlite3_prepare_v2/v3(), and definitely not
+** from client code.
+**
+** Returns err_code.
+*/
+static int s3jni_db_error(sqlite3*db, int err_code, const char *zMsg){
+ if( db!=0 ){
+ if( 0!=zMsg ){
+ const int nMsg = sqlite3Strlen30(zMsg);
+ sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg);
+ }else{
+ sqlite3ErrorWithMsg(db, err_code, NULL);
+ }
+ }
+ return err_code;
+}
+
+
+
+/* Sets a native int32 value in OutputPointer.Int32 object ppOut. */
+static void setOutputInt32(JNIEnv * env, jobject ppOut, int v){
+ jmethodID setter = 0;
+ struct NphCacheLine * const cacheLine =
+ S3Global_nph_cache(env, ClassNames.OutputPointer_Int32);
+ if(cacheLine && cacheLine->klazz && cacheLine->midSet){
+ setter = cacheLine->midSet;
+ }else{
+ const jclass klazz = (*env)->GetObjectClass(env, ppOut);
+ setter = (*env)->GetMethodID(env, klazz, "setValue", "(I)V");
+ if(cacheLine){
+ assert(!cacheLine->midSet);
+ cacheLine->midSet = setter;
+ }
+ }
+ (*env)->CallVoidMethod(env, ppOut, setter, (jint)v);
+ IFTHREW_REPORT;
+}
+
+#if 0
+/* Fetches a native int32 value from OutputPointer.Int32 object pObj. */
+static int getOutputInt(JNIEnv * env, jobject pObj){
+ const jclass klazz = (*env)->GetObjectClass(env, pObj);
+ const jmethodID getter =
+ (*env)->GetMethodID(env, klazz, "getValue", "(V)I;");
+ return (int)(*env)->CallIntMethod(env, pObj, getter);
+}
+#define VAL_GET_INT(OBJ) getOutputInt(env, OBJ)
+#endif
+
+static int encodingTypeIsValid(int eTextRep){
+ switch(eTextRep){
+ case SQLITE_UTF8: case SQLITE_UTF16:
+ case SQLITE_UTF16LE: case SQLITE_UTF16BE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/**
+ State for binding Java-side collation sequences.
+*/
+typedef struct {
+ jclass klazz /* Collation object's class */;
+ jobject oCollation /* Collation instance */;
+ jmethodID midCompare /* cached xCompare */;
+ JNIEnv * env; /* env registered from */;
+} CollationState;
+
+static CollationState * CollationState_alloc(void){
+ CollationState * rc = sqlite3_malloc(sizeof(CollationState));
+ if(rc) memset(rc, 0, sizeof(CollationState));
+ return rc;
+}
+
+static void CollationState_free(CollationState * cs){
+ JNIEnv * const env = cs->env;
+ if(env){
+ //MARKER(("Collation cleanup...\n"));
+ if(cs->oCollation) UNREF_G(cs->oCollation);
+ if(cs->klazz) UNREF_G(cs->klazz);
+ }
+ sqlite3_free(cs);
+}
+
+static int collation_xCompare_proxy(void *pArg, int nLhs, const void *lhs,
+ int nRhs, const void *rhs){
+ CollationState * const cs = (CollationState*)pArg;
+ JNIEnv * env = cs->env;
+ jint rc;
+ jbyteArray jbaLhs = (*env)->NewByteArray(env, (jint)nLhs);
+ jbyteArray jbaRhs = (*env)->NewByteArray(env, (jint)nRhs);
+ //MARKER(("native xCompare nLhs=%d nRhs=%d\n", nLhs, nRhs));
+ (*env)->SetByteArrayRegion(env, jbaLhs, 0, (jint)nLhs, (const jbyte*)lhs);
+ (*env)->SetByteArrayRegion(env, jbaRhs, 0, (jint)nRhs, (const jbyte*)rhs);
+ rc = (*env)->CallIntMethod(env, cs->oCollation, cs->midCompare,
+ jbaLhs, jbaRhs);
+ EXCEPTION_IGNORE;
+ UNREF_L(jbaLhs);
+ UNREF_L(jbaRhs);
+ return (int)rc;
+}
+
+static void collation_xDestroy_proxy(void *pArg){
+ CollationState * const cs = (CollationState*)pArg;
+ if(cs->oCollation){
+ JNIEnv * const env = cs->env;
+ const jmethodID method = (*env)->GetMethodID(env, cs->klazz, "xDestroy",
+ "()V");
+ //MARKER(("Calling Collation.xDestroy()...\n"));
+ (*env)->CallVoidMethod(env, cs->oCollation, method);
+ IFTHREW {
+ MARKER(("Collation.xDestroy() threw. Ignoring!\n"));
+ EXCEPTION_REPORT;
+ EXCEPTION_CLEAR;
+ }
+ //MARKER(("Returned from Collation.xDestroy().\n"));
+ }
+ CollationState_free(cs);
+}
+
+/* State for sqlite3_result_java_object() and
+ sqlite3_value_java_object(). */
+typedef struct {
+ /* POTENTIAL bug: the JNI docs say that the JNIEnv pointer
+ is guaranteed to resolve the same for the same contexts,
+ but the docs are unclear as to whether it's the (JNIEnv *env)
+ or (*env) which resolves consistently.
+
+ This posts claims it's unsave to cache JNIEnv at all, even when
+ it's always used in the same thread:
+
+ https://stackoverflow.com/questions/12420463
+
+ And this one seems to contradict that:
+
+ https://stackoverflow.com/questions/13964608
+
+ For later reference:
+
+ https://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/design.html#wp1242
+
+ https://developer.android.com/training/articles/perf-jni
+
+ The later has the following say about caching:
+
+ > If performance is important, it's useful to look the
+ [class/method ID] values up once and cache the results in your
+ native code. Because there is a limit of one JavaVM per
+ process, it's reasonable to store this data in a static local
+ structure. ... The class references, field IDs, and method IDs
+ are guaranteed valid until the class is unloaded. Classes are
+ only unloaded if all classes associated with a ClassLoader can
+ be garbage collected, which is rare but will not be impossible
+ in Android. Note however that the jclass is a class reference
+ and must be protected with a call to NewGlobalRef (see the next
+ section).
+ */
+ JNIEnv * env;
+ jobject jObj;
+} ResultJavaVal;
+
+/* For use with sqlite3_result/value_pointer() */
+#define RESULT_JAVA_VAL_STRING "ResultJavaVal"
+
+static ResultJavaVal * ResultJavaVal_alloc(JNIEnv *env, jobject jObj){
+ ResultJavaVal * rv = sqlite3_malloc(sizeof(ResultJavaVal));
+ if(rv){
+ rv->env = env;
+ rv->jObj = jObj ? REF_G(jObj) : 0;
+ }
+ return rv;
+}
+
+static void ResultJavaVal_finalizer(void *v){
+ if(v){
+ ResultJavaVal * const rv = (ResultJavaVal*)v;
+ if(rv->jObj) (*(rv->env))->DeleteGlobalRef(rv->env, rv->jObj);
+ sqlite3_free(rv);
+ }
+}
+
+
+
+/**
+ 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
+ pNative. Hypothetically returns NULL if Java fails to allocate, but
+ the JNI docs are not entirely clear on that detail.
+
+ Always use a string literal for the 2nd argument so that we can use
+ its address as a cache key.
+*/
+static jobject new_NativePointerHolder_object(JNIEnv *env, const char *zClassName,
+ void * pNative){
+ jobject rv = 0;
+ jclass klazz = 0;
+ jmethodID ctor = 0;
+ struct NphCacheLine * const cacheLine =
+ S3Global_nph_cache(env, zClassName);
+ if(cacheLine && cacheLine->midCtor){
+ assert( cacheLine->klazz );
+ klazz = cacheLine->klazz;
+ ctor = cacheLine->midCtor;
+ }else{
+ klazz = cacheLine
+ ? cacheLine->klazz
+ : (*env)->FindClass(env, zClassName);
+ ctor = (*env)->GetMethodID(env, klazz, "<init>", "()V");
+ if(cacheLine){
+ assert(zClassName == cacheLine->zClassName);
+ assert(cacheLine->klazz);
+ assert(!cacheLine->midCtor);
+ cacheLine->midCtor = ctor;
+ }
+ }
+ assert(klazz);
+ assert(ctor);
+ rv = (*env)->NewObject(env, klazz, ctor);
+ if(rv) setNativePointer(env, rv, pNative, zClassName);
+ return rv;
+}
+
+static jobject new_sqlite3_value_wrapper(JNIEnv *env, sqlite3_value *sv){
+ return new_NativePointerHolder_object(env, "org/sqlite/jni/sqlite3_value", sv);
+}
+
+static jobject new_sqlite3_context_wrapper(JNIEnv *env, sqlite3_context *sv){
+ return new_NativePointerHolder_object(env, "org/sqlite/jni/sqlite3_context", sv);
+}
+
+static jobject new_sqlite3_wrapper(JNIEnv *env, sqlite3 *sv){
+ return new_NativePointerHolder_object(env, "org/sqlite/jni/sqlite3", sv);
+}
+
+enum UDFType {
+ UDF_SCALAR = 1,
+ UDF_AGGREGATE,
+ UDF_WINDOW,
+ UDF_UNKNOWN_TYPE/*for error propagation*/
+};
+
+typedef void (*udf_xFunc_f)(sqlite3_context*,int,sqlite3_value**);
+typedef void (*udf_xStep_f)(sqlite3_context*,int,sqlite3_value**);
+typedef void (*udf_xFinal_f)(sqlite3_context*);
+/*typedef void (*udf_xValue_f)(sqlite3_context*);*/
+/*typedef void (*udf_xInverse_f)(sqlite3_context*,int,sqlite3_value**);*/
+
+/**
+ State for binding Java-side UDFs.
+*/
+typedef struct {
+ JNIEnv * env; /* env registered from */;
+ jobject jObj /* SQLFunction instance */;
+ jclass klazz /* jObj's class */;
+ char * zFuncName /* Only for error reporting and debug logging */;
+ enum UDFType type;
+ /** Method IDs for the various UDF methods. */
+ jmethodID jmidxFunc;
+ jmethodID jmidxStep;
+ jmethodID jmidxFinal;
+ jmethodID jmidxValue;
+ jmethodID jmidxInverse;
+} UDFState;
+
+static UDFState * UDFState_alloc(JNIEnv *env, jobject jObj){
+ UDFState * const s = sqlite3_malloc(sizeof(UDFState));
+ if(s){
+ const char * zFSI = /* signature for xFunc, xStep, xInverse */
+ "(Lorg/sqlite/jni/sqlite3_context;[Lorg/sqlite/jni/sqlite3_value;)V";
+ const char * zFV = /* signature for xFinal, xValue */
+ "(Lorg/sqlite/jni/sqlite3_context;)V";
+ memset(s, 0, sizeof(UDFState));
+ s->env = env;
+ s->jObj = REF_G(jObj);
+ s->klazz = REF_G((*env)->GetObjectClass(env, jObj));
+#define FGET(FuncName,FuncType,Field) \
+ s->Field = (*env)->GetMethodID(env, s->klazz, FuncName, FuncType); \
+ if(!s->Field) (*env)->ExceptionClear(env)
+ FGET("xFunc", zFSI, jmidxFunc);
+ FGET("xStep", zFSI, jmidxStep);
+ FGET("xFinal", zFV, jmidxFinal);
+ FGET("xValue", zFV, jmidxValue);
+ FGET("xInverse", zFSI, jmidxInverse);
+#undef FGET
+ if(s->jmidxFunc) s->type = UDF_SCALAR;
+ else if(s->jmidxStep && s->jmidxFinal){
+ s->type = s->jmidxValue ? UDF_WINDOW : UDF_AGGREGATE;
+ }else{
+ s->type = UDF_UNKNOWN_TYPE;
+ }
+ }
+ return s;
+}
+
+static void UDFState_free(UDFState * s){
+ JNIEnv * const env = s->env;
+ if(env){
+ //MARKER(("Collation cleanup...\n"));
+ if(s->jObj){
+ const jmethodID method =
+ (*env)->GetMethodID(env, s->klazz, "xDestroy", "()V");
+ if(method){
+ //MARKER(("aCalling SQLFunction.xDestroy()...\n"));
+ (*env)->CallVoidMethod(env, s->jObj, method);
+ EXCEPTION_IGNORE;
+ //MARKER(("Returned from SQLFunction.xDestroy().\n"));
+ }else{
+ (*env)->ExceptionClear(env);
+ }
+ }
+ UNREF_G(s->jObj);
+ UNREF_G(s->klazz);
+ }
+ sqlite3_free(s->zFuncName);
+ sqlite3_free(s);
+}
+
+static void UDFState_finalizer(void * s){
+ if(s) UDFState_free((UDFState*)s);
+}
+
+/**
+ Helper for processing args to UDF handlers
+ with signature (sqlite3_context*,int,sqlite3_value**).
+*/
+typedef struct {
+ jobject jcx;
+ jobjectArray jargv;
+} udf_jargs;
+
+static int udf_args(sqlite3_context * const cx,
+ int argc, sqlite3_value**argv,
+ UDFState * const s,
+ udf_jargs * const args){
+ jobjectArray ja = 0;
+ JNIEnv * const env = s->env;
+ jobject jcx = new_sqlite3_context_wrapper(s->env, cx);
+ jint i;
+ args->jcx = 0;
+ args->jargv = 0;
+ if(!jcx) goto error_oom;
+ ja = (*(s->env))->NewObjectArray(s->env, argc,
+ S3Global_env_cache(env)->globalClassObj,
+ NULL);
+ if(!ja) goto error_oom;
+ for(i = 0; i < argc; ++i){
+ jobject jsv = new_sqlite3_value_wrapper(s->env, argv[i]);
+ if(!jsv) goto error_oom;
+ (*env)->SetObjectArrayElement(env, ja, i, jsv);
+ UNREF_L(jsv)/*array has a ref*/;
+ }
+ args->jcx = jcx;
+ args->jargv = ja;
+ return 0;
+error_oom:
+ sqlite3_result_error_nomem(cx);
+ UNREF_L(jcx);
+ UNREF_L(ja);
+ return 1;
+}
+
+static int udf_report_exception(sqlite3_context * cx, UDFState *s,
+ const char *zFuncType){
+ int rc;
+ char * z =
+ sqlite3_mprintf("UDF %s.%s() threw. FIXME: extract "
+ "Java-side exception message.",
+ s->zFuncName, zFuncType);
+ if(z){
+ sqlite3_result_error(cx, z, -1);
+ sqlite3_free(z);
+ rc = SQLITE_ERROR;
+ }else{
+ rc = SQLITE_NOMEM;
+ }
+ return rc;
+}
+
+static int udf_xFSI(sqlite3_context* cx, int argc,
+ sqlite3_value** argv,
+ UDFState * s,
+ jmethodID xMethodID,
+ const char * zFuncType){
+ udf_jargs args;
+ JNIEnv * const env = s->env;
+ int rc = udf_args(cx, argc, argv, s, &args);
+ if(rc) return rc;
+ //MARKER(("UDF::%s.%s()\n", s->zFuncName, zFuncType));
+ (*env)->CallVoidMethod(env, s->jObj, xMethodID, args.jcx, args.jargv);
+ IFTHREW{
+ rc = udf_report_exception(cx,s, zFuncType);
+ }
+ UNREF_L(args.jcx);
+ UNREF_L(args.jargv);
+ return rc;
+}
+
+static int udf_xFV(sqlite3_context* cx, UDFState * s,
+ jmethodID xMethodID,
+ const char *zFuncType){
+ JNIEnv * const env = s->env;
+ jobject jcx = new_sqlite3_context_wrapper(s->env, cx);
+ int rc = 0;
+ if(!jcx){
+ sqlite3_result_error_nomem(cx);
+ return SQLITE_NOMEM;
+ }
+ //MARKER(("UDF::%s.%s()\n", s->zFuncName, zFuncType));
+ (*env)->CallVoidMethod(env, s->jObj, xMethodID, jcx);
+ IFTHREW{
+ rc = udf_report_exception(cx,s, zFuncType);
+ }
+ UNREF_L(jcx);
+ return rc;
+}
+
+static void udf_xFunc(sqlite3_context* cx, int argc,
+ sqlite3_value** argv){
+ UDFState * const s = (UDFState*)sqlite3_user_data(cx);
+ udf_xFSI(cx, argc, argv, s, s->jmidxFunc, "xFunc");
+}
+static void udf_xStep(sqlite3_context* cx, int argc,
+ sqlite3_value** argv){
+ UDFState * const s = (UDFState*)sqlite3_user_data(cx);
+ udf_xFSI(cx, argc, argv, s, s->jmidxStep, "xStep");
+}
+static void udf_xFinal(sqlite3_context* cx){
+ UDFState * const s = (UDFState*)sqlite3_user_data(cx);
+ udf_xFV(cx, s, s->jmidxFinal, "xFinal");
+}
+static void udf_xValue(sqlite3_context* cx){
+ UDFState * const s = (UDFState*)sqlite3_user_data(cx);
+ udf_xFV(cx, s, s->jmidxValue, "xValue");
+}
+static void udf_xInverse(sqlite3_context* cx, int argc,
+ sqlite3_value** argv){
+ UDFState * const s = (UDFState*)sqlite3_user_data(cx);
+ udf_xFSI(cx, argc, argv, s, s->jmidxInverse, "xInverse");
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// What follows is the JNI/C bindings. They are in alphabetical order
+// except for this macro-generated subset which are kept together here
+// at the front...
+////////////////////////////////////////////////////////////////////////
+WRAP_INT_DB(1errcode, sqlite3_errcode)
+WRAP_INT_DB(1error_1offset, sqlite3_error_offset)
+WRAP_INT_DB(1extended_1errcode, sqlite3_extended_errcode)
+WRAP_INT_STMT(1bind_1parameter_1count, sqlite3_bind_parameter_count)
+WRAP_INT_DB(1changes, sqlite3_changes)
+WRAP_INT64_DB(1changes64, sqlite3_changes64)
+WRAP_INT_STMT(1clear_1bindings, sqlite3_clear_bindings)
+WRAP_INT_STMT_INT(1column_1bytes, sqlite3_column_bytes)
+WRAP_INT_STMT_INT(1column_1bytes16, sqlite3_column_bytes16)
+WRAP_INT_STMT(1column_1count, sqlite3_column_count)
+WRAP_STR_STMT_INT(1column_1decltype, sqlite3_column_decltype)
+WRAP_STR_STMT_INT(1column_1name, sqlite3_column_name)
+WRAP_STR_STMT_INT(1column_1database_1name, sqlite3_column_database_name)
+WRAP_STR_STMT_INT(1column_1origin_1name, sqlite3_column_origin_name)
+WRAP_STR_STMT_INT(1column_1table_1name, sqlite3_column_table_name)
+WRAP_INT_STMT_INT(1column_1type, sqlite3_column_type)
+WRAP_INT_STMT(1data_1count, sqlite3_data_count)
+WRAP_MUTF8_VOID(1libversion, sqlite3_libversion)
+WRAP_INT_VOID(1libversion_1number, sqlite3_libversion_number)
+WRAP_INT_STMT(1reset, sqlite3_reset)
+WRAP_INT_INT(1sleep, sqlite3_sleep)
+WRAP_MUTF8_VOID(1sourceid, sqlite3_sourceid)
+WRAP_INT_STMT(1step, sqlite3_step)
+WRAP_INT_VOID(1threadsafe, sqlite3_threadsafe)
+WRAP_INT_DB(1total_1changes, sqlite3_total_changes)
+WRAP_INT64_DB(1total_1changes64, sqlite3_total_changes64)
+WRAP_INT_SVALUE(1value_1bytes, sqlite3_value_bytes)
+WRAP_INT_SVALUE(1value_1bytes16, sqlite3_value_bytes16)
+WRAP_INT_SVALUE(1value_1encoding, sqlite3_value_encoding)
+WRAP_INT_SVALUE(1value_1frombind, sqlite3_value_frombind)
+WRAP_INT_SVALUE(1value_1nochange, sqlite3_value_nochange)
+WRAP_INT_SVALUE(1value_1numeric_1type, sqlite3_value_numeric_type)
+WRAP_INT_SVALUE(1value_1subtype, sqlite3_value_subtype)
+WRAP_INT_SVALUE(1value_1type, sqlite3_value_type)
+
+JDECL(jint,1bind_1blob)(JENV_JSELF, jobject jpStmt,
+ jint ndx, jbyteArray baData, jint nMax){
+ int rc;
+ if(!baData){
+ rc = sqlite3_bind_null(PtrGet_sqlite3_stmt(jpStmt), ndx);
+ }else{
+ jbyte * const pBuf = JBA_TOC(baData);
+ rc = sqlite3_bind_blob(PtrGet_sqlite3_stmt(jpStmt), (int)ndx, pBuf, (int)nMax,
+ SQLITE_TRANSIENT);
+ JBA_RELEASE(baData,pBuf);
+ }
+ return (jint)rc;
+}
+
+JDECL(jint,1bind_1double)(JENV_JSELF, jobject jpStmt,
+ jint ndx, jdouble val){
+ return (jint)sqlite3_bind_double(PtrGet_sqlite3_stmt(jpStmt), (int)ndx, (double)val);
+}
+
+JDECL(jint,1bind_1int)(JENV_JSELF, jobject jpStmt,
+ jint ndx, jint val){
+ return (jint)sqlite3_bind_int(PtrGet_sqlite3_stmt(jpStmt), (int)ndx, (int)val);
+}
+
+JDECL(jint,1bind_1int64)(JENV_JSELF, jobject jpStmt,
+ jint ndx, jlong val){
+ return (jint)sqlite3_bind_int64(PtrGet_sqlite3_stmt(jpStmt), (int)ndx, (sqlite3_int64)val);
+}
+
+JDECL(jint,1bind_1null)(JENV_JSELF, jobject jpStmt,
+ jint ndx){
+ return (jint)sqlite3_bind_null(PtrGet_sqlite3_stmt(jpStmt), (int)ndx);
+}
+
+JDECL(jint,1bind_1parameter_1index)(JENV_JSELF, jobject jpStmt, jbyteArray jName){
+ int rc = 0;
+ jbyte * const pBuf = JBA_TOC(jName);
+ if(pBuf){
+ rc = sqlite3_bind_parameter_index(PtrGet_sqlite3_stmt(jpStmt),
+ (const char *)pBuf);
+ JBA_RELEASE(jName, pBuf);
+ }
+ return rc;
+}
+
+JDECL(jint,1bind_1text)(JENV_JSELF, jobject jpStmt,
+ jint ndx, jbyteArray baData, jint nMax){
+ if(baData){
+ jbyte * const pBuf = JBA_TOC(baData);
+ int rc = sqlite3_bind_text(PtrGet_sqlite3_stmt(jpStmt), (int)ndx, (const char *)pBuf,
+ (int)nMax, SQLITE_TRANSIENT);
+ JBA_RELEASE(baData, pBuf);
+ return (jint)rc;
+ }else{
+ return sqlite3_bind_null(PtrGet_sqlite3_stmt(jpStmt), (int)ndx);
+ }
+}
+
+JDECL(jint,1bind_1zeroblob)(JENV_JSELF, jobject jpStmt,
+ jint ndx, jint n){
+ return (jint)sqlite3_bind_zeroblob(PtrGet_sqlite3_stmt(jpStmt), (int)ndx, (int)n);
+}
+
+JDECL(jint,1bind_1zeroblob64)(JENV_JSELF, jobject jpStmt,
+ jint ndx, jlong n){
+ return (jint)sqlite3_bind_zeroblob(PtrGet_sqlite3_stmt(jpStmt), (int)ndx, (sqlite3_uint64)n);
+}
+
+JDECL(jint,1busy_1timeout)(JENV_JSELF, jobject pDb, jint ms){
+ return sqlite3_busy_timeout(PtrGet_sqlite3(pDb), (int)ms);
+}
+
+/**
+ Wrapper for sqlite3_close(_v2)().
+*/
+static jint s3jni_close_db(JNIEnv *env, jobject jDb, int version){
+ sqlite3 * pDb;
+ int rc = 0;
+ PerDbState * pS;
+ assert(version == 1 || version == 2);
+ pDb = PtrGet_sqlite3(jDb);
+ if(!pDb) return rc;
+ pS = PerDbState_for_db(env, pDb, 0);
+ rc = 1==version ? (jint)sqlite3_close(pDb) : (jint)sqlite3_close_v2(pDb);
+ if(pS) PerDbState_set_aside(pS)
+ /* MUST come after close() because of pS->trace. */;
+ setNativePointer(env, jDb, 0, ClassNames.sqlite3);
+ return (jint)rc;
+}
+
+JDECL(jint,1close_1v2)(JENV_JSELF, jobject pDb){
+ return s3jni_close_db(env, pDb, 2);
+}
+
+JDECL(jint,1close)(JENV_JSELF, jobject pDb){
+ return s3jni_close_db(env, pDb, 1);
+}
+
+JDECL(jbyteArray,1column_1blob)(JENV_JSELF, jobject jpStmt,
+ jint ndx){
+ sqlite3_stmt * const pStmt = PtrGet_sqlite3_stmt(jpStmt);
+ void const * const p = sqlite3_column_blob(pStmt, (int)ndx);
+ int const n = p ? sqlite3_column_bytes(pStmt, (int)ndx) : 0;
+ if( 0==p ) return NULL;
+ else{
+ jbyteArray const jba = (*env)->NewByteArray(env, n);
+ (*env)->SetByteArrayRegion(env, jba, 0, n, (const jbyte *)p);
+ return jba;
+ }
+}
+
+JDECL(jdouble,1column_1double)(JENV_JSELF, jobject jpStmt,
+ jint ndx){
+ return (jdouble)sqlite3_column_double(PtrGet_sqlite3_stmt(jpStmt), (int)ndx);
+}
+
+JDECL(jint,1column_1int)(JENV_JSELF, jobject jpStmt,
+ jint ndx){
+ return (jint)sqlite3_column_int(PtrGet_sqlite3_stmt(jpStmt), (int)ndx);
+}
+
+JDECL(jlong,1column_1int64)(JENV_JSELF, jobject jpStmt,
+ jint ndx){
+ return (jlong)sqlite3_column_int64(PtrGet_sqlite3_stmt(jpStmt), (int)ndx);
+}
+
+/**
+ Expects to be passed a pointer from sqlite3_column_text16() or
+ sqlite3_value_text16() and a length value from
+ sqlite3_column_bytes16() or sqlite3_value_bytes16(). It creates a
+ Java String of exactly half that length, returning NULL if !p or
+ (*env)->NewString() fails.
+*/
+static jstring s3jni_text_to_jstring(JNIEnv *env, const void * const p, int nP){
+ return p
+ ? (*env)->NewString(env, (const jchar *)p, (jsize)(nP/2))
+ : NULL;
+}
+
+/**
+ Creates a new jByteArray of length nP, copies p's contents into it, and
+ returns that byte array.
+ */
+static jbyteArray s3jni_new_jbyteArray(JNIEnv *env, const unsigned char * const p, int nP){
+ jbyteArray jba = (*env)->NewByteArray(env, (jint)nP);
+ if(jba){
+ (*env)->SetByteArrayRegion(env, jba, 0, (jint)nP, (const jbyte*)p);
+ }
+ return jba;
+}
+
+JDECL(jstring,1column_1text)(JENV_JSELF, jobject jpStmt,
+ jint ndx){
+ sqlite3_stmt * const stmt = PtrGet_sqlite3_stmt(jpStmt);
+ const int n = sqlite3_column_bytes16(stmt, (int)ndx);
+ const void * const p = sqlite3_column_text16(stmt, (int)ndx);
+ return s3jni_text_to_jstring(env, p, n);
+}
+
+JDECL(jbyteArray,1column_1text_1utf8)(JENV_JSELF, jobject jpStmt,
+ jint ndx){
+ sqlite3_stmt * const stmt = PtrGet_sqlite3_stmt(jpStmt);
+ const int n = sqlite3_column_bytes(stmt, (int)ndx);
+ const unsigned char * const p = sqlite3_column_text(stmt, (int)ndx);
+ return s3jni_new_jbyteArray(env, p, n);
+}
+
+JDECL(jobject,1column_1value)(JENV_JSELF, jobject jpStmt,
+ jint ndx){
+ sqlite3_value * const sv = sqlite3_column_value(PtrGet_sqlite3_stmt(jpStmt), (int)ndx);
+ return new_sqlite3_value_wrapper(env, sv);
+}
+
+JDECL(jstring,1compileoption_1get)(JENV_JSELF, jint n){
+ return (*env)->NewStringUTF( env, sqlite3_compileoption_get(n) );
+}
+
+JDECL(jboolean,1compileoption_1used)(JENV_JSELF, jstring name){
+ const char *zUtf8 = (*env)->GetStringUTFChars(env, name, NULL);
+ const jboolean rc =
+ 0==sqlite3_compileoption_used(zUtf8) ? JNI_FALSE : JNI_TRUE;
+ (*env)->ReleaseStringUTFChars(env, name, zUtf8);
+ return rc;
+}
+
+JDECL(jobject,1context_1db_1handle)(JENV_JSELF, jobject jpCx){
+ sqlite3 * const db = sqlite3_context_db_handle(PtrGet_sqlite3_context(jpCx));
+ return db ? new_sqlite3_wrapper(env, db) : NULL;
+}
+
+JDECL(jint,1create_1collation)(JENV_JSELF, jobject jpDb,
+ jstring name, jint eTextRep,
+ jobject oCollation){
+ const jclass klazz = (*env)->GetObjectClass(env, oCollation);
+ int rc;
+ const char *zName;
+ CollationState * const cs = CollationState_alloc();
+ if(!cs) return (jint)SQLITE_NOMEM;
+ cs->env = env;
+ cs->oCollation = REF_G(oCollation);
+ cs->klazz = REF_G(klazz);
+ cs->midCompare = (*env)->GetMethodID(env, klazz, "xCompare",
+ "([B[B)I");
+ zName = JSTR_TOC(name);
+ rc = sqlite3_create_collation_v2(PtrGet_sqlite3(jpDb), zName, (int)eTextRep,
+ cs, collation_xCompare_proxy,
+ collation_xDestroy_proxy);
+ JSTR_RELEASE(name, zName);
+ if(0 != rc) collation_xDestroy_proxy(cs);
+ return (jint)rc;
+}
+
+static jint create_function(JNIEnv * env, jobject jDb, jstring jFuncName,
+ jint nArg, jint eTextRep, jobject jFunctor){
+ UDFState * s = 0;
+ int rc;
+ sqlite3 * const pDb = PtrGet_sqlite3(jDb);
+ const char * zFuncName = 0;
+
+ if( !encodingTypeIsValid(eTextRep) ){
+ return s3jni_db_error(pDb, SQLITE_FORMAT,
+ "Invalid function encoding option.");
+ }
+ s = UDFState_alloc(env, jFunctor);
+ if( !s ) return SQLITE_NOMEM;
+ else if( UDF_UNKNOWN_TYPE==s->type ){
+ UDFState_free(s);
+ rc = s3jni_db_error(pDb, SQLITE_MISUSE,
+ "Cannot unambiguously determine function type.");
+ goto error_cleanup;
+ }
+ zFuncName = JSTR_TOC(jFuncName);
+ if(!zFuncName){
+ UDFState_free(s);
+ rc = SQLITE_NOMEM;
+ goto error_cleanup;
+ }
+ if( UDF_WINDOW == s->type ){
+ rc = sqlite3_create_window_function(pDb, zFuncName, nArg, eTextRep, s,
+ udf_xStep, udf_xFinal, udf_xValue,
+ udf_xInverse, UDFState_finalizer);
+ }else{
+ udf_xFunc_f xFunc = 0;
+ udf_xStep_f xStep = 0;
+ udf_xFinal_f xFinal = 0;
+ if( UDF_SCALAR == s->type ){
+ xFunc = udf_xFunc;
+ }else{
+ assert( UDF_AGGREGATE == s->type );
+ xStep = udf_xStep;
+ xFinal = udf_xFinal;
+ }
+ rc = sqlite3_create_function_v2(pDb, zFuncName, nArg, eTextRep, s,
+ xFunc, xStep, xFinal,
+ UDFState_finalizer);
+ }
+ s->zFuncName = sqlite3_mprintf("%s", zFuncName);
+ if(!s->zFuncName){
+ rc = SQLITE_NOMEM;
+ UDFState_free(s);
+ }
+error_cleanup:
+ JSTR_RELEASE(jFuncName, zFuncName);
+ /* on create_function() error, s will be destroyed via create_function() */
+ return (jint)rc;
+}
+
+JDECL(jint,1create_1function)(JENV_JSELF, jobject jDb, jstring jFuncName,
+ jint nArg, jint eTextRep, jobject jFunctor){
+ return create_function(env, jDb, jFuncName, nArg, eTextRep, jFunctor);
+}
+
+/*
+JDECL(jint,1create_1window_1function)(JENV_JSELF, jstring jFuncName, jint nArg,
+ jint eTextRep, jobject jFunctor){
+ return create_function_mega(env, jFuncName, nArg, eTextRep, jFunctor);
+}
+*/
+
+JDECL(jstring,1errmsg)(JENV_JSELF, jobject jpDb){
+ return (*env)->NewStringUTF(env, sqlite3_errmsg(PtrGet_sqlite3(jpDb)));
+}
+
+JDECL(jstring,1errstr)(JENV_JSELF, jint rcCode){
+ return (*env)->NewStringUTF(env, sqlite3_errstr((int)rcCode));
+}
+
+JDECL(jboolean,1extended_1result_1codes)(JENV_JSELF, jobject jpDb,
+ jboolean onoff){
+ int const rc = sqlite3_extended_result_codes(PtrGet_sqlite3(jpDb), onoff ? 1 : 0);
+ return rc ? JNI_TRUE : JNI_FALSE;
+}
+
+JDECL(jint,1initialize)(JENV_JSELF){
+ return sqlite3_initialize();
+}
+
+JDECL(jint,1finalize)(JENV_JSELF, jobject jpStmt){
+ if(jpStmt){
+ sqlite3_stmt * pStmt = PtrGet_sqlite3_stmt(jpStmt);
+ setNativePointer(env, jpStmt, 0, ClassNames.sqlite3_stmt);
+ sqlite3_finalize(pStmt);
+ }
+ return 0;
+}
+
+
+JDECL(jlong,1last_1insert_1rowid)(JENV_JSELF, jobject jpDb){
+ return (jlong)sqlite3_last_insert_rowid(PtrGet_sqlite3(jpDb));
+}
+
+
+JDECL(jint,1open)(JENV_JSELF, jstring strName, jobject ppOut){
+ sqlite3 * pOut = 0;
+ const char *zName = strName ? JSTR_TOC(strName) : 0;
+ int nrc = sqlite3_open(zName, &pOut);
+ //MARKER(("env=%p, *env=%p\n", env, *env));
+ setNativePointer(env, ppOut, pOut, ClassNames.sqlite3);
+ assert(nrc==0 ? pOut!=0 : 1);
+ JSTR_RELEASE(strName, zName);
+ return (jint)nrc;
+}
+
+JDECL(jint,1open_1v2)(JENV_JSELF, jstring strName,
+ jobject ppOut, jint flags, jstring strVfs){
+ sqlite3 * pOut = 0;
+ const char *zName = strName ? JSTR_TOC(strName) : 0;
+ const char *zVfs = strVfs ? JSTR_TOC(strVfs) : 0;
+ int nrc = sqlite3_open_v2(zName, &pOut, (int)flags, zVfs);
+ /*MARKER(("zName=%s, zVfs=%s, pOut=%p, flags=%d, nrc=%d\n",
+ zName, zVfs, pOut, (int)flags, nrc));*/
+ setNativePointer(env, ppOut, pOut, ClassNames.sqlite3);
+ assert(nrc==0 ? pOut!=0 : 1);
+ JSTR_RELEASE(strName, zName);
+ JSTR_RELEASE(strVfs, zVfs);
+ return (jint)nrc;
+}
+
+/* Proxy for the sqlite3_prepare[_v2/3]() family. */
+static jint sqlite3_jni_prepare_v123(int prepVersion, JNIEnv *env, jclass self,
+ jobject jpDb, jbyteArray baSql,
+ jint nMax, jint prepFlags,
+ jobject outStmt, jobject outTail){
+ sqlite3_stmt * pStmt = 0;
+ const char * zTail = 0;
+ jbyte * const pBuf = JBA_TOC(baSql);
+ int rc = SQLITE_ERROR;
+ assert(prepVersion==1 || prepVersion==2 || prepVersion==3);
+ switch( prepVersion ){
+ case 1: rc = sqlite3_prepare(PtrGet_sqlite3(jpDb), (const char *)pBuf,
+ (int)nMax, &pStmt, &zTail);
+ break;
+ case 2: rc = sqlite3_prepare_v2(PtrGet_sqlite3(jpDb), (const char *)pBuf,
+ (int)nMax, &pStmt, &zTail);
+ break;
+ case 3: rc = sqlite3_prepare_v3(PtrGet_sqlite3(jpDb), (const char *)pBuf,
+ (int)nMax, (unsigned int)prepFlags,
+ &pStmt, &zTail);
+ break;
+ default:
+ assert(0 && "Invalid prepare() version");
+ }
+ 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));
+ }
+ setNativePointer(env, outStmt, pStmt, ClassNames.sqlite3_stmt);
+ return (jint)rc;
+}
+JDECL(jint,1prepare)(JNIEnv *env, jclass self, jobject jpDb, jbyteArray baSql,
+ jint nMax, jobject outStmt, jobject outTail){
+ return sqlite3_jni_prepare_v123(1, env, self, jpDb, baSql, nMax, 0,
+ outStmt, outTail);
+}
+JDECL(jint,1prepare_1v2)(JNIEnv *env, jclass self, jobject jpDb, jbyteArray baSql,
+ jint nMax, jobject outStmt, jobject outTail){
+ return sqlite3_jni_prepare_v123(2, env, self, jpDb, baSql, nMax, 0,
+ outStmt, outTail);
+}
+JDECL(jint,1prepare_1v3)(JNIEnv *env, jclass self, jobject jpDb, jbyteArray baSql,
+ jint nMax, jint prepFlags, jobject outStmt, jobject outTail){
+ return sqlite3_jni_prepare_v123(3, env, self, jpDb, baSql, nMax,
+ prepFlags, outStmt, outTail);
+}
+
+/* sqlite3_result_text/blob() and friends. */
+static void result_blob_text(int asBlob, int as64,
+ int eTextRep/*only for (asBlob=0)*/,
+ JNIEnv *env, sqlite3_context *pCx,
+ jbyteArray jBa, jlong nMax){
+ if(jBa){
+ jbyte * const pBuf = JBA_TOC(jBa);
+ jsize nBa = (*env)->GetArrayLength(env, jBa);
+ if( nMax>=0 && nBa>(jsize)nMax ){
+ nBa = (jsize)nMax;
+ /**
+ From the sqlite docs:
+
+ > If the 3rd parameter to any of the sqlite3_result_text*
+ interfaces other than sqlite3_result_text64() is negative,
+ then SQLite computes the string length itself by searching
+ the 2nd parameter for the first zero character.
+
+ Note that the text64() interfaces take an unsigned value for
+ the length, which Java does not support. This binding takes
+ the approach of passing on negative values to the C API,
+ which will, in turn fail with SQLITE_TOOBIG at some later
+ point (recall that the sqlite3_result_xyz() family do not
+ have result values).
+ */
+ }
+ if(as64){ /* 64-bit... */
+ static const jsize nLimit64 =
+ SQLITE_MAX_ALLOCATION_SIZE/*only _kinda_ arbitrary!*/
+ /* jsize is int32, not int64! */;
+ if(nBa > nLimit64){
+ sqlite3_result_error_toobig(pCx);
+ }else if(asBlob){
+ sqlite3_result_blob64(pCx, pBuf, (sqlite3_uint64)nBa,
+ SQLITE_TRANSIENT);
+ }else{ /* text64... */
+ if(encodingTypeIsValid(eTextRep)){
+ sqlite3_result_text64(pCx, (const char *)pBuf,
+ (sqlite3_uint64)nBa,
+ SQLITE_TRANSIENT, eTextRep);
+ }else{
+ sqlite3_result_error_code(pCx, SQLITE_FORMAT);
+ }
+ }
+ }else{ /* 32-bit... */
+ static const jsize nLimit = SQLITE_MAX_ALLOCATION_SIZE;
+ if(nBa > nLimit){
+ sqlite3_result_error_toobig(pCx);
+ }else if(asBlob){
+ sqlite3_result_blob(pCx, pBuf, (int)nBa,
+ SQLITE_TRANSIENT);
+ }else{
+ switch(eTextRep){
+ case SQLITE_UTF8:
+ sqlite3_result_text(pCx, (const char *)pBuf, (int)nBa,
+ SQLITE_TRANSIENT);
+ break;
+ case SQLITE_UTF16:
+ sqlite3_result_text16(pCx, (const char *)pBuf, (int)nBa,
+ SQLITE_TRANSIENT);
+ break;
+ case SQLITE_UTF16LE:
+ sqlite3_result_text16le(pCx, (const char *)pBuf, (int)nBa,
+ SQLITE_TRANSIENT);
+ break;
+ case SQLITE_UTF16BE:
+ sqlite3_result_text16be(pCx, (const char *)pBuf, (int)nBa,
+ SQLITE_TRANSIENT);
+ break;
+ }
+ }
+ JBA_RELEASE(jBa, pBuf);
+ }
+ }else{
+ sqlite3_result_null(pCx);
+ }
+}
+
+JDECL(void,1result_1blob)(JENV_JSELF, jobject jpCx, jbyteArray jBa, jint nMax){
+ return result_blob_text(1, 0, 0, env, PtrGet_sqlite3_context(jpCx), jBa, nMax);
+}
+
+JDECL(void,1result_1blob64)(JENV_JSELF, jobject jpCx, jbyteArray jBa, jlong nMax){
+ return result_blob_text(1, 1, 0, env, PtrGet_sqlite3_context(jpCx), jBa, nMax);
+}
+
+JDECL(void,1result_1double)(JENV_JSELF, jobject jpCx, jdouble v){
+ sqlite3_result_double(PtrGet_sqlite3_context(jpCx), v);
+}
+
+JDECL(void,1result_1error)(JENV_JSELF, jobject jpCx, jbyteArray baMsg,
+ int eTextRep){
+ const char * zUnspecified = "Unspecified error.";
+ jsize const baLen = (*env)->GetArrayLength(env, baMsg);
+ jbyte * const pjBuf = baMsg ? JBA_TOC(baMsg) : NULL;
+ switch(pjBuf ? eTextRep : SQLITE_UTF8){
+ case SQLITE_UTF8: {
+ const char *zMsg = pjBuf ? (const char *)pjBuf : zUnspecified;
+ sqlite3_result_error(PtrGet_sqlite3_context(jpCx), zMsg, baLen);
+ break;
+ }
+ case SQLITE_UTF16: {
+ const void *zMsg = pjBuf
+ ? (const void *)pjBuf : (const void *)zUnspecified;
+ sqlite3_result_error16(PtrGet_sqlite3_context(jpCx), zMsg, baLen);
+ break;
+ }
+ default:
+ sqlite3_result_error(PtrGet_sqlite3_context(jpCx),
+ "Invalid encoding argument passed "
+ "to sqlite3_result_error().", -1);
+ break;
+ }
+ JBA_RELEASE(baMsg,pjBuf);
+}
+
+JDECL(void,1result_1error_1code)(JENV_JSELF, jobject jpCx, jint v){
+ sqlite3_result_error_code(PtrGet_sqlite3_context(jpCx), v ? (int)v : SQLITE_ERROR);
+}
+
+JDECL(void,1result_1error_1nomem)(JENV_JSELF, jobject jpCx){
+ sqlite3_result_error_nomem(PtrGet_sqlite3_context(jpCx));
+}
+
+JDECL(void,1result_1error_1toobig)(JENV_JSELF, jobject jpCx){
+ sqlite3_result_error_toobig(PtrGet_sqlite3_context(jpCx));
+}
+
+JDECL(void,1result_1int)(JENV_JSELF, jobject jpCx, jint v){
+ sqlite3_result_int(PtrGet_sqlite3_context(jpCx), (int)v);
+}
+
+JDECL(void,1result_1int64)(JENV_JSELF, jobject jpCx, jlong v){
+ sqlite3_result_int64(PtrGet_sqlite3_context(jpCx), (sqlite3_int64)v);
+}
+
+JDECL(void,1result_1java_1object)(JENV_JSELF, jobject jpCx, jobject v){
+ if(v){
+ ResultJavaVal * const rjv = ResultJavaVal_alloc(env, v);
+ if(rjv){
+ sqlite3_result_pointer(PtrGet_sqlite3_context(jpCx), rjv, RESULT_JAVA_VAL_STRING,
+ ResultJavaVal_finalizer);
+ }else{
+ sqlite3_result_error_nomem(PtrGet_sqlite3_context(jpCx));
+ }
+ }else{
+ sqlite3_result_null(PtrGet_sqlite3_context(jpCx));
+ }
+}
+
+JDECL(void,1result_1null)(JENV_JSELF, jobject jpCx){
+ sqlite3_result_null(PtrGet_sqlite3_context(jpCx));
+}
+
+JDECL(void,1result_1text)(JENV_JSELF, jobject jpCx, jbyteArray jBa, jint nMax){
+ return result_blob_text(0, 0, SQLITE_UTF8, env, PtrGet_sqlite3_context(jpCx), jBa, nMax);
+}
+
+JDECL(void,1result_1text64)(JENV_JSELF, jobject jpCx, jbyteArray jBa, jlong nMax,
+ jint eTextRep){
+ return result_blob_text(0, 1, eTextRep, env, PtrGet_sqlite3_context(jpCx), jBa, nMax);
+}
+
+JDECL(void,1result_1value)(JENV_JSELF, jobject jpCx, jobject jpSVal){
+ sqlite3_result_value(PtrGet_sqlite3_context(jpCx), PtrGet_sqlite3_value(jpSVal));
+}
+
+JDECL(void,1result_1zeroblob)(JENV_JSELF, jobject jpCx, jint v){
+ sqlite3_result_zeroblob(PtrGet_sqlite3_context(jpCx), (int)v);
+}
+
+JDECL(jint,1result_1zeroblob64)(JENV_JSELF, jobject jpCx, jlong v){
+ return (jint)sqlite3_result_zeroblob64(PtrGet_sqlite3_context(jpCx), (sqlite3_int64)v);
+}
+
+
+JDECL(void,1set_1last_1insert_1rowid)(JENV_JSELF, jobject jpDb, jlong rowId){
+ sqlite3_set_last_insert_rowid(PtrGet_sqlite3_context(jpDb),
+ (sqlite3_int64)rowId);
+}
+
+JDECL(jint,1shutdown)(JENV_JSELF){
+ PerDbState_free_all();
+ JNIEnvCache_clear(&S3Global.envCache);
+ /* Do not clear S3Global.jvm: it's legal to call
+ sqlite3_initialize() again to restart the lib. */
+ return sqlite3_shutdown();
+}
+
+static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
+ PerDbState * const ps = (PerDbState *)pC;
+ JNIEnv * const env = ps->env;
+ jobject jX = NULL;
+ JNIEnvCacheLine * const pEcl = S3Global_env_cache(env);
+ int rc;
+ /**
+ TODO: convert pX depending on traceflag:
+
+ SQLITE_TRACE_STMT: String
+ SQLITE_TRACE_PROFILE: Long
+ others: null
+ */
+ switch(traceflag){
+ case SQLITE_TRACE_STMT:
+ /* This is not _quite_ right: we're converting to MUTF-8. It
+ should(?) suffice for purposes of tracing, though. */
+ jX = (*env)->NewStringUTF(env, (const char *)pX);
+ break;
+ case SQLITE_TRACE_PROFILE:
+ jX = (*env)->NewObject(env, pEcl->globalClassLong, pEcl->ctorLong1,
+ (jlong)*((sqlite3_int64*)pX));
+ break;
+ }
+ rc = (int)(*env)->CallIntMethod(env, ps->trace.jObj,
+ ps->trace.midCallback,
+ (jint)traceflag, (jlong)pP, jX);
+ UNREF_L(jX);
+ IFTHREW{
+ EXCEPTION_CLEAR;
+ return rc ? rc :
+ s3jni_db_error(ps->pDb, SQLITE_ERROR,
+ "sqlite3_trace_v2() callback threw.");
+ }
+ return rc;
+}
+
+JDECL(jint,1trace_1v2)(JENV_JSELF,jobject jDb, jint traceMask, jobject jTracer){
+ sqlite3 * const pDb = PtrGet_sqlite3(jDb);
+ PerDbState * ps;
+ jclass klazz;
+ if( !traceMask || !jTracer ){
+ return (jint)sqlite3_trace_v2(pDb, 0, 0, 0);
+ }
+ ps = PerDbState_for_db(env, pDb, 1);
+ if(!ps) return SQLITE_NOMEM;
+ klazz = (*env)->GetObjectClass(env, jTracer);
+ ps->trace.midCallback = (*env)->GetMethodID(env, klazz, "xCallback",
+ "(IJLjava/lang/Object;)I");
+ IFTHREW {
+ /* Leave ps in place - it might contain other state. */
+ EXCEPTION_CLEAR;
+ return s3jni_db_error(pDb, SQLITE_ERROR,
+ "Cannot not find matchin xCallback() on Tracer object.");
+ }
+ ps->trace.jObj = REF_G(jTracer);
+ return sqlite3_trace_v2(pDb, (unsigned)traceMask, s3jni_trace_impl, ps);
+}
+
+
+JDECL(jbyteArray,1value_1blob)(JENV_JSELF, jobject jpSVal){
+ sqlite3_value * const sv = PtrGet_sqlite3_value(jpSVal);
+ int const nLen = sqlite3_value_bytes(sv);
+ const jbyte * pBytes = sqlite3_value_blob(sv);
+ jbyteArray const jba = pBytes
+ ? (*env)->NewByteArray(env, (jsize)nLen)
+ : NULL;
+ if(jba){
+ (*env)->SetByteArrayRegion(env, jba, 0, nLen, pBytes);
+ }
+ return jba;
+}
+
+
+JDECL(jdouble,1value_1double)(JENV_JSELF, jobject jpSVal){
+ return (jdouble) sqlite3_value_double(PtrGet_sqlite3_value(jpSVal));
+}
+
+
+JDECL(jobject,1value_1dup)(JENV_JSELF, jobject jpSVal){
+ sqlite3_value * const sv = sqlite3_value_dup(PtrGet_sqlite3_value(jpSVal));
+ return sv ? new_sqlite3_value_wrapper(env, sv) : 0;
+}
+
+JDECL(void,1value_1free)(JENV_JSELF, jobject jpSVal){
+ sqlite3_value_free(PtrGet_sqlite3_value(jpSVal));
+}
+
+JDECL(jint,1value_1int)(JENV_JSELF, jobject jpSVal){
+ return (jint) sqlite3_value_int(PtrGet_sqlite3_value(jpSVal));
+}
+
+JDECL(jlong,1value_1int64)(JENV_JSELF, jobject jpSVal){
+ return (jlong) sqlite3_value_int64(PtrGet_sqlite3_value(jpSVal));
+}
+
+JDECL(jobject,1value_1java_1object)(JENV_JSELF, jobject jpSVal){
+ ResultJavaVal * const rv = sqlite3_value_pointer(PtrGet_sqlite3_value(jpSVal), RESULT_JAVA_VAL_STRING);
+ return rv ? rv->jObj : NULL;
+}
+
+JDECL(jstring,1value_1text)(JENV_JSELF, jobject jpSVal){
+ sqlite3_value * const sv = PtrGet_sqlite3_value(jpSVal);
+ int const n = sqlite3_value_bytes16(sv);
+ const void * const p = sqlite3_value_text16(sv);
+ return s3jni_text_to_jstring(env, p, n);
+}
+
+JDECL(jbyteArray,1value_1text_1utf8)(JENV_JSELF, jobject jpSVal){
+ sqlite3_value * const sv = PtrGet_sqlite3_value(jpSVal);
+ int const n = sqlite3_value_bytes(sv);
+ const unsigned char * const p = sqlite3_value_text(sv);
+ return s3jni_new_jbyteArray(env, p, n);
+}
+
+static jbyteArray value_text16(int mode, JNIEnv *env, jobject jpSVal){
+ int const nLen = sqlite3_value_bytes16(PtrGet_sqlite3_value(jpSVal));
+ jbyteArray jba;
+ const jbyte * pBytes;
+ switch(mode){
+ case SQLITE_UTF16:
+ pBytes = sqlite3_value_text16(PtrGet_sqlite3_value(jpSVal));
+ break;
+ case SQLITE_UTF16LE:
+ pBytes = sqlite3_value_text16le(PtrGet_sqlite3_value(jpSVal));
+ break;
+ case SQLITE_UTF16BE:
+ pBytes = sqlite3_value_text16be(PtrGet_sqlite3_value(jpSVal));
+ break;
+ default:
+ assert(!"not possible");
+ return NULL;
+ }
+ jba = pBytes
+ ? (*env)->NewByteArray(env, (jsize)nLen)
+ : NULL;
+ if(jba){
+ (*env)->SetByteArrayRegion(env, jba, 0, nLen, pBytes);
+ }
+ return jba;
+}
+
+JDECL(jbyteArray,1value_1text16)(JENV_JSELF, jobject jpSVal){
+ return value_text16(SQLITE_UTF16, env, jpSVal);
+}
+
+JDECL(jbyteArray,1value_1text16le)(JENV_JSELF, jobject jpSVal){
+ return value_text16(SQLITE_UTF16LE, env, jpSVal);
+}
+
+JDECL(jbyteArray,1value_1text16be)(JENV_JSELF, jobject jpSVal){
+ return value_text16(SQLITE_UTF16BE, env, jpSVal);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// End of the main API bindings. What follows are internal utilities.
+////////////////////////////////////////////////////////////////////////
+
+/**
+ Called during static init of the SQLite3Jni class to sync certain
+ compile-time constants to Java-space.
+
+ This routine is why we have to #include sqlite3.c instead of
+ sqlite3.h.
+*/
+JNIEXPORT void JNICALL
+Java_org_sqlite_jni_SQLite3Jni_init(JNIEnv *env, jclass self, jobject sJni){
+ typedef struct {
+ const char *zName;
+ int value;
+ } LimitEntry;
+ const LimitEntry aLimits[] = {
+ {"SQLITE_MAX_ALLOCATION_SIZE", SQLITE_MAX_ALLOCATION_SIZE},
+ {"SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH},
+ {"SQLITE_MAX_LENGTH", SQLITE_MAX_LENGTH},
+ {"SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH},
+ {"SQLITE_MAX_SQL_LENGTH", SQLITE_MAX_SQL_LENGTH},
+ {"SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN},
+ {"SQLITE_MAX_COLUMN", SQLITE_MAX_COLUMN},
+ {"SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH},
+ {"SQLITE_MAX_EXPR_DEPTH", SQLITE_MAX_EXPR_DEPTH},
+ {"SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT},
+ {"SQLITE_MAX_COMPOUND_SELECT", SQLITE_MAX_COMPOUND_SELECT},
+ {"SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP},
+ {"SQLITE_MAX_VDBE_OP", SQLITE_MAX_VDBE_OP},
+ {"SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG},
+ {"SQLITE_MAX_FUNCTION_ARG", SQLITE_MAX_FUNCTION_ARG},
+ {"SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED},
+ {"SQLITE_MAX_ATTACHED", SQLITE_MAX_ATTACHED},
+ {"SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH},
+ {"SQLITE_MAX_LIKE_PATTERN_LENGTH", SQLITE_MAX_LIKE_PATTERN_LENGTH},
+ {"SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER},
+ {"SQLITE_MAX_VARIABLE_NUMBER", SQLITE_MAX_VARIABLE_NUMBER},
+ {"SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH},
+ {"SQLITE_MAX_TRIGGER_DEPTH", SQLITE_MAX_TRIGGER_DEPTH},
+ {"SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS},
+ {"SQLITE_MAX_WORKER_THREADS", SQLITE_MAX_WORKER_THREADS},
+ {0,0}
+ };
+ jfieldID fieldId;
+ jclass const klazz = (*env)->GetObjectClass(env, sJni);
+ const LimitEntry * pLimit;
+ memset(&S3Global, 0, sizeof(S3Global));
+ (void)S3Global_env_cache(env);
+ assert( 1 == S3Global.envCache.used );
+ assert( env == S3Global.envCache.lines[0].env );
+ assert( 0 != S3Global.envCache.lines[0].globalClassObj );
+ if( (*env)->GetJavaVM(env, &S3Global.jvm) ){
+ (*env)->FatalError(env, "GetJavaVM() failure shouldn't be possible.");
+ }
+
+ for( pLimit = &aLimits[0]; pLimit->zName; ++pLimit ){
+ fieldId = (*env)->GetStaticFieldID(env, klazz, pLimit->zName, "I");
+ //MARKER(("Setting %s (field=%p) = %d\n", pLimit->zName, fieldId, pLimit->value));
+ assert(fieldId);
+ (*env)->SetStaticIntField(env, klazz, fieldId, (jint)pLimit->value);
+ }
+}
--- /dev/null
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_sqlite_jni_SQLite3Jni */
+
+#ifndef _Included_org_sqlite_jni_SQLite3Jni
+#define _Included_org_sqlite_jni_SQLite3Jni
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ACCESS_EXISTS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ACCESS_EXISTS 0L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ACCESS_READWRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ACCESS_READWRITE 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ACCESS_READ
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ACCESS_READ 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DENY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DENY 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IGNORE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IGNORE 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_INDEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_INDEX 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TABLE 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TEMP_INDEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TEMP_INDEX 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TEMP_TABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TEMP_TABLE 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TEMP_TRIGGER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TEMP_TRIGGER 5L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TEMP_VIEW
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TEMP_VIEW 6L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TRIGGER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_TRIGGER 7L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_VIEW
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_VIEW 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DELETE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DELETE 9L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DROP_INDEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DROP_INDEX 10L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TABLE 11L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TEMP_INDEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TEMP_INDEX 12L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TEMP_TABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TEMP_TABLE 13L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TEMP_TRIGGER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TEMP_TRIGGER 14L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TEMP_VIEW
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TEMP_VIEW 15L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TRIGGER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DROP_TRIGGER 16L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DROP_VIEW
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DROP_VIEW 17L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INSERT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INSERT 18L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_PRAGMA
+#define org_sqlite_jni_SQLite3Jni_SQLITE_PRAGMA 19L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_READ
+#define org_sqlite_jni_SQLite3Jni_SQLITE_READ 20L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_SELECT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_SELECT 21L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TRANSACTION
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TRANSACTION 22L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_UPDATE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_UPDATE 23L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ATTACH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ATTACH 24L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DETACH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DETACH 25L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ALTER_TABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ALTER_TABLE 26L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_REINDEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_REINDEX 27L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ANALYZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ANALYZE 28L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_VTABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CREATE_VTABLE 29L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DROP_VTABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DROP_VTABLE 30L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FUNCTION
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FUNCTION 31L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_SAVEPOINT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_SAVEPOINT 32L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_RECURSIVE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_RECURSIVE 33L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STATIC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STATIC 0L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TRANSIENT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TRANSIENT -1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESETSTART_INVERT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESETSTART_INVERT 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESETAPPLY_NOSAVEPOINT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESETAPPLY_NOSAVEPOINT 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESETAPPLY_INVERT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESETAPPLY_INVERT 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESETAPPLY_IGNORENOOP
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESETAPPLY_IGNORENOOP 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_DATA
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_DATA 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_NOTFOUND
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_NOTFOUND 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_CONFLICT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_CONFLICT 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_CONSTRAINT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_CONSTRAINT 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_FOREIGN_KEY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_FOREIGN_KEY 5L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_OMIT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_OMIT 0L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_REPLACE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_REPLACE 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_ABORT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CHANGESET_ABORT 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SINGLETHREAD
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SINGLETHREAD 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MULTITHREAD
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MULTITHREAD 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SERIALIZED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SERIALIZED 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MALLOC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MALLOC 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_GETMALLOC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_GETMALLOC 5L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SCRATCH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SCRATCH 6L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PAGECACHE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PAGECACHE 7L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_HEAP
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_HEAP 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MEMSTATUS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MEMSTATUS 9L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MUTEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MUTEX 10L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_GETMUTEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_GETMUTEX 11L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_LOOKASIDE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_LOOKASIDE 13L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PCACHE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PCACHE 14L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_GETPCACHE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_GETPCACHE 15L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_LOG
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_LOG 16L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_URI
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_URI 17L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PCACHE2
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PCACHE2 18L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_GETPCACHE2
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_GETPCACHE2 19L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_COVERING_INDEX_SCAN
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_COVERING_INDEX_SCAN 20L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SQLLOG
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SQLLOG 21L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MMAP_SIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MMAP_SIZE 22L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_WIN32_HEAPSIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_WIN32_HEAPSIZE 23L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PCACHE_HDRSZ
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PCACHE_HDRSZ 24L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PMASZ
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_PMASZ 25L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_STMTJRNL_SPILL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_STMTJRNL_SPILL 26L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SMALL_MALLOC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SMALL_MALLOC 27L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SORTERREF_SIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_SORTERREF_SIZE 28L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MEMDB_MAXSIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONFIG_MEMDB_MAXSIZE 29L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INTEGER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INTEGER 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FLOAT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FLOAT 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TEXT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TEXT 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_BLOB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_BLOB 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_NULL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_NULL 5L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_MAINDBNAME
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_MAINDBNAME 1000L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_LOOKASIDE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_LOOKASIDE 1001L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_FKEY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_FKEY 1002L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_TRIGGER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_TRIGGER 1003L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_QPSG
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_QPSG 1007L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_TRIGGER_EQP
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_TRIGGER_EQP 1008L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_RESET_DATABASE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_RESET_DATABASE 1009L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_DEFENSIVE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_DEFENSIVE 1010L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_WRITABLE_SCHEMA
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_DQS_DML
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_DQS_DML 1013L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_DQS_DDL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_DQS_DDL 1014L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_VIEW
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_ENABLE_VIEW 1015L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_LEGACY_FILE_FORMAT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_TRUSTED_SCHEMA
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_STMT_SCANSTATUS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_STMT_SCANSTATUS 1018L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_REVERSE_SCANORDER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_REVERSE_SCANORDER 1019L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_MAX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBCONFIG_MAX 1019L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_LOOKASIDE_USED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_LOOKASIDE_USED 0L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_USED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_USED 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_SCHEMA_USED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_SCHEMA_USED 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_STMT_USED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_STMT_USED 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_LOOKASIDE_HIT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_LOOKASIDE_HIT 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_HIT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_HIT 7L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_MISS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_MISS 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_WRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_WRITE 9L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_DEFERRED_FKS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_DEFERRED_FKS 10L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_USED_SHARED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_USED_SHARED 11L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_SPILL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_CACHE_SPILL 12L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_MAX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DBSTATUS_MAX 12L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_UTF8
+#define org_sqlite_jni_SQLite3Jni_SQLITE_UTF8 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_UTF16LE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_UTF16LE 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_UTF16BE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_UTF16BE 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_UTF16
+#define org_sqlite_jni_SQLite3Jni_SQLITE_UTF16 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_UTF16_ALIGNED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_UTF16_ALIGNED 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_LOCKSTATE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_LOCKSTATE 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_GET_LOCKPROXYFILE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_GET_LOCKPROXYFILE 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SET_LOCKPROXYFILE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SET_LOCKPROXYFILE 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_LAST_ERRNO
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_LAST_ERRNO 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SIZE_HINT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SIZE_HINT 5L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_CHUNK_SIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_CHUNK_SIZE 6L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_FILE_POINTER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_FILE_POINTER 7L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SYNC_OMITTED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SYNC_OMITTED 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_WIN32_AV_RETRY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_WIN32_AV_RETRY 9L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_PERSIST_WAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_PERSIST_WAL 10L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_OVERWRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_OVERWRITE 11L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_VFSNAME
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_VFSNAME 12L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_POWERSAFE_OVERWRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_POWERSAFE_OVERWRITE 13L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_PRAGMA
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_PRAGMA 14L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_BUSYHANDLER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_BUSYHANDLER 15L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_TEMPFILENAME
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_TEMPFILENAME 16L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_MMAP_SIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_MMAP_SIZE 18L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_TRACE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_TRACE 19L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_HAS_MOVED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_HAS_MOVED 20L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SYNC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SYNC 21L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_COMMIT_PHASETWO
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_COMMIT_PHASETWO 22L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_WIN32_SET_HANDLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_WIN32_SET_HANDLE 23L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_WAL_BLOCK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_WAL_BLOCK 24L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_ZIPVFS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_ZIPVFS 25L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_RBU
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_RBU 26L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_VFS_POINTER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_VFS_POINTER 27L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_JOURNAL_POINTER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_JOURNAL_POINTER 28L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_WIN32_GET_HANDLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_WIN32_GET_HANDLE 29L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_PDB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_PDB 30L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_BEGIN_ATOMIC_WRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_COMMIT_ATOMIC_WRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_LOCK_TIMEOUT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_LOCK_TIMEOUT 34L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_DATA_VERSION
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_DATA_VERSION 35L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SIZE_LIMIT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_SIZE_LIMIT 36L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_CKPT_DONE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_CKPT_DONE 37L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_RESERVE_BYTES
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_RESERVE_BYTES 38L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_CKPT_START
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_CKPT_START 39L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_EXTERNAL_READER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_EXTERNAL_READER 40L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_CKSM_FILE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_CKSM_FILE 41L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_RESET_CACHE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FCNTL_RESET_CACHE 42L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_NONE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_NONE 0L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_SHARED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_SHARED 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_RESERVED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_RESERVED 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_PENDING
+#define org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_PENDING 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_EXCLUSIVE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_LOCK_EXCLUSIVE 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC512
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC512 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC1K
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC1K 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC2K
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC2K 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC4K
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC4K 16L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC8K
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC8K 32L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC16K
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC16K 64L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC32K
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC32K 128L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC64K
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_ATOMIC64K 256L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_SAFE_APPEND
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_SAFE_APPEND 512L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_SEQUENTIAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_SEQUENTIAL 1024L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 2048L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_POWERSAFE_OVERWRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_POWERSAFE_OVERWRITE 4096L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_IMMUTABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_IMMUTABLE 8192L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_BATCH_ATOMIC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOCAP_BATCH_ATOMIC 16384L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_READONLY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_READONLY 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_READWRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_READWRITE 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_CREATE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_CREATE 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_URI
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_URI 64L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_MEMORY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_MEMORY 128L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_NOMUTEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_NOMUTEX 32768L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_FULLMUTEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_FULLMUTEX 65536L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_SHAREDCACHE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_SHAREDCACHE 131072L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_PRIVATECACHE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_PRIVATECACHE 262144L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_EXRESCODE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_EXRESCODE 33554432L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_NOFOLLOW
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_NOFOLLOW 16777216L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_MAIN_DB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_MAIN_DB 256L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_MAIN_JOURNAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_MAIN_JOURNAL 2048L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_TEMP_DB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_TEMP_DB 512L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_TEMP_JOURNAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_TEMP_JOURNAL 4096L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_TRANSIENT_DB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_TRANSIENT_DB 1024L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_SUBJOURNAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_SUBJOURNAL 8192L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_SUPER_JOURNAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_SUPER_JOURNAL 16384L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_WAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_WAL 524288L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_DELETEONCLOSE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_DELETEONCLOSE 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_EXCLUSIVE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OPEN_EXCLUSIVE 16L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_PREPARE_PERSISTENT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_PREPARE_PERSISTENT 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_PREPARE_NORMALIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_PREPARE_NORMALIZE 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_PREPARE_NO_VTAB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_PREPARE_NO_VTAB 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OK 0L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ERROR
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ERROR 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INTERNAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INTERNAL 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_PERM
+#define org_sqlite_jni_SQLite3Jni_SQLITE_PERM 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ABORT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ABORT 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_BUSY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_BUSY 5L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_LOCKED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_LOCKED 6L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_NOMEM
+#define org_sqlite_jni_SQLite3Jni_SQLITE_NOMEM 7L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_READONLY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_READONLY 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INTERRUPT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INTERRUPT 9L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR 10L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CORRUPT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CORRUPT 11L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_NOTFOUND
+#define org_sqlite_jni_SQLite3Jni_SQLITE_NOTFOUND 12L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FULL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FULL 13L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN 14L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_PROTOCOL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_PROTOCOL 15L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_EMPTY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_EMPTY 16L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_SCHEMA
+#define org_sqlite_jni_SQLite3Jni_SQLITE_SCHEMA 17L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TOOBIG
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TOOBIG 18L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT 19L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_MISMATCH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_MISMATCH 20L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_MISUSE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_MISUSE 21L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_NOLFS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_NOLFS 22L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_AUTH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_AUTH 23L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FORMAT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FORMAT 24L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_RANGE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_RANGE 25L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_NOTADB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_NOTADB 26L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_NOTICE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_NOTICE 27L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_WARNING
+#define org_sqlite_jni_SQLite3Jni_SQLITE_WARNING 28L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ROW
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ROW 100L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DONE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DONE 101L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ERROR_MISSING_COLLSEQ
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ERROR_MISSING_COLLSEQ 257L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ERROR_RETRY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ERROR_RETRY 513L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ERROR_SNAPSHOT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ERROR_SNAPSHOT 769L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_READ
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_READ 266L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHORT_READ
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHORT_READ 522L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_WRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_WRITE 778L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_FSYNC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_FSYNC 1034L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DIR_FSYNC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DIR_FSYNC 1290L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_TRUNCATE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_TRUNCATE 1546L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_FSTAT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_FSTAT 1802L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_UNLOCK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_UNLOCK 2058L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_RDLOCK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_RDLOCK 2314L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DELETE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DELETE 2570L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_BLOCKED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_BLOCKED 2826L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_NOMEM
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_NOMEM 3082L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_ACCESS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_ACCESS 3338L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_CHECKRESERVEDLOCK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_CHECKRESERVEDLOCK 3594L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_LOCK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_LOCK 3850L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_CLOSE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_CLOSE 4106L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DIR_CLOSE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DIR_CLOSE 4362L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHMOPEN
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHMOPEN 4618L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHMSIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHMSIZE 4874L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHMLOCK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHMLOCK 5130L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHMMAP
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SHMMAP 5386L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SEEK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_SEEK 5642L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DELETE_NOENT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DELETE_NOENT 5898L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_MMAP
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_MMAP 6154L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_GETTEMPPATH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_GETTEMPPATH 6410L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_CONVPATH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_CONVPATH 6666L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_VNODE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_VNODE 6922L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_AUTH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_AUTH 7178L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_BEGIN_ATOMIC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_BEGIN_ATOMIC 7434L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_COMMIT_ATOMIC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_COMMIT_ATOMIC 7690L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_ROLLBACK_ATOMIC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_ROLLBACK_ATOMIC 7946L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DATA
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_DATA 8202L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_CORRUPTFS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_IOERR_CORRUPTFS 8458L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_LOCKED_SHAREDCACHE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_LOCKED_SHAREDCACHE 262L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_LOCKED_VTAB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_LOCKED_VTAB 518L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_BUSY_RECOVERY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_BUSY_RECOVERY 261L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_BUSY_SNAPSHOT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_BUSY_SNAPSHOT 517L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_BUSY_TIMEOUT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_BUSY_TIMEOUT 773L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_NOTEMPDIR
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_NOTEMPDIR 270L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_ISDIR
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_ISDIR 526L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_FULLPATH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_FULLPATH 782L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_CONVPATH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_CONVPATH 1038L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_SYMLINK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CANTOPEN_SYMLINK 1550L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CORRUPT_VTAB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CORRUPT_VTAB 267L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CORRUPT_SEQUENCE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CORRUPT_SEQUENCE 523L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CORRUPT_INDEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CORRUPT_INDEX 779L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_RECOVERY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_RECOVERY 264L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_CANTLOCK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_CANTLOCK 520L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_ROLLBACK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_ROLLBACK 776L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_DBMOVED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_DBMOVED 1032L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_CANTINIT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_CANTINIT 1288L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_DIRECTORY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_READONLY_DIRECTORY 1544L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ABORT_ROLLBACK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ABORT_ROLLBACK 516L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_CHECK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_CHECK 275L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_COMMITHOOK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_COMMITHOOK 531L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_FOREIGNKEY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_FOREIGNKEY 787L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_FUNCTION
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_FUNCTION 1043L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_NOTNULL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_NOTNULL 1299L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_PRIMARYKEY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_PRIMARYKEY 1555L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_TRIGGER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_TRIGGER 1811L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_UNIQUE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_UNIQUE 2067L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_VTAB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_VTAB 2323L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_ROWID
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_ROWID 2579L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_PINNED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_PINNED 2835L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_DATATYPE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_CONSTRAINT_DATATYPE 3091L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_NOTICE_RECOVER_WAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_NOTICE_RECOVER_WAL 283L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_NOTICE_RECOVER_ROLLBACK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_NOTICE_RECOVER_ROLLBACK 539L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_WARNING_AUTOINDEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_WARNING_AUTOINDEX 284L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_AUTH_USER
+#define org_sqlite_jni_SQLite3Jni_SQLITE_AUTH_USER 279L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_OK_LOAD_PERMANENTLY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_OK_LOAD_PERMANENTLY 256L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_SERIALIZE_NOCOPY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_SERIALIZE_NOCOPY 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DESERIALIZE_FREEONCLOSE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DESERIALIZE_FREEONCLOSE 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DESERIALIZE_READONLY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DESERIALIZE_READONLY 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DESERIALIZE_RESIZEABLE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DESERIALIZE_RESIZEABLE 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_SESSION_CONFIG_STRMSIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_SESSION_CONFIG_STRMSIZE 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_SESSION_OBJCONFIG_SIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_SESSION_OBJCONFIG_SIZE 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_MEMORY_USED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_MEMORY_USED 0L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_PAGECACHE_USED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_PAGECACHE_USED 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_PAGECACHE_OVERFLOW
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_PAGECACHE_OVERFLOW 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_MALLOC_SIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_MALLOC_SIZE 5L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_PARSER_STACK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_PARSER_STACK 6L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_PAGECACHE_SIZE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_PAGECACHE_SIZE 7L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_MALLOC_COUNT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STATUS_MALLOC_COUNT 9L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_FULLSCAN_STEP
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_FULLSCAN_STEP 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_SORT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_SORT 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_AUTOINDEX
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_AUTOINDEX 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_VM_STEP
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_VM_STEP 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_REPREPARE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_REPREPARE 5L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_RUN
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_RUN 6L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_FILTER_MISS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_FILTER_MISS 7L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_FILTER_HIT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_FILTER_HIT 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_MEMUSED
+#define org_sqlite_jni_SQLite3Jni_SQLITE_STMTSTATUS_MEMUSED 99L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_SYNC_NORMAL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_SYNC_NORMAL 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_SYNC_FULL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_SYNC_FULL 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_SYNC_DATAONLY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_SYNC_DATAONLY 16L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TRACE_STMT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TRACE_STMT 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TRACE_PROFILE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TRACE_PROFILE 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TRACE_ROW
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TRACE_ROW 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TRACE_CLOSE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TRACE_CLOSE 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TXN_NONE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TXN_NONE 0L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TXN_READ
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TXN_READ 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_TXN_WRITE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_TXN_WRITE 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DETERMINISTIC
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DETERMINISTIC 2048L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_DIRECTONLY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_DIRECTONLY 524288L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INNOCUOUS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INNOCUOUS 2097152L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_SCAN_UNIQUE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_SCAN_UNIQUE 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_EQ
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_EQ 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_GT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_GT 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_LE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_LE 8L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_LT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_LT 16L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_GE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_GE 32L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_MATCH
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_MATCH 64L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_LIKE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_LIKE 65L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_GLOB
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_GLOB 66L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_REGEXP
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_REGEXP 67L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_NE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_NE 68L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_ISNOT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_ISNOT 69L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_ISNOTNULL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_ISNULL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_ISNULL 71L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_IS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_IS 72L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_LIMIT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_LIMIT 73L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_OFFSET
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_OFFSET 74L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_FUNCTION
+#define org_sqlite_jni_SQLite3Jni_SQLITE_INDEX_CONSTRAINT_FUNCTION 150L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_VTAB_CONSTRAINT_SUPPORT
+#define org_sqlite_jni_SQLite3Jni_SQLITE_VTAB_CONSTRAINT_SUPPORT 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_VTAB_INNOCUOUS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_VTAB_INNOCUOUS 2L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_VTAB_DIRECTONLY
+#define org_sqlite_jni_SQLite3Jni_SQLITE_VTAB_DIRECTONLY 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_VTAB_USES_ALL_SCHEMAS
+#define org_sqlite_jni_SQLite3Jni_SQLITE_VTAB_USES_ALL_SCHEMAS 4L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_ROLLBACK
+#define org_sqlite_jni_SQLite3Jni_SQLITE_ROLLBACK 1L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_FAIL
+#define org_sqlite_jni_SQLite3Jni_SQLITE_FAIL 3L
+#undef org_sqlite_jni_SQLite3Jni_SQLITE_REPLACE
+#define org_sqlite_jni_SQLite3Jni_SQLITE_REPLACE 5L
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: init
+ * Signature: (Lorg/sqlite/jni/SQLite3Jni;)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_init
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_blob
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1blob
+ (JNIEnv *, jclass, jobject, jint, jbyteArray, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_double
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;ID)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1double
+ (JNIEnv *, jclass, jobject, jint, jdouble);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_int
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;II)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1int
+ (JNIEnv *, jclass, jobject, jint, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_int64
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;IJ)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1int64
+ (JNIEnv *, jclass, jobject, jint, jlong);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_null
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1null
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_parameter_count
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1parameter_1count
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_parameter_index
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;[B)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1parameter_1index
+ (JNIEnv *, jclass, jobject, jbyteArray);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_text
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1text
+ (JNIEnv *, jclass, jobject, jint, jbyteArray, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_zeroblob
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;II)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1zeroblob
+ (JNIEnv *, jclass, jobject, jint, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_bind_zeroblob64
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;IJ)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1zeroblob64
+ (JNIEnv *, jclass, jobject, jint, jlong);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_busy_timeout
+ * Signature: (Lorg/sqlite/jni/sqlite3;I)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1busy_1timeout
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_changes
+ * Signature: (Lorg/sqlite/jni/sqlite3;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1changes
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_changes64
+ * Signature: (Lorg/sqlite/jni/sqlite3;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1changes64
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_clear_bindings
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1clear_1bindings
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_close
+ * Signature: (Lorg/sqlite/jni/sqlite3;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1close
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_close_v2
+ * Signature: (Lorg/sqlite/jni/sqlite3;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1close_1v2
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_blob
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1blob
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_bytes
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1bytes
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_bytes16
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1bytes16
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_count
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1count
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_double
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)D
+ */
+JNIEXPORT jdouble JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1double
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_int
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1int
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_int64
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)J
+ */
+JNIEXPORT jlong JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1int64
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_name
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1name
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_database_name
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1database_1name
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_origin_name
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1origin_1name
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_table_name
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1table_1name
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_text
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1text
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_text_utf8
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1text_1utf8
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_type
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1type
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_column_value
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;I)Lorg/sqlite/jni/sqlite3_value;
+ */
+JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1column_1value
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_context_db_handle
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;)Lorg/sqlite/jni/sqlite3;
+ */
+JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1context_1db_1handle
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_compileoption_get
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1compileoption_1get
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_compileoption_used
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1compileoption_1used
+ (JNIEnv *, jclass, jstring);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_create_collation
+ * Signature: (Lorg/sqlite/jni/sqlite3;Ljava/lang/String;ILorg/sqlite/jni/Collation;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1create_1collation
+ (JNIEnv *, jclass, jobject, jstring, jint, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_create_function
+ * Signature: (Lorg/sqlite/jni/sqlite3;Ljava/lang/String;IILorg/sqlite/jni/SQLFunction;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1create_1function
+ (JNIEnv *, jclass, jobject, jstring, jint, jint, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_data_count
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1data_1count
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_errcode
+ * Signature: (Lorg/sqlite/jni/sqlite3;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1errcode
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_extended_errcode
+ * Signature: (Lorg/sqlite/jni/sqlite3;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1extended_1errcode
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_extended_result_codes
+ * Signature: (Lorg/sqlite/jni/sqlite3;Z)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1extended_1result_1codes
+ (JNIEnv *, jclass, jobject, jboolean);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_errmsg
+ * Signature: (Lorg/sqlite/jni/sqlite3;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1errmsg
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_errstr
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1errstr
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_error_offset
+ * Signature: (Lorg/sqlite/jni/sqlite3;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1error_1offset
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_finalize
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1finalize
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_initialize
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1initialize
+ (JNIEnv *, jclass);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_last_insert_rowid
+ * Signature: (Lorg/sqlite/jni/sqlite3;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1last_1insert_1rowid
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_libversion
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1libversion
+ (JNIEnv *, jclass);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_libversion_number
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1libversion_1number
+ (JNIEnv *, jclass);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_open
+ * Signature: (Ljava/lang/String;Lorg/sqlite/jni/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
+ */
+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
+ */
+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
+ */
+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
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1prepare_1v3
+ (JNIEnv *, jclass, jobject, jbyteArray, jint, jint, jobject, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_reset
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1reset
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_double
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;D)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1double
+ (JNIEnv *, jclass, jobject, jdouble);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_error
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;[BI)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1error
+ (JNIEnv *, jclass, jobject, jbyteArray, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_error_toobig
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1error_1toobig
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_error_nomem
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1error_1nomem
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_error_code
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;I)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1error_1code
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_null
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1null
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_int
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;I)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1int
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_int64
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;J)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1int64
+ (JNIEnv *, jclass, jobject, jlong);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_java_object
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1java_1object
+ (JNIEnv *, jclass, jobject, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_value
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;Lorg/sqlite/jni/sqlite3_value;)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1value
+ (JNIEnv *, jclass, jobject, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_zeroblob
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;I)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1zeroblob
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_zeroblob64
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;J)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1zeroblob64
+ (JNIEnv *, jclass, jobject, jlong);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_blob
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;[BI)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1blob
+ (JNIEnv *, jclass, jobject, jbyteArray, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_blob64
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;[BJ)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1blob64
+ (JNIEnv *, jclass, jobject, jbyteArray, jlong);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_result_text
+ * Signature: (Lorg/sqlite/jni/sqlite3_context;[BI)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1text
+ (JNIEnv *, jclass, jobject, jbyteArray, jint);
+
+/*
+ * 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_set_last_insert_rowid
+ * Signature: (Lorg/sqlite/jni/sqlite3;J)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1set_1last_1insert_1rowid
+ (JNIEnv *, jclass, jobject, jlong);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_sleep
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1sleep
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_sourceid
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1sourceid
+ (JNIEnv *, jclass);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_step
+ * Signature: (Lorg/sqlite/jni/sqlite3_stmt;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1step
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_threadsafe
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1threadsafe
+ (JNIEnv *, jclass);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_total_changes
+ * Signature: (Lorg/sqlite/jni/sqlite3;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1total_1changes
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_total_changes64
+ * Signature: (Lorg/sqlite/jni/sqlite3;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1total_1changes64
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_trace_v2
+ * Signature: (Lorg/sqlite/jni/sqlite3;ILorg/sqlite/jni/Tracer;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1trace_1v2
+ (JNIEnv *, jclass, jobject, jint, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_blob
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1blob
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_bytes
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1bytes
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_bytes16
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1bytes16
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_double
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)D
+ */
+JNIEXPORT jdouble JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1double
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_dupe
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)Lorg/sqlite/jni/sqlite3_value;
+ */
+JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1dupe
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_encoding
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1encoding
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_free
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)V
+ */
+JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1free
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_int
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1int
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_int64
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1int64
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_java_object
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1java_1object
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_text
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1text
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_text_utf8
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1text_1utf8
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_text16
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1text16
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_text16le
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1text16le
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_text16be
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1text16be
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_type
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1type
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_numeric_type
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1numeric_1type
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_nochange
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1nochange
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_frombind
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1frombind
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_value_subtype
+ * Signature: (Lorg/sqlite/jni/sqlite3_value;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1subtype
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: org_sqlite_jni_SQLite3Jni
+ * Method: sqlite3_shutdown
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1shutdown
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null
+/*
+** 2023-07-22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+*/
+public abstract class Collation {
+ /**
+ Must compare the given byte arrays using memcmp() semantics.
+ */
+ public abstract int xCompare(byte[] lhs, byte[] rhs);
+ /**
+ Called by SQLite when the collation is destroyed. If a Collation
+ requires custom cleanup, override this method.
+ */
+ public void xDestroy() {}
+}
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+ A helper for passing pointers between JNI C code and Java, in
+ particular for output pointers of high-level object types in the
+ sqlite3 C API, e.g. (sqlite3**) and (sqlite3_stmt**). This is
+ intended to be subclassed and the ContextType is intended to be the
+ class which is doing the subclassing. The intent of the ContextType
+ is strictly to provide some level of type safety by avoiding that
+ NativePointerHolder is not inadvertently passed to an incompatible
+ function signature.
+
+ These objects are not intended to _own_ the pointer they refer to.
+ They are intended to simply communicate that pointer between C and
+ Java.
+*/
+public class NativePointerHolder<ContextType> {
+ private long pointer;
+ public NativePointerHolder(long pointer){
+ this.pointer = pointer;
+ }
+ public NativePointerHolder(){
+ this.pointer = 0;
+ }
+ public final long getNativePointer(){ return pointer; }
+ public final void setNativePointer(long p){ pointer = p; }
+}
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+ Helper classes for handling JNI output pointers for primitive
+ types. Higher-level classes which use output pointers have their
+ own corresponding Java class, e.g. sqlite3 and sqlite3_stmt.
+
+ We do not use a generic OutputPointer<T> because working with those
+ from the native JNI code is unduly quirky due to a lack of
+ autoboxing at that level.
+*/
+public final class OutputPointer {
+ public static final class Int32 {
+ private int value;
+ public final void setValue(int v){value = v;}
+ public final int getValue(){return value;}
+ }
+ public static final class Int64 {
+ private long value;
+ public final void setValue(long v){value = v;}
+ public final long getValue(){return value;}
+ }
+}
--- /dev/null
+/*
+** 2023-07-22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+ Callback proxy for use with sqlite3_progress_handler().
+*/
+public interface ProgressHandler {
+ /**
+ */
+ int xCallback();
+}
--- /dev/null
+/*
+** 2023-07-22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+ SQLFunction is used in conjunction with the
+ sqlite3_create_function() JNI-bound API to give that native code
+ access to the callback functions needed in order to implement SQL
+ functions in Java. This class is not used by itself: see the
+ three inner classes.
+*/
+public abstract class SQLFunction {
+
+ //! Subclass for creating scalar functions.
+ public static abstract class Scalar extends SQLFunction {
+ public abstract void xFunc(sqlite3_context cx, sqlite3_value[] args);
+ /**
+ Optionally override to be notified when the function is
+ finalized by SQLite.
+ */
+ public void xDestroy() {}
+ }
+
+ //! Subclass for creating aggregate functions.
+ public static abstract class Aggregate extends SQLFunction {
+ public abstract void xStep(sqlite3_context cx, sqlite3_value[] args);
+ public abstract void xFinal(sqlite3_context cx);
+ public void xDestroy() {}
+ }
+
+ //! Subclass for creating window functions.
+ public static abstract class Window extends SQLFunction {
+ public abstract void xStep(sqlite3_context cx, sqlite3_value[] args);
+ public abstract void xInverse(sqlite3_context cx, sqlite3_value[] args);
+ public abstract void xFinal(sqlite3_context cx);
+ public abstract void xValue(sqlite3_context cx);
+ public void xDestroy() {}
+ }
+}
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file declares JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+import java.nio.charset.StandardCharsets;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ This annotation is for flagging parameters which may legally be
+ null, noting that they may behave different if passed null but are
+ prepared to expect null as a value.
+
+ This annotation is solely for the reader's information.
+*/
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+@interface Nullable{}
+
+/**
+ This annotation is for flagging parameters which may not legally be
+ null. Note that the C-style API does _not_ throw any
+ NullPointerExceptions on its own because it has a no-throw policy
+ in order to retain its C-style semantics.
+
+ This annotation is solely for the reader's information. No policy
+ is in place to programmatically ensure that NotNull is conformed to
+ in client code.
+*/
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+@interface NotNull{}
+
+/**
+ This class contains the entire sqlite3 JNI API binding. For
+ client-side use, a static import is recommended:
+
+ ```
+ import static org.sqlite.jni.SQLite3Jni.*;
+ ```
+
+ The C-side part can be found in sqlite3-jni.c.
+
+
+ Only functions which materially differ from their C counterparts
+ are documented here. The C documetation is otherwise applicable
+ here:
+
+ https://sqlite.org/c3ref/intro.html
+
+ A small handful of Java-specific APIs have been added.
+*/
+public final class SQLite3Jni {
+ static {
+ System.loadLibrary("sqlite3-jni");
+ }
+ private SQLite3Jni(){}
+ private static native void init(@NotNull SQLite3Jni s);
+
+ //////////////////////////////////////////////////////////////////////
+ // Maintenance reminder: please keep the functions alphabetized.
+ // The SQLITE_... values. on the other hand, are grouped by category.
+
+ public static int sqlite3_bind_blob(@NotNull sqlite3_stmt stmt, int ndx,
+ @Nullable byte[] data){
+ return (null == data)
+ ? sqlite3_bind_null(stmt, ndx)
+ : sqlite3_bind_blob(stmt, ndx, data, data.length);
+ }
+
+ private static native int sqlite3_bind_blob(@NotNull sqlite3_stmt stmt,
+ int ndx, @Nullable byte[] data,
+ int n);
+
+ public static native int sqlite3_bind_double(@NotNull sqlite3_stmt stmt,
+ int ndx, double v);
+
+ public static native int sqlite3_bind_int(@NotNull sqlite3_stmt stmt,
+ int ndx, int v);
+
+ public static native int sqlite3_bind_int64(@NotNull sqlite3_stmt stmt,
+ int ndx, long v);
+
+ public static native int sqlite3_bind_null(@NotNull sqlite3_stmt stmt, int ndx);
+
+ public static native int sqlite3_bind_parameter_count(@NotNull sqlite3_stmt stmt);
+
+
+ private static native int sqlite3_bind_parameter_index(@NotNull sqlite3_stmt stmt,
+ byte[] paramName);
+
+ public static int sqlite3_bind_parameter_index(@NotNull sqlite3_stmt stmt,
+ @NotNull String paramName){
+ final byte[] utf8 = (paramName+"\0").getBytes(StandardCharsets.UTF_8);
+ return sqlite3_bind_parameter_index(stmt, utf8);
+ }
+
+ public static int sqlite3_bind_text(@NotNull sqlite3_stmt stmt, int ndx,
+ @Nullable String data){
+ if(null == data) return sqlite3_bind_null(stmt, ndx);
+ final byte[] utf8 = data.getBytes(StandardCharsets.UTF_8);
+ return sqlite3_bind_text(stmt, ndx, utf8, utf8.length);
+ }
+
+ public static int sqlite3_bind_text(@NotNull sqlite3_stmt stmt, int ndx,
+ @Nullable byte[] data){
+ return (null == data)
+ ? sqlite3_bind_null(stmt, ndx)
+ : sqlite3_bind_text(stmt, ndx, data, data.length);
+ }
+
+ /**
+ Works like the C-level sqlite3_bind_text() but (A) assumes
+ SQLITE_TRANSIENT for the final parameter and (B) behaves like
+ sqlite3_bind_null() if the data argument is null.
+ */
+ private static native int sqlite3_bind_text(@NotNull sqlite3_stmt stmt, int ndx,
+ @Nullable byte[] data, int maxBytes);
+
+ public static native int sqlite3_bind_zeroblob(@NotNull sqlite3_stmt stmt, int ndx, int n);
+
+ public static native int sqlite3_bind_zeroblob64(@NotNull sqlite3_stmt stmt, int ndx, long n);
+
+ //TODO? public static native int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
+
+ public static native int sqlite3_busy_timeout(@NotNull sqlite3 db, int ms);
+
+ public static native int sqlite3_changes(@NotNull sqlite3 db);
+
+ public static native long sqlite3_changes64(@NotNull sqlite3 db);
+
+ public static native int sqlite3_clear_bindings(@NotNull sqlite3_stmt stmt);
+
+ public static native int sqlite3_close(@NotNull sqlite3 db);
+
+ public static native int sqlite3_close_v2(@NotNull sqlite3 db);
+
+ //TODO? public static native int sqlite3_collation_needed(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*));
+ //TODO? public static native int sqlite3_collation_needed16(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*));
+
+ public static native byte[] sqlite3_column_blob(@NotNull sqlite3_stmt stmt, int ndx);
+
+ public static native int sqlite3_column_bytes(@NotNull sqlite3_stmt stmt, int ndx);
+
+ public static native int sqlite3_column_bytes16(@NotNull sqlite3_stmt stmt, int ndx);
+
+ public static native int sqlite3_column_count(@NotNull sqlite3_stmt stmt);
+
+ public static native double sqlite3_column_double(@NotNull sqlite3_stmt stmt, int ndx);
+
+ public static native int sqlite3_column_int(@NotNull sqlite3_stmt stmt, int ndx);
+
+ public static native long sqlite3_column_int64(@NotNull sqlite3_stmt stmt, int ndx);
+
+ public static native String sqlite3_column_name(@NotNull sqlite3_stmt stmt, int ndx);
+
+ public static native String sqlite3_column_database_name(@NotNull sqlite3_stmt stmt, int ndx);
+
+ /**
+ Column counterpart of sqlite3_value_java_object().
+ */
+ public static Object sqlite3_column_java_object(@NotNull sqlite3_stmt stmt,
+ int ndx){
+ Object rv = null;
+ sqlite3_value v = sqlite3_column_value(stmt, ndx);
+ if(null!=v){
+ v = sqlite3_value_dupe(v) /* we need a "protected" value */;
+ if(null!=v){
+ rv = sqlite3_value_java_object(v);
+ sqlite3_value_free(v);
+ }
+ }
+ return rv;
+ }
+
+ /**
+ Column counterpart of sqlite3_value_java_casted().
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T sqlite3_column_java_casted(@NotNull sqlite3_stmt stmt,
+ int ndx,
+ @NotNull Class<T> type){
+ final Object o = sqlite3_column_java_object(stmt, ndx);
+ return (null!=o && type.isInstance(o)) ? (T)o : null;
+ }
+
+ public static native String sqlite3_column_origin_name(@NotNull sqlite3_stmt stmt, int ndx);
+
+ public static native String sqlite3_column_table_name(@NotNull sqlite3_stmt stmt, int ndx);
+
+ /**
+ Because Java strings use UTF-16 and JNI speaks Modified UTF-8
+ instead of standard UTF8[^1], this routine functions equivalently to
+ the native sqlite3_column_text16(), so requires conversion from
+ the db if the db uses the default encoding of UTF-8.
+
+ To extract _standard_ UTF-8, use sqlite3_column_text_utf8().
+ This API includes no functions for working with Modified UTF-8.
+
+ [^1]: https://stackoverflow.com/questions/7921016
+ */
+ public static native String sqlite3_column_text(@NotNull sqlite3_stmt stmt, int ndx);
+
+ /**
+ Similar to sqlite3_column_text(), but the result is an array encoded
+ in standard UTF-8, not Modified UTF-8.
+ */
+ public static native byte[] sqlite3_column_text_utf8(@NotNull sqlite3_stmt stmt,
+ int ndx);
+ //TODO public static native ?type? sqlite3_column_text16(@NotNull sqlite3_stmt stmt, int ndx);
+ //TODO: public static Object sqlite3_column_to_java(@NotNull sqlite3_value v){...}
+
+ public static native int sqlite3_column_type(@NotNull sqlite3_stmt stmt,
+ int ndx);
+
+ public static native sqlite3_value sqlite3_column_value(@NotNull sqlite3_stmt stmt,
+ int ndx);
+
+ // TODO public static native int sqlite3_collation_needed(
+ //sqlite3 db, void(*)(void*,sqlite3*,int eTextRep,const char*))
+
+ //TODO public static native int sqlite3_collation_needed16(
+ // sqlite3 db, void(*)(void*,sqlite3*,int eTextRep,const void*)
+
+ public static native sqlite3 sqlite3_context_db_handle(@NotNull sqlite3_context cx);
+
+ //TODO? void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
+
+ public static native String sqlite3_compileoption_get(int n);
+
+ public static native boolean sqlite3_compileoption_used(@NotNull String optName);
+
+ public static native int sqlite3_create_collation(@NotNull sqlite3 db,
+ @NotNull String name,
+ int eTextRep,
+ @NotNull Collation col);
+
+ //! Convenience overload which assumes SQLITE_UTF8 encoding.
+ public static int sqlite3_create_collation(@NotNull sqlite3 db,
+ @NotNull String name,
+ @NotNull Collation col){
+ return sqlite3_create_collation(db, name, SQLITE_UTF8, col);
+ }
+
+ public static native int sqlite3_create_function(@NotNull sqlite3 db,
+ @NotNull String functionName,
+ int nArg, int eTextRep,
+ @NotNull SQLFunction func);
+
+ public static native int sqlite3_data_count(@NotNull sqlite3_stmt stmt);
+
+ public static native int sqlite3_errcode(@NotNull sqlite3 db);
+
+ public static native int sqlite3_extended_errcode(@NotNull sqlite3 db);
+
+ public static native boolean sqlite3_extended_result_codes(@NotNull sqlite3 db,
+ boolean onoff);
+
+ public static native String sqlite3_errmsg(@NotNull sqlite3 db);
+
+ public static native String sqlite3_errstr(int resultCode);
+
+ public static native int sqlite3_error_offset(@NotNull sqlite3 db);
+
+ public static native int sqlite3_finalize(@NotNull sqlite3_stmt stmt);
+
+ public static native int sqlite3_initialize();
+
+ public static native long sqlite3_last_insert_rowid(@NotNull sqlite3 db);
+
+ //TODO? void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+
+ public static native String sqlite3_libversion();
+
+ public static native int sqlite3_libversion_number();
+
+ public static native int sqlite3_open(@Nullable String filename,
+ @NotNull sqlite3 ppDb);
+
+ public static native int sqlite3_open_v2(@Nullable String filename,
+ @NotNull sqlite3 ppDb,
+ int flags, @Nullable String zVfs);
+
+ /**
+ The sqlite3_prepare() family of functions require slightly
+ different signatures than their native counterparts, but
+ overloading allows us to install several convenience forms.
+
+ All of them which take their SQL in the form of a byte[] require
+ that it be in UTF-8 encoding unless explicitly noted otherwise.
+
+ The forms which take a "tail" output pointer return (via that
+ output object) the index into their SQL byte array at which the
+ end of the first SQL statement processed by the call was
+ found. That's fundamentally how the C APIs work but making use of
+ that value requires more copying of the input SQL into
+ consecutively smaller arrays in order to consume all of
+ it. (There is an example of doing that in this project's Tester1
+ class.) For that vast majority of uses, that capability is not
+ necessary, however, and overloads are provided which gloss over
+ that.
+ */
+ private static native int sqlite3_prepare(@NotNull sqlite3 db,
+ @NotNull byte[] sqlUtf8, int maxBytes,
+ @NotNull sqlite3_stmt outStmt,
+ @Nullable OutputPointer.Int32 pTailOffset);
+
+ public static int sqlite3_prepare(@NotNull sqlite3 db,
+ @NotNull byte[] sqlUtf8,
+ @NotNull 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){
+ return sqlite3_prepare(db, sqlUtf8, sqlUtf8.length, outStmt, null);
+ }
+
+ public static int sqlite3_prepare(@NotNull sqlite3 db, @NotNull String sql,
+ @NotNull 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,
+ @Nullable OutputPointer.Int32 pTailOffset);
+
+ public static int sqlite3_prepare_v2(@NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
+ @NotNull 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){
+ 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){
+ 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,
+ @Nullable OutputPointer.Int32 pTailOffset);
+
+ public static int sqlite3_prepare_v3(@NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
+ int prepFlags,
+ @NotNull 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){
+ 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){
+ final byte[] utf8 = sql.getBytes(StandardCharsets.UTF_8);
+ return sqlite3_prepare_v3(db, utf8, utf8.length, prepFlags, outStmt, null);
+ }
+
+
+ //TODO public static native void sqlite3_progress_handler(sqlite3 db, int n, ProgressHandler h);
+
+ public static native int sqlite3_reset(@NotNull sqlite3_stmt stmt);
+
+ public static native void sqlite3_result_double(@NotNull sqlite3_context cx, double v);
+
+ /**
+ The main sqlite3_result_error() impl of which all others are
+ proxies. eTextRep must be one of SQLITE_UTF8 or SQLITE_UTF16 and
+ msg must be encoded correspondingly. Any other eTextRep value
+ results in the C-level sqlite3_result_error() being called with
+ a complaint about the invalid argument.
+ */
+ private static native void sqlite3_result_error(@NotNull sqlite3_context cx,
+ @Nullable byte[] msg,
+ int eTextRep);
+
+ public static void sqlite3_result_error(@NotNull sqlite3_context cx,
+ @NotNull byte[] utf8){
+ sqlite3_result_error(cx, utf8, SQLITE_UTF8);
+ }
+
+ public static void sqlite3_result_error(@NotNull sqlite3_context cx,
+ @NotNull String msg){
+ final byte[] utf8 = (msg+"\0").getBytes(StandardCharsets.UTF_8);
+ sqlite3_result_error(cx, utf8, SQLITE_UTF8);
+ }
+
+ public static void sqlite3_result_error16(@NotNull sqlite3_context cx,
+ @Nullable byte[] utf16){
+ sqlite3_result_error(cx, utf16, SQLITE_UTF16);
+ }
+
+ public static void sqlite3_result_error16(@NotNull sqlite3_context cx,
+ @NotNull String msg){
+ final byte[] utf8 = (msg+"\0").getBytes(StandardCharsets.UTF_16);
+ sqlite3_result_error(cx, utf8, SQLITE_UTF16);
+ }
+
+ public static void sqlite3_result_error(@NotNull sqlite3_context cx,
+ @NotNull Exception e){
+ sqlite3_result_error(cx, e.getMessage());
+ }
+
+ public static void sqlite3_result_error16(@NotNull sqlite3_context cx,
+ @NotNull Exception e){
+ sqlite3_result_error16(cx, e.getMessage());
+ }
+
+ public static native void sqlite3_result_error_toobig(@NotNull sqlite3_context cx);
+
+ public static native void sqlite3_result_error_nomem(@NotNull sqlite3_context cx);
+
+ public static native void sqlite3_result_error_code(@NotNull sqlite3_context cx, int c);
+
+ public static native void sqlite3_result_null(@NotNull sqlite3_context cx);
+
+ public static native void sqlite3_result_int(@NotNull sqlite3_context cx, int v);
+
+ public static native void sqlite3_result_int64(@NotNull sqlite3_context cx, long v);
+
+ /**
+ Binds the SQL result to the given object, or
+ sqlite3_result_null() if o is null. Use
+ sqlite3_value_java_object() or sqlite3_column_java_object() to
+ fetch it.
+
+ This is implemented in terms of sqlite3_result_pointer(), but
+ that function is not exposed to JNI because its 3rd argument must
+ be a constant string (the library does not copy it), which we
+ cannot implement cross-language here unless, in the JNI layer, we
+ allocate such strings and store them somewhere for long-term use
+ (leaking them more likely than not). Even then, passing around a
+ pointer via Java like that has little practical use.
+ */
+ public static native void sqlite3_result_java_object(@NotNull sqlite3_context cx,
+ @NotNull Object o);
+
+ public static void sqlite3_result_set(@NotNull sqlite3_context cx,
+ @NotNull Integer v){
+ sqlite3_result_int(cx, v);
+ }
+
+ public static void sqlite3_result_set(@NotNull sqlite3_context cx, int v){
+ sqlite3_result_int(cx, v);
+ }
+
+ public static void sqlite3_result_set(@NotNull sqlite3_context cx,
+ @NotNull Boolean v){
+ sqlite3_result_int(cx, v ? 1 : 0);
+ }
+
+ public static void sqlite3_result_set(@NotNull sqlite3_context cx, boolean v){
+ sqlite3_result_int(cx, v ? 1 : 0);
+ }
+
+ public static void sqlite3_result_set(@NotNull sqlite3_context cx,
+ @NotNull Long v){
+ sqlite3_result_int64(cx, v);
+ }
+
+ public static void sqlite3_result_set(@NotNull sqlite3_context cx, long v){
+ sqlite3_result_int64(cx, v);
+ }
+
+ public static void sqlite3_result_set(@NotNull sqlite3_context cx,
+ @NotNull Double v){
+ sqlite3_result_double(cx, v);
+ }
+
+ public static void sqlite3_result_set(@NotNull sqlite3_context cx, double v){
+ sqlite3_result_double(cx, v);
+ }
+
+ public static void sqlite3_result_set(@NotNull sqlite3_context cx,
+ @Nullable String v){
+ sqlite3_result_text(cx, v);
+ }
+
+ public static native void sqlite3_result_value(@NotNull sqlite3_context cx,
+ @NotNull sqlite3_value v);
+
+ public static native void sqlite3_result_zeroblob(@NotNull sqlite3_context cx,
+ int n);
+
+ public static native int sqlite3_result_zeroblob64(@NotNull sqlite3_context cx,
+ long n);
+
+ private static native void sqlite3_result_blob(@NotNull sqlite3_context cx,
+ @Nullable byte[] blob,
+ int maxLen);
+
+ public static void sqlite3_result_blob(@NotNull sqlite3_context cx, @Nullable byte[] blob){
+ sqlite3_result_blob(cx, blob, (int)(null==blob ? 0 : blob.length));
+ }
+
+ /**
+ Binds the given text using C's sqlite3_result_blob64() unless:
+
+ - blob is null ==> sqlite3_result_null()
+
+ - blob is too large ==> sqlite3_result_error_toobig()
+
+ If maxLen is larger than blob.length, it is truncated to that
+ value. If it is negative, results are undefined.
+ */
+ private static native void sqlite3_result_blob64(@NotNull sqlite3_context cx,
+ @Nullable byte[] blob,
+ long maxLen);
+
+ public static void sqlite3_result_blob64(@NotNull sqlite3_context cx,
+ @Nullable byte[] blob){
+ sqlite3_result_blob64(cx, blob, (long)(null==blob ? 0 : blob.length));
+ }
+
+ private static native void sqlite3_result_text(@NotNull sqlite3_context cx,
+ @Nullable byte[] text, int maxLen);
+
+ public static void sqlite3_result_text(@NotNull sqlite3_context cx,
+ @Nullable byte[] text){
+ sqlite3_result_text(cx, text, null==text ? 0 : text.length);
+ }
+
+ public static void sqlite3_result_text(@NotNull sqlite3_context cx,
+ @Nullable String text){
+ if(null == text) sqlite3_result_null(cx);
+ else{
+ final byte[] utf8 = text.getBytes(StandardCharsets.UTF_8);
+ sqlite3_result_text(cx, utf8, utf8.length);
+ }
+ }
+
+ /**
+ Binds the given text using C's sqlite3_result_text64() unless:
+
+ - text is null ==> sqlite3_result_null()
+
+ - text is too large ==> sqlite3_result_error_toobig()
+
+ - The `encoding` argument has an invalid value ==>
+ sqlite3_result_error_code() with SQLITE_FORMAT
+
+ If maxLength (in bytes, not characters) is larger than
+ text.length, it is silently truncated to text.length. If it is
+ negative, results are undefined.
+ */
+ private static native void sqlite3_result_text64(@NotNull sqlite3_context cx,
+ @Nullable byte[] text,
+ long maxLength, int encoding);
+
+ /**
+ 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){
+ sqlite3_result_text64(cx, text, text.length, SQLITE_UTF16);
+ }
+
+ public static void sqlite3_result_text16(@NotNull sqlite3_context cx,
+ @Nullable String text){
+ if(null == text) sqlite3_result_null(cx);
+ else{
+ final byte[] b = text.getBytes(StandardCharsets.UTF_16);
+ sqlite3_result_text64(cx, b, b.length, SQLITE_UTF16);
+ }
+ }
+
+ /**
+ Sets the current UDF result to the given bytes, which are assumed
+ be encoded in UTF-16LE.
+ */
+ public static void sqlite3_result_text16le(@NotNull sqlite3_context cx,
+ @Nullable String text){
+ if(null == text) sqlite3_result_null(cx);
+ else{
+ final byte[] b = text.getBytes(StandardCharsets.UTF_16LE);
+ sqlite3_result_text64(cx, b, b.length, SQLITE_UTF16LE);
+ }
+ }
+
+ /**
+ Sets the current UDF result to the given bytes, which are assumed
+ be encoded in UTF-16BE.
+ */
+ public static void sqlite3_result_text16be(@NotNull sqlite3_context cx,
+ @Nullable byte[] text){
+ sqlite3_result_text64(cx, text, text.length, SQLITE_UTF16BE);
+ }
+
+ public static void sqlite3_result_text16be(@NotNull sqlite3_context cx,
+ @NotNull String text){
+ final byte[] b = text.getBytes(StandardCharsets.UTF_16BE);
+ sqlite3_result_text64(cx, b, b.length, SQLITE_UTF16BE);
+ }
+
+ /**
+ public static void sqlite3_result_text64(@NotNull sqlite3_context cx,
+ @Nullable byte[] text){
+ sqlite3_result_text64(cx, text, null==text ? 0 : text.length, SQLITE_UTF8);
+ }**/
+
+ public static native void sqlite3_set_last_insert_rowid(@NotNull sqlite3 db, long rowid);
+
+ public static native int sqlite3_sleep(int ms);
+
+ public static native String sqlite3_sourceid();
+
+ public static native int sqlite3_step(@NotNull sqlite3_stmt stmt);
+
+ public static native int sqlite3_threadsafe();
+
+ public static native int sqlite3_total_changes(@NotNull sqlite3 db);
+
+ public static native long sqlite3_total_changes64(@NotNull sqlite3 db);
+
+ /**
+ Works like C's sqlite3_trace_v2() except that the 3rd argument to that
+ function is elided here because the roles of that functions' 3rd and 4th
+ arguments are encapsulated in the final argument to this function.
+
+ Unlike the C API, which is documented as always returning 0, this
+ implementation returns SQLITE_NOMEM if allocation of per-db
+ mapping state fails and SQLITE_ERROR if the given callback object
+ cannot be processed propertly (i.e. an internal error).
+ */
+ public static native int sqlite3_trace_v2(@NotNull sqlite3 db, int traceMask,
+ @Nullable Tracer tracer);
+
+ public static native byte[] sqlite3_value_blob(@NotNull sqlite3_value v);
+
+ public static native int sqlite3_value_bytes(@NotNull sqlite3_value v);
+
+ public static native int sqlite3_value_bytes16(@NotNull sqlite3_value v);
+
+ public static native double sqlite3_value_double(@NotNull sqlite3_value v);
+
+ public static native sqlite3_value sqlite3_value_dupe(@NotNull sqlite3_value v);
+
+ public static native int sqlite3_value_encoding(@NotNull sqlite3_value v);
+
+ public static native void sqlite3_value_free(@Nullable sqlite3_value v);
+
+ public static native int sqlite3_value_int(@NotNull sqlite3_value v);
+
+ public static native long sqlite3_value_int64(@NotNull sqlite3_value v);
+
+ /**
+ If the given value was set using sqlite3_result_java_value() then
+ this function returns that object, else it returns null.
+
+ It is up to the caller to inspect the object to determine its
+ type, and cast it if necessary.
+ */
+ public static native Object sqlite3_value_java_object(@NotNull sqlite3_value v);
+
+ /**
+ A variant of sqlite3_value_java_object() which returns the
+ fetched object cast to T if the object is an instance of the
+ given Class. It returns null in all other cases.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T sqlite3_value_java_casted(@NotNull sqlite3_value v,
+ @NotNull Class<T> type){
+ final Object o = sqlite3_value_java_object(v);
+ return (null!=o && type.isInstance(o)) ? (T)o : null;
+ }
+
+ /**
+ See sqlite3_column_text() for notes about encoding conversions.
+ See sqlite3_value_text_utf8() for how to extract text in standard
+ UTF-8.
+ */
+ public static native String sqlite3_value_text(@NotNull sqlite3_value v);
+
+ /**
+ The sqlite3_value counterpart of sqlite3_column_text_utf8().
+ */
+ public static native byte[] sqlite3_value_text_utf8(@NotNull sqlite3_value v);
+
+ public static native byte[] sqlite3_value_text16(@NotNull sqlite3_value v);
+
+ public static native byte[] sqlite3_value_text16le(@NotNull sqlite3_value v);
+
+ public static native byte[] sqlite3_value_text16be(@NotNull sqlite3_value v);
+
+ //TODO: to_java() should return a closest-match type for the given
+ //value. The quirk is that it would need to return object-type values,
+ //e.g. Integer instead of int, and creating those is a bit of a nuisance
+ //from JNI.
+ //public static native Object sqlite3_value_to_java(@NotNull sqlite3_value v);
+ // Or we can just implement it in Java:
+ //public static Object sqlite3_value_to_java(@NotNull sqlite3_value v){...}
+
+ public static native int sqlite3_value_type(@NotNull sqlite3_value v);
+
+ public static native int sqlite3_value_numeric_type(@NotNull sqlite3_value v);
+
+ public static native int sqlite3_value_nochange(@NotNull sqlite3_value v);
+
+ public static native int sqlite3_value_frombind(@NotNull sqlite3_value v);
+
+ public static native int sqlite3_value_subtype(@NotNull sqlite3_value v);
+
+ public static native int sqlite3_shutdown();
+
+ //////////////////////////////////////////////////////////////////////
+ // SQLITE_... constants follow...
+
+ // version info
+ public static final int SQLITE_VERSION_NUMBER = sqlite3_libversion_number();
+ public static final String SQLITE_VERSION = sqlite3_libversion();
+ public static final String SQLITE_SOURCE_ID = sqlite3_sourceid();
+
+ // access
+ public static final int SQLITE_ACCESS_EXISTS = 0;
+ public static final int SQLITE_ACCESS_READWRITE = 1;
+ public static final int SQLITE_ACCESS_READ = 2;
+
+ // authorizer
+ public static final int SQLITE_DENY = 1;
+ public static final int SQLITE_IGNORE = 2;
+ public static final int SQLITE_CREATE_INDEX = 1;
+ public static final int SQLITE_CREATE_TABLE = 2;
+ public static final int SQLITE_CREATE_TEMP_INDEX = 3;
+ public static final int SQLITE_CREATE_TEMP_TABLE = 4;
+ public static final int SQLITE_CREATE_TEMP_TRIGGER = 5;
+ public static final int SQLITE_CREATE_TEMP_VIEW = 6;
+ public static final int SQLITE_CREATE_TRIGGER = 7;
+ public static final int SQLITE_CREATE_VIEW = 8;
+ public static final int SQLITE_DELETE = 9;
+ public static final int SQLITE_DROP_INDEX = 10;
+ public static final int SQLITE_DROP_TABLE = 11;
+ public static final int SQLITE_DROP_TEMP_INDEX = 12;
+ public static final int SQLITE_DROP_TEMP_TABLE = 13;
+ public static final int SQLITE_DROP_TEMP_TRIGGER = 14;
+ public static final int SQLITE_DROP_TEMP_VIEW = 15;
+ public static final int SQLITE_DROP_TRIGGER = 16;
+ public static final int SQLITE_DROP_VIEW = 17;
+ public static final int SQLITE_INSERT = 18;
+ public static final int SQLITE_PRAGMA = 19;
+ public static final int SQLITE_READ = 20;
+ public static final int SQLITE_SELECT = 21;
+ public static final int SQLITE_TRANSACTION = 22;
+ public static final int SQLITE_UPDATE = 23;
+ public static final int SQLITE_ATTACH = 24;
+ public static final int SQLITE_DETACH = 25;
+ public static final int SQLITE_ALTER_TABLE = 26;
+ public static final int SQLITE_REINDEX = 27;
+ public static final int SQLITE_ANALYZE = 28;
+ public static final int SQLITE_CREATE_VTABLE = 29;
+ public static final int SQLITE_DROP_VTABLE = 30;
+ public static final int SQLITE_FUNCTION = 31;
+ public static final int SQLITE_SAVEPOINT = 32;
+ public static final int SQLITE_RECURSIVE = 33;
+
+ // blob finalizers:
+ public static final int SQLITE_STATIC = 0;
+ public static final int SQLITE_TRANSIENT = -1;
+
+ // changeset
+ public static final int SQLITE_CHANGESETSTART_INVERT = 2;
+ public static final int SQLITE_CHANGESETAPPLY_NOSAVEPOINT = 1;
+ public static final int SQLITE_CHANGESETAPPLY_INVERT = 2;
+ public static final int SQLITE_CHANGESETAPPLY_IGNORENOOP = 4;
+ public static final int SQLITE_CHANGESET_DATA = 1;
+ public static final int SQLITE_CHANGESET_NOTFOUND = 2;
+ public static final int SQLITE_CHANGESET_CONFLICT = 3;
+ public static final int SQLITE_CHANGESET_CONSTRAINT = 4;
+ public static final int SQLITE_CHANGESET_FOREIGN_KEY = 5;
+ public static final int SQLITE_CHANGESET_OMIT = 0;
+ public static final int SQLITE_CHANGESET_REPLACE = 1;
+ public static final int SQLITE_CHANGESET_ABORT = 2;
+
+ // config
+ public static final int SQLITE_CONFIG_SINGLETHREAD = 1;
+ public static final int SQLITE_CONFIG_MULTITHREAD = 2;
+ public static final int SQLITE_CONFIG_SERIALIZED = 3;
+ public static final int SQLITE_CONFIG_MALLOC = 4;
+ public static final int SQLITE_CONFIG_GETMALLOC = 5;
+ public static final int SQLITE_CONFIG_SCRATCH = 6;
+ public static final int SQLITE_CONFIG_PAGECACHE = 7;
+ public static final int SQLITE_CONFIG_HEAP = 8;
+ public static final int SQLITE_CONFIG_MEMSTATUS = 9;
+ public static final int SQLITE_CONFIG_MUTEX = 10;
+ public static final int SQLITE_CONFIG_GETMUTEX = 11;
+ public static final int SQLITE_CONFIG_LOOKASIDE = 13;
+ public static final int SQLITE_CONFIG_PCACHE = 14;
+ public static final int SQLITE_CONFIG_GETPCACHE = 15;
+ public static final int SQLITE_CONFIG_LOG = 16;
+ public static final int SQLITE_CONFIG_URI = 17;
+ public static final int SQLITE_CONFIG_PCACHE2 = 18;
+ public static final int SQLITE_CONFIG_GETPCACHE2 = 19;
+ public static final int SQLITE_CONFIG_COVERING_INDEX_SCAN = 20;
+ public static final int SQLITE_CONFIG_SQLLOG = 21;
+ public static final int SQLITE_CONFIG_MMAP_SIZE = 22;
+ public static final int SQLITE_CONFIG_WIN32_HEAPSIZE = 23;
+ public static final int SQLITE_CONFIG_PCACHE_HDRSZ = 24;
+ public static final int SQLITE_CONFIG_PMASZ = 25;
+ public static final int SQLITE_CONFIG_STMTJRNL_SPILL = 26;
+ public static final int SQLITE_CONFIG_SMALL_MALLOC = 27;
+ public static final int SQLITE_CONFIG_SORTERREF_SIZE = 28;
+ public static final int SQLITE_CONFIG_MEMDB_MAXSIZE = 29;
+
+ // data types
+ public static final int SQLITE_INTEGER = 1;
+ public static final int SQLITE_FLOAT = 2;
+ public static final int SQLITE_TEXT = 3;
+ public static final int SQLITE_BLOB = 4;
+ public static final int SQLITE_NULL = 5;
+
+ // db config
+ public static final int SQLITE_DBCONFIG_MAINDBNAME = 1000;
+ public static final int SQLITE_DBCONFIG_LOOKASIDE = 1001;
+ public static final int SQLITE_DBCONFIG_ENABLE_FKEY = 1002;
+ public static final int SQLITE_DBCONFIG_ENABLE_TRIGGER = 1003;
+ public static final int SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER = 1004;
+ public static final int SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION = 1005;
+ public static final int SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE = 1006;
+ public static final int SQLITE_DBCONFIG_ENABLE_QPSG = 1007;
+ public static final int SQLITE_DBCONFIG_TRIGGER_EQP = 1008;
+ public static final int SQLITE_DBCONFIG_RESET_DATABASE = 1009;
+ public static final int SQLITE_DBCONFIG_DEFENSIVE = 1010;
+ public static final int SQLITE_DBCONFIG_WRITABLE_SCHEMA = 1011;
+ public static final int SQLITE_DBCONFIG_LEGACY_ALTER_TABLE = 1012;
+ public static final int SQLITE_DBCONFIG_DQS_DML = 1013;
+ public static final int SQLITE_DBCONFIG_DQS_DDL = 1014;
+ public static final int SQLITE_DBCONFIG_ENABLE_VIEW = 1015;
+ public static final int SQLITE_DBCONFIG_LEGACY_FILE_FORMAT = 1016;
+ public static final int SQLITE_DBCONFIG_TRUSTED_SCHEMA = 1017;
+ public static final int SQLITE_DBCONFIG_STMT_SCANSTATUS = 1018;
+ public static final int SQLITE_DBCONFIG_REVERSE_SCANORDER = 1019;
+ public static final int SQLITE_DBCONFIG_MAX = 1019;
+
+ // db status
+ public static final int SQLITE_DBSTATUS_LOOKASIDE_USED = 0;
+ public static final int SQLITE_DBSTATUS_CACHE_USED = 1;
+ public static final int SQLITE_DBSTATUS_SCHEMA_USED = 2;
+ public static final int SQLITE_DBSTATUS_STMT_USED = 3;
+ public static final int SQLITE_DBSTATUS_LOOKASIDE_HIT = 4;
+ public static final int SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE = 5;
+ public static final int SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL = 6;
+ public static final int SQLITE_DBSTATUS_CACHE_HIT = 7;
+ public static final int SQLITE_DBSTATUS_CACHE_MISS = 8;
+ public static final int SQLITE_DBSTATUS_CACHE_WRITE = 9;
+ public static final int SQLITE_DBSTATUS_DEFERRED_FKS = 10;
+ public static final int SQLITE_DBSTATUS_CACHE_USED_SHARED = 11;
+ public static final int SQLITE_DBSTATUS_CACHE_SPILL = 12;
+ public static final int SQLITE_DBSTATUS_MAX = 12;
+
+ // encodings
+ public static final int SQLITE_UTF8 = 1;
+ public static final int SQLITE_UTF16LE = 2;
+ public static final int SQLITE_UTF16BE = 3;
+ public static final int SQLITE_UTF16 = 4;
+ public static final int SQLITE_UTF16_ALIGNED = 8;
+
+ // fcntl
+ public static final int SQLITE_FCNTL_LOCKSTATE = 1;
+ public static final int SQLITE_FCNTL_GET_LOCKPROXYFILE = 2;
+ public static final int SQLITE_FCNTL_SET_LOCKPROXYFILE = 3;
+ public static final int SQLITE_FCNTL_LAST_ERRNO = 4;
+ public static final int SQLITE_FCNTL_SIZE_HINT = 5;
+ public static final int SQLITE_FCNTL_CHUNK_SIZE = 6;
+ public static final int SQLITE_FCNTL_FILE_POINTER = 7;
+ public static final int SQLITE_FCNTL_SYNC_OMITTED = 8;
+ public static final int SQLITE_FCNTL_WIN32_AV_RETRY = 9;
+ public static final int SQLITE_FCNTL_PERSIST_WAL = 10;
+ public static final int SQLITE_FCNTL_OVERWRITE = 11;
+ public static final int SQLITE_FCNTL_VFSNAME = 12;
+ public static final int SQLITE_FCNTL_POWERSAFE_OVERWRITE = 13;
+ public static final int SQLITE_FCNTL_PRAGMA = 14;
+ public static final int SQLITE_FCNTL_BUSYHANDLER = 15;
+ public static final int SQLITE_FCNTL_TEMPFILENAME = 16;
+ public static final int SQLITE_FCNTL_MMAP_SIZE = 18;
+ public static final int SQLITE_FCNTL_TRACE = 19;
+ public static final int SQLITE_FCNTL_HAS_MOVED = 20;
+ public static final int SQLITE_FCNTL_SYNC = 21;
+ public static final int SQLITE_FCNTL_COMMIT_PHASETWO = 22;
+ public static final int SQLITE_FCNTL_WIN32_SET_HANDLE = 23;
+ public static final int SQLITE_FCNTL_WAL_BLOCK = 24;
+ public static final int SQLITE_FCNTL_ZIPVFS = 25;
+ public static final int SQLITE_FCNTL_RBU = 26;
+ public static final int SQLITE_FCNTL_VFS_POINTER = 27;
+ public static final int SQLITE_FCNTL_JOURNAL_POINTER = 28;
+ public static final int SQLITE_FCNTL_WIN32_GET_HANDLE = 29;
+ public static final int SQLITE_FCNTL_PDB = 30;
+ public static final int SQLITE_FCNTL_BEGIN_ATOMIC_WRITE = 31;
+ public static final int SQLITE_FCNTL_COMMIT_ATOMIC_WRITE = 32;
+ public static final int SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE = 33;
+ public static final int SQLITE_FCNTL_LOCK_TIMEOUT = 34;
+ public static final int SQLITE_FCNTL_DATA_VERSION = 35;
+ public static final int SQLITE_FCNTL_SIZE_LIMIT = 36;
+ public static final int SQLITE_FCNTL_CKPT_DONE = 37;
+ public static final int SQLITE_FCNTL_RESERVE_BYTES = 38;
+ public static final int SQLITE_FCNTL_CKPT_START = 39;
+ public static final int SQLITE_FCNTL_EXTERNAL_READER = 40;
+ public static final int SQLITE_FCNTL_CKSM_FILE = 41;
+ public static final int SQLITE_FCNTL_RESET_CACHE = 42;
+
+ // flock
+ public static final int SQLITE_LOCK_NONE = 0;
+ public static final int SQLITE_LOCK_SHARED = 1;
+ public static final int SQLITE_LOCK_RESERVED = 2;
+ public static final int SQLITE_LOCK_PENDING = 3;
+ public static final int SQLITE_LOCK_EXCLUSIVE = 4;
+
+ // iocap
+ public static final int SQLITE_IOCAP_ATOMIC = 1;
+ public static final int SQLITE_IOCAP_ATOMIC512 = 2;
+ public static final int SQLITE_IOCAP_ATOMIC1K = 4;
+ public static final int SQLITE_IOCAP_ATOMIC2K = 8;
+ public static final int SQLITE_IOCAP_ATOMIC4K = 16;
+ public static final int SQLITE_IOCAP_ATOMIC8K = 32;
+ public static final int SQLITE_IOCAP_ATOMIC16K = 64;
+ public static final int SQLITE_IOCAP_ATOMIC32K = 128;
+ public static final int SQLITE_IOCAP_ATOMIC64K = 256;
+ public static final int SQLITE_IOCAP_SAFE_APPEND = 512;
+ public static final int SQLITE_IOCAP_SEQUENTIAL = 1024;
+ public static final int SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN = 2048;
+ public static final int SQLITE_IOCAP_POWERSAFE_OVERWRITE = 4096;
+ public static final int SQLITE_IOCAP_IMMUTABLE = 8192;
+ public static final int SQLITE_IOCAP_BATCH_ATOMIC = 16384;
+
+ // limits. These get injected at init-time so that they stay in sync
+ // with the compile-time options. This unfortunately means they are
+ // not final, but keeping them in sync with their C values seems
+ // more important than protecting users from assigning to these
+ // (with unpredictable results).
+ public static int SQLITE_MAX_ALLOCATION_SIZE = -1;
+ public static int SQLITE_LIMIT_LENGTH = -1;
+ public static int SQLITE_MAX_LENGTH = -1;
+ public static int SQLITE_LIMIT_SQL_LENGTH = -1;
+ public static int SQLITE_MAX_SQL_LENGTH = -1;
+ public static int SQLITE_LIMIT_COLUMN = -1;
+ public static int SQLITE_MAX_COLUMN = -1;
+ public static int SQLITE_LIMIT_EXPR_DEPTH = -1;
+ public static int SQLITE_MAX_EXPR_DEPTH = -1;
+ public static int SQLITE_LIMIT_COMPOUND_SELECT = -1;
+ public static int SQLITE_MAX_COMPOUND_SELECT = -1;
+ public static int SQLITE_LIMIT_VDBE_OP = -1;
+ public static int SQLITE_MAX_VDBE_OP = -1;
+ public static int SQLITE_LIMIT_FUNCTION_ARG = -1;
+ public static int SQLITE_MAX_FUNCTION_ARG = -1;
+ public static int SQLITE_LIMIT_ATTACHED = -1;
+ public static int SQLITE_MAX_ATTACHED = -1;
+ public static int SQLITE_LIMIT_LIKE_PATTERN_LENGTH = -1;
+ public static int SQLITE_MAX_LIKE_PATTERN_LENGTH = -1;
+ public static int SQLITE_LIMIT_VARIABLE_NUMBER = -1;
+ public static int SQLITE_MAX_VARIABLE_NUMBER = -1;
+ public static int SQLITE_LIMIT_TRIGGER_DEPTH = -1;
+ public static int SQLITE_MAX_TRIGGER_DEPTH = -1;
+ public static int SQLITE_LIMIT_WORKER_THREADS = -1;
+ public static int SQLITE_MAX_WORKER_THREADS = -1;
+
+ // open flags
+ public static final int SQLITE_OPEN_READONLY = 1;
+ public static final int SQLITE_OPEN_READWRITE = 2;
+ public static final int SQLITE_OPEN_CREATE = 4;
+ public static final int SQLITE_OPEN_URI = 64;
+ public static final int SQLITE_OPEN_MEMORY = 128;
+ public static final int SQLITE_OPEN_NOMUTEX = 32768;
+ public static final int SQLITE_OPEN_FULLMUTEX = 65536;
+ public static final int SQLITE_OPEN_SHAREDCACHE = 131072;
+ public static final int SQLITE_OPEN_PRIVATECACHE = 262144;
+ public static final int SQLITE_OPEN_EXRESCODE = 33554432;
+ public static final int SQLITE_OPEN_NOFOLLOW = 16777216;
+ public static final int SQLITE_OPEN_MAIN_DB = 256;
+ public static final int SQLITE_OPEN_MAIN_JOURNAL = 2048;
+ public static final int SQLITE_OPEN_TEMP_DB = 512;
+ public static final int SQLITE_OPEN_TEMP_JOURNAL = 4096;
+ public static final int SQLITE_OPEN_TRANSIENT_DB = 1024;
+ public static final int SQLITE_OPEN_SUBJOURNAL = 8192;
+ public static final int SQLITE_OPEN_SUPER_JOURNAL = 16384;
+ public static final int SQLITE_OPEN_WAL = 524288;
+ public static final int SQLITE_OPEN_DELETEONCLOSE = 8;
+ public static final int SQLITE_OPEN_EXCLUSIVE = 16;
+
+ // prepare flags
+ public static final int SQLITE_PREPARE_PERSISTENT = 1;
+ public static final int SQLITE_PREPARE_NORMALIZE = 2;
+ public static final int SQLITE_PREPARE_NO_VTAB = 4;
+
+ // result codes
+ public static final int SQLITE_OK = 0;
+ public static final int SQLITE_ERROR = 1;
+ public static final int SQLITE_INTERNAL = 2;
+ public static final int SQLITE_PERM = 3;
+ public static final int SQLITE_ABORT = 4;
+ public static final int SQLITE_BUSY = 5;
+ public static final int SQLITE_LOCKED = 6;
+ public static final int SQLITE_NOMEM = 7;
+ public static final int SQLITE_READONLY = 8;
+ public static final int SQLITE_INTERRUPT = 9;
+ public static final int SQLITE_IOERR = 10;
+ public static final int SQLITE_CORRUPT = 11;
+ public static final int SQLITE_NOTFOUND = 12;
+ public static final int SQLITE_FULL = 13;
+ public static final int SQLITE_CANTOPEN = 14;
+ public static final int SQLITE_PROTOCOL = 15;
+ public static final int SQLITE_EMPTY = 16;
+ public static final int SQLITE_SCHEMA = 17;
+ public static final int SQLITE_TOOBIG = 18;
+ public static final int SQLITE_CONSTRAINT = 19;
+ public static final int SQLITE_MISMATCH = 20;
+ public static final int SQLITE_MISUSE = 21;
+ public static final int SQLITE_NOLFS = 22;
+ public static final int SQLITE_AUTH = 23;
+ public static final int SQLITE_FORMAT = 24;
+ public static final int SQLITE_RANGE = 25;
+ public static final int SQLITE_NOTADB = 26;
+ public static final int SQLITE_NOTICE = 27;
+ public static final int SQLITE_WARNING = 28;
+ public static final int SQLITE_ROW = 100;
+ public static final int SQLITE_DONE = 101;
+ public static final int SQLITE_ERROR_MISSING_COLLSEQ = 257;
+ public static final int SQLITE_ERROR_RETRY = 513;
+ public static final int SQLITE_ERROR_SNAPSHOT = 769;
+ public static final int SQLITE_IOERR_READ = 266;
+ public static final int SQLITE_IOERR_SHORT_READ = 522;
+ public static final int SQLITE_IOERR_WRITE = 778;
+ public static final int SQLITE_IOERR_FSYNC = 1034;
+ public static final int SQLITE_IOERR_DIR_FSYNC = 1290;
+ public static final int SQLITE_IOERR_TRUNCATE = 1546;
+ public static final int SQLITE_IOERR_FSTAT = 1802;
+ public static final int SQLITE_IOERR_UNLOCK = 2058;
+ public static final int SQLITE_IOERR_RDLOCK = 2314;
+ public static final int SQLITE_IOERR_DELETE = 2570;
+ public static final int SQLITE_IOERR_BLOCKED = 2826;
+ public static final int SQLITE_IOERR_NOMEM = 3082;
+ public static final int SQLITE_IOERR_ACCESS = 3338;
+ public static final int SQLITE_IOERR_CHECKRESERVEDLOCK = 3594;
+ public static final int SQLITE_IOERR_LOCK = 3850;
+ public static final int SQLITE_IOERR_CLOSE = 4106;
+ public static final int SQLITE_IOERR_DIR_CLOSE = 4362;
+ public static final int SQLITE_IOERR_SHMOPEN = 4618;
+ public static final int SQLITE_IOERR_SHMSIZE = 4874;
+ public static final int SQLITE_IOERR_SHMLOCK = 5130;
+ public static final int SQLITE_IOERR_SHMMAP = 5386;
+ public static final int SQLITE_IOERR_SEEK = 5642;
+ public static final int SQLITE_IOERR_DELETE_NOENT = 5898;
+ public static final int SQLITE_IOERR_MMAP = 6154;
+ public static final int SQLITE_IOERR_GETTEMPPATH = 6410;
+ public static final int SQLITE_IOERR_CONVPATH = 6666;
+ public static final int SQLITE_IOERR_VNODE = 6922;
+ public static final int SQLITE_IOERR_AUTH = 7178;
+ public static final int SQLITE_IOERR_BEGIN_ATOMIC = 7434;
+ public static final int SQLITE_IOERR_COMMIT_ATOMIC = 7690;
+ public static final int SQLITE_IOERR_ROLLBACK_ATOMIC = 7946;
+ public static final int SQLITE_IOERR_DATA = 8202;
+ public static final int SQLITE_IOERR_CORRUPTFS = 8458;
+ public static final int SQLITE_LOCKED_SHAREDCACHE = 262;
+ public static final int SQLITE_LOCKED_VTAB = 518;
+ public static final int SQLITE_BUSY_RECOVERY = 261;
+ public static final int SQLITE_BUSY_SNAPSHOT = 517;
+ public static final int SQLITE_BUSY_TIMEOUT = 773;
+ public static final int SQLITE_CANTOPEN_NOTEMPDIR = 270;
+ public static final int SQLITE_CANTOPEN_ISDIR = 526;
+ public static final int SQLITE_CANTOPEN_FULLPATH = 782;
+ public static final int SQLITE_CANTOPEN_CONVPATH = 1038;
+ public static final int SQLITE_CANTOPEN_SYMLINK = 1550;
+ public static final int SQLITE_CORRUPT_VTAB = 267;
+ public static final int SQLITE_CORRUPT_SEQUENCE = 523;
+ public static final int SQLITE_CORRUPT_INDEX = 779;
+ public static final int SQLITE_READONLY_RECOVERY = 264;
+ public static final int SQLITE_READONLY_CANTLOCK = 520;
+ public static final int SQLITE_READONLY_ROLLBACK = 776;
+ public static final int SQLITE_READONLY_DBMOVED = 1032;
+ public static final int SQLITE_READONLY_CANTINIT = 1288;
+ public static final int SQLITE_READONLY_DIRECTORY = 1544;
+ public static final int SQLITE_ABORT_ROLLBACK = 516;
+ public static final int SQLITE_CONSTRAINT_CHECK = 275;
+ public static final int SQLITE_CONSTRAINT_COMMITHOOK = 531;
+ public static final int SQLITE_CONSTRAINT_FOREIGNKEY = 787;
+ public static final int SQLITE_CONSTRAINT_FUNCTION = 1043;
+ public static final int SQLITE_CONSTRAINT_NOTNULL = 1299;
+ public static final int SQLITE_CONSTRAINT_PRIMARYKEY = 1555;
+ public static final int SQLITE_CONSTRAINT_TRIGGER = 1811;
+ public static final int SQLITE_CONSTRAINT_UNIQUE = 2067;
+ public static final int SQLITE_CONSTRAINT_VTAB = 2323;
+ public static final int SQLITE_CONSTRAINT_ROWID = 2579;
+ public static final int SQLITE_CONSTRAINT_PINNED = 2835;
+ public static final int SQLITE_CONSTRAINT_DATATYPE = 3091;
+ public static final int SQLITE_NOTICE_RECOVER_WAL = 283;
+ public static final int SQLITE_NOTICE_RECOVER_ROLLBACK = 539;
+ public static final int SQLITE_WARNING_AUTOINDEX = 284;
+ public static final int SQLITE_AUTH_USER = 279;
+ public static final int SQLITE_OK_LOAD_PERMANENTLY = 256;
+
+ // serialize
+ public static final int SQLITE_SERIALIZE_NOCOPY = 1;
+ public static final int SQLITE_DESERIALIZE_FREEONCLOSE = 1;
+ public static final int SQLITE_DESERIALIZE_READONLY = 4;
+ public static final int SQLITE_DESERIALIZE_RESIZEABLE = 2;
+
+ // session
+ public static final int SQLITE_SESSION_CONFIG_STRMSIZE = 1;
+ public static final int SQLITE_SESSION_OBJCONFIG_SIZE = 1;
+
+ // sqlite3 status
+ public static final int SQLITE_STATUS_MEMORY_USED = 0;
+ public static final int SQLITE_STATUS_PAGECACHE_USED = 1;
+ public static final int SQLITE_STATUS_PAGECACHE_OVERFLOW = 2;
+ public static final int SQLITE_STATUS_MALLOC_SIZE = 5;
+ public static final int SQLITE_STATUS_PARSER_STACK = 6;
+ public static final int SQLITE_STATUS_PAGECACHE_SIZE = 7;
+ public static final int SQLITE_STATUS_MALLOC_COUNT = 9;
+
+ // stmt status
+ public static final int SQLITE_STMTSTATUS_FULLSCAN_STEP = 1;
+ public static final int SQLITE_STMTSTATUS_SORT = 2;
+ public static final int SQLITE_STMTSTATUS_AUTOINDEX = 3;
+ public static final int SQLITE_STMTSTATUS_VM_STEP = 4;
+ public static final int SQLITE_STMTSTATUS_REPREPARE = 5;
+ public static final int SQLITE_STMTSTATUS_RUN = 6;
+ public static final int SQLITE_STMTSTATUS_FILTER_MISS = 7;
+ public static final int SQLITE_STMTSTATUS_FILTER_HIT = 8;
+ public static final int SQLITE_STMTSTATUS_MEMUSED = 99;
+
+ // sync flags
+ public static final int SQLITE_SYNC_NORMAL = 2;
+ public static final int SQLITE_SYNC_FULL = 3;
+ public static final int SQLITE_SYNC_DATAONLY = 16;
+
+ // tracing flags
+ public static final int SQLITE_TRACE_STMT = 1;
+ public static final int SQLITE_TRACE_PROFILE = 2;
+ public static final int SQLITE_TRACE_ROW = 4;
+ public static final int SQLITE_TRACE_CLOSE = 8;
+
+ // transaction state
+ public static final int SQLITE_TXN_NONE = 0;
+ public static final int SQLITE_TXN_READ = 1;
+ public static final int SQLITE_TXN_WRITE = 2;
+
+ // udf flags
+ public static final int SQLITE_DETERMINISTIC = 2048;
+ public static final int SQLITE_DIRECTONLY = 524288;
+ public static final int SQLITE_INNOCUOUS = 2097152;
+
+ // virtual tables
+ public static final int SQLITE_INDEX_SCAN_UNIQUE = 1;
+ public static final int SQLITE_INDEX_CONSTRAINT_EQ = 2;
+ public static final int SQLITE_INDEX_CONSTRAINT_GT = 4;
+ public static final int SQLITE_INDEX_CONSTRAINT_LE = 8;
+ public static final int SQLITE_INDEX_CONSTRAINT_LT = 16;
+ public static final int SQLITE_INDEX_CONSTRAINT_GE = 32;
+ public static final int SQLITE_INDEX_CONSTRAINT_MATCH = 64;
+ public static final int SQLITE_INDEX_CONSTRAINT_LIKE = 65;
+ public static final int SQLITE_INDEX_CONSTRAINT_GLOB = 66;
+ public static final int SQLITE_INDEX_CONSTRAINT_REGEXP = 67;
+ public static final int SQLITE_INDEX_CONSTRAINT_NE = 68;
+ public static final int SQLITE_INDEX_CONSTRAINT_ISNOT = 69;
+ public static final int SQLITE_INDEX_CONSTRAINT_ISNOTNULL = 70;
+ public static final int SQLITE_INDEX_CONSTRAINT_ISNULL = 71;
+ public static final int SQLITE_INDEX_CONSTRAINT_IS = 72;
+ public static final int SQLITE_INDEX_CONSTRAINT_LIMIT = 73;
+ public static final int SQLITE_INDEX_CONSTRAINT_OFFSET = 74;
+ public static final int SQLITE_INDEX_CONSTRAINT_FUNCTION = 150;
+ public static final int SQLITE_VTAB_CONSTRAINT_SUPPORT = 1;
+ public static final int SQLITE_VTAB_INNOCUOUS = 2;
+ public static final int SQLITE_VTAB_DIRECTONLY = 3;
+ public static final int SQLITE_VTAB_USES_ALL_SCHEMAS = 4;
+ public static final int SQLITE_ROLLBACK = 1;
+ public static final int SQLITE_FAIL = 3;
+ public static final int SQLITE_REPLACE = 5;
+ static {
+ // This MUST come after the SQLITE_MAX_... values or else
+ // attempting to modify them silently fails.
+ init(new SQLite3Jni());
+ }
+}
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains a set of tests for the sqlite3 JNI bindings.
+** They make heavy use of assert(), so must be run with java's -ea
+** (enble assert) flag.
+*/
+package org.sqlite.jni;
+import static org.sqlite.jni.SQLite3Jni.*;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+public class Tester1 {
+
+ private static <T> void out(T val){
+ System.out.print(val);
+ }
+
+ private static <T> void outln(T val){
+ System.out.println(val);
+ }
+
+ private static int assertCount = 0;
+ private static void myassert(Boolean v){
+ ++assertCount;
+ assert( v );
+ }
+
+ private static void test1(){
+ outln("libversion_number: "
+ + sqlite3_libversion_number()
+ + "\n"
+ + sqlite3_libversion()
+ + "\n"
+ + SQLITE_SOURCE_ID);
+ myassert(sqlite3_libversion_number() == SQLITE_VERSION_NUMBER);
+ //outln("threadsafe = "+sqlite3_threadsafe());
+ myassert(SQLITE_MAX_LENGTH > 0);
+ myassert(SQLITE_MAX_TRIGGER_DEPTH>0);
+ }
+
+ 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 execSql(sqlite3 db, String[] sql){
+ execSql(db, String.join("", sql));
+ }
+ private static void execSql(sqlite3 db, 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();
+ while(pos < sqlChunk.length){
+ if(pos > 0){
+ sqlChunk = Arrays.copyOfRange(sqlChunk, pos,
+ sqlChunk.length);
+ }
+ if( 0==sqlChunk.length ) break;
+ int rc = sqlite3_prepare_v2(db, sqlChunk, stmt, oTail);
+ myassert(0 == rc);
+ pos = oTail.getValue();
+ myassert(0 != stmt.getNativePointer());
+ rc = sqlite3_step(stmt);
+ sqlite3_finalize(stmt);
+ myassert(0 == stmt.getNativePointer());
+ if(0!=rc && SQLITE_ROW!=rc && SQLITE_DONE!=rc){
+ throw new RuntimeException("db op failed with rc="+rc);
+ }
+ }
+ }
+ private static void testOpenDb1(){
+ sqlite3 db = new sqlite3();
+ myassert(0 == db.getNativePointer());
+ int rc = sqlite3_open(":memory:", db);
+ myassert(0 == rc);
+ myassert(0 < db.getNativePointer());
+ sqlite3_close(db);
+ myassert(0 == db.getNativePointer());
+ }
+
+ private static void testOpenDb2(){
+ sqlite3 db = new sqlite3();
+ myassert(0 == db.getNativePointer());
+ int rc = sqlite3_open_v2(":memory:", db,
+ SQLITE_OPEN_READWRITE
+ | SQLITE_OPEN_CREATE, null);
+ myassert(0 == rc);
+ myassert(0 < db.getNativePointer());
+ sqlite3_close_v2(db);
+ myassert(0 == db.getNativePointer());
+ }
+
+ private static sqlite3 createNewDb(){
+ sqlite3 db = new sqlite3();
+ myassert(0 == db.getNativePointer());
+ int rc = sqlite3_open(":memory:", db);
+ myassert(0 == rc);
+ myassert(0 != db.getNativePointer());
+ rc = sqlite3_busy_timeout(db, 2000);
+ myassert( 0 == rc );
+ return db;
+ }
+
+ private static void testPrepare123(){
+ sqlite3 db = createNewDb();
+ int rc;
+ sqlite3_stmt stmt = new sqlite3_stmt();
+ myassert(0 == stmt.getNativePointer());
+ rc = sqlite3_prepare(db, "CREATE TABLE t1(a);", stmt);
+ myassert(0 == rc);
+ myassert(0 != stmt.getNativePointer());
+ rc = sqlite3_step(stmt);
+ myassert(SQLITE_DONE == rc);
+ sqlite3_finalize(stmt);
+ myassert(0 == stmt.getNativePointer());
+
+ { /* Demonstrate how to use the "zTail" option of
+ sqlite3_prepare() family of functions. */
+ OutputPointer.Int32 oTail = new OutputPointer.Int32();
+ final byte[] sqlUtf8 =
+ "CREATE TABLE t2(a); INSERT INTO t2(a) VALUES(1),(2),(3)"
+ .getBytes(StandardCharsets.UTF_8);
+ int pos = 0, n = 1;
+ byte[] sqlChunk = sqlUtf8;
+ while(pos < sqlChunk.length){
+ if(pos > 0){
+ sqlChunk = Arrays.copyOfRange(sqlChunk, pos, sqlChunk.length);
+ }
+ //outln("SQL chunk #"+n+" length = "+sqlChunk.length+", pos = "+pos);
+ if( 0==sqlChunk.length ) break;
+ rc = sqlite3_prepare_v2(db, sqlChunk, stmt, oTail);
+ myassert(0 == rc);
+ pos = oTail.getValue();
+ /*outln("SQL tail pos = "+pos+". Chunk = "+
+ (new String(Arrays.copyOfRange(sqlChunk,0,pos),
+ StandardCharsets.UTF_8)));*/
+ switch(n){
+ case 1: myassert(19 == pos); break;
+ case 2: myassert(36 == pos); break;
+ default: myassert( false /* can't happen */ );
+
+ }
+ ++n;
+ myassert(0 != stmt.getNativePointer());
+ rc = sqlite3_step(stmt);
+ myassert(SQLITE_DONE == rc);
+ sqlite3_finalize(stmt);
+ myassert(0 == stmt.getNativePointer());
+ }
+ }
+
+
+ rc = sqlite3_prepare_v3(db, "INSERT INTO t2(a) VALUES(1),(2),(3)",
+ SQLITE_PREPARE_NORMALIZE, stmt);
+ myassert(0 == rc);
+ myassert(0 != stmt.getNativePointer());
+ sqlite3_finalize(stmt);
+ myassert(0 == stmt.getNativePointer() );
+ sqlite3_close_v2(db);
+ }
+
+ private static void testBindFetchInt(){
+ 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);
+ myassert(0 == rc);
+ myassert(1 == sqlite3_bind_parameter_count(stmt));
+ final int paramNdx = sqlite3_bind_parameter_index(stmt, ":a");
+ myassert(1 == paramNdx);
+ int total1 = 0;
+ long rowid = -1;
+ int changes = sqlite3_changes(db);
+ int changesT = sqlite3_total_changes(db);
+ long changes64 = sqlite3_changes64(db);
+ long changesT64 = sqlite3_total_changes64(db);
+ for(int i = 99; i < 102; ++i ){
+ total1 += i;
+ rc = sqlite3_bind_int(stmt, paramNdx, i);
+ myassert(0 == rc);
+ rc = sqlite3_step(stmt);
+ sqlite3_reset(stmt);
+ myassert(SQLITE_DONE == rc);
+ long x = sqlite3_last_insert_rowid(db);
+ myassert(x > rowid);
+ rowid = x;
+ }
+ sqlite3_finalize(stmt);
+ myassert(total1 > 0);
+ myassert(sqlite3_changes(db) > changes);
+ myassert(sqlite3_total_changes(db) > changesT);
+ myassert(sqlite3_changes64(db) > changes64);
+ myassert(sqlite3_total_changes64(db) > changesT64);
+ rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
+ myassert(0 == rc);
+ int total2 = 0;
+ while( SQLITE_ROW == sqlite3_step(stmt) ){
+ total2 += sqlite3_column_int(stmt, 0);
+ sqlite3_value sv = sqlite3_column_value(stmt, 0);
+ myassert( null != sv );
+ myassert( 0 != sv.getNativePointer() );
+ myassert( SQLITE_INTEGER == sqlite3_value_type(sv) );
+ }
+ sqlite3_finalize(stmt);
+ myassert(total1 == total2);
+ sqlite3_close_v2(db);
+ myassert(0 == db.getNativePointer());
+ }
+
+ 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);
+ long total1 = 0;
+ for(long i = 0xffffffff; i < 0xffffffff + 3; ++i ){
+ total1 += i;
+ sqlite3_bind_int64(stmt, 1, i);
+ sqlite3_step(stmt);
+ sqlite3_reset(stmt);
+ }
+ sqlite3_finalize(stmt);
+ rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
+ myassert(0 == rc);
+ long total2 = 0;
+ while( SQLITE_ROW == sqlite3_step(stmt) ){
+ total2 += sqlite3_column_int64(stmt, 0);
+ }
+ sqlite3_finalize(stmt);
+ myassert(total1 == total2);
+ sqlite3_close_v2(db);
+ }
+
+ 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);
+ double total1 = 0;
+ for(double i = 1.5; i < 5.0; i = i + 1.0 ){
+ total1 += i;
+ sqlite3_bind_double(stmt, 1, i);
+ sqlite3_step(stmt);
+ sqlite3_reset(stmt);
+ }
+ sqlite3_finalize(stmt);
+ rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
+ myassert(0 == rc);
+ double total2 = 0;
+ int counter = 0;
+ while( SQLITE_ROW == sqlite3_step(stmt) ){
+ ++counter;
+ total2 += sqlite3_column_double(stmt, 0);
+ }
+ myassert(4 == counter);
+ sqlite3_finalize(stmt);
+ myassert(total2<=total1+0.01 && total2>=total1-0.01);
+ sqlite3_close_v2(db);
+ }
+
+ 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);
+ String list1[] = { "hell🤩", "w😃rld", "!" };
+ for( String e : list1 ){
+ rc = sqlite3_bind_text(stmt, 1, e);
+ myassert(0 == rc);
+ rc = sqlite3_step(stmt);
+ myassert(SQLITE_DONE==rc);
+ sqlite3_reset(stmt);
+ }
+ sqlite3_finalize(stmt);
+ rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
+ myassert(0 == rc);
+ StringBuffer sbuf = new StringBuffer();
+ int n = 0;
+ while( SQLITE_ROW == sqlite3_step(stmt) ){
+ String txt = sqlite3_column_text(stmt, 0);
+ //outln("txt = "+txt);
+ sbuf.append( txt );
+ ++n;
+ }
+ sqlite3_finalize(stmt);
+ myassert(3 == n);
+ myassert("w😃rldhell🤩!".equals(sbuf.toString()));
+ sqlite3_close_v2(db);
+ }
+
+ 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);
+ byte list1[] = { 0x32, 0x33, 0x34 };
+ rc = sqlite3_bind_blob(stmt, 1, list1);
+ rc = sqlite3_step(stmt);
+ myassert(SQLITE_DONE == rc);
+ sqlite3_finalize(stmt);
+ rc = sqlite3_prepare(db, "SELECT a FROM t ORDER BY a DESC;", stmt);
+ myassert(0 == rc);
+ int n = 0;
+ int total = 0;
+ while( SQLITE_ROW == sqlite3_step(stmt) ){
+ byte blob[] = sqlite3_column_blob(stmt, 0);
+ myassert(3 == blob.length);
+ int i = 0;
+ for(byte b : blob){
+ myassert(b == list1[i++]);
+ total += b;
+ }
+ ++n;
+ }
+ sqlite3_finalize(stmt);
+ myassert(1 == n);
+ myassert(total == 0x32 + 0x33 + 0x34);
+ sqlite3_close_v2(db);
+ }
+
+ private static void testCollation(){
+ sqlite3 db = createNewDb();
+ execSql(db, "CREATE TABLE t(a); INSERT INTO t(a) VALUES('a'),('b'),('c')");
+ final ValueHolder<Boolean> xDestroyCalled = new ValueHolder<>(false);
+ final Collation myCollation = new Collation() {
+ private String myState =
+ "this is local state. There is much like it, but this is mine.";
+ @Override
+ // Reverse-sorts its inputs...
+ public int xCompare(byte[] lhs, byte[] rhs){
+ int len = lhs.length > rhs.length ? rhs.length : lhs.length;
+ int c = 0, i = 0;
+ for(i = 0; i < len; ++i){
+ c = lhs[i] - rhs[i];
+ if(0 != c) break;
+ }
+ if(0==c){
+ if(i < lhs.length) c = 1;
+ else if(i < rhs.length) c = -1;
+ }
+ return -c;
+ }
+ @Override
+ public void xDestroy() {
+ // Just demonstrates that xDestroy is called.
+ xDestroyCalled.value = true;
+ }
+ };
+ int rc = sqlite3_create_collation(db, "reversi", SQLITE_UTF8, myCollation);
+ myassert(0 == rc);
+ sqlite3_stmt stmt = new sqlite3_stmt();
+ sqlite3_prepare(db, "SELECT a FROM t ORDER BY a COLLATE reversi", stmt);
+ int counter = 0;
+ while( SQLITE_ROW == sqlite3_step(stmt) ){
+ final String val = sqlite3_column_text(stmt, 0);
+ ++counter;
+ //outln("REVERSI'd row#"+counter+": "+val);
+ switch(counter){
+ case 1: myassert("c".equals(val)); break;
+ case 2: myassert("b".equals(val)); break;
+ case 3: myassert("a".equals(val)); break;
+ }
+ }
+ myassert(3 == counter);
+ sqlite3_finalize(stmt);
+ sqlite3_prepare(db, "SELECT a FROM t ORDER BY a", stmt);
+ counter = 0;
+ while( SQLITE_ROW == sqlite3_step(stmt) ){
+ final String val = sqlite3_column_text(stmt, 0);
+ ++counter;
+ //outln("Non-REVERSI'd row#"+counter+": "+val);
+ switch(counter){
+ case 3: myassert("c".equals(val)); break;
+ case 2: myassert("b".equals(val)); break;
+ case 1: myassert("a".equals(val)); break;
+ }
+ }
+ myassert(3 == counter);
+ sqlite3_finalize(stmt);
+ myassert(!xDestroyCalled.value);
+ sqlite3_close(db);
+ myassert(xDestroyCalled.value);
+ }
+
+ private static void testToUtf8(){
+ /**
+ Java docs seem contradictory, claiming to use "modified UTF-8"
+ encoding while also claiming to export using RFC 2279:
+
+ https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html
+ */
+ final byte[] ba = "a \0 b".getBytes(StandardCharsets.UTF_8);
+ //out("\"a NUL b\" via getBytes(): ");
+ myassert( 5 == ba.length /* as opposed to 6 in modified utf-8 */);
+ //for( byte b : ba ) out( ""+b );
+ //outln("");
+ }
+
+ 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);
+
+ // Create an SQLFunction instance using one of its 3 subclasses:
+ // Scalar, Aggregate, or Window:
+ SQLFunction func =
+ // Each of the 3 subclasses requires a different set of
+ // functions, all of which must be implemented. Anonymous
+ // classes are a convenient way to implement these, though the
+ // result is possibly somewhat noisy for those not at home in
+ // Java...
+ new SQLFunction.Scalar(){
+ public void xFunc(sqlite3_context cx, sqlite3_value args[]){
+ myassert(db.getNativePointer()
+ == sqlite3_context_db_handle(cx).getNativePointer());
+ int result = 0;
+ for( sqlite3_value v : args ) result += sqlite3_value_int(v);
+ xFuncAccum.value += result;// just for post-run testing
+ sqlite3_result_int(cx, result);
+ }
+ /* OPTIONALLY override xDestroy... */
+ public void xDestroy(){
+ xDestroyCalled.value = true;
+ }
+ };
+
+ // Register and use the function...
+ int rc = sqlite3_create_function(db, "myfunc", -1, SQLITE_UTF8, func);
+ assert(0 == rc);
+ assert(0 == xFuncAccum.value);
+ execSql(db, "SELECT myfunc(1,2,3)");
+ assert(6 == xFuncAccum.value);
+ assert( !xDestroyCalled.value );
+ sqlite3_close(db);
+ assert( xDestroyCalled.value );
+ }
+
+ private static void testUdfJavaObject(){
+ final sqlite3 db = createNewDb();
+ final ValueHolder<Long> testResult = new ValueHolder<>(42L);
+ 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);
+ assert(0 == rc);
+ sqlite3_stmt stmt = new sqlite3_stmt();
+ sqlite3_prepare(db, "select myfunc()", stmt);
+ assert( 0 != stmt.getNativePointer() );
+ int n = 0;
+ if( SQLITE_ROW == sqlite3_step(stmt) ){
+ sqlite3_value v = sqlite3_column_value(stmt, 0);
+ assert( testResult.value == sqlite3_value_java_object(v) );
+ assert( testResult.value == sqlite3_value_java_casted(v, Long.class) );
+ assert( testResult.value ==
+ sqlite3_value_java_casted(v, testResult.value.getClass()) );
+ assert( null == sqlite3_value_java_casted(v, Double.class) );
+ ++n;
+ }
+ sqlite3_finalize(stmt);
+ assert( 1 == n );
+ sqlite3_close(db);
+ }
+
+ private static void testUdfAggregate(){
+ final sqlite3 db = createNewDb();
+ SQLFunction func = new SQLFunction.Aggregate(){
+ private int accum = 0;
+ @Override public void xStep(sqlite3_context cx, sqlite3_value args[]){
+ this.accum += sqlite3_value_int(args[0]);
+ }
+ @Override public void xFinal(sqlite3_context cx){
+ sqlite3_result_int(cx, this.accum);
+ this.accum = 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);
+ assert(0 == rc);
+ sqlite3_stmt stmt = new sqlite3_stmt();
+ sqlite3_prepare(db, "select myfunc(a) from t", stmt);
+ assert( 0 != stmt.getNativePointer() );
+ int n = 0;
+ if( SQLITE_ROW == sqlite3_step(stmt) ){
+ final int v = sqlite3_column_int(stmt, 0);
+ myassert( 6 == v );
+ ++n;
+ }
+ sqlite3_reset(stmt);
+ // Ensure that the accumulator is reset...
+ n = 0;
+ if( SQLITE_ROW == sqlite3_step(stmt) ){
+ final int v = sqlite3_column_int(stmt, 0);
+ myassert( 6 == v );
+ ++n;
+ }
+ sqlite3_finalize(stmt);
+ assert( 1==n );
+ sqlite3_close(db);
+ }
+
+ private static void testUdfWindow(){
+ final sqlite3 db = createNewDb();
+ /* Example window function, table, and results taken from:
+ https://sqlite.org/windowfunctions.html#udfwinfunc */
+ final SQLFunction func = new SQLFunction.Window(){
+ private int accum = 0;
+ private void xStepInverse(int v){
+ this.accum += v;
+ }
+ private void xFinalValue(sqlite3_context cx){
+ sqlite3_result_int(cx, this.accum);
+ }
+ @Override public void xStep(sqlite3_context cx, sqlite3_value[] args){
+ this.xStepInverse(sqlite3_value_int(args[0]));
+ }
+ @Override public void xInverse(sqlite3_context cx, sqlite3_value[] args){
+ this.xStepInverse(-sqlite3_value_int(args[0]));
+ }
+ @Override public void xFinal(sqlite3_context cx){
+ this.xFinalValue(cx);
+ this.accum = 0;
+ }
+ @Override public void xValue(sqlite3_context cx){
+ this.xFinalValue(cx);
+ }
+ };
+ int rc = sqlite3_create_function(db, "winsumint", 1, SQLITE_UTF8, func);
+ myassert( 0 == rc );
+ execSql(db, new String[] {
+ "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,
+ "SELECT x, winsumint(y) OVER ("+
+ "ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING"+
+ ") AS sum_y "+
+ "FROM twin ORDER BY x;", stmt);
+ myassert( 0 == rc );
+ int n = 0;
+ while( SQLITE_ROW == sqlite3_step(stmt) ){
+ final String s = sqlite3_column_text(stmt, 0);
+ final int i = sqlite3_column_int(stmt, 1);
+ switch(++n){
+ case 1: myassert( "a".equals(s) && 9==i ); break;
+ case 2: myassert( "b".equals(s) && 12==i ); break;
+ case 3: myassert( "c".equals(s) && 16==i ); break;
+ case 4: myassert( "d".equals(s) && 12==i ); break;
+ case 5: myassert( "e".equals(s) && 9==i ); break;
+ default: myassert( false /* cannot happen */ );
+ }
+ }
+ sqlite3_finalize(stmt);
+ myassert( 5 == n );
+ sqlite3_close(db);
+ }
+
+ private static void listBoundMethods(){
+ //public static List<Field> getStatics(Class<?> clazz) {
+ if(false){
+ final java.lang.reflect.Field[] declaredFields =
+ SQLite3Jni.class.getDeclaredFields();
+ outln("Bound constants:\n");
+ for(java.lang.reflect.Field field : declaredFields) {
+ if(java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
+ outln("\t"+field.getName());
+ }
+ }
+ }
+ final java.lang.reflect.Method[] declaredMethods =
+ SQLite3Jni.class.getDeclaredMethods();
+ final java.util.List<String> funcList = new java.util.ArrayList<>();
+ for(java.lang.reflect.Method m : declaredMethods){
+ if((m.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0){
+ final String name = m.getName();
+ if(name.startsWith("sqlite3_")){
+ funcList.add(name);
+ }
+ }
+ }
+ int count = 0;
+ java.util.Collections.sort(funcList);
+ for(String n : funcList){
+ ++count;
+ outln("\t"+n+"()");
+ }
+ outln(count+" functions named sqlite3_*.");
+ }
+
+ private static void testTrace(){
+ final sqlite3 db = createNewDb();
+ final ValueHolder<Integer> counter = new ValueHolder<>(0);
+ sqlite3_trace_v2(
+ db, SQLITE_TRACE_STMT | SQLITE_TRACE_PROFILE
+ | SQLITE_TRACE_ROW | SQLITE_TRACE_CLOSE,
+ new Tracer(){
+ public int xCallback(int traceFlag, long pNative, Object x){
+ ++counter.value;
+ //outln("Trace #"+counter.value+" flag="+traceFlag+": "+x);
+ switch(traceFlag){
+ case SQLITE_TRACE_STMT:
+ // pNative ==> sqlite3_stmt
+ myassert(x instanceof String); break;
+ case SQLITE_TRACE_PROFILE:
+ // pNative ==> sqlite3_stmt
+ myassert(x instanceof Long); break;
+ case SQLITE_TRACE_ROW:
+ // pNative ==> sqlite3_stmt
+ case SQLITE_TRACE_CLOSE:
+ // pNative ==> sqlite3
+ myassert(null == x);
+ }
+ return 0;
+ }
+ });
+ execSql(db, "SELECT 1; SELECT 2");
+ myassert( 6 == counter.value );
+ sqlite3_close(db);
+ myassert( 7 == counter.value );
+ }
+
+ private static void testMisc(){
+ outln("Sleeping...");
+ sqlite3_sleep(500);
+ outln("Woke up.");
+ }
+
+ public static void main(String[] args){
+ test1();
+ if(false) testCompileOption();
+ final java.util.List<String> liArgs =
+ java.util.Arrays.asList(args);
+ testOpenDb1();
+ testOpenDb2();
+ testPrepare123();
+ testBindFetchInt();
+ testBindFetchInt64();
+ testBindFetchDouble();
+ testBindFetchText();
+ testBindFetchBlob();
+ testCollation();
+ testToUtf8();
+ testUdf1();
+ testUdfJavaObject();
+ testUdfAggregate();
+ testUdfWindow();
+ testTrace();
+ testMisc();
+ if(liArgs.indexOf("-v")>0){
+ listBoundMethods();
+ }
+ outln("Tests done. "+assertCount+" assertion(s) checked.");
+ }
+}
--- /dev/null
+/*
+** 2023-07-22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+ Callback proxy for use with sqlite3_trace_v2().
+*/
+public interface Tracer {
+ /**
+ Called by sqlite3 for various tracing operations, as per
+ sqlite3_trace_v2(). Note that this interface elides the 2nd
+ argument to the native trace callback, as that role is better
+ filled by instance-local state.
+
+ The 2nd argument to this function, if non-0, will be a native
+ pointer to either an sqlite3 or sqlite3_stmt object, depending on
+ the first argument (see below). Client code can pass it to the
+ sqlite3 resp. sqlite3_stmt constructor to create a wrapping
+ object, if necessary. This API does not do so by default because
+ tracing can be called frequently, creating such a wrapper for
+ each call is comparatively expensive, and the objects are
+ probably only seldom useful.
+
+ The final argument to this function is the "X" argument
+ documented for sqlite3_trace() and sqlite3_trace_v2(). Its type
+ depends on value of the first argument:
+
+ - SQLITE_TRACE_STMT: pNative is a sqlite3_stmt. pX is a string
+ containing the prepared SQL, with one caveat/FIXME: JNI only
+ provides us with the ability to convert that string to MUTF-8,
+ as opposed to standard UTF-8, and is cannot be ruled out that
+ that difference may be significant for certain inputs. The
+ alternative would be that we first convert it to UTF-16 before
+ passing it on, but there's no readily-available way to do that
+ without calling back into the db to peform the conversion
+ (which would lead to further tracing).
+
+ - SQLITE_TRACE_PROFILE: pNative is a sqlite3_stmt. pX is a Long
+ holding an approximate number of nanoseconds the statement took
+ to run.
+
+ - SQLITE_TRACE_ROW: pNative is a sqlite3_stmt. pX is null.
+
+ - SQLITE_TRACE_CLOSE: pNative is a sqlite3. pX is null.
+ */
+ int xCallback(int traceFlag, long pNative, Object pX);
+}
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+ A helper class which simply holds a single value. Its current use
+ is for communicating values out of anonymous classes, as doing so
+ requires a "final" reference.
+*/
+public class ValueHolder<T> {
+ public T value;
+ public ValueHolder(){}
+ public ValueHolder(T v){value = v;}
+}
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+ A wrapper for communicating C-level (sqlite3*) instances with
+ Java. These wrappers do not own their associated pointer, they
+ simply provide a type-safe way to communicate it between Java
+ and C via JNI.
+*/
+public class sqlite3 extends NativePointerHolder<sqlite3> {
+ public sqlite3() {
+ super();
+ }
+ /**
+ Construct a new instance which refers to an existing
+ native (sqlite3*). The argument may be 0. Results are
+ undefined if it is not 0 and refers to a memory address
+ other than a valid (sqlite*).
+ */
+ public sqlite3(long nativePointer) {
+ super(nativePointer);
+ }
+}
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+public class sqlite3_context extends NativePointerHolder<sqlite3_context> {
+ public sqlite3_context() {
+ super();
+ }
+}
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+ A wrapper for communicating C-level (sqlite3_stmt*) instances with
+ Java. These wrappers do not own their associated pointer, they
+ simply provide a type-safe way to communicate it between Java and C
+ via JNI.
+*/
+public class sqlite3_stmt extends NativePointerHolder<sqlite3_stmt> {
+ public sqlite3_stmt() {
+ super();
+ }
+ /**
+ Construct a new instance which refers to an existing native
+ (sqlite3_stmt*). The argument may be 0. Results are undefined if
+ it is not 0 and refers to a memory address other than a valid
+ (sqlite_stmt*).
+ */
+ public sqlite3_stmt(long nativePointer) {
+ super(nativePointer);
+ }
+}
--- /dev/null
+/*
+** 2023-07-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+public class sqlite3_value extends NativePointerHolder<sqlite3_value> {
+ public sqlite3_value() {
+ super();
+ }
+}
-C Add\sthe\scontentless_delete=1\soption\sto\sfts5.\sFor\screating\scontentless\stables\sthat\ssupport\sDELETE\sand\sREPLACE\sstatements.
-D 2023-07-27T19:13:35.663
+C Initial\scheck-in\sof\sJNI\s(Java\sNative\sInterface)\sbindings\sfor\sthe\score\sC\sAPI.
+D 2023-07-27T20:02:49.521
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
+F ext/jni/GNUmakefile 56a014dbff9516774d895ec1ae9df0ed442765b556f79a0fc0b5bc438217200d
+F ext/jni/README.md 5ce36c6f64208a2d8e7641e7ac255400a99f378f726fa44943a008bcb403aeb0
+F ext/jni/src/c/sqlite3-jni.c 55bf5624beee849b1c063bf929e6066dc95437564c3212d30e672280bec45da8
+F ext/jni/src/c/sqlite3-jni.h ef862321bb153135472ebe6be6df9db3e47448ae3ef6bb3cb7953c54971efcf8
+F ext/jni/src/org/sqlite/jni/Collation.java 8dffbb00938007ad0967b2ab424d3c908413af1bbd3d212b9c9899910f1218d1
+F ext/jni/src/org/sqlite/jni/NativePointerHolder.java 70dc7bc41f80352ff3d4331e2e24f45fcd23353b3641e2f68a81bd8262215861
+F ext/jni/src/org/sqlite/jni/OutputPointer.java 08a752b58a33696c5eaf0eb9361a0966b188dec40f4a3613eb133123951f6c5f
+F ext/jni/src/org/sqlite/jni/ProgressHandler.java 5a1d7b2607eb2ef596fcf4492a49d1b3a5bdea3af9918e11716831ffd2f02284
+F ext/jni/src/org/sqlite/jni/SQLFunction.java 2f5d197f6c7d73b6031ba1a19598d7e3eee5ebad467eeee62c72e585bd6556a5
+F ext/jni/src/org/sqlite/jni/SQLite3Jni.java d588c88c17290f5b0d1e4e2a1ea68cf9acab40891c98e08203f1b90ac2aaf8dd
+F ext/jni/src/org/sqlite/jni/Tester1.java 512e545357ce1a5788b250395f2b198ae862f915aee1a8b7b8fae4620d0cfc8d
+F ext/jni/src/org/sqlite/jni/Tracer.java c2fe1eba4a76581b93b375a7b95ab1919e5ae60accfb06d6beb067b033e9bae1
+F ext/jni/src/org/sqlite/jni/ValueHolder.java f022873abaabf64f3dd71ab0d6037c6e71cece3b8819fa10bf26a5461dc973ee
+F ext/jni/src/org/sqlite/jni/sqlite3.java c7d0500c7269882243aafb41425928d094b2fcbdbc2fd1caffc276871cd3fae3
+F ext/jni/src/org/sqlite/jni/sqlite3_context.java d781c72237e4a442adf6726b2edf15124405c28eba0387a279078858700f567c
+F ext/jni/src/org/sqlite/jni/sqlite3_stmt.java 3193693440071998a66870544d1d2314f144bea397ce4c3f83ff225d587067a0
+F ext/jni/src/org/sqlite/jni/sqlite3_value.java f9d8c0766b1d1b290564cb35db8d37be54c42adc8df22ee77b8d39e3e93398cd
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 fd59226b34fffb1479fb2d7bd7c0aff982aa4a1a73e6c0d81de6eaf9c075998c 719973d7f5a47b110e9919fcb96d21feab1e41356dbb3ec674c1116c17bbb778
-R aea8a90a4ab6b65ce2d69f610973d78d
-T +closed 719973d7f5a47b110e9919fcb96d21feab1e41356dbb3ec674c1116c17bbb778
-U dan
-Z dc969c62dd2115415f4e48c1e3d95206
+P d66b182d2bc6ce0772e69401b7affe1adbc1b128c4631cb3c17f98dde72af00a
+R 9595d1bd6387113a14191c3a678b4869
+T *branch * jni
+T *sym-jni *
+T -sym-trunk * Cancelled\sby\sbranch.
+U stephan
+Z 1ff9901b09f119a40a482027609a6cc2
# Remove this line to create a well-formed Fossil manifest.
-d66b182d2bc6ce0772e69401b7affe1adbc1b128c4631cb3c17f98dde72af00a
\ No newline at end of file
+b5374b9ef58fa0be80aefccde0721f5599fb820464b13940b6361b9aa09a59d5
\ No newline at end of file