mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-01 06:27:03 +03:00
Merge the Java Native Interface (JNI) binding into trunk.
FossilOrigin-Name: 48b13edcec6935bf125b265b41a3e6f7b2407afff89d5b4daa2939e3c5679ca0
This commit is contained in:
346
ext/jni/GNUmakefile
Normal file
346
ext/jni/GNUmakefile
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
# Quick-and-dirty makefile to bootstrap the sqlite3-jni project. This
|
||||||
|
# build assumes a Linux-like system.
|
||||||
|
default: all
|
||||||
|
|
||||||
|
JAVA_HOME ?= $(HOME)/jdk/current
|
||||||
|
# e.g. /usr/lib/jvm/default-javajava-19-openjdk-amd64
|
||||||
|
JDK_HOME ?= $(JAVA_HOME)
|
||||||
|
# ^^^ JDK_HOME is not as widely used as JAVA_HOME
|
||||||
|
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.jar := sqlite3-jni.jar
|
||||||
|
|
||||||
|
dir.top := ../..
|
||||||
|
dir.tool := ../../tool
|
||||||
|
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.src.jni.tester := $(dir.src.jni)/tester
|
||||||
|
$(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
|
||||||
|
SQLTester.java := src/org/sqlite/jni/tester/SQLTester.java
|
||||||
|
SQLite3Jni.class := $(SQLite3Jni.java:.java=.class)
|
||||||
|
SQLTester.class := $(SQLTester.java:.java=.class)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# The future of FTS5 customization in this API is as yet unclear.
|
||||||
|
# It would be a real doozy to bind to JNI.
|
||||||
|
enable.fts5 ?= 1
|
||||||
|
# If enable.tester is 0, the org/sqlite/jni/tester/* bits are elided.
|
||||||
|
enable.tester ?= 1
|
||||||
|
|
||||||
|
# bin.version-info = binary to output various sqlite3 version info
|
||||||
|
# building the distribution zip file.
|
||||||
|
bin.version-info := $(dir.top)/version-info
|
||||||
|
.NOTPARALLEL: $(bin.version-info)
|
||||||
|
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
||||||
|
$(MAKE) -C $(dir.top) version-info
|
||||||
|
|
||||||
|
# Be explicit about which Java files to compile so that we can work on
|
||||||
|
# in-progress files without requiring them to be in a compilable statae.
|
||||||
|
JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/%,\
|
||||||
|
BusyHandler.java \
|
||||||
|
Collation.java \
|
||||||
|
CollationNeeded.java \
|
||||||
|
CommitHook.java \
|
||||||
|
NativePointerHolder.java \
|
||||||
|
OutputPointer.java \
|
||||||
|
ProgressHandler.java \
|
||||||
|
ResultCode.java \
|
||||||
|
RollbackHook.java \
|
||||||
|
SQLFunction.java \
|
||||||
|
sqlite3_context.java \
|
||||||
|
sqlite3.java \
|
||||||
|
SQLite3Jni.java \
|
||||||
|
sqlite3_stmt.java \
|
||||||
|
sqlite3_value.java \
|
||||||
|
Tester1.java \
|
||||||
|
Tracer.java \
|
||||||
|
UpdateHook.java \
|
||||||
|
ValueHolder.java \
|
||||||
|
)
|
||||||
|
ifeq (1,$(enable.fts5))
|
||||||
|
JAVA_FILES.main += $(patsubst %,$(dir.src.jni)/%,\
|
||||||
|
fts5_api.java \
|
||||||
|
fts5_extension_function.java \
|
||||||
|
fts5_tokenizer.java \
|
||||||
|
Fts5.java \
|
||||||
|
Fts5Context.java \
|
||||||
|
Fts5ExtensionApi.java \
|
||||||
|
Fts5Function.java \
|
||||||
|
Fts5PhraseIter.java \
|
||||||
|
Fts5Tokenizer.java \
|
||||||
|
TesterFts5.java \
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
JAVA_FILES.tester := $(dir.src.jni.tester)/SQLTester.java
|
||||||
|
|
||||||
|
CLASS_FILES.main := $(JAVA_FILES.main:.java=.class)
|
||||||
|
CLASS_FILES.tester := $(JAVA_FILES.tester:.java=.class)
|
||||||
|
|
||||||
|
JAVA_FILES += $(JAVA_FILES.main)
|
||||||
|
ifeq (1,$(enable.tester))
|
||||||
|
JAVA_FILES += $(JAVA_FILES.tester)
|
||||||
|
endif
|
||||||
|
|
||||||
|
CLASS_FILES :=
|
||||||
|
define DOTCLASS_DEPS
|
||||||
|
$(1).class: $(1).java $(MAKEFILE)
|
||||||
|
all: $(1).class
|
||||||
|
CLASS_FILES += $(1).class
|
||||||
|
endef
|
||||||
|
$(foreach B,$(basename $(JAVA_FILES)),$(eval $(call DOTCLASS_DEPS,$(B))))
|
||||||
|
$(CLASS_FILES.tester): $(CLASS_FILES.main)
|
||||||
|
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 := $(firstword $(wildcard $(dir.src.c)/sqlite3.c) $(dir.top)/sqlite3.c)
|
||||||
|
sqlite3.canonical.h := $(firstword $(wildcard $(dir.src.c)/sqlite3.h) $(dir.top)/sqlite3.h)
|
||||||
|
sqlite3.c := $(sqlite3.canonical.c)
|
||||||
|
sqlite3.h := $(sqlite3.canonical.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_RTREE \
|
||||||
|
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
|
||||||
|
-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_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().
|
||||||
|
|
||||||
|
SQLITE_OPT += -g -DDEBUG -UNDEBUG
|
||||||
|
|
||||||
|
ifeq (1,$(enable.fts5))
|
||||||
|
SQLITE_OPT += -DSQLITE_ENABLE_FTS5
|
||||||
|
endif
|
||||||
|
|
||||||
|
sqlite3-jni.c := $(dir.src.c)/sqlite3-jni.c
|
||||||
|
sqlite3-jni.o := $(dir.bld.c)/sqlite3-jni.o
|
||||||
|
sqlite3-jni.h := $(dir.src.c)/sqlite3-jni.h
|
||||||
|
sqlite3-jni.dll := $(dir.bld.c)/libsqlite3-jni.so
|
||||||
|
# All javac-generated .h files must be listed in $(sqlite3-jni.h.in):
|
||||||
|
sqlite3-jni.h.in :=
|
||||||
|
define ADD_JNI_H
|
||||||
|
sqlite3-jni.h.in += $$(dir.bld.c)/org_sqlite_jni_$(1).h
|
||||||
|
$$(dir.bld.c)/org_sqlite_jni_$(1).h: $$(dir.src.jni)/$(1).java
|
||||||
|
endef
|
||||||
|
$(eval $(call ADD_JNI_H,SQLite3Jni))
|
||||||
|
ifeq (1,$(enable.fts5))
|
||||||
|
$(eval $(call ADD_JNI_H,Fts5ExtensionApi))
|
||||||
|
$(eval $(call ADD_JNI_H,fts5_api))
|
||||||
|
$(eval $(call ADD_JNI_H,fts5_tokenizer))
|
||||||
|
endif
|
||||||
|
ifeq (1,$(enable.tester))
|
||||||
|
sqlite3-jni.h.in += $(dir.bld.c)/org_sqlite_jni_tester_SQLTester.h
|
||||||
|
$(dir.bld.c)/org_sqlite_jni_tester_SQLTester.h: $(dir.src.jni.tester)/SQLTester.java
|
||||||
|
endif
|
||||||
|
#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.
|
||||||
|
########################################################################
|
||||||
|
ifeq (1,$(enable.tester))
|
||||||
|
sqlite3-jni.dll.cflags += -DS3JNI_ENABLE_SQLTester
|
||||||
|
endif
|
||||||
|
$(sqlite3-jni.h): $(sqlite3-jni.h.in) $(MAKEFILE)
|
||||||
|
cat $(sqlite3-jni.h.in) > $@
|
||||||
|
$(sqlite3-jni.dll): $(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)
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test.flags ?= -v
|
||||||
|
test: $(SQLite3Jni.class) $(sqlite3-jni.dll)
|
||||||
|
$(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
|
||||||
|
$(java.flags) -cp $(classpath) \
|
||||||
|
org.sqlite.jni.Tester1 $(if $(test.flags),-- $(test.flags),)
|
||||||
|
|
||||||
|
tester.scripts := $(sort $(wildcard $(dir.src)/tests/*.test))
|
||||||
|
tester.flags ?= # --verbose
|
||||||
|
.PHONY: tester tester-local tester-ext
|
||||||
|
ifeq (1,$(enable.tester))
|
||||||
|
tester-local: $(CLASS_FILES.tester) $(sqlite3-jni.dll)
|
||||||
|
$(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
|
||||||
|
$(java.flags) -cp $(classpath) \
|
||||||
|
org.sqlite.jni.tester.SQLTester $(tester.flags) $(tester.scripts)
|
||||||
|
tester: tester-local
|
||||||
|
else
|
||||||
|
tester:
|
||||||
|
@echo "SQLTester support is disabled. Build with enable.tester=1 to enable it."
|
||||||
|
endif
|
||||||
|
|
||||||
|
tester.extdir.default := src/tests/ext
|
||||||
|
tester.extdir ?= $(tester.extdir.default)
|
||||||
|
tester.extern-scripts := $(wildcard $(tester.extdir)/*.test)
|
||||||
|
ifneq (,$(tester.extern-scripts))
|
||||||
|
tester-ext:
|
||||||
|
$(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
|
||||||
|
$(java.flags) -cp $(classpath) \
|
||||||
|
org.sqlite.jni.tester.SQLTester $(tester.flags) $(tester.extern-scripts)
|
||||||
|
else
|
||||||
|
tester-ext:
|
||||||
|
@echo "******************************************************"; \
|
||||||
|
echo "*** Include the out-of-tree test suite in the 'tester'"; \
|
||||||
|
echo "*** target by either symlinking its directory to"; \
|
||||||
|
echo "*** $(tester.extdir.default) or passing it to make"; \
|
||||||
|
echo "*** as tester.extdir=/path/to/that/dir."; \
|
||||||
|
echo "******************************************************";
|
||||||
|
endif
|
||||||
|
|
||||||
|
tester-ext: tester-local
|
||||||
|
tester: tester-ext
|
||||||
|
tests: test tester
|
||||||
|
package.jar.in := $(abspath $(dir.src)/jar.in)
|
||||||
|
CLEAN_FILES += $(package.jar.in)
|
||||||
|
$(package.jar.in): $(MAKEFILE) $(CLASS_FILES.main)
|
||||||
|
cd $(dir.src); ls -1 org/sqlite/jni/*.java org/sqlite/jni/*.class > $@
|
||||||
|
@ls -la $@
|
||||||
|
@echo "To use this jar you will need the -Djava.library.path=DIR/WITH/libsqlite3-jni.so flag."
|
||||||
|
@echo "e.g. java -jar $@ -Djava.library.path=bld"
|
||||||
|
|
||||||
|
$(package.jar): $(CLASS_FILES) $(MAKEFILE) $(package.jar.in)
|
||||||
|
rm -f $(dir.src)/c/*~ $(dir.src.jni)/*~
|
||||||
|
cd $(dir.src); $(bin.jar) -cfe ../$@ org.sqlite.jni.Tester1 @$(package.jar.in)
|
||||||
|
|
||||||
|
jar: $(package.jar)
|
||||||
|
|
||||||
|
CLEAN_FILES += $(dir.bld.c)/* \
|
||||||
|
$(dir.src.jni)/*.class \
|
||||||
|
$(dir.src.jni.tester)/*.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)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# disttribution bundle rules...
|
||||||
|
|
||||||
|
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
|
||||||
|
dist-name-prefix := sqlite-jni
|
||||||
|
else
|
||||||
|
dist-name-prefix := sqlite-jni-snapshot-$(shell /usr/bin/date +%Y%m%d)
|
||||||
|
endif
|
||||||
|
dist-name := $(dist-name-prefix)-TEMP
|
||||||
|
|
||||||
|
|
||||||
|
dist-dir.top := $(dist-name)
|
||||||
|
dist-dir.src := $(dist-dir.top)/src
|
||||||
|
dist.top.extras := \
|
||||||
|
README.md
|
||||||
|
|
||||||
|
.PHONY: dist snapshot
|
||||||
|
|
||||||
|
dist: \
|
||||||
|
$(bin.version-info) $(sqlite3.canonical.c) \
|
||||||
|
$(package.jar) $(MAKEFILE)
|
||||||
|
@echo "Making end-user deliverables..."
|
||||||
|
@rm -fr $(dist-dir.top)
|
||||||
|
@mkdir -p $(dist-dir.src)
|
||||||
|
@cp -p $(dist.top.extras) $(dist-dir.top)/.
|
||||||
|
@cp -p jar-dist.make $(dist-dir.top)/Makefile
|
||||||
|
@cp -p $(dir.src.c)/*.[ch] $(dist-dir.src)/.
|
||||||
|
@cp -p $(sqlite3.canonical.c) $(sqlite3.canonical.h) $(dist-dir.src)/.
|
||||||
|
@set -e; \
|
||||||
|
vnum=$$($(bin.version-info) --download-version); \
|
||||||
|
vjar=$$($(bin.version-info) --version); \
|
||||||
|
vdir=$(dist-name-prefix)-$$vnum; \
|
||||||
|
arczip=$$vdir.zip; \
|
||||||
|
cp -p $(package.jar) $(dist-dir.top)/sqlite3-jni-$${vjar}.jar; \
|
||||||
|
echo "Making $$arczip ..."; \
|
||||||
|
rm -fr $$arczip $$vdir; \
|
||||||
|
mv $(dist-dir.top) $$vdir; \
|
||||||
|
zip -qr $$arczip $$vdir; \
|
||||||
|
rm -fr $$vdir; \
|
||||||
|
ls -la $$arczip; \
|
||||||
|
set +e; \
|
||||||
|
unzip -lv $$arczip || echo "Missing unzip app? Not fatal."
|
||||||
|
|
||||||
|
snapshot: dist
|
||||||
|
|
||||||
|
.PHONY: dist-clean
|
||||||
|
clean: dist-clean
|
||||||
|
dist-clean:
|
||||||
|
rm -fr $(dist-name) $(wildcard sqlite-jni-*.zip)
|
233
ext/jni/README.md
Normal file
233
ext/jni/README.md
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
SQLite3 via JNI
|
||||||
|
========================================================================
|
||||||
|
|
||||||
|
This directory houses a Java Native Interface (JNI) binding for the
|
||||||
|
sqlite3 API. If you are reading this from the distribution ZIP file,
|
||||||
|
links to resources in the canonical source tree will note work. The
|
||||||
|
canonical copy of this file can be browsed at:
|
||||||
|
|
||||||
|
<https://sqlite.org/src/doc/trunk/ext/jni/README.md>
|
||||||
|
|
||||||
|
Technical support is available in the forum:
|
||||||
|
|
||||||
|
<https://sqlite.org/forum>
|
||||||
|
|
||||||
|
|
||||||
|
> **FOREWARNING:** this subproject 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](https://sqlite.org/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 neither interfere with each other nor become
|
||||||
|
a maintenance burden for the sqlite developers.
|
||||||
|
|
||||||
|
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. Most "day-to-day" functionality is already
|
||||||
|
in place and is believed to work well.
|
||||||
|
|
||||||
|
|
||||||
|
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 JAVA_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_ unless _very explicitly documented_ as being
|
||||||
|
throw-safe. Exceptions are generally 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 UTF-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).
|
||||||
|
|
||||||
|
Known consequences and limitations of this discrepancy include:
|
||||||
|
|
||||||
|
- Names of databases, tables, and collations must not contain
|
||||||
|
characters which differ in MUTF-8 and UTF-8, or certain APIs will
|
||||||
|
mis-translate them on their way between languages. APIs which
|
||||||
|
transfer other client-side data to Java take extra care to
|
||||||
|
convert the data at the cost of performance.
|
||||||
|
|
||||||
|
[modutf8]: https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html#modified-utf-8
|
||||||
|
|
||||||
|
|
||||||
|
Unwieldy 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](https://sqlite.org/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,
|
||||||
|
if desired.
|
||||||
|
|
||||||
|
- 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()`](https://sqlite.org/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 Java API has only one core function-registration function:
|
||||||
|
|
||||||
|
```
|
||||||
|
int sqlite3_create_function(sqlite3 db, String funcName, int nArgs,
|
||||||
|
int encoding, SQLFunction func);
|
||||||
|
```
|
||||||
|
|
||||||
|
> Design question: does the encoding argument serve any purpose in JS?
|
||||||
|
|
||||||
|
`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/ext/jni/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
|
59
ext/jni/jar-dist.make
Normal file
59
ext/jni/jar-dist.make
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#!/this/is/make
|
||||||
|
#^^^^ help emacs out
|
||||||
|
#
|
||||||
|
# This is a POSIX-make-compatible makefile for building the sqlite3
|
||||||
|
# JNI library from "dist" zip file. It must be edited to set the
|
||||||
|
# proper top-level JDK directory and, depending on the platform, add a
|
||||||
|
# platform-specific -I directory. It should build as-is with any
|
||||||
|
# 2020s-era version of gcc or clang. It requires JDK version 8 or
|
||||||
|
# higher.
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
JAVA_HOME = /usr/lib/jvm/java-1.8.0-openjdk-amd64
|
||||||
|
CFLAGS = \
|
||||||
|
-fPIC \
|
||||||
|
-Isrc \
|
||||||
|
-I$(JAVA_HOME)/include \
|
||||||
|
-I$(JAVA_HOME)/include/linux \
|
||||||
|
-I$(JAVA_HOME)/include/apple \
|
||||||
|
-I$(JAVA_HOME)/include/bsd \
|
||||||
|
-Wall
|
||||||
|
|
||||||
|
SQLITE_OPT = \
|
||||||
|
-DSQLITE_ENABLE_RTREE \
|
||||||
|
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
|
||||||
|
-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_THREADSAFE=0 \
|
||||||
|
-DSQLITE_TEMP_STORE=2 \
|
||||||
|
-DSQLITE_USE_URI=1 \
|
||||||
|
-DSQLITE_ENABLE_FTS5 \
|
||||||
|
-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.dll = libsqlite3-jni.so
|
||||||
|
$(sqlite3-jni.dll):
|
||||||
|
@echo "************************************************************************"; \
|
||||||
|
echo "*** If this fails to build, be sure to edit this makefile ***"; \
|
||||||
|
echo "*** to configure it for your system. ***"; \
|
||||||
|
echo "************************************************************************"
|
||||||
|
$(CC) $(CFLAGS) $(SQLITE_OPT) \
|
||||||
|
src/sqlite3-jni.c -shared -o $@
|
||||||
|
@echo "Now try running it with: make test"
|
||||||
|
|
||||||
|
test: $(sqlite3-jni.dll)
|
||||||
|
java -jar -Djava.library.path=. sqlite3-jni-*.jar
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f $(sqlite3-jni.dll)
|
||||||
|
|
||||||
|
all: $(sqlite3-jni.dll)
|
4420
ext/jni/src/c/sqlite3-jni.c
Normal file
4420
ext/jni/src/c/sqlite3-jni.c
Normal file
File diff suppressed because it is too large
Load Diff
1989
ext/jni/src/c/sqlite3-jni.h
Normal file
1989
ext/jni/src/c/sqlite3-jni.h
Normal file
File diff suppressed because it is too large
Load Diff
32
ext/jni/src/org/sqlite/jni/Authorizer.java
Normal file
32
ext/jni/src/org/sqlite/jni/Authorizer.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-05
|
||||||
|
**
|
||||||
|
** 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 callback for use with sqlite3_set_authorizer().
|
||||||
|
*/
|
||||||
|
public interface Authorizer {
|
||||||
|
/**
|
||||||
|
Must functions as described for the sqlite3_set_authorizer()
|
||||||
|
callback, with one caveat: the string values passed here were
|
||||||
|
initially (at the C level) encoded in standard UTF-8. If they
|
||||||
|
contained any constructs which are not compatible with MUTF-8,
|
||||||
|
these strings will not have the expected values. For further
|
||||||
|
details, see the documentation for the SQLite3Jni class.
|
||||||
|
|
||||||
|
Must not throw.
|
||||||
|
*/
|
||||||
|
int xAuth(int opId, @Nullable String s1, @Nullable String s2,
|
||||||
|
@Nullable String s3, @Nullable String s4);
|
||||||
|
}
|
31
ext/jni/src/org/sqlite/jni/AutoExtension.java
Normal file
31
ext/jni/src/org/sqlite/jni/AutoExtension.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-05
|
||||||
|
**
|
||||||
|
** 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 callback for use with sqlite3_auto_extension().
|
||||||
|
*/
|
||||||
|
public interface AutoExtension {
|
||||||
|
/**
|
||||||
|
Must function as described for the sqlite3_auto_extension(),
|
||||||
|
with the caveat that the signature is more limited.
|
||||||
|
|
||||||
|
As an exception (as it were) to the callbacks-must-not-throw
|
||||||
|
rule, AutoExtensions may do so and the exception's error message
|
||||||
|
will be set as the db's error string.
|
||||||
|
|
||||||
|
Results are undefined if db is closed by an auto-extension.
|
||||||
|
*/
|
||||||
|
int xEntryPoint(sqlite3 db);
|
||||||
|
}
|
45
ext/jni/src/org/sqlite/jni/BusyHandler.java
Normal file
45
ext/jni/src/org/sqlite/jni/BusyHandler.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
** 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_busy_handler().
|
||||||
|
*/
|
||||||
|
public abstract class BusyHandler {
|
||||||
|
/**
|
||||||
|
Must function as documented for the sqlite3_busy_handler()
|
||||||
|
callback argument, minus the (void*) argument the C-level
|
||||||
|
function requires.
|
||||||
|
|
||||||
|
Any exceptions thrown by this callback are suppressed in order to
|
||||||
|
retain the C-style API semantics of the JNI bindings.
|
||||||
|
*/
|
||||||
|
public abstract int xCallback(int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Optionally override to perform any cleanup when this busy
|
||||||
|
handler is destroyed. It is destroyed when:
|
||||||
|
|
||||||
|
- The associated db is passed to sqlite3_close() or
|
||||||
|
sqlite3_close_v2().
|
||||||
|
|
||||||
|
- sqlite3_busy_handler() is called to replace the handler,
|
||||||
|
whether it's passed a null handler or any other instance of
|
||||||
|
this class.
|
||||||
|
|
||||||
|
- sqlite3_busy_timeout() is called, which implicitly installs
|
||||||
|
a busy handler.
|
||||||
|
*/
|
||||||
|
public void xDestroy(){}
|
||||||
|
}
|
28
ext/jni/src/org/sqlite/jni/Collation.java
Normal file
28
ext/jni/src/org/sqlite/jni/Collation.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
** 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() {}
|
||||||
|
}
|
28
ext/jni/src/org/sqlite/jni/CollationNeeded.java
Normal file
28
ext/jni/src/org/sqlite/jni/CollationNeeded.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
** 2023-07-30
|
||||||
|
**
|
||||||
|
** 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_collation_needed().
|
||||||
|
*/
|
||||||
|
public interface CollationNeeded {
|
||||||
|
/**
|
||||||
|
Has the same semantics as the C-level sqlite3_create_collation()
|
||||||
|
callback.
|
||||||
|
|
||||||
|
If it throws, the exception message is passed on to the db and
|
||||||
|
the exception is suppressed.
|
||||||
|
*/
|
||||||
|
int xCollationNeeded(sqlite3 db, int eTextRep, String collationName);
|
||||||
|
}
|
25
ext/jni/src/org/sqlite/jni/CommitHook.java
Normal file
25
ext/jni/src/org/sqlite/jni/CommitHook.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
** 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_commit_hook().
|
||||||
|
*/
|
||||||
|
public interface CommitHook {
|
||||||
|
/**
|
||||||
|
Works as documented for the sqlite3_commit_hook() callback.
|
||||||
|
Must not throw.
|
||||||
|
*/
|
||||||
|
int xCommitHook();
|
||||||
|
}
|
38
ext/jni/src/org/sqlite/jni/Fts5.java
Normal file
38
ext/jni/src/org/sqlite/jni/Fts5.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-05
|
||||||
|
**
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
INCOMPLETE AND COMPLETELY UNTESTED.
|
||||||
|
|
||||||
|
A wrapper for communicating C-level (fts5_api*) 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 final class Fts5 {
|
||||||
|
/* Not used */
|
||||||
|
private Fts5(){}
|
||||||
|
|
||||||
|
//! Callback type for use with xTokenize() variants
|
||||||
|
public static interface xTokenizeCallback {
|
||||||
|
int xToken(int tFlags, byte txt[], int iStart, int iEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int FTS5_TOKENIZE_QUERY = 0x0001;
|
||||||
|
public static final int FTS5_TOKENIZE_PREFIX = 0x0002;
|
||||||
|
public static final int FTS5_TOKENIZE_DOCUMENT = 0x0004;
|
||||||
|
public static final int FTS5_TOKENIZE_AUX = 0x0008;
|
||||||
|
public static final int FTS5_TOKEN_COLOCATED = 0x0001;
|
||||||
|
}
|
23
ext/jni/src/org/sqlite/jni/Fts5Context.java
Normal file
23
ext/jni/src/org/sqlite/jni/Fts5Context.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-04
|
||||||
|
**
|
||||||
|
** 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 (Fts5Context*) 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 final class Fts5Context extends NativePointerHolder<Fts5Context> {
|
||||||
|
}
|
86
ext/jni/src/org/sqlite/jni/Fts5ExtensionApi.java
Normal file
86
ext/jni/src/org/sqlite/jni/Fts5ExtensionApi.java
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-04
|
||||||
|
**
|
||||||
|
** 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;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
ALMOST COMPLETELY UNTESTED.
|
||||||
|
|
||||||
|
FAR FROM COMPLETE and the feasibility of binding this to Java
|
||||||
|
is still undetermined. This might be removed.
|
||||||
|
*/
|
||||||
|
public final class Fts5ExtensionApi extends NativePointerHolder<Fts5ExtensionApi> {
|
||||||
|
//! Only called from JNI
|
||||||
|
private Fts5ExtensionApi(){}
|
||||||
|
private int iVersion = 2;
|
||||||
|
|
||||||
|
/* Callback type for used by xQueryPhrase(). */
|
||||||
|
public static interface xQueryPhraseCallback {
|
||||||
|
int xCallback(Fts5ExtensionApi fapi, Fts5Context cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the singleton instance of this class.
|
||||||
|
*/
|
||||||
|
public static synchronized native Fts5ExtensionApi getInstance();
|
||||||
|
|
||||||
|
public synchronized native int xColumnCount(@NotNull Fts5Context fcx);
|
||||||
|
public synchronized native int xColumnSize(@NotNull Fts5Context cx, int iCol,
|
||||||
|
@NotNull OutputPointer.Int32 pnToken);
|
||||||
|
public synchronized native int xColumnText(@NotNull Fts5Context cx, int iCol,
|
||||||
|
@NotNull OutputPointer.String txt);
|
||||||
|
public synchronized native int xColumnTotalSize(@NotNull Fts5Context fcx, int iCol,
|
||||||
|
@NotNull OutputPointer.Int64 pnToken);
|
||||||
|
public synchronized native Object xGetAuxdata(@NotNull Fts5Context cx, boolean clearIt);
|
||||||
|
public synchronized native int xInst(@NotNull Fts5Context cx, int iIdx,
|
||||||
|
@NotNull OutputPointer.Int32 piPhrase,
|
||||||
|
@NotNull OutputPointer.Int32 piCol,
|
||||||
|
@NotNull OutputPointer.Int32 piOff);
|
||||||
|
public synchronized native int xInstCount(@NotNull Fts5Context fcx,
|
||||||
|
@NotNull OutputPointer.Int32 pnInst);
|
||||||
|
public synchronized native int xPhraseCount(@NotNull Fts5Context fcx);
|
||||||
|
public synchronized native int xPhraseFirst(@NotNull Fts5Context cx, int iPhrase,
|
||||||
|
@NotNull Fts5PhraseIter iter,
|
||||||
|
@NotNull OutputPointer.Int32 iCol,
|
||||||
|
@NotNull OutputPointer.Int32 iOff);
|
||||||
|
public synchronized native int xPhraseFirstColumn(@NotNull Fts5Context cx, int iPhrase,
|
||||||
|
@NotNull Fts5PhraseIter iter,
|
||||||
|
@NotNull OutputPointer.Int32 iCol);
|
||||||
|
public synchronized native void xPhraseNext(@NotNull Fts5Context cx,
|
||||||
|
@NotNull Fts5PhraseIter iter,
|
||||||
|
@NotNull OutputPointer.Int32 iCol,
|
||||||
|
@NotNull OutputPointer.Int32 iOff);
|
||||||
|
public synchronized native void xPhraseNextColumn(@NotNull Fts5Context cx,
|
||||||
|
@NotNull Fts5PhraseIter iter,
|
||||||
|
@NotNull OutputPointer.Int32 iCol);
|
||||||
|
public synchronized native int xPhraseSize(@NotNull Fts5Context fcx, int iPhrase);
|
||||||
|
public synchronized native int xQueryPhrase(@NotNull Fts5Context cx, int iPhrase,
|
||||||
|
@NotNull xQueryPhraseCallback callback);
|
||||||
|
public synchronized native int xRowCount(@NotNull Fts5Context fcx,
|
||||||
|
@NotNull OutputPointer.Int64 nRow);
|
||||||
|
public synchronized native long xRowid(@NotNull Fts5Context cx);
|
||||||
|
/* Note that the JNI binding lacks the C version's xDelete()
|
||||||
|
callback argument. Instead, if pAux has an xDestroy() method, it
|
||||||
|
is called if the FTS5 API finalizes the aux state (including if
|
||||||
|
allocation of storage for the auxdata fails). Any reference to
|
||||||
|
pAux held by the JNI layer will be relinquished regardless of
|
||||||
|
whether pAux has an xDestroy() method. */
|
||||||
|
public synchronized native int xSetAuxdata(@NotNull Fts5Context cx, @Nullable Object pAux);
|
||||||
|
public synchronized native int xTokenize(@NotNull Fts5Context cx, @NotNull byte pText[],
|
||||||
|
@NotNull Fts5.xTokenizeCallback callback);
|
||||||
|
|
||||||
|
public synchronized native Object xUserData(Fts5Context cx);
|
||||||
|
//^^^ returns the pointer passed as the 3rd arg to the C-level
|
||||||
|
// fts5_api::xCreateFunction.
|
||||||
|
}
|
27
ext/jni/src/org/sqlite/jni/Fts5Function.java
Normal file
27
ext/jni/src/org/sqlite/jni/Fts5Function.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-04
|
||||||
|
**
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fts5Function is used in conjunction with the
|
||||||
|
sqlite3_create_fts_function() JNI-bound API to give that native code
|
||||||
|
access to the callback functions needed in order to implement
|
||||||
|
FTS5 auxiliary functions in Java.
|
||||||
|
*/
|
||||||
|
public abstract class Fts5Function {
|
||||||
|
|
||||||
|
public abstract void xFunction(Fts5ExtensionApi pApi, Fts5Context pFts,
|
||||||
|
sqlite3_context pCtx, sqlite3_value argv[]);
|
||||||
|
public void xDestroy() {}
|
||||||
|
}
|
24
ext/jni/src/org/sqlite/jni/Fts5PhraseIter.java
Normal file
24
ext/jni/src/org/sqlite/jni/Fts5PhraseIter.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-04
|
||||||
|
**
|
||||||
|
** 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 C-level Fts5PhraseIter. They are only modified and
|
||||||
|
inspected by native-level code.
|
||||||
|
*/
|
||||||
|
public final class Fts5PhraseIter extends NativePointerHolder<Fts5PhraseIter> {
|
||||||
|
//! Updated and used only by native code.
|
||||||
|
private long a;
|
||||||
|
private long b;
|
||||||
|
}
|
30
ext/jni/src/org/sqlite/jni/Fts5Tokenizer.java
Normal file
30
ext/jni/src/org/sqlite/jni/Fts5Tokenizer.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-05x
|
||||||
|
**
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
INCOMPLETE AND COMPLETELY UNTESTED.
|
||||||
|
|
||||||
|
A wrapper for communicating C-level (Fts5Tokenizer*) 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.
|
||||||
|
|
||||||
|
At the C level, the Fts5Tokenizer type is essentially a void
|
||||||
|
pointer used specifically for tokenizers.
|
||||||
|
*/
|
||||||
|
public final class Fts5Tokenizer extends NativePointerHolder<Fts5Tokenizer> {
|
||||||
|
//! Only called from JNI.
|
||||||
|
private Fts5Tokenizer(){}
|
||||||
|
}
|
33
ext/jni/src/org/sqlite/jni/NativePointerHolder.java
Normal file
33
ext/jni/src/org/sqlite/jni/NativePointerHolder.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
** 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 do not _own_ the pointer they refer to. They are
|
||||||
|
intended simply to communicate that pointer between C and Java.
|
||||||
|
*/
|
||||||
|
public class NativePointerHolder<ContextType> {
|
||||||
|
//! Only set from JNI, where access permissions don't matter.
|
||||||
|
private long nativePointer = 0;
|
||||||
|
public final long getNativePointer(){ return nativePointer; }
|
||||||
|
}
|
165
ext/jni/src/org/sqlite/jni/OutputPointer.java
Normal file
165
ext/jni/src/org/sqlite/jni/OutputPointer.java
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
** 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The usage is similar for all of thes types:
|
||||||
|
|
||||||
|
```
|
||||||
|
OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
|
||||||
|
assert( null==out.get() );
|
||||||
|
int rc = sqlite3_open(":memory:", out);
|
||||||
|
if( 0!=rc ) ... error;
|
||||||
|
assert( null!=out.get() );
|
||||||
|
sqlite3 db = out.take();
|
||||||
|
assert( null==out.get() );
|
||||||
|
```
|
||||||
|
|
||||||
|
With the minor exception that the primitive types permit direct
|
||||||
|
access to the object's value via the `value` property, whereas the
|
||||||
|
JNI-level opaque types do not permit client-level code to set that
|
||||||
|
property.
|
||||||
|
*/
|
||||||
|
public final class OutputPointer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Output pointer for use with routines, such as sqlite3_open(),
|
||||||
|
which return a database handle via an output pointer. These
|
||||||
|
pointers can only be set by the JNI layer, not by client-level
|
||||||
|
code.
|
||||||
|
*/
|
||||||
|
public static final class sqlite3 {
|
||||||
|
private org.sqlite.jni.sqlite3 value;
|
||||||
|
//! Initializes with a null value.
|
||||||
|
public sqlite3(){value = null;}
|
||||||
|
//! Sets the current value to null.
|
||||||
|
public void clear(){value = null;}
|
||||||
|
//! Returns the current value.
|
||||||
|
public final org.sqlite.jni.sqlite3 get(){return value;}
|
||||||
|
//! Equivalent to calling get() then clear().
|
||||||
|
public final org.sqlite.jni.sqlite3 take(){
|
||||||
|
final org.sqlite.jni.sqlite3 v = value;
|
||||||
|
value = null;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Output pointer for use with routines, such as sqlite3_prepare(),
|
||||||
|
which return a statement handle via an output pointer. These
|
||||||
|
pointers can only be set by the JNI layer, not by client-level
|
||||||
|
code.
|
||||||
|
*/
|
||||||
|
public static final class sqlite3_stmt {
|
||||||
|
private org.sqlite.jni.sqlite3_stmt value;
|
||||||
|
//! Initializes with a null value.
|
||||||
|
public sqlite3_stmt(){value = null;}
|
||||||
|
//! Sets the current value to null.
|
||||||
|
public void clear(){value = null;}
|
||||||
|
//! Returns the current value.
|
||||||
|
public final org.sqlite.jni.sqlite3_stmt get(){return value;}
|
||||||
|
//! Equivalent to calling get() then clear().
|
||||||
|
public final org.sqlite.jni.sqlite3_stmt take(){
|
||||||
|
final org.sqlite.jni.sqlite3_stmt v = value;
|
||||||
|
value = null;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Output pointer for use with native routines which return integers via
|
||||||
|
output pointers.
|
||||||
|
*/
|
||||||
|
public static final class Int32 {
|
||||||
|
/**
|
||||||
|
This is public for ease of use. Accessors are provided for
|
||||||
|
consistency with the higher-level types.
|
||||||
|
*/
|
||||||
|
public int value;
|
||||||
|
//! Initializes with the value 0.
|
||||||
|
public Int32(){this(0);}
|
||||||
|
//! Initializes with the value v.
|
||||||
|
public Int32(int v){value = v;}
|
||||||
|
//! Returns the current value.
|
||||||
|
public final int get(){return value;}
|
||||||
|
//! Sets the current value to v.
|
||||||
|
public final void set(int v){value = v;}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Output pointer for use with native routines which return 64-bit integers
|
||||||
|
via output pointers.
|
||||||
|
*/
|
||||||
|
public static final class Int64 {
|
||||||
|
/**
|
||||||
|
This is public for ease of use. Accessors are provided for
|
||||||
|
consistency with the higher-level types.
|
||||||
|
*/
|
||||||
|
public long value;
|
||||||
|
//! Initializes with the value 0.
|
||||||
|
public Int64(){this(0);}
|
||||||
|
//! Initializes with the value v.
|
||||||
|
public Int64(long v){value = v;}
|
||||||
|
//! Returns the current value.
|
||||||
|
public final long get(){return value;}
|
||||||
|
//! Sets the current value.
|
||||||
|
public final void set(long v){value = v;}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Output pointer for use with native routines which return strings via
|
||||||
|
output pointers.
|
||||||
|
*/
|
||||||
|
public static final class String {
|
||||||
|
/**
|
||||||
|
This is public for ease of use. Accessors are provided for
|
||||||
|
consistency with the higher-level types.
|
||||||
|
*/
|
||||||
|
public java.lang.String value;
|
||||||
|
//! Initializes with a null value.
|
||||||
|
public String(){this(null);}
|
||||||
|
//! Initializes with the value v.
|
||||||
|
public String(java.lang.String v){value = v;}
|
||||||
|
//! Returns the current value.
|
||||||
|
public final java.lang.String get(){return value;}
|
||||||
|
//! Sets the current value.
|
||||||
|
public final void set(java.lang.String v){value = v;}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Output pointer for use with native routines which return byte
|
||||||
|
arrays via output pointers.
|
||||||
|
*/
|
||||||
|
public static final class ByteArray {
|
||||||
|
/**
|
||||||
|
This is public for ease of use. Accessors are provided for
|
||||||
|
consistency with the higher-level types.
|
||||||
|
*/
|
||||||
|
public byte[] value;
|
||||||
|
//! Initializes with the value null.
|
||||||
|
public ByteArray(){this(null);}
|
||||||
|
//! Initializes with the value v.
|
||||||
|
public ByteArray(byte[] v){value = v;}
|
||||||
|
//! Returns the current value.
|
||||||
|
public final byte[] get(){return value;}
|
||||||
|
//! Sets the current value.
|
||||||
|
public final void set(byte[] v){value = v;}
|
||||||
|
}
|
||||||
|
}
|
27
ext/jni/src/org/sqlite/jni/ProgressHandler.java
Normal file
27
ext/jni/src/org/sqlite/jni/ProgressHandler.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
** 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 {
|
||||||
|
/**
|
||||||
|
Works as documented for the sqlite3_progress_handler() callback.
|
||||||
|
|
||||||
|
If it throws, the exception message is passed on to the db and
|
||||||
|
the exception is suppressed.
|
||||||
|
*/
|
||||||
|
int xCallback();
|
||||||
|
}
|
155
ext/jni/src/org/sqlite/jni/ResultCode.java
Normal file
155
ext/jni/src/org/sqlite/jni/ResultCode.java
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This enum contains all of the core and "extended" result codes used
|
||||||
|
by the sqlite3 library. It is provided not for use with the C-style
|
||||||
|
API (with which it won't work) but for higher-level code which may
|
||||||
|
find it useful to map SQLite result codes to human-readable names.
|
||||||
|
*/
|
||||||
|
public enum ResultCode {
|
||||||
|
SQLITE_OK(SQLite3Jni.SQLITE_OK),
|
||||||
|
SQLITE_ERROR(SQLite3Jni.SQLITE_ERROR),
|
||||||
|
SQLITE_INTERNAL(SQLite3Jni.SQLITE_INTERNAL),
|
||||||
|
SQLITE_PERM(SQLite3Jni.SQLITE_PERM),
|
||||||
|
SQLITE_ABORT(SQLite3Jni.SQLITE_ABORT),
|
||||||
|
SQLITE_BUSY(SQLite3Jni.SQLITE_BUSY),
|
||||||
|
SQLITE_LOCKED(SQLite3Jni.SQLITE_LOCKED),
|
||||||
|
SQLITE_NOMEM(SQLite3Jni.SQLITE_NOMEM),
|
||||||
|
SQLITE_READONLY(SQLite3Jni.SQLITE_READONLY),
|
||||||
|
SQLITE_INTERRUPT(SQLite3Jni.SQLITE_INTERRUPT),
|
||||||
|
SQLITE_IOERR(SQLite3Jni.SQLITE_IOERR),
|
||||||
|
SQLITE_CORRUPT(SQLite3Jni.SQLITE_CORRUPT),
|
||||||
|
SQLITE_NOTFOUND(SQLite3Jni.SQLITE_NOTFOUND),
|
||||||
|
SQLITE_FULL(SQLite3Jni.SQLITE_FULL),
|
||||||
|
SQLITE_CANTOPEN(SQLite3Jni.SQLITE_CANTOPEN),
|
||||||
|
SQLITE_PROTOCOL(SQLite3Jni.SQLITE_PROTOCOL),
|
||||||
|
SQLITE_EMPTY(SQLite3Jni.SQLITE_EMPTY),
|
||||||
|
SQLITE_SCHEMA(SQLite3Jni.SQLITE_SCHEMA),
|
||||||
|
SQLITE_TOOBIG(SQLite3Jni.SQLITE_TOOBIG),
|
||||||
|
SQLITE_CONSTRAINT(SQLite3Jni.SQLITE_CONSTRAINT),
|
||||||
|
SQLITE_MISMATCH(SQLite3Jni.SQLITE_MISMATCH),
|
||||||
|
SQLITE_MISUSE(SQLite3Jni.SQLITE_MISUSE),
|
||||||
|
SQLITE_NOLFS(SQLite3Jni.SQLITE_NOLFS),
|
||||||
|
SQLITE_AUTH(SQLite3Jni.SQLITE_AUTH),
|
||||||
|
SQLITE_FORMAT(SQLite3Jni.SQLITE_FORMAT),
|
||||||
|
SQLITE_RANGE(SQLite3Jni.SQLITE_RANGE),
|
||||||
|
SQLITE_NOTADB(SQLite3Jni.SQLITE_NOTADB),
|
||||||
|
SQLITE_NOTICE(SQLite3Jni.SQLITE_NOTICE),
|
||||||
|
SQLITE_WARNING(SQLite3Jni.SQLITE_WARNING),
|
||||||
|
SQLITE_ROW(SQLite3Jni.SQLITE_ROW),
|
||||||
|
SQLITE_DONE(SQLite3Jni.SQLITE_DONE),
|
||||||
|
SQLITE_ERROR_MISSING_COLLSEQ(SQLite3Jni.SQLITE_ERROR_MISSING_COLLSEQ),
|
||||||
|
SQLITE_ERROR_RETRY(SQLite3Jni.SQLITE_ERROR_RETRY),
|
||||||
|
SQLITE_ERROR_SNAPSHOT(SQLite3Jni.SQLITE_ERROR_SNAPSHOT),
|
||||||
|
SQLITE_IOERR_READ(SQLite3Jni.SQLITE_IOERR_READ),
|
||||||
|
SQLITE_IOERR_SHORT_READ(SQLite3Jni.SQLITE_IOERR_SHORT_READ),
|
||||||
|
SQLITE_IOERR_WRITE(SQLite3Jni.SQLITE_IOERR_WRITE),
|
||||||
|
SQLITE_IOERR_FSYNC(SQLite3Jni.SQLITE_IOERR_FSYNC),
|
||||||
|
SQLITE_IOERR_DIR_FSYNC(SQLite3Jni.SQLITE_IOERR_DIR_FSYNC),
|
||||||
|
SQLITE_IOERR_TRUNCATE(SQLite3Jni.SQLITE_IOERR_TRUNCATE),
|
||||||
|
SQLITE_IOERR_FSTAT(SQLite3Jni.SQLITE_IOERR_FSTAT),
|
||||||
|
SQLITE_IOERR_UNLOCK(SQLite3Jni.SQLITE_IOERR_UNLOCK),
|
||||||
|
SQLITE_IOERR_RDLOCK(SQLite3Jni.SQLITE_IOERR_RDLOCK),
|
||||||
|
SQLITE_IOERR_DELETE(SQLite3Jni.SQLITE_IOERR_DELETE),
|
||||||
|
SQLITE_IOERR_BLOCKED(SQLite3Jni.SQLITE_IOERR_BLOCKED),
|
||||||
|
SQLITE_IOERR_NOMEM(SQLite3Jni.SQLITE_IOERR_NOMEM),
|
||||||
|
SQLITE_IOERR_ACCESS(SQLite3Jni.SQLITE_IOERR_ACCESS),
|
||||||
|
SQLITE_IOERR_CHECKRESERVEDLOCK(SQLite3Jni.SQLITE_IOERR_CHECKRESERVEDLOCK),
|
||||||
|
SQLITE_IOERR_LOCK(SQLite3Jni.SQLITE_IOERR_LOCK),
|
||||||
|
SQLITE_IOERR_CLOSE(SQLite3Jni.SQLITE_IOERR_CLOSE),
|
||||||
|
SQLITE_IOERR_DIR_CLOSE(SQLite3Jni.SQLITE_IOERR_DIR_CLOSE),
|
||||||
|
SQLITE_IOERR_SHMOPEN(SQLite3Jni.SQLITE_IOERR_SHMOPEN),
|
||||||
|
SQLITE_IOERR_SHMSIZE(SQLite3Jni.SQLITE_IOERR_SHMSIZE),
|
||||||
|
SQLITE_IOERR_SHMLOCK(SQLite3Jni.SQLITE_IOERR_SHMLOCK),
|
||||||
|
SQLITE_IOERR_SHMMAP(SQLite3Jni.SQLITE_IOERR_SHMMAP),
|
||||||
|
SQLITE_IOERR_SEEK(SQLite3Jni.SQLITE_IOERR_SEEK),
|
||||||
|
SQLITE_IOERR_DELETE_NOENT(SQLite3Jni.SQLITE_IOERR_DELETE_NOENT),
|
||||||
|
SQLITE_IOERR_MMAP(SQLite3Jni.SQLITE_IOERR_MMAP),
|
||||||
|
SQLITE_IOERR_GETTEMPPATH(SQLite3Jni.SQLITE_IOERR_GETTEMPPATH),
|
||||||
|
SQLITE_IOERR_CONVPATH(SQLite3Jni.SQLITE_IOERR_CONVPATH),
|
||||||
|
SQLITE_IOERR_VNODE(SQLite3Jni.SQLITE_IOERR_VNODE),
|
||||||
|
SQLITE_IOERR_AUTH(SQLite3Jni.SQLITE_IOERR_AUTH),
|
||||||
|
SQLITE_IOERR_BEGIN_ATOMIC(SQLite3Jni.SQLITE_IOERR_BEGIN_ATOMIC),
|
||||||
|
SQLITE_IOERR_COMMIT_ATOMIC(SQLite3Jni.SQLITE_IOERR_COMMIT_ATOMIC),
|
||||||
|
SQLITE_IOERR_ROLLBACK_ATOMIC(SQLite3Jni.SQLITE_IOERR_ROLLBACK_ATOMIC),
|
||||||
|
SQLITE_IOERR_DATA(SQLite3Jni.SQLITE_IOERR_DATA),
|
||||||
|
SQLITE_IOERR_CORRUPTFS(SQLite3Jni.SQLITE_IOERR_CORRUPTFS),
|
||||||
|
SQLITE_LOCKED_SHAREDCACHE(SQLite3Jni.SQLITE_LOCKED_SHAREDCACHE),
|
||||||
|
SQLITE_LOCKED_VTAB(SQLite3Jni.SQLITE_LOCKED_VTAB),
|
||||||
|
SQLITE_BUSY_RECOVERY(SQLite3Jni.SQLITE_BUSY_RECOVERY),
|
||||||
|
SQLITE_BUSY_SNAPSHOT(SQLite3Jni.SQLITE_BUSY_SNAPSHOT),
|
||||||
|
SQLITE_BUSY_TIMEOUT(SQLite3Jni.SQLITE_BUSY_TIMEOUT),
|
||||||
|
SQLITE_CANTOPEN_NOTEMPDIR(SQLite3Jni.SQLITE_CANTOPEN_NOTEMPDIR),
|
||||||
|
SQLITE_CANTOPEN_ISDIR(SQLite3Jni.SQLITE_CANTOPEN_ISDIR),
|
||||||
|
SQLITE_CANTOPEN_FULLPATH(SQLite3Jni.SQLITE_CANTOPEN_FULLPATH),
|
||||||
|
SQLITE_CANTOPEN_CONVPATH(SQLite3Jni.SQLITE_CANTOPEN_CONVPATH),
|
||||||
|
SQLITE_CANTOPEN_SYMLINK(SQLite3Jni.SQLITE_CANTOPEN_SYMLINK),
|
||||||
|
SQLITE_CORRUPT_VTAB(SQLite3Jni.SQLITE_CORRUPT_VTAB),
|
||||||
|
SQLITE_CORRUPT_SEQUENCE(SQLite3Jni.SQLITE_CORRUPT_SEQUENCE),
|
||||||
|
SQLITE_CORRUPT_INDEX(SQLite3Jni.SQLITE_CORRUPT_INDEX),
|
||||||
|
SQLITE_READONLY_RECOVERY(SQLite3Jni.SQLITE_READONLY_RECOVERY),
|
||||||
|
SQLITE_READONLY_CANTLOCK(SQLite3Jni.SQLITE_READONLY_CANTLOCK),
|
||||||
|
SQLITE_READONLY_ROLLBACK(SQLite3Jni.SQLITE_READONLY_ROLLBACK),
|
||||||
|
SQLITE_READONLY_DBMOVED(SQLite3Jni.SQLITE_READONLY_DBMOVED),
|
||||||
|
SQLITE_READONLY_CANTINIT(SQLite3Jni.SQLITE_READONLY_CANTINIT),
|
||||||
|
SQLITE_READONLY_DIRECTORY(SQLite3Jni.SQLITE_READONLY_DIRECTORY),
|
||||||
|
SQLITE_ABORT_ROLLBACK(SQLite3Jni.SQLITE_ABORT_ROLLBACK),
|
||||||
|
SQLITE_CONSTRAINT_CHECK(SQLite3Jni.SQLITE_CONSTRAINT_CHECK),
|
||||||
|
SQLITE_CONSTRAINT_COMMITHOOK(SQLite3Jni.SQLITE_CONSTRAINT_COMMITHOOK),
|
||||||
|
SQLITE_CONSTRAINT_FOREIGNKEY(SQLite3Jni.SQLITE_CONSTRAINT_FOREIGNKEY),
|
||||||
|
SQLITE_CONSTRAINT_FUNCTION(SQLite3Jni.SQLITE_CONSTRAINT_FUNCTION),
|
||||||
|
SQLITE_CONSTRAINT_NOTNULL(SQLite3Jni.SQLITE_CONSTRAINT_NOTNULL),
|
||||||
|
SQLITE_CONSTRAINT_PRIMARYKEY(SQLite3Jni.SQLITE_CONSTRAINT_PRIMARYKEY),
|
||||||
|
SQLITE_CONSTRAINT_TRIGGER(SQLite3Jni.SQLITE_CONSTRAINT_TRIGGER),
|
||||||
|
SQLITE_CONSTRAINT_UNIQUE(SQLite3Jni.SQLITE_CONSTRAINT_UNIQUE),
|
||||||
|
SQLITE_CONSTRAINT_VTAB(SQLite3Jni.SQLITE_CONSTRAINT_VTAB),
|
||||||
|
SQLITE_CONSTRAINT_ROWID(SQLite3Jni.SQLITE_CONSTRAINT_ROWID),
|
||||||
|
SQLITE_CONSTRAINT_PINNED(SQLite3Jni.SQLITE_CONSTRAINT_PINNED),
|
||||||
|
SQLITE_CONSTRAINT_DATATYPE(SQLite3Jni.SQLITE_CONSTRAINT_DATATYPE),
|
||||||
|
SQLITE_NOTICE_RECOVER_WAL(SQLite3Jni.SQLITE_NOTICE_RECOVER_WAL),
|
||||||
|
SQLITE_NOTICE_RECOVER_ROLLBACK(SQLite3Jni.SQLITE_NOTICE_RECOVER_ROLLBACK),
|
||||||
|
SQLITE_WARNING_AUTOINDEX(SQLite3Jni.SQLITE_WARNING_AUTOINDEX),
|
||||||
|
SQLITE_AUTH_USER(SQLite3Jni.SQLITE_AUTH_USER),
|
||||||
|
SQLITE_OK_LOAD_PERMANENTLY(SQLite3Jni.SQLITE_OK_LOAD_PERMANENTLY);
|
||||||
|
|
||||||
|
public final int value;
|
||||||
|
|
||||||
|
ResultCode(int rc){
|
||||||
|
value = rc;
|
||||||
|
ResultCodeMap.set(rc, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the entry from this enum for the given result code, or
|
||||||
|
null if no match is found.
|
||||||
|
*/
|
||||||
|
public static ResultCode getEntryForInt(int rc){
|
||||||
|
return ResultCodeMap.get(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal level of indirection required because we cannot initialize
|
||||||
|
static enum members in an enum before the enum constructor is
|
||||||
|
invoked.
|
||||||
|
*/
|
||||||
|
private static final class ResultCodeMap {
|
||||||
|
private static final java.util.Map<Integer,ResultCode> i2e
|
||||||
|
= new java.util.HashMap<>();
|
||||||
|
private static void set(int rc, ResultCode e){ i2e.put(rc, e); }
|
||||||
|
private static ResultCode get(int rc){ return i2e.get(rc); }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
ext/jni/src/org/sqlite/jni/RollbackHook.java
Normal file
25
ext/jni/src/org/sqlite/jni/RollbackHook.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
** 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_rollback_hook().
|
||||||
|
*/
|
||||||
|
public interface RollbackHook {
|
||||||
|
/**
|
||||||
|
Works as documented for the sqlite3_rollback_hook() callback.
|
||||||
|
Must not throw.
|
||||||
|
*/
|
||||||
|
void xRollbackHook();
|
||||||
|
}
|
172
ext/jni/src/org/sqlite/jni/SQLFunction.java
Normal file
172
ext/jni/src/org/sqlite/jni/SQLFunction.java
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
** 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, but is a marker base class. The
|
||||||
|
three UDF types are modelled by the inner classes Scalar,
|
||||||
|
Aggregate<T>, and Window<T>. Most simply, clients may create
|
||||||
|
anonymous classes from those to implement UDFs. Clients are free to
|
||||||
|
create their own classes for use with UDFs, so long as they conform
|
||||||
|
to the public interfaces defined by those three classes. The JNI
|
||||||
|
layer only actively relies on the SQLFunction base class.
|
||||||
|
*/
|
||||||
|
public abstract class SQLFunction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
PerContextState assists aggregate and window functions in
|
||||||
|
managinga their accumulator state across calls to the UDF's
|
||||||
|
callbacks.
|
||||||
|
|
||||||
|
If a given aggregate or window function is called multiple times
|
||||||
|
in a single SQL statement, e.g. SELECT MYFUNC(A), MYFUNC(B)...,
|
||||||
|
then the clients need some way of knowing which call is which so
|
||||||
|
that they can map their state between their various UDF callbacks
|
||||||
|
and reset it via xFinal(). This class takes care of such
|
||||||
|
mappings.
|
||||||
|
|
||||||
|
This class works by mapping
|
||||||
|
sqlite3_context.getAggregateContext() to a single piece of
|
||||||
|
state, of a client-defined type (the T part of this class), which
|
||||||
|
persists across a "matching set" of the UDF's callbacks.
|
||||||
|
|
||||||
|
This class is a helper providing commonly-needed functionality -
|
||||||
|
it is not required for use with aggregate or window functions.
|
||||||
|
Client UDFs are free to perform such mappings using custom
|
||||||
|
approaches. The provided Aggregate<T> and Window<T> classes
|
||||||
|
use this.
|
||||||
|
*/
|
||||||
|
public static final class PerContextState<T> {
|
||||||
|
private final java.util.Map<Long,ValueHolder<T>> map
|
||||||
|
= new java.util.HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Should be called from a UDF's xStep(), xValue(), and xInverse()
|
||||||
|
methods, passing it that method's first argument and an initial
|
||||||
|
value for the persistent state. If there is currently no
|
||||||
|
mapping for cx.getAggregateContext() within the map, one is
|
||||||
|
created using the given initial value, else the existing one is
|
||||||
|
used and the 2nd argument is ignored. It returns a
|
||||||
|
ValueHolder<T> which can be used to modify that state directly
|
||||||
|
without requiring that the client update the underlying map's
|
||||||
|
entry.
|
||||||
|
|
||||||
|
T must be of a type which can be legally stored as a value in
|
||||||
|
java.util.HashMap<KeyType,T>.
|
||||||
|
*/
|
||||||
|
public ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
|
||||||
|
ValueHolder<T> rc = map.get(cx.getAggregateContext());
|
||||||
|
if(null == rc){
|
||||||
|
map.put(cx.getAggregateContext(), rc = new ValueHolder<>(initialValue));
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Should be called from a UDF's xFinal() method and passed that
|
||||||
|
method's first argument. This function removes the value
|
||||||
|
associated with cx.getAggregateContext() from the map and
|
||||||
|
returns it, returning null if no other UDF method has been
|
||||||
|
called to set up such a mapping. The latter condition will be
|
||||||
|
the case if a UDF is used in a statement which has no result
|
||||||
|
rows.
|
||||||
|
*/
|
||||||
|
public T takeAggregateState(sqlite3_context cx){
|
||||||
|
final ValueHolder<T> h = map.remove(cx.getAggregateContext());
|
||||||
|
return null==h ? null : h.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Subclass for creating scalar functions.
|
||||||
|
public static abstract class Scalar extends SQLFunction {
|
||||||
|
|
||||||
|
//! As for the xFunc() argument of the C API's sqlite3_create_function()
|
||||||
|
public abstract void xFunc(sqlite3_context cx, sqlite3_value[] args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Optionally override to be notified when the UDF is finalized by
|
||||||
|
SQLite.
|
||||||
|
*/
|
||||||
|
public void xDestroy() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
SQLFunction Subclass for creating aggregate functions. Its T is
|
||||||
|
the data type of its "accumulator" state, an instance of which is
|
||||||
|
intended to be be managed using the getAggregateState() and
|
||||||
|
takeAggregateState() methods.
|
||||||
|
*/
|
||||||
|
public static abstract class Aggregate<T> extends SQLFunction {
|
||||||
|
|
||||||
|
//! As for the xStep() argument of the C API's sqlite3_create_function()
|
||||||
|
public abstract void xStep(sqlite3_context cx, sqlite3_value[] args);
|
||||||
|
|
||||||
|
//! As for the xFinal() argument of the C API's sqlite3_create_function()
|
||||||
|
public abstract void xFinal(sqlite3_context cx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Optionally override to be notified when the UDF is finalized by
|
||||||
|
SQLite.
|
||||||
|
*/
|
||||||
|
public void xDestroy() {}
|
||||||
|
|
||||||
|
//! Per-invocation state for the UDF.
|
||||||
|
private final PerContextState<T> map = new PerContextState<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
To be called from the implementation's xStep() method, as well
|
||||||
|
as the xValue() and xInverse() methods of the Window<T>
|
||||||
|
subclass, to fetch the current per-call UDF state. On the
|
||||||
|
first call to this method for any given sqlite3_context
|
||||||
|
argument, the context is set to the given initial value. On all other
|
||||||
|
calls, the 2nd argument is ignored.
|
||||||
|
|
||||||
|
@see PerContextState<T>#takeAggregateState()
|
||||||
|
*/
|
||||||
|
protected final ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
|
||||||
|
return map.getAggregateState(cx, initialValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
To be called from the implementation's xFinal() method to fetch
|
||||||
|
the final state of the UDF and remove its mapping.
|
||||||
|
|
||||||
|
@see PerContextState<T>#takeAggregateState()
|
||||||
|
*/
|
||||||
|
protected final T takeAggregateState(sqlite3_context cx){
|
||||||
|
return map.takeAggregateState(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
An SQLFunction subclass for creating window functions. Note that
|
||||||
|
Window<T> inherits from Aggregate<T> and each instance is
|
||||||
|
required to implement the inherited abstract methods from that
|
||||||
|
class. See Aggregate<T> for information on managing the UDF's
|
||||||
|
invocation-specific state.
|
||||||
|
*/
|
||||||
|
public static abstract class Window<T> extends Aggregate<T> {
|
||||||
|
|
||||||
|
//! As for the xInverse() argument of the C API's sqlite3_create_window_function()
|
||||||
|
public abstract void xInverse(sqlite3_context cx, sqlite3_value[] args);
|
||||||
|
|
||||||
|
//! As for the xValue() argument of the C API's sqlite3_create_window_function()
|
||||||
|
public abstract void xValue(sqlite3_context cx);
|
||||||
|
}
|
||||||
|
}
|
1645
ext/jni/src/org/sqlite/jni/SQLite3Jni.java
Normal file
1645
ext/jni/src/org/sqlite/jni/SQLite3Jni.java
Normal file
File diff suppressed because it is too large
Load Diff
1164
ext/jni/src/org/sqlite/jni/Tester1.java
Normal file
1164
ext/jni/src/org/sqlite/jni/Tester1.java
Normal file
File diff suppressed because it is too large
Load Diff
87
ext/jni/src/org/sqlite/jni/TesterFts5.java
Normal file
87
ext/jni/src/org/sqlite/jni/TesterFts5.java
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-04
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
*/
|
||||||
|
package org.sqlite.jni;
|
||||||
|
import static org.sqlite.jni.SQLite3Jni.*;
|
||||||
|
import static org.sqlite.jni.Tester1.*;
|
||||||
|
|
||||||
|
public class TesterFts5 {
|
||||||
|
|
||||||
|
private static void test1(){
|
||||||
|
Fts5ExtensionApi fea = Fts5ExtensionApi.getInstance();
|
||||||
|
affirm( null != fea );
|
||||||
|
affirm( fea.getNativePointer() != 0 );
|
||||||
|
affirm( fea == Fts5ExtensionApi.getInstance() )/*singleton*/;
|
||||||
|
|
||||||
|
sqlite3 db = createNewDb();
|
||||||
|
fts5_api fApi = fts5_api.getInstanceForDb(db);
|
||||||
|
affirm( fApi != null );
|
||||||
|
affirm( fApi == fts5_api.getInstanceForDb(db) /* singleton per db */ );
|
||||||
|
|
||||||
|
execSql(db, new String[] {
|
||||||
|
"CREATE VIRTUAL TABLE ft USING fts5(a, b);",
|
||||||
|
"INSERT INTO ft(rowid, a, b) VALUES(1, 'X Y', 'Y Z');",
|
||||||
|
"INSERT INTO ft(rowid, a, b) VALUES(2, 'A Z', 'Y Y');"
|
||||||
|
});
|
||||||
|
|
||||||
|
final String pUserData = "This is pUserData";
|
||||||
|
ValueHolder<Boolean> xDestroyCalled = new ValueHolder<>(false);
|
||||||
|
ValueHolder<Integer> xFuncCount = new ValueHolder<>(0);
|
||||||
|
final fts5_extension_function func = new fts5_extension_function(){
|
||||||
|
public void xFunction(Fts5ExtensionApi ext, Fts5Context fCx,
|
||||||
|
sqlite3_context pCx, sqlite3_value argv[]){
|
||||||
|
int nCols = ext.xColumnCount(fCx);
|
||||||
|
affirm( 2 == nCols );
|
||||||
|
affirm( nCols == argv.length );
|
||||||
|
affirm( ext.xUserData(fCx) == pUserData );
|
||||||
|
if(true){
|
||||||
|
OutputPointer.String op = new OutputPointer.String();
|
||||||
|
for(int i = 0; i < nCols; ++i ){
|
||||||
|
int rc = ext.xColumnText(fCx, i, op);
|
||||||
|
affirm( 0 == rc );
|
||||||
|
final String val = op.value;
|
||||||
|
affirm( val.equals(sqlite3_value_text(argv[i])) );
|
||||||
|
//outln("xFunction col "+i+": "+val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++xFuncCount.value;
|
||||||
|
}
|
||||||
|
public void xDestroy(){
|
||||||
|
xDestroyCalled.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int rc = fApi.xCreateFunction("myaux", pUserData, func);
|
||||||
|
affirm( 0==rc );
|
||||||
|
|
||||||
|
affirm( 0==xFuncCount.value );
|
||||||
|
execSql(db, "select myaux(ft,a,b) from ft;");
|
||||||
|
affirm( 2==xFuncCount.value );
|
||||||
|
affirm( !xDestroyCalled.value );
|
||||||
|
sqlite3_close_v2(db);
|
||||||
|
affirm( xDestroyCalled.value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public TesterFts5(){
|
||||||
|
int oldAffirmCount = Tester1.affirmCount;
|
||||||
|
Tester1.affirmCount = 0;
|
||||||
|
final long timeStart = System.nanoTime();
|
||||||
|
test1();
|
||||||
|
final long timeEnd = System.nanoTime();
|
||||||
|
outln("FTS5 Tests done. Metrics:");
|
||||||
|
outln("\tAssertions checked: "+Tester1.affirmCount);
|
||||||
|
outln("\tTotal time = "
|
||||||
|
+((timeEnd - timeStart)/1000000.0)+"ms");
|
||||||
|
Tester1.affirmCount = oldAffirmCount;
|
||||||
|
}
|
||||||
|
}
|
62
ext/jni/src/org/sqlite/jni/Tracer.java
Normal file
62
ext/jni/src/org/sqlite/jni/Tracer.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
** 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 {
|
||||||
|
/**
|
||||||
|
Achtung: this interface is subject to change because the current
|
||||||
|
approach to mapping the passed-in natives back to Java is
|
||||||
|
uncomfortably quirky.
|
||||||
|
|
||||||
|
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: 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, Object pNative, Object pX);
|
||||||
|
}
|
25
ext/jni/src/org/sqlite/jni/UpdateHook.java
Normal file
25
ext/jni/src/org/sqlite/jni/UpdateHook.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
** 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_update_hook().
|
||||||
|
*/
|
||||||
|
public interface UpdateHook {
|
||||||
|
/**
|
||||||
|
Works as documented for the sqlite3_update_hook() callback.
|
||||||
|
Must not throw.
|
||||||
|
*/
|
||||||
|
void xUpdateHook(int opId, String dbName, String tableName, long rowId);
|
||||||
|
}
|
25
ext/jni/src/org/sqlite/jni/ValueHolder.java
Normal file
25
ext/jni/src/org/sqlite/jni/ValueHolder.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
** 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;}
|
||||||
|
}
|
69
ext/jni/src/org/sqlite/jni/fts5_api.java
Normal file
69
ext/jni/src/org/sqlite/jni/fts5_api.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-05
|
||||||
|
**
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
INCOMPLETE AND COMPLETELY UNTESTED.
|
||||||
|
|
||||||
|
A wrapper for communicating C-level (fts5_api*) 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 final class fts5_api extends NativePointerHolder<fts5_api> {
|
||||||
|
/* Only invoked from JNI */
|
||||||
|
private fts5_api(){}
|
||||||
|
public final int iVersion = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the fts5_api instance associated with the given db, or
|
||||||
|
null if something goes horribly wrong.
|
||||||
|
*/
|
||||||
|
public static synchronized native fts5_api getInstanceForDb(@NotNull sqlite3 db);
|
||||||
|
|
||||||
|
// int (*xCreateTokenizer)(
|
||||||
|
// fts5_api *pApi,
|
||||||
|
// const char *zName,
|
||||||
|
// void *pContext,
|
||||||
|
// fts5_tokenizer *pTokenizer,
|
||||||
|
// void (*xDestroy)(void*)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// /* Find an existing tokenizer */
|
||||||
|
// int (*xFindTokenizer)(
|
||||||
|
// fts5_api *pApi,
|
||||||
|
// const char *zName,
|
||||||
|
// void **ppContext,
|
||||||
|
// fts5_tokenizer *pTokenizer
|
||||||
|
// );
|
||||||
|
|
||||||
|
// /* Create a new auxiliary function */
|
||||||
|
// int (*xCreateFunction)(
|
||||||
|
// fts5_api *pApi,
|
||||||
|
// const char *zName,
|
||||||
|
// void *pContext,
|
||||||
|
// fts5_extension_function xFunction,
|
||||||
|
// void (*xDestroy)(void*)
|
||||||
|
// );
|
||||||
|
|
||||||
|
public synchronized native int xCreateFunction(@NotNull String name,
|
||||||
|
@Nullable Object userData,
|
||||||
|
@NotNull fts5_extension_function xFunction);
|
||||||
|
|
||||||
|
public int xCreateFunction(@NotNull String name,
|
||||||
|
@NotNull fts5_extension_function xFunction){
|
||||||
|
return xCreateFunction(name, null, xFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
ext/jni/src/org/sqlite/jni/fts5_extension_function.java
Normal file
37
ext/jni/src/org/sqlite/jni/fts5_extension_function.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-05
|
||||||
|
**
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
JNI-level wrapper for C's fts5_extension_function type.
|
||||||
|
|
||||||
|
*/
|
||||||
|
public abstract class fts5_extension_function {
|
||||||
|
// typedef void (*fts5_extension_function)(
|
||||||
|
// const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
|
||||||
|
// Fts5Context *pFts, /* First arg to pass to pApi functions */
|
||||||
|
// sqlite3_context *pCtx, /* Context for returning result/error */
|
||||||
|
// int nVal, /* Number of values in apVal[] array */
|
||||||
|
// sqlite3_value **apVal /* Array of trailing arguments */
|
||||||
|
// );
|
||||||
|
|
||||||
|
/**
|
||||||
|
The callback implementation, corresponding to the xFunction
|
||||||
|
argument of C's fts5_api::xCreateFunction().
|
||||||
|
*/
|
||||||
|
public abstract void xFunction(Fts5ExtensionApi ext, Fts5Context fCx,
|
||||||
|
sqlite3_context pCx, sqlite3_value argv[]);
|
||||||
|
//! Optionally override
|
||||||
|
public void xDestroy(){}
|
||||||
|
}
|
49
ext/jni/src/org/sqlite/jni/fts5_tokenizer.java
Normal file
49
ext/jni/src/org/sqlite/jni/fts5_tokenizer.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-05
|
||||||
|
**
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
INCOMPLETE AND COMPLETELY UNTESTED.
|
||||||
|
|
||||||
|
A wrapper for communicating C-level (fts5_tokenizer*) 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 final class fts5_tokenizer extends NativePointerHolder<fts5_tokenizer> {
|
||||||
|
/* Only invoked by JNI */
|
||||||
|
private fts5_tokenizer(){}
|
||||||
|
|
||||||
|
// int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
|
||||||
|
// void (*xDelete)(Fts5Tokenizer*);
|
||||||
|
|
||||||
|
public native int xTokenize(@NotNull Fts5Tokenizer t, int tokFlags,
|
||||||
|
@NotNull byte pText[],
|
||||||
|
@NotNull Fts5.xTokenizeCallback callback);
|
||||||
|
|
||||||
|
|
||||||
|
// int (*xTokenize)(Fts5Tokenizer*,
|
||||||
|
// void *pCtx,
|
||||||
|
// int flags, /* Mask of FTS5_TOKENIZE_* flags */
|
||||||
|
// const char *pText, int nText,
|
||||||
|
// int (*xToken)(
|
||||||
|
// void *pCtx, /* Copy of 2nd argument to xTokenize() */
|
||||||
|
// int tflags, /* Mask of FTS5_TOKEN_* flags */
|
||||||
|
// const char *pToken, /* Pointer to buffer containing token */
|
||||||
|
// int nToken, /* Size of token in bytes */
|
||||||
|
// int iStart, /* Byte offset of token within input text */
|
||||||
|
// int iEnd /* Byte offset of end of token within input text */
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
}
|
37
ext/jni/src/org/sqlite/jni/sqlite3.java
Normal file
37
ext/jni/src/org/sqlite/jni/sqlite3.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
** 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 final class sqlite3 extends NativePointerHolder<sqlite3> {
|
||||||
|
// Only invoked from JNI
|
||||||
|
private sqlite3(){}
|
||||||
|
|
||||||
|
public String toString(){
|
||||||
|
long ptr = getNativePointer();
|
||||||
|
if( 0==ptr ){
|
||||||
|
return sqlite3.class.getSimpleName()+"@null";
|
||||||
|
}
|
||||||
|
String fn = SQLite3Jni.sqlite3_db_filename(this, "main");
|
||||||
|
return sqlite3.class.getSimpleName()
|
||||||
|
+"@"+String.format("0x%08x",ptr)
|
||||||
|
+"["+((null == fn) ? "<unnamed>" : fn)+"]"
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
66
ext/jni/src/org/sqlite/jni/sqlite3_context.java
Normal file
66
ext/jni/src/org/sqlite/jni/sqlite3_context.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
sqlite3_context instances are used in conjunction with user-defined
|
||||||
|
SQL functions (a.k.a. UDFs).
|
||||||
|
*/
|
||||||
|
public final class sqlite3_context extends NativePointerHolder<sqlite3_context> {
|
||||||
|
/**
|
||||||
|
For use only by the JNI layer. It's permitted to set this even
|
||||||
|
though it's private.
|
||||||
|
*/
|
||||||
|
private long aggregateContext = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
getAggregateContext() corresponds to C's
|
||||||
|
sqlite3_aggregate_context(), with a slightly different interface
|
||||||
|
to account for cross-language differences. It serves the same
|
||||||
|
purposes in a slightly different way: it provides a key which is
|
||||||
|
stable across invocations of "matching sets" of a UDF's callbacks,
|
||||||
|
such that all calls into those callbacks can determine which "set"
|
||||||
|
of those calls they belong to.
|
||||||
|
|
||||||
|
If this object is being used in the context of an aggregate or
|
||||||
|
window UDF, this function returns a non-0 value which is distinct
|
||||||
|
for each set of UDF callbacks from a single invocation of the
|
||||||
|
UDF, otherwise it returns 0. The returned value is only only
|
||||||
|
valid within the context of execution of a single SQL statement,
|
||||||
|
and may be re-used by future invocations of the UDF in different
|
||||||
|
SQL statements.
|
||||||
|
|
||||||
|
Consider this SQL, where MYFUNC is a user-defined aggregate function:
|
||||||
|
|
||||||
|
SELECT MYFUNC(A), MYFUNC(B) FROM T;
|
||||||
|
|
||||||
|
The xStep() and xFinal() methods of the callback need to be able
|
||||||
|
to differentiate between those two invocations in order to
|
||||||
|
perform their work properly. The value returned by
|
||||||
|
getAggregateContext() will be distinct for each of those
|
||||||
|
invocations of MYFUNC() and is intended to be used as a lookup
|
||||||
|
key for mapping callback invocations to whatever client-defined
|
||||||
|
state is needed by the UDF.
|
||||||
|
|
||||||
|
There is one case where this will return 0 in the context of an
|
||||||
|
aggregate or window function: if the result set has no rows,
|
||||||
|
the UDF's xFinal() will be called without any other x...() members
|
||||||
|
having been called. In that one case, no aggregate context key will
|
||||||
|
have been generated. xFinal() implementations need to be prepared to
|
||||||
|
accept that condition as legal.
|
||||||
|
*/
|
||||||
|
public long getAggregateContext(){
|
||||||
|
return aggregateContext;
|
||||||
|
}
|
||||||
|
}
|
25
ext/jni/src/org/sqlite/jni/sqlite3_stmt.java
Normal file
25
ext/jni/src/org/sqlite/jni/sqlite3_stmt.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
** 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 final class sqlite3_stmt extends NativePointerHolder<sqlite3_stmt> {
|
||||||
|
// Only invoked from JNI.
|
||||||
|
private sqlite3_stmt(){}
|
||||||
|
}
|
19
ext/jni/src/org/sqlite/jni/sqlite3_value.java
Normal file
19
ext/jni/src/org/sqlite/jni/sqlite3_value.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
** 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 final class sqlite3_value extends NativePointerHolder<sqlite3_value> {
|
||||||
|
//! Invoked only from JNI.
|
||||||
|
private sqlite3_value(){}
|
||||||
|
}
|
1421
ext/jni/src/org/sqlite/jni/tester/SQLTester.java
Normal file
1421
ext/jni/src/org/sqlite/jni/tester/SQLTester.java
Normal file
File diff suppressed because it is too large
Load Diff
269
ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md
Normal file
269
ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
# Specifications For A Rudimentary SQLite Test Script Interpreter
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The purpose of the Test Script Interpreter is to read and interpret
|
||||||
|
script files that contain SQL commands and desired results. The
|
||||||
|
interpreter will check results and report an discrepencies found.
|
||||||
|
|
||||||
|
The test script files are ASCII text files. The filename always ends with
|
||||||
|
".test". Each script is evaluated independently; context does not carry
|
||||||
|
forward from one script to the next. So, for example, the --null command
|
||||||
|
run in one test script does not cause any changes in the behavior of
|
||||||
|
subsequent test scripts. All open database connections are closed
|
||||||
|
at the end of each test script. All database files created by a test
|
||||||
|
script are deleted when the script finishes.
|
||||||
|
|
||||||
|
## Parsing Rules:
|
||||||
|
|
||||||
|
1. The test script is read line by line, where a line is a sequence of
|
||||||
|
characters that runs up to the next '\\n' (0x0a) character or until
|
||||||
|
the end of the file. There is never a need to read ahead past the
|
||||||
|
end of the current line.
|
||||||
|
|
||||||
|
2. If any line contains the string " MODULE_NAME:" (with a space before
|
||||||
|
the initial "M") or "MIXED_MODULE_NAME:" then that test script is
|
||||||
|
incompatible with this spec. Processing of the test script should
|
||||||
|
end immediately. There is no need to read any more of the file.
|
||||||
|
In verbose mode, the interpreter might choose to emit an informational
|
||||||
|
messages saying that the test script was abandoned due to an
|
||||||
|
incompatible module type.
|
||||||
|
|
||||||
|
3. If any line contains the string "SCRIPT_MODULE_NAME:" then the input
|
||||||
|
script is known to be of the correct type for this specification and
|
||||||
|
processing may continue. The "MODULE_NAME" checking in steps 2 and 3
|
||||||
|
may optionally be discontinued after sighting a "SCRIPT_MODULE_NAME".
|
||||||
|
|
||||||
|
4. If any line contains "REQUIRED_PROPERTIES:" and that substring is followed
|
||||||
|
by any non-whitespace text, then the script is not compatible with this
|
||||||
|
spec. Processing should stop immediately. In verbose mode, the
|
||||||
|
interpreter might choose to emit an information message saying that the
|
||||||
|
test script was abandoned due to unsupported requirement properties.
|
||||||
|
|
||||||
|
5. If any line begins with the "\|" (0x7c) character, that indicates that
|
||||||
|
the input script is not compatible with this specification. Processing
|
||||||
|
of the script should stop immediately. In verbose mode, the interpreter
|
||||||
|
might choose to emit an informational message indicating that the
|
||||||
|
test script was abandoned because it contained "a dbtotxt format database
|
||||||
|
specification".
|
||||||
|
|
||||||
|
6. Any line that begins with "#" is a C-preprocessor line. The interpreter
|
||||||
|
described by this spec does not know how to deal with C-preprocessor lines.
|
||||||
|
Hence, processing should be abandoned. In verbose mode, the interpreter
|
||||||
|
might emit an informational message similar to
|
||||||
|
"script NAME abandoned due to C-preprocessor line: ..."
|
||||||
|
|
||||||
|
7. If a line begins with exactly two minus signs followed by a
|
||||||
|
lowercase letter, that is a command. Process commands as described
|
||||||
|
below.
|
||||||
|
|
||||||
|
8. All other lines should be accumulated into the "input buffer".
|
||||||
|
The various commands will have access to this input buffer.
|
||||||
|
Some commands will reset the buffer.
|
||||||
|
|
||||||
|
## Initialization
|
||||||
|
|
||||||
|
The initial state of the interpreter at the start of processing each script
|
||||||
|
is as if the following command sequence had been run:
|
||||||
|
|
||||||
|
> ~~~
|
||||||
|
--close all
|
||||||
|
--db 0
|
||||||
|
--new test.db
|
||||||
|
--null nil
|
||||||
|
~~~
|
||||||
|
|
||||||
|
In words, all database connections are closed except for connection 0 (the
|
||||||
|
default) which is open on an empty database named "test.db". The string
|
||||||
|
"nil" is displayed for NULL column values.
|
||||||
|
|
||||||
|
The only context carried forward after the evaluation of one test script
|
||||||
|
into the evaluation of the next test script is the count of the number of
|
||||||
|
tests run and the number of failures seen.
|
||||||
|
|
||||||
|
## Commands:
|
||||||
|
|
||||||
|
Each command looks like an SQL comment. The command begins at the left
|
||||||
|
margin (no leading space) and starts with exactly 2 minus signs ("-").
|
||||||
|
The command name consists of lowercase letters and maybe a "-" or two.
|
||||||
|
Some commands have arguments.
|
||||||
|
The arguments are separated from the command name by one or more spaces.
|
||||||
|
|
||||||
|
Commands have access to the input buffer and might reset the input buffer.
|
||||||
|
The command can also optionally read (and consume) additional text from
|
||||||
|
script that comes after the command.
|
||||||
|
|
||||||
|
Unknown or unrecognized commands indicate that the script contains features
|
||||||
|
that are not (yet) supported by this specification. Processing of the
|
||||||
|
script should terminate immediately. When this happens and when the
|
||||||
|
interpreter is in a "verbose" mode, the interpreter might choose to emit
|
||||||
|
an informational message along the lines of "test script NAME abandoned
|
||||||
|
due to unsupported command: --whatever".
|
||||||
|
|
||||||
|
The initial implemention will only recognize a few commands. Other
|
||||||
|
commands may be added later. The following is the initial set of
|
||||||
|
commands:
|
||||||
|
|
||||||
|
### The --testcase command
|
||||||
|
|
||||||
|
Every test case starts with a --testcase command. The --testcase
|
||||||
|
command resets both the "input buffer" and the "result buffer". The
|
||||||
|
argument to the --testcase command is the name of the test case. That
|
||||||
|
test case name is used for logging and debugging and when printing
|
||||||
|
errors. The input buffer is set to the body of the test case.
|
||||||
|
|
||||||
|
### The --result command
|
||||||
|
|
||||||
|
The --result command tries to execute the text in the input buffer as SQL.
|
||||||
|
For each row of result coming out of this SQL, the text of that result is
|
||||||
|
appended to the "result buffer". If a result row contains multiple columns,
|
||||||
|
the columns are processed from left to right. For each column, text is
|
||||||
|
appended to the result buffer according to the following rules:
|
||||||
|
|
||||||
|
* If the result buffer already contains some text, append a space.
|
||||||
|
(In this way, all column values and all row values are separated from
|
||||||
|
each other by a single space.)
|
||||||
|
|
||||||
|
* If sqlite3_column_text() returns NULL, then append "nil" - or
|
||||||
|
some other text that is specified by the --null command - and skip
|
||||||
|
all subsequent rules.
|
||||||
|
|
||||||
|
* If sqlite3_column_text() is an empty string, append `{}` to the
|
||||||
|
result buffer and skip all subsequent rules.
|
||||||
|
|
||||||
|
* If sqlite3_column_text() does not contain any special
|
||||||
|
characters, append it to the result buffer without any
|
||||||
|
formatting and skip all subsequent rules. Special characters are:
|
||||||
|
0x00 to 0x20 (inclusive), double-quote (0x22), backslash (0x5c),
|
||||||
|
curly braces (0x7b and 0x7d).
|
||||||
|
|
||||||
|
* If sqlite3_column_text() does not contains curly braces, then put
|
||||||
|
the text inside of `{...}` and append it and skip all subsequent rules.
|
||||||
|
|
||||||
|
* Append the text within double-quotes (`"..."`) and within the text
|
||||||
|
escape '"' and '\\' by prepending a single '\\' and escape any
|
||||||
|
control characters (characters less than 0x20) using octal notation:
|
||||||
|
'\\NNN'.
|
||||||
|
|
||||||
|
If an error is encountered while running the SQL, then append the
|
||||||
|
symbolic C-preprocessor name for the error
|
||||||
|
code (ex: "SQLITE_CONSTRAINT") as if it were a column value. Then append
|
||||||
|
the error message text as if it where a column value. Then stop processing.
|
||||||
|
|
||||||
|
After the SQL text has been run, compare the content of the result buffer
|
||||||
|
against the argument to the --result command and report a testing error if
|
||||||
|
there are any differences.
|
||||||
|
|
||||||
|
The --result command resets the input buffer, but it does not reset
|
||||||
|
the result buffer. This distinction does not matter for the --result
|
||||||
|
command itself, but it is important for related commands like --glob
|
||||||
|
and --notglob. Sometimes test cases will contains a bunch of SQL
|
||||||
|
followed by multiple --glob and/or --notglob statements. All of the
|
||||||
|
globs should be evaluted agains the result buffer correct, but the SQL
|
||||||
|
should only be run once. This is accomplished by resetting the input
|
||||||
|
buffer but not the result buffer.
|
||||||
|
|
||||||
|
### The --glob command
|
||||||
|
|
||||||
|
The --glob command works just like --result except that the argument to
|
||||||
|
--glob is interpreted as a TEST-GLOB pattern and the results are compared
|
||||||
|
using that glob pattern rather than using strcmp(). Other than that,
|
||||||
|
the two operate the same.
|
||||||
|
|
||||||
|
The TEST-GLOB pattern is slightly different for a standard GLOB:
|
||||||
|
|
||||||
|
* The '*' character matches zero or more characters.
|
||||||
|
|
||||||
|
* The '?' character matches any single character
|
||||||
|
|
||||||
|
* The '[...]' character sequence machines a single character
|
||||||
|
in between the brackets.
|
||||||
|
|
||||||
|
* The '#' character matches one or more digits (This is the main
|
||||||
|
difference between standard unix-glob and TEST-GLOB. unix-glob
|
||||||
|
does not have this feature. It was added to because it comes
|
||||||
|
up a lot during SQLite testing.)
|
||||||
|
|
||||||
|
### The --notglob command
|
||||||
|
|
||||||
|
The --notglob command works just like --glob except that it reports an
|
||||||
|
error if the GLOB does match, rather than if the GLOB does not matches.
|
||||||
|
|
||||||
|
### The --oom command
|
||||||
|
|
||||||
|
This command is to be used for out-of-memory testing. It means that
|
||||||
|
OOM errors should be simulated to ensure that SQLite is able to deal with
|
||||||
|
them. This command can be silently ignored for now. We might add support
|
||||||
|
for this later.
|
||||||
|
|
||||||
|
### The --tableresult command
|
||||||
|
|
||||||
|
The --tableresult command works like --glob except that the GLOB pattern
|
||||||
|
to be matched is taken from subsequent lines of the input script up to
|
||||||
|
the next --end. Every span of one or more whitespace characters in this
|
||||||
|
pattern text is collapsed into a single space (0x20).
|
||||||
|
Leading and trailing whitespace are removed from the pattern.
|
||||||
|
The --end that ends the GLOB pattern is not part of the GLOB pattern, but
|
||||||
|
the --end is consumed from the script input.
|
||||||
|
|
||||||
|
### The --new and --open commands
|
||||||
|
|
||||||
|
The --new and --open commands cause a database file to be opened.
|
||||||
|
The name of the file is the argument to the command. The --new command
|
||||||
|
opens an initially empty database (it deletes the file before opening it)
|
||||||
|
whereas the --open command opens an existing database if it already
|
||||||
|
exists.
|
||||||
|
|
||||||
|
### The --db command
|
||||||
|
|
||||||
|
The script interpreter can have up to 7 different SQLite database
|
||||||
|
connections open at a time. The --db command is used to switch between
|
||||||
|
them. The argument to --db is an integer between 0 and 6 that selects
|
||||||
|
which database connection to use moving forward.
|
||||||
|
|
||||||
|
### The --close command
|
||||||
|
|
||||||
|
The --close command causes an existing database connection to close.
|
||||||
|
This command is a no-op if the database connection is not currently
|
||||||
|
open. There can be up to 7 different database connections, numbered 0
|
||||||
|
through 6. The number of the database connection to close is an
|
||||||
|
argument to the --close command, which will fail if an out-of-range
|
||||||
|
value is provided. Or if the argument to --close is "all" then all
|
||||||
|
open database connections are closed. If passed no argument, the
|
||||||
|
currently-active database is assumed.
|
||||||
|
|
||||||
|
### The --null command
|
||||||
|
|
||||||
|
The NULL command changes the text that is used to represent SQL NULL
|
||||||
|
values in the result buffer.
|
||||||
|
|
||||||
|
### The --run command
|
||||||
|
|
||||||
|
The --run command executes text in the input buffer as if it where SQL.
|
||||||
|
However, nothing is added to the result buffer. Any output from the SQL
|
||||||
|
is silently ignored. Errors in the SQL are silently ignored.
|
||||||
|
|
||||||
|
The --run command normally executes the SQL in the current database
|
||||||
|
connection. However, if --run has an argument that is an integer between
|
||||||
|
0 and 6 then the SQL is run in the alternative database connection specified
|
||||||
|
by that argument.
|
||||||
|
|
||||||
|
### The --json and --json-block commands
|
||||||
|
|
||||||
|
The --json and --json-block commands work like --result and --tableresult,
|
||||||
|
respectively. The difference is that column values are appended to the
|
||||||
|
result buffer literally, without ever enclosing the values in `{...}` or
|
||||||
|
`"..."` and without escaping any characters in the column value and comparison
|
||||||
|
is always an exact strcmp() not a GLOB.
|
||||||
|
|
||||||
|
### The --print command
|
||||||
|
|
||||||
|
The --print command emits both its arguments and its body (if any) to
|
||||||
|
stdout, indenting each line of output.
|
||||||
|
|
||||||
|
### The --column-names command
|
||||||
|
|
||||||
|
The --column-names command requires 0 or 1 as an argument, to disable
|
||||||
|
resp. enable it, and modifies SQL execution to include column names
|
||||||
|
in output. When this option is on, each column value emitted gets
|
||||||
|
prefixed by its column name, with a single space between them.
|
52
ext/jni/src/tests/000-000-sanity.test
Normal file
52
ext/jni/src/tests/000-000-sanity.test
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
** This is a comment. There are many like it but this one is mine.
|
||||||
|
**
|
||||||
|
** SCRIPT_MODULE_NAME: sanity-check
|
||||||
|
** xMIXED_MODULE_NAME: mixed-module
|
||||||
|
** xMODULE_NAME: module-name
|
||||||
|
** xREQUIRED_PROPERTIES: small fast reliable
|
||||||
|
** xREQUIRED_PROPERTIES: RECURSIVE_TRIGGERS
|
||||||
|
** xREQUIRED_PROPERTIES: TEMPSTORE_MEM TEMPSTORE_FILE
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
--print starting up 😃
|
||||||
|
--close all
|
||||||
|
--oom
|
||||||
|
--db 0
|
||||||
|
--new my.db
|
||||||
|
--null zilch
|
||||||
|
--testcase 1.0
|
||||||
|
SELECT 1, null;
|
||||||
|
--result 1 zilch
|
||||||
|
--glob *zil*
|
||||||
|
--notglob *ZIL*
|
||||||
|
SELECT 1, 2;
|
||||||
|
intentional error;
|
||||||
|
--run
|
||||||
|
--testcase json-1
|
||||||
|
SELECT json_array(1,2,3)
|
||||||
|
--json [1,2,3]
|
||||||
|
--testcase tableresult-1
|
||||||
|
select 1, 'a';
|
||||||
|
select 2, 'b';
|
||||||
|
--tableresult
|
||||||
|
# [a-z]
|
||||||
|
2 b
|
||||||
|
--end
|
||||||
|
--testcase json-block-1
|
||||||
|
select json_array(1,2,3);
|
||||||
|
select json_object('a',1,'b',2);
|
||||||
|
--json-block
|
||||||
|
[1,2,3]
|
||||||
|
{"a":1,"b":2}
|
||||||
|
--end
|
||||||
|
--testcase col-names-on
|
||||||
|
--column-names 1
|
||||||
|
select 1 as 'a', 2 as 'b';
|
||||||
|
--result a 1 b 2
|
||||||
|
--testcase col-names-off
|
||||||
|
--column-names 0
|
||||||
|
select 1 as 'a', 2 as 'b';
|
||||||
|
--result 1 2
|
||||||
|
--close
|
||||||
|
--print reached the end 😃
|
9
ext/jni/src/tests/000-001-ignored.test
Normal file
9
ext/jni/src/tests/000-001-ignored.test
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
** This script must be marked as ignored because it contains
|
||||||
|
** content which triggers that condition.
|
||||||
|
**
|
||||||
|
** SCRIPT_MODULE_NAME: ignored
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
|
51
manifest
51
manifest
@ -1,5 +1,5 @@
|
|||||||
C Update\swasm's\spush-testing\srule\sto\sexclude\sfiles\swhich\swere\srecently\sremoved\sfrom\sthe\sbuild.
|
C Merge\sthe\sJava\sNative\sInterface\s(JNI)\sbinding\sinto\strunk.
|
||||||
D 2023-08-12T21:08:41.355
|
D 2023-08-12T21:39:18.053
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -231,6 +231,46 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
|||||||
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
|
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
|
||||||
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
|
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
|
||||||
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
||||||
|
F ext/jni/GNUmakefile 435485ff2005c4bcdea808f5efe6d4ee66a00430c2499dcc4927b20378486bea
|
||||||
|
F ext/jni/README.md 7a614a2fa6c561205f7a53fd8626cf93a7b5711ff454fc1814517f796df398eb
|
||||||
|
F ext/jni/jar-dist.make f90a553203a57934bf275bed86479485135a52f48ac5c1cfe6499ae07b0b35a4
|
||||||
|
F ext/jni/src/c/sqlite3-jni.c bea6b8691a5fa3a8626a771757bb261208d3c5fc6598266d3b0ee23d88e35632
|
||||||
|
F ext/jni/src/c/sqlite3-jni.h c5f941b057a24ee62942e6e1bf5a7fd527e5004d20d9638e84a9382813c3cf2a
|
||||||
|
F ext/jni/src/org/sqlite/jni/Authorizer.java 1308988f7f40579ea0e4deeaec3c6be971630566bd021c31367fe3f5140db892
|
||||||
|
F ext/jni/src/org/sqlite/jni/AutoExtension.java 18e83f6f463e306df60b2dceb65247d32af1f78af4bbbae9155411a8c6cdb093
|
||||||
|
F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c
|
||||||
|
F ext/jni/src/org/sqlite/jni/Collation.java 8dffbb00938007ad0967b2ab424d3c908413af1bbd3d212b9c9899910f1218d1
|
||||||
|
F ext/jni/src/org/sqlite/jni/CollationNeeded.java ad67843b6dd1c06b6b0a1dc72887b7c48e2a98042fcf6cacf14d42444037eab8
|
||||||
|
F ext/jni/src/org/sqlite/jni/CommitHook.java 87c6a8e5138c61a8eeff018fe16d23f29219150239746032687f245938baca1a
|
||||||
|
F ext/jni/src/org/sqlite/jni/Fts5.java 13844685231e8b4840a706db3bed84d5dfcf15be0ae7e809eac40420dba24901
|
||||||
|
F ext/jni/src/org/sqlite/jni/Fts5Context.java 0a5a02047a6a1dd3e4a38b0e542a8dd2de365033ba30e6ae019a676305959890
|
||||||
|
F ext/jni/src/org/sqlite/jni/Fts5ExtensionApi.java 01f890105c6b7edbbad1c0f5635f783cea62c4b2ae694a71e76514a936ee03ec
|
||||||
|
F ext/jni/src/org/sqlite/jni/Fts5Function.java 65cde7151e441fee012250a5e03277de7babcd11a0c308a832b7940574259bcc
|
||||||
|
F ext/jni/src/org/sqlite/jni/Fts5PhraseIter.java 6642beda341c0b1b46af4e2d7f6f9ab03a7aede43277b2c92859176d6bce3be9
|
||||||
|
F ext/jni/src/org/sqlite/jni/Fts5Tokenizer.java 91489893596b6528c0df5cd7180bd5b55809c26e2b797fb321dfcdbc1298c060
|
||||||
|
F ext/jni/src/org/sqlite/jni/NativePointerHolder.java 9c5d901cce4f7e57c3d623f4e2476f9f79a8eed6e51b2a603f37866018e040ee
|
||||||
|
F ext/jni/src/org/sqlite/jni/OutputPointer.java d81f8bd43d2296ae373692370cfad16ddde76f5c14cd2760f7b4e1113ef56d4c
|
||||||
|
F ext/jni/src/org/sqlite/jni/ProgressHandler.java 6f62053a828a572de809828b1ee495380677e87daa29a1c57a0e2c06b0a131dc
|
||||||
|
F ext/jni/src/org/sqlite/jni/ResultCode.java ba701f20213a5f259e94cfbfdd36eb7ac7ce7797f2c6c7fca2004ff12ce20f86
|
||||||
|
F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f69df0ba909e49ba18d73f4268d92564
|
||||||
|
F ext/jni/src/org/sqlite/jni/SQLFunction.java 09ce81c1c637e31c3a830d4c859cce95d65f5e02ff45f8bd1985b3479381bc46
|
||||||
|
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 4b6fd22e04e63eb65d8e4e38fda39ecf15ce244d034607517627ce2e766e7e65
|
||||||
|
F ext/jni/src/org/sqlite/jni/Tester1.java 07c14a90427529ceba54b5e8344ca03602f5789dc53c4163ce22f92d8c577a11
|
||||||
|
F ext/jni/src/org/sqlite/jni/TesterFts5.java 59e22dd24af033ea8827d36225a2f3297908fb6af8818ead8850c6c6847557b1
|
||||||
|
F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d
|
||||||
|
F ext/jni/src/org/sqlite/jni/UpdateHook.java e58645a1727f8a9bbe72dc072ec5b40d9f9362cb0aa24acfe93f49ff56a9016d
|
||||||
|
F ext/jni/src/org/sqlite/jni/ValueHolder.java f022873abaabf64f3dd71ab0d6037c6e71cece3b8819fa10bf26a5461dc973ee
|
||||||
|
F ext/jni/src/org/sqlite/jni/fts5_api.java 5198be71c162e3e0cb1f4962a7cdf0d7596e8af53f70c4af6db24aab8d53d9ba
|
||||||
|
F ext/jni/src/org/sqlite/jni/fts5_extension_function.java ac825035d7d83fc7fd960347abfa6803e1614334a21533302041823ad5fc894c
|
||||||
|
F ext/jni/src/org/sqlite/jni/fts5_tokenizer.java e530b36e6437fcc500e95d5d75fbffe272bdea20d2fac6be2e1336c578fba98b
|
||||||
|
F ext/jni/src/org/sqlite/jni/sqlite3.java 62b1b81935ccf3393472d17cb883dc5ff39c388ec3bc1de547f098a0217158fc
|
||||||
|
F ext/jni/src/org/sqlite/jni/sqlite3_context.java d26573fc7b309228cb49786e9078597d96232257defa955a3425d10897bca810
|
||||||
|
F ext/jni/src/org/sqlite/jni/sqlite3_stmt.java 78e6d1b95ac600a9475e9db4623f69449322b0c93d1bd4e1616e76ed547ed9fc
|
||||||
|
F ext/jni/src/org/sqlite/jni/sqlite3_value.java 3d1d4903e267bc0bc81d57d21f5e85978eff389a1a6ed46726dbe75f85e6914a
|
||||||
|
F ext/jni/src/org/sqlite/jni/tester/SQLTester.java 1f1286428fab38dfefe328e72b5735f533b19af8dd17712dd3df7e044d21c8b8
|
||||||
|
F ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md f9f25126127045d051e918fe59004a1485311c50a13edbf18c79a6ff9160030e
|
||||||
|
F ext/jni/src/tests/000-000-sanity.test cfe6dc1b950751d6096e3f5695becaadcdaa048bfe9567209d6eb676e693366d
|
||||||
|
F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
|
||||||
F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9
|
F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9
|
||||||
F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
|
F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
|
||||||
F ext/lsm1/lsm-test/README 87ea529d2abe615e856d4714bfe8bb185e6c2771b8612aa6298588b7b43e6f86
|
F ext/lsm1/lsm-test/README 87ea529d2abe615e856d4714bfe8bb185e6c2771b8612aa6298588b7b43e6f86
|
||||||
@ -2051,8 +2091,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 01f49448cd0cfe3af499aedfe887b7b0be4f1ab09cd5a16119ddafb32b107708
|
P 0a6930a7ff8f8c6ca244d1d654532f3d2a02d77ef67c6cae0c53092743d59ea6 1ba7754045a009d9c94b23ac76b9bb8d9c9cb24d42dcdf1203ee75ac85765d3e
|
||||||
R 2ecaec09aa6a0d3ef6dc669f83d54223
|
R 71919983f1228c04d42d3555e47fba1b
|
||||||
|
T +closed 1ba7754045a009d9c94b23ac76b9bb8d9c9cb24d42dcdf1203ee75ac85765d3e Closed\sby\sintegrate-merge.
|
||||||
U stephan
|
U stephan
|
||||||
Z 90975d5312aef561538895b18087fc5f
|
Z 06dd3519c67c3e383d12eeb6b6fbb0d1
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
0a6930a7ff8f8c6ca244d1d654532f3d2a02d77ef67c6cae0c53092743d59ea6
|
48b13edcec6935bf125b265b41a3e6f7b2407afff89d5b4daa2939e3c5679ca0
|
Reference in New Issue
Block a user