1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Merge latest changes from the wal2 branch into this one.

FossilOrigin-Name: 4d8df0c426b8ce3db6cfb71e23f752026ef886b9bb833dc4be9717db9955b1db
This commit is contained in:
dan
2023-08-21 18:31:53 +00:00
83 changed files with 14363 additions and 598 deletions

View File

@@ -1316,6 +1316,9 @@ testrunner: testfixture$(TEXE)
#
devtest: testfixture$(TEXE) fuzztest testrunner
mdevtest:
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest
# Testing for a release
#
releasetest: testfixture$(TEXE)

View File

@@ -56,7 +56,7 @@ USE_STDCALL = 0
# in the core library.
#
!IFNDEF USE_SEH
USE_SEH = 0
USE_SEH = 1
!ENDIF
# Set this non-0 to have the shell executable link against the core dynamic
@@ -225,6 +225,12 @@ WIN32HEAP = 0
OSTRACE = 0
!ENDIF
# enable address sanitizer using ASAN=1 on the command-line.
#
!IFNDEF ASAN
ASAN = 0
!ENDIF
# Set this to one of the following values to enable various debugging
# features. Each level includes the debugging options from the previous
# levels. Currently, the recognized values for DEBUG are:
@@ -891,6 +897,13 @@ RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
!ENDIF
!ENDIF
# Address sanitizer if ASAN=1
#
!IF $(ASAN)>0
TCC = $(TCC) /fsanitize=address
!ENDIF
# <<mark>>
# The locations of the Tcl header and library files. Also, the library that
# non-stubs enabled programs using Tcl must link against. These variables
@@ -2506,6 +2519,9 @@ testrunner: testfixture.exe
#
devtest: testfixture.exe fuzztest testrunner
mdevtest:
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest
# Testing for a release
#
releasetest: testfixture.exe fuzztest

View File

@@ -104,9 +104,9 @@ For example:
mkdir bld ;# Build will occur in a sibling directory
cd bld ;# Change to the build directory
../sqlite/configure ;# Run the configure script
make ;# Run the makefile.
make ;# Builds the "sqlite3" command-line tool
make sqlite3.c ;# Build the "amalgamation" source file
make test ;# Run some tests (requires Tcl)
make devtest ;# Run some tests (requires Tcl)
See the makefile for additional targets.
@@ -119,29 +119,30 @@ show what changes are needed.
## Using MSVC for Windows systems
On Windows, all applicable build products can be compiled with MSVC.
First open the command prompt window associated with the desired compiler
version (e.g. "Developer Command Prompt for VS2013"). Next, use NMAKE
with the provided "Makefile.msc" to build one of the supported targets.
You will also need a working installation of TCL.
See the [compile-for-windows.md](doc/compile-for-windows.md) document for
additional information about how to install MSVC and TCL and configure your
build environment.
For example, from the parent directory of the source subtree named "sqlite":
If you want to run tests, you need to let SQLite know the location of your
TCL library, using a command like this:
mkdir bld
cd bld
nmake /f ..\sqlite\Makefile.msc TOP=..\sqlite
nmake /f ..\sqlite\Makefile.msc sqlite3.c TOP=..\sqlite
nmake /f ..\sqlite\Makefile.msc sqlite3.dll TOP=..\sqlite
nmake /f ..\sqlite\Makefile.msc sqlite3.exe TOP=..\sqlite
nmake /f ..\sqlite\Makefile.msc test TOP=..\sqlite
set TCLDIR=c:\Tcl
There are several build options that can be set via the NMAKE command
line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
to the "sqlite3.dll" command line above. When debugging into the SQLite
code, adding the "DEBUG=1" argument to one of the above command lines is
recommended.
SQLite uses "tclsh.exe" as part of the build process, and so that utility
program will need to be somewhere on your %PATH%. The finished SQLite library
does not contain any TCL code, but it does use TCL to help with the build process
and to run tests.
SQLite does not require [Tcl](http://www.tcl.tk/) to run, but a Tcl installation
is required by the makefiles (including those for MSVC). SQLite contains
a lot of generated code and Tcl is used to do much of that code generation.
Build using Makefile.msc. Example:
nmake /f Makefile.msc
nmake /f Makefile.msc sqlite3.c
nmake /f Makefile.msc devtest
nmake /f Makefile.msc releasetest
There are many other makefile targets. See comments in Makefile.msc for
details.
## Source Code Tour

View File

@@ -9,7 +9,7 @@ sqlite3_SOURCES = shell.c sqlite3.h
EXTRA_sqlite3_SOURCES = sqlite3.c
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS)
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_DQS=0 -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS)
include_HEADERS = sqlite3.h sqlite3ext.h

View File

@@ -56,7 +56,7 @@ USE_STDCALL = 0
# in the core library.
#
!IFNDEF USE_SEH
USE_SEH = 0
USE_SEH = 1
!ENDIF
# Set this non-0 to have the shell executable link against the core dynamic

View File

@@ -0,0 +1,85 @@
# Notes On Compiling SQLite On Windows 11
Here are step-by-step instructions on how to build SQLite from
canonical source on a new Windows 11 PC, as of 2023-08-16:
1. Install Microsoft Visual Studio. The free "community edition"
will work fine. Do a standard install for C++ development.
SQLite only needs the
"cl" compiler and the "nmake" build tool.
2. Under the "Start" menu, find "All Apps" then go to "Visual Studio 20XX"
and find "x64 Native Tools Command Prompt for VS 20XX". Pin that
application to your task bar, as you will use it a lot. Bring up
an instance of this command prompt and do all of the subsequent steps
in that "x64 Native Tools" command prompt. (Or use "x86" if you want
a 32-bit build.) The subsequent steps will not work in a vanilla
DOS prompt. Nor will they work in PowerShell.
3. Install TCL development libraries. This note assumes that you wil
install the TCL development libraries in the "`c:\Tcl`" directory.
Make adjustments
if you want TCL installed somewhere else. SQLite needs both the
"tclsh.exe" command-line tool as part of the build process, and
the "tcl86.lib" library in order to run tests. You will need
TCL version 8.6 or later.
<ol type="a">
<li>Get the TCL source archive, perhaps from
<https://www.tcl.tk/software/tcltk/download.html>.
<li>Untar or unzip the source archive. CD into the "win/" subfolder
of the source tree.
<li>Run: `nmake /f makefile.vc release`
<li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl install`
<li>CD to c:\\Tcl\\lib. In that subfolder make a copy of the
"`tcl86t.lib`" file to the alternative name "`tcl86.lib`"
(omitting the second 't'). Leave the copy in the same directory
as the original.
<li>CD to c:\\Tcl\\bin. Make a copy of the "`tclsh86t.exe`"
file into "`tclsh.exe`" (without the "86t") in the same directory.
<li>Add c:\\Tcl\\bin to your %PATH%. To do this, go to Settings
and search for "path". Select "edit environment variables for
your account" and modify your default PATH accordingly.
You will need to close and reopen your command prompts after
making this change.
</ol>
4. Download the SQLite source tree and unpack it. CD into the
toplevel directory of the source tree.
5. Set the TCLDIR environment variable to point to your TCL installation.
Like this:
<ul>
<li> `set TCLDIR=c:\Tcl`
</ul>
6. Run the "`Makefile.msc`" makefile with an appropriate target.
Examples:
<ul>
<li> `nmake /f makefile.msc`
<li> `nmake /f makefile.msc sqlite3.c`
<li> `nmake /f makefile.msc devtest`
<li> `nmake /f makefile.msc releasetest`
</ul>
## 32-bit Builds
Doing a 32-bit build is just like doing a 64-bit build with the
following minor changes:
1. Use the "x86 Native Tools Command Prompt" instead of
"x64 Native Tools Command Prompt". "**x86**" instead of "**x64**".
2. Use a different installation directory for TCL.
The recommended directory is `c:\tcl32`. Thus you end up
with two TCL builds:
<ul>
<li> `c:\tcl` &larr; 64-bit (the default)
<li> `c:\tcl32` &larr; 32-bit
</ul>
3. Ensure that c:\\tcl32\\bin comes before c:\\tcl\\bin on
your PATH environment variable. You can achieve this using
a command like:
<ul>
<li> `set PATH=c:\tcl32\bin;%PATH%`
</ul>

View File

@@ -492,8 +492,8 @@ struct Fts5ExtensionApi {
** as separate queries of the FTS index are required for each synonym.
**
** When using methods (2) or (3), it is important that the tokenizer only
** provide synonyms when tokenizing document text (method (2)) or query
** text (method (3)), not both. Doing so will not cause any errors, but is
** provide synonyms when tokenizing document text (method (3)) or query
** text (method (2)), not both. Doing so will not cause any errors, but is
** inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;

View File

@@ -2583,6 +2583,8 @@ static char *fts5ExprPrintTcl(
if( zRet==0 ) return 0;
}
}else if( pExpr->eType==0 ){
zRet = sqlite3_mprintf("{}");
}else{
char const *zOp = 0;
int i;

View File

@@ -5421,7 +5421,8 @@ static void fts5FlushOneHash(Fts5Index *p){
writer.bFirstRowidInPage = 0;
fts5WriteDlidxAppend(p, &writer, iRowid);
}else{
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid-iPrev);
u64 iDelta = (u64)iRowid - (u64)iPrev;
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
}
if( p->rc!=SQLITE_OK ) break;
assert( pBuf->n<=pBuf->nSpace );
@@ -7815,7 +7816,7 @@ static void fts5DecodeFunction(
fts5DecodeRowidList(&rc, &s, &a[4], iTermOff-4);
iOff = iTermOff;
while( iOff<szLeaf ){
while( iOff<szLeaf && rc==SQLITE_OK ){
int nAppend;
/* Read the term data for the next term*/
@@ -7835,8 +7836,11 @@ static void fts5DecodeFunction(
}else{
iTermOff = szLeaf;
}
fts5DecodeRowidList(&rc, &s, &a[iOff], iTermOff-iOff);
if( iTermOff>szLeaf ){
rc = FTS5_CORRUPT;
}else{
fts5DecodeRowidList(&rc, &s, &a[iOff], iTermOff-iOff);
}
iOff = iTermOff;
if( iOff<szLeaf ){
iOff += fts5GetVarint32(&a[iOff], nKeep);

View File

@@ -95,6 +95,9 @@ do_execsql_test 3.3 {
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"/" OR "just"' ORDER BY rank;
} {1 -1e-06}
do_execsql_test 3.4 "
SELECT fts5_expr_tcl('e AND \" \"');
" {{AND [nearset -- {e}] [{}]}}
finish_test

View File

@@ -50,6 +50,25 @@ do_test 1.3 {
expr $phc(1)*5 < $phc(2)
} {1}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
INSERT INTO t1(t1, rank) VALUES('secure-delete', $sd)
}
do_execsql_test 2.1 {
BEGIN;
INSERT INTO t1(rowid, x) VALUES(-100000, 'abc def ghi');
INSERT INTO t1(rowid, x) VALUES(-99999, 'abc def ghi');
INSERT INTO t1(rowid, x) VALUES(9223372036854775800, 'abc def ghi');
COMMIT;
}
do_execsql_test 2.2 {
SELECT rowid FROM t1('def')
} {-100000 -99999 9223372036854775800}
finish_test

View File

@@ -122,6 +122,9 @@ foreach {tn expr} {
4.1 "NEAR(one two, 2)"
4.2 "NEAR(one two three, 2)"
4.3 "NEAR(eight nine, 1) OR NEAR(six seven, 1)"
5.1 "one + two"
5.2 "1 + two"
} {
if {[fts5_expr_ok $expr ss]==0} {
do_test 1.$tok.$tn.OMITTED { list } [list]

346
ext/jni/GNUmakefile Normal file
View 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)

234
ext/jni/README.md Normal file
View File

@@ -0,0 +1,234 @@
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
========================================================================
- The initial beta release with version 3.43 has severe threading
limitations. Namely, two threads cannot call into the JNI-bound API
at once. This limitation will be remove in a subsequent release.
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

55
ext/jni/jar-dist.make Normal file
View File

@@ -0,0 +1,55 @@
#!/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
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

File diff suppressed because it is too large Load Diff

1989
ext/jni/src/c/sqlite3-jni.h Normal file

File diff suppressed because it is too large Load Diff

View 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);
}

View 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);
}

View 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(){}
}

View 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() {}
}

View 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);
}

View 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();
}

View 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;
}

View 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> {
}

View 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.
}

View 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() {}
}

View 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;
}

View 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(){}
}

View 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; }
}

View 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;}
}
}

View 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();
}

View 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); }
}
}

View 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();
}

View 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);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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;
}
}

View 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);
}

View 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);
}

View 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;}
}

View 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);
}
}

View 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(){}
}

View 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 */
// )
// );
}

View 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)+"]"
;
}
}

View 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;
}
}

View 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(){}
}

View 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(){}
}

File diff suppressed because it is too large Load Diff

View 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.

View 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 😃

View File

@@ -0,0 +1,9 @@
/*
** This script must be marked as ignored because it contains
** content which triggers that condition.
**
** SCRIPT_MODULE_NAME: ignored
**
*/
|

View File

@@ -642,7 +642,7 @@ static Decimal *decimalFromDouble(double r){
/*
** SQL Function: decimal(X)
** OR: decimal_sci(X)
** OR: decimal_exp(X)
**
** Convert input X into decimal and then back into text.
**
@@ -650,7 +650,7 @@ static Decimal *decimalFromDouble(double r){
** point value is done. Or if X is an 8-byte blob, it is interpreted
** as a float and similarly expanded.
**
** The decimal_sci(X) function returns the result in scientific notation.
** The decimal_exp(X) function returns the result in exponential notation.
** decimal(X) returns a complete decimal, without the e+NNN at the end.
*/
static void decimalFunc(
@@ -853,7 +853,7 @@ int sqlite3_decimal_init(
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aFunc[] = {
{ "decimal", 1, 0, decimalFunc },
{ "decimal_sci", 1, 1, decimalFunc },
{ "decimal_exp", 1, 1, decimalFunc },
{ "decimal_cmp", 2, 0, decimalCmpFunc },
{ "decimal_add", 2, 0, decimalAddFunc },
{ "decimal_sub", 2, 0, decimalSubFunc },

View File

@@ -1919,7 +1919,7 @@ static int rtreeFilter(
#else
p->u.rValue = (double)iVal;
if( iVal>=((sqlite3_int64)1)<<48
|| -iVal>=((sqlite3_int64)1)<<48
|| iVal<=-(((sqlite3_int64)1)<<48)
){
if( p->op==RTREE_LT ) p->op = RTREE_LE;
if( p->op==RTREE_GT ) p->op = RTREE_GE;

View File

@@ -1046,8 +1046,7 @@ endif
# Push files to public wasm-testing.sqlite.org server
wasm-testing.include = *.js *.mjs *.html \
./tests \
batch-runner.list \
$(dir.dout) $(dir.sql) $(dir.common) $(dir.fiddle) $(dir.jacc)
$(dir.dout) $(dir.common) $(dir.fiddle) $(dir.jacc)
wasm-testing.exclude = sql/speedtest1.sql
wasm-testing.dir = /jail/sites/wasm-testing
wasm-testing.dest ?= wasm-testing:$(wasm-testing.dir)

View File

@@ -942,6 +942,9 @@ testrunner: testfixture$(EXE)
#
devtest: testfixture$(EXE) fuzztest testrunner
mdevtest:
tclsh $(TOP)/test/testrunner.tcl mdevtest
# A very quick test using only testfixture and omitting all the slower
# tests. Designed to run in under 3 minutes on a workstation.
#

131
manifest
View File

@@ -1,21 +1,21 @@
C Fix\sproblems\srelated\sto\sstructured-exception-handling\son\sthis\sbranch.
D 2023-08-21T18:25:41.874
C Merge\slatest\schanges\sfrom\sthe\swal2\sbranch\sinto\sthis\sone.
D 2023-08-21T18:31:53.800
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 1ac6badc8e625d87c76f64fad033ece76721c6d9341c685baeb17aea5f620acd
F Makefile.in 0a5501ba18ddbe0ef10c02bfc12931b55148a216f2b14af79b2b76d715c4c65b
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc 0b57ab2867b1fdc90c4e35a6777a3b24b81006cc7ba947c8db13929b4edd3800
F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224
F Makefile.msc 01eac287493d2ea7b0ced738dcf19a2234c60195d39e1c86f2b0fa20c9d7d14e
F README.md 093d7054271141a0a8518558e3d49087cb71f84d33b50ee10053946ed85dcac8
F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
F autoconf/Makefile.am adedc1324b6a87fdd1265ddd336d2fb7d4f36a0e77b86ea553ae7cc4ea239347
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
F autoconf/Makefile.msc 00f11ce1f7904416fe841c33e7d789defe8c39e1df6b97e93ed2af3b1bbaf9d7
F autoconf/Makefile.msc 012cdd820963653a7db147a185ebe9085756b6ab15ac964e8cc1dae4c29485cd
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
@@ -38,6 +38,7 @@ F configure.ac 4654d32ac0a0d0b48f1e1e79bdc3d777b723cf2f63c33eb1d7c4ed8b435938e8
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/begin_concurrent.md 4bee2c3990d1eb800f1ce3726a911292a8e4b889300b2ffd4b08d357370db299
F doc/compile-for-windows.md e9d49959f44114a35dbec66f6aa5c3688ea9cb1b3f969a8537cd80b86d8969f7
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/lemon.html d2862dbef72496e87f7996f37e814b146848190a742c12161d13fd15346051b0
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
@@ -87,14 +88,14 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6dbd6348ef0cfc324a7
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h 9bebc9fb8b75b0777e741c758540e07c3c80ce75204198979028fe6cc4c59486
F ext/fts5/fts5.h 05501612cc655504c5dce8ba765ab621d50fc478490089beaa0d75e00b23e520
F ext/fts5/fts5Int.h 78a63cc0795186cde5384816a9403a68c65774b35d952e05b81a1b4b158e07c8
F ext/fts5/fts5_aux.c 572d5ec92ba7301df2fea3258576332f2f4d2dfd66d8263afd157d9deceac480
F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b729225eeaf6a5
F ext/fts5/fts5_config.c 054359543566cbff1ba65a188330660a5457299513ac71c53b3a07d934c7b081
F ext/fts5/fts5_expr.c 2473c13542f463cae4b938c498d6193c90d38ea1a2a4f9849c0479736e50d24d
F ext/fts5/fts5_expr.c bd3b81ce669c4104e34ffe66570af1999a317b142c15fccb112de9fb0caa57a6
F ext/fts5/fts5_hash.c 65e7707bc8774706574346d18c20218facf87de3599b995963c3e6d6809f203d
F ext/fts5/fts5_index.c 93b4cd116b76b6adf224cd3d213f1e06cfe10ae0eb21d6372b1c53b8f0c382a3
F ext/fts5/fts5_index.c 7990b39f68010d6ee0d89a92784900a5fe582b90ca02fedc8a5d4b6b589498b8
F ext/fts5/fts5_main.c 4df36d3e7e641dd8af1244fdd9b1639d80844d4559531580586edb802691c353
F ext/fts5/fts5_storage.c 3c9b41fce41b6410f2e8f82eb035c6a29b2560483f773e6dc98cf3cb2e4ddbb5
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
@@ -153,7 +154,7 @@ F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3
F ext/fts5/test/fts5dlidx.test b90852c55881b29dbac6380b274de27beae623ac4b6d567c6c8fb9cdc315a86e
F ext/fts5/test/fts5doclist.test faa9e9cc3c0645fa6203667cb5f007c359447c6ee66753f71a58175c2497cacd
F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
F ext/fts5/test/fts5eb.test a973baadac524dbbb4ad9b0e99030e12cabde2c6b28e0ac437298007b642cd12
F ext/fts5/test/fts5eb.test 5f0a86e9fe4715912e6bfa556368aae96d13c61a481373f24daa40429d5d5ca1
F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd
F ext/fts5/test/fts5fault2.test 69c8fdbef830cd0d450908d4504d5bb86609e255af99c421c20a0756251fe344
F ext/fts5/test/fts5fault3.test da2f9e3e56ff5740d68ebdd6877c97089e7ed28ddff28a0da87a6afea27e5522
@@ -204,13 +205,13 @@ F ext/fts5/test/fts5secure2.test 2e961d7eef939f294c56b5d895cac7f1c3a60b934ee2cfd
F ext/fts5/test/fts5secure3.test 12bc9ffa5dbd5a0951c6fe73bbf53b1c6507217589d7c8f5d4637a4fbb534401
F ext/fts5/test/fts5secure4.test 0d10a80590c07891478700af7793b232962042677432b9846cf7fc8337b67c97
F ext/fts5/test/fts5secure5.test c07a68ced5951567ac116c22f2d2aafae497e47fe9fcb6a335c22f9c7a4f2c3a
F ext/fts5/test/fts5secure6.test 7a959d834be6725c641b3c3b38ef86570ea671216ad803e054e4fdff33a72ce2
F ext/fts5/test/fts5secure6.test a0a28cfb9bf9721408b65b5d7c7ce369af3d688e273da24d101c25d60cdce05c
F ext/fts5/test/fts5securefault.test dbca2b6a1c16700017f5051138991b705410889933f2a37c57ae8a23b296b10b
F ext/fts5/test/fts5simple.test a298670508c1458b88ce6030440f26a30673931884eb5f4094ac1773b3ba217b
F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0
F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f
F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074ae82cfa870d8bb7fb
F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947ec60b6fadbc4b3fb17a
F ext/fts5/test/fts5synonym2.test 8f891fc49cc1e8daed727051e77e1f42849c784a6a54bef82564761b2cb3e016
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
@@ -234,6 +235,46 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
F ext/jni/GNUmakefile 3deba6bc0bf37c1ee5f15d1ff3c3512ae2f3cf44a2b8ae7b4af92690514b0cb4
F ext/jni/README.md 5c60e4580aa5c94ff74d7bef1fb6231e578f7764e831a07b5981b6ab62b35560
F ext/jni/jar-dist.make 93da95f8fe01ef22fccacc27f2e805938058e91e8c72c0532558d3a812a42e74
F ext/jni/src/c/sqlite3-jni.c bea6b8691a5fa3a8626a771757bb261208d3c5fc6598266d3b0ee23d88e35632
F ext/jni/src/c/sqlite3-jni.h 28565de9efc971195c684095ba0d184b90401290698c987f7ea3f54e47ff4f2f
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 4253dc7bcff64500a9388f1a17d3d39dbe4eb9d7db9fc035ce6e2380d45ad5fc
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.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
F ext/lsm1/lsm-test/README 87ea529d2abe615e856d4714bfe8bb185e6c2771b8612aa6298588b7b43e6f86
@@ -297,7 +338,7 @@ F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8b
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
F ext/misc/csv.c ca8d6dafc5469639de81937cb66ae2e6b358542aba94c4f791910d355a8e7f73
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
F ext/misc/decimal.c a61343b36672760e1d6d5b20a42cb52264db55bcd11d0a44e2e06e8ce23227e3
F ext/misc/decimal.c 172cf81a8634e6a0f0bedaf71a8372fee63348cf5a3c4e1b78bb233c35889fdc
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 0086fab288d4352ea638cf40ac382aad3b0dc5e845a1ea829a694c015fd970fe
F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebfb720
@@ -415,7 +456,7 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/geopoly.c 971e0b5bd9adaf0811feb8c0842a310811159da10319eb0e74fdb42bf26b99ca
F ext/rtree/rtree.c fb36e05027505f2c0dab24564e1d58ca4b789a6dfa48cf51aeee570018cf4814
F ext/rtree/rtree.c 6954f4a3ca51c2e3db35c52e0513f3520999eb7a967f3d53b71db7ebddd8b3a5
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 877d40b8b61b1f88cec9d4dc0ff8334f5b05299fac12a35141532e2881860e9d
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -496,7 +537,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
F ext/wasm/GNUmakefile 8159bc5f9433fe21022c1a8e8c30cb1a523530ba9ef53bdf5d1e0a2186554806
F ext/wasm/GNUmakefile d02f3c8798b754f68b1f6b422ccff894a10bf352fc9c4eb8945baeace1acac28
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api c5eaceabb9e759aaae7d3101a4a3e542f96ab2c99d89a80ce20ec18c23115f33
@@ -571,7 +612,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk 17ab4dd35f863772967540d8ebcb659691638e18c746b68ce8a8b3f545cb8ec3
F main.mk 5fe45da4f1e5f705eb9c2dfc896bc8b0e212e4edee70fb989ae243118dd314a9
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -580,7 +621,7 @@ F mptest/mptest.c aa41ace6dbc5050d76b02548d3521e6bbccae4f0
F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
F src/alter.c 3ff8c2fca0c0636d43459154bb40d79c882df1b34df77f89c4ec47ab2e2389f5
@@ -604,7 +645,7 @@ F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
F src/expr.c 1affe0cc049683ef0ef3545d9b6901508556b0ef7e2892a344c3df6d7288d79d
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c a7fcbf7e66d14dbb73cf49f31489ebf66d0e6006c62b95246924a3bae9f37b36
F src/func.c cb04a0496022ed1b32f2701695632cae4a44c806684178a298f2efaf27160519
F src/func.c 2c5b3d0c5f9998fa60ef2eda64fcb51d59a950dd0e695cdb5324943c4947c3d9
F src/global.c 29f56a330ed9d1b5cd9b79ac0ca36f97ac3afc730ff8bfa987b0db9e559d684d
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
@@ -613,7 +654,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
F src/json.c ae840f87b418f039f5d336b488933d09396bd31e6b31e855b93055ccaee4e255
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 176d6b2cb18a6ad73b133db17f6fc351c4d9a2d510deebdb76c22bde9cfd1465
F src/loadext.c 98cfba10989b3da6f1807ad42444017742db7f100a54f1032af7a8b1295912c0
F src/main.c e56843b488ead74369eeffc64cd5b9d3a7ffbf8621bb0cd695272d9b9ce53afa
F src/malloc.c 47b82c5daad557d9b963e3873e99c22570fb470719082c6658bf64e3012f7d23
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
@@ -636,10 +677,10 @@ F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
F src/os_unix.c c8003dfe6502315cf930160b6cf1b93f82211bed5ab9226509faa6324030c8ea
F src/os_win.c 7038223a1cda0a47e2ab4db47f63bf1833fe53ba0542f0f283a062ea13894103
F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c fda6c42c41a7eb58a62fd786cdef7a0e836234553ab8e59e03ea10b4dc3e26a1
F src/pager.h 55870bc2e0cabd29bcbaf650d342d3b970e316f440886f388052e34623ad1e29
F src/pager.h 314eb19f250d6ce31bdc32255a47141125f9b7c13cc202da2995eed5ef3c9825
F src/parse.y 92a9cc670816e1274a107d02ed8efec6028c23713c767f035479fde411c86f27
F src/pcache.c 4cd4a0043167da9ba7e19b4d179a0e6354e7fe32c16f781ecf9bf0a5ff63b40b
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
@@ -652,17 +693,17 @@ F src/random.c 9bd018738ec450bf35d28050b4b33fa9a6eebf3aaefb1a1cff42dc14a7725673
F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 996dda45d2a1a0228005849702348c7fd598437afa169c2c110f2c2ee582b382
F src/shell.c.in 694aaf751f00610381533d4a31c83d142cfc83ef91ef65e2aa6912ace7c39b40
F src/shell.c.in 2f9be25294b68b07e7e81f0adcec4475aba6011b64f160e414efe226910c4d7b
F src/sqlite.h.in bc319c39cb72ef72c4f1d1d3b7662bce1fb8ba961913e0c145472f2d9fc11a3b
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
F src/sqlite3ext.h 2f30b2671f4c03cd27a43f039e11251391066c97d11385f5f963bb40b03038ac
F src/sqliteInt.h d639aff687cfaa64f273a0f62eebb81bad875fdb9e8ff02d1a0235a8c1957e96
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd
F src/test1.c 91addc5c30c1389d257380b6e42ae0681d32d24553b9938d798a47ff96fa75ca
F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
F src/test2.c 54520d0565ef2b9bf0f8f1dcac43dc4d06baf4ffe13d10905f8d8c3ad3e4b9ab
F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
@@ -716,15 +757,15 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 23d9f4539880b40226254ad9072f4ecf12eb1902e62aea47aac29928afafcfd5
F src/treeview.c 1d52fbc4e97161e65858d36e3424ea6e3fc045dd8a679c82b4b9593dc30de3bd
F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
F src/update.c eafa1d6e32de4749986cbebc32ffb094c4401318bb713e5d2a18fe3e5a93ae8d
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
F src/update.c 0f8df185d63e1d3a777ae889880be1f9227bb37bb40d3e461555a6925ac298f8
F src/upsert.c fa125a8d3410ce9a97b02cb50f7ae68a2476c405c76aa692d3acf6b8586e9242
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c a40062117e705eb3339201842717a022092816b92479eead6397cde28af32ff9
F src/util.c 278b81c3b33db1b5a5f3859adf8905c165b910080043061d44d3c5a25b4b406d
F src/vacuum.c b1dd6d73869229b6e08bac910ac011dc9da42e3120ec2b7241accc5a752bd419
F src/vdbe.c 3ef180bab789aa99aec753fd26ecb8f3d56c9f6870997cafd8c5fc2b7c989a43
F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
F src/vdbeapi.c f37822f215740ede2a8fcae99bc13f2cc3a72dd0e1d22b81b9298c5ca67dbc38
F src/vdbeapi.c 37341acd781fda162e8cf4d9fc2eaea2febad3b365877a9d7233b8c6d0960d85
F src/vdbeaux.c 2c87c99975ac23e777e9c270d979eca38f2a021b1f14f061c83faab5b24d5576
F src/vdbeblob.c 2516697b3ee8154eb8915f29466fb5d4f1ae39ee8b755ea909cefaf57ec5e2ce
F src/vdbemem.c 317b9f48708139db6239ade40c7980b4bc8233168383690d588dad6d8437f722
@@ -733,8 +774,8 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
F src/vdbevtab.c 57fa8f56478e5b5cb558cb425e7878515e0a105c54f96f1d1bbf4b9433529254
F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 56eedfe60c278d0ee53f8a91b513ab40020773a1e83e29ec7ccc6a000ad5bd28
F src/wal.h dcb0533caecf286be1c87b683e1282f3ca29fa5c00eb798e9226ce377a687cf4
F src/wal.c ba4ea857cac27bb2fa9eb4bfecec4b552baca0fdbe527aac324e106de5201cc6
F src/wal.h 8d02ab8c2a93a941f5898eb3345bf711c1d3f8f86f4be8d5428fb6c074962d8a
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c b8917792f1e0dbfa28fb29e6cd3d560060d69667be0ba4c491cbc772363264f5
F src/whereInt.h c7d19902863beadec1d04e66aca39c0bcd60b74f05f0eaa7422c7005dfc5d51a
@@ -966,7 +1007,7 @@ F test/dbpage.test fce29035c7566fd7835ec0f19422cb4b9c6944ce0e1b936ff8452443f92e8
F test/dbpagefault.test d9111a62f3601d3efc6841ace3940181937342d245f92a1cca6cba8206d4f58a
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
F test/decimal.test 18e7b4cb12e8d5c60d768b686ba52af3e1ca3ced4f870231f0476666fd9fab7e
F test/decimal.test ef731887b43ee32ef86e1c8fddb61a40789f988332c029c601dcf2c319277e9e
F test/default.test 9687cfb16717e4b8238c191697c98be88c0b16e568dd5368cd9284154097ef50
F test/delete.test 2686e1c98d552ef37d79ad55b17b93fe96fad9737786917ce3839767f734c48f
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
@@ -1151,7 +1192,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c 29a2f0237553375498f891c9487a2ef3267b47deecc5d5b4335fa37f904cb8d3
F test/fuzzcheck.c 69b8549e112fb815931a8c14c7955a0c407ae91a79356eecb82458384f2cb989
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1253,7 +1294,7 @@ F test/json/README.md 63e3e589e1df8fd3cc1588ba1faaff659214003f8b77a15af5c6452b35
F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd28656fb261bddc8a3f
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
F test/json/json-speed-check.sh 8b7babf530faa58bd59d6d362cec8e9036a68c5457ff46f3b1f1511d21af6737 x
F test/json101.test 243b0a2650218ac5eafde6ce2a92a0e9d02bf24f62aec68693b69d9a693f120a
F test/json101.test dc9d5a2a5b1fd1b54dbd71c538b17933cc98d84b4c1f821ead754933663dca55
F test/json102.test 24f6f204f9cde45b971016691d0b92a9b4c58040d699e36d6b12cb165f9083ff
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
@@ -1265,7 +1306,7 @@ F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7
F test/like.test 5fe0bc37f307aef0a453ce2de4632bdfc0759448f0421c39f6d53caefe905fac
F test/like.test 242ee7f5d08a031144c0daf63bbd7e7710c847ccf387a83347e0b61b3aa69526
F test/like2.test d3be15fefee3e02fc88942a9b98f26c5339bbdef7783c90023c092c4955fe3d3
F test/like3.test a76e5938fadbe6d32807284c796bafd869974a961057bc5fc5a28e06de98745c
F test/limit.test 350f5d03c29e7dff9a2cde016f84f8d368d40bcd02fa2b2a52fa10c4bf3cbfaf
@@ -1390,7 +1431,7 @@ F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/pendingrace.test cbdf0f74bc939fb43cebad64dda7a0b5a3941a10b7e9cc2b596ff3e423a18156
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test afbe9e54e88b93bb9b9b55d078d6c826de33a48b784258ba74d9549d2eb000a1
F test/permutations.test f46a1b5a8f1c81b7e3054f59a8354d8d7af3ca1827a347d4a9865440fc8c47b9
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test 57a36226218c03cfb381019fe43234b2cefbd8a1f12825514f906a17ccf7991e
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
@@ -1419,7 +1460,7 @@ F test/recover.test fd5199f928757cb308661b5fdca1abc19398a798ff7f24b57c3071e9f8e0
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
F test/releasetest_data.tcl c8cf85aeb313a771e18dae01396f5ca70e85d4574df681990629b1103f185afe
F test/releasetest_data.tcl 80ef3941bf7ad136f4dc3d8960786f10a4f488797238171bdd757cc6eb4c3efa
F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/returning1.test db532cde29d6aebbc48c6ddc3149b30476f8e69ca7a2c4b53986c7635e6fd8ec
@@ -1523,7 +1564,7 @@ F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a3
F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
F test/sort.test f86751134159abb5e5fd4381a0d7038c91013638cd1e3fa1d7850901f6df6196
F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0
F test/sort2.test 2f8c66402a03adebe77ce7aafca129fbf32df27d6c9b8f7a9f1b958e39f56da8
F test/sort3.test 1480ed7c4c157682542224e05e3b75faf4a149e5
F test/sort4.test cca6f4b0b5255882645bbbe346a6a9f4a5c7b6a18513a6a7bf4ac1c4761ddc19
F test/sort5.test 6b43ae0e2169b5ceed441844492e55ba7f1ae0790528395ddf7888ab3094525d
@@ -1582,8 +1623,8 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl e6b9adcf4e56aa5c658501c10650646fee467b85d51a4ac80263d2cdae3993ba
F test/testrunner.tcl 59490f189cac99b16b0376d0cc0a7ecfb753a84b89c9f4c361af337d88db53ac
F test/testrunner_data.tcl 8169c68654ac8906833b8a6aadca973358a441ebf88270dd05c153e5f96f76b8
F test/testrunner.tcl 56a744d4e6e516b2091c2ca6b7b27b9600e9ded136a2c860c350515511ebe20a
F test/testrunner_data.tcl 8afa4eeec7f7421db3d3af64cdd5544015e887c4289cf871a730cca5a7a8d934
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1800,7 +1841,7 @@ F test/upfrom2.test 66f3ebf721b3cebd922faee5c386bf244f816d416b57c000753ff51af623
F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
F test/upfrom4.test 78f742a6577c91a7a55c64edb8811004e7c6aa99b8d57b2320f70a918c357807
F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
F test/upsert1.test b0ae2f58680c5205b4bc1cdeed3c3d444057c506f6c44494fa3eac60731d68a2
F test/upsert1.test a512e2f884d3a36159fce2e45108c236f78ae38e35bda55f4050db580ceb25d3
F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
@@ -2052,7 +2093,7 @@ F tool/sqldiff.c 2a693b4e7c1818c23f871f82f0c3fe67d80b67e3f087893089d33da29c1e387
F tool/sqlite3_analyzer.c.in f88615bf33098945e0a42f17733f472083d150b58bdaaa5555a7129d0a51621c
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F tool/src-verify.c f0cef434a8d8629c4928a02a644fb85e33c8b875a7f2352ba68cc50965a7d213
F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/stripccomments.c 20b8aabc4694d0d4af5566e42da1f1a03aff057689370326e9269a9ddcffdc37
@@ -2088,8 +2129,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 331f2f3e5db9b6139be984f1b959cd0d51563adaa68452aa2f42741c69bc6319
R 8cf5124efb077972dc4592e59c017049
P d3d77e35ea39df9e22032a7e1af5b7f38d53a4d43bc46afe36e342cdcfd17528 135bf72c6b5f436b11463dd40b3a73bcc610bf9c2dcbe6646dbedd0d9325f6a9
R b7d659f9bcf8ba358058d0baa617e913
U dan
Z 86179e20e1202dcde51614a70e1512c5
Z 380a55b5d6a3d9fc5af4f4bcbddcaf42
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
d3d77e35ea39df9e22032a7e1af5b7f38d53a4d43bc46afe36e342cdcfd17528
4d8df0c426b8ce3db6cfb71e23f752026ef886b9bb833dc4be9717db9955b1db

161
sqlite3.1
View File

@@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH SQLITE3 1 "Fri Oct 31 10:41:31 EDT 2014"
.TH SQLITE3 1 "Fri Aug 11 23:50:12 CET 2023"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@@ -49,9 +49,9 @@ a table named "memos" and insert a couple of records into that table:
$
.B sqlite3 mydata.db
.br
SQLite version 3.8.8
SQLite version 3.43.0 2023-08-11 17:45:23
.br
Enter ".help" for instructions
Enter ".help" for usage hints.
.br
sqlite>
.B create table memos(text, priority INTEGER);
@@ -108,141 +108,13 @@ sqlite>
.B .help
.nf
.tr %.
%backup ?DB? FILE Backup DB (default "main") to FILE
%bail on|off Stop after hitting an error. Default OFF
%clone NEWDB Clone data into NEWDB from the existing database
%databases List names and files of attached databases
%dump ?TABLE? ... Dump the database in an SQL text format
If TABLE specified, only dump tables matching
LIKE pattern TABLE.
%echo on|off Turn command echo on or off
%eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN
%exit Exit this program
%explain ?on|off? Turn output mode suitable for EXPLAIN on or off.
With no args, it turns EXPLAIN on.
%fullschema Show schema and the content of sqlite_stat tables
%headers on|off Turn display of headers on or off
%help Show this message
%import FILE TABLE Import data from FILE into TABLE
%indices ?TABLE? Show names of all indices
If TABLE specified, only show indices for tables
matching LIKE pattern TABLE.
%load FILE ?ENTRY? Load an extension library
%log FILE|off Turn logging on or off. FILE can be stderr/stdout
%mode MODE ?TABLE? Set output mode where MODE is one of:
csv Comma-separated values
column Left-aligned columns. (See .width)
html HTML <table> code
insert SQL insert statements for TABLE
line One value per line
list Values delimited by .separator string
tabs Tab-separated values
tcl TCL list elements
%nullvalue STRING Use STRING in place of NULL values
%once FILENAME Output for the next SQL command only to FILENAME
%open ?FILENAME? Close existing database and reopen FILENAME
%output ?FILENAME? Send output to FILENAME or stdout
%print STRING... Print literal STRING
%prompt MAIN CONTINUE Replace the standard prompts
%quit Exit this program
%read FILENAME Execute SQL in FILENAME
%restore ?DB? FILE Restore content of DB (default "main") from FILE
%save FILE Write in-memory database into FILE
%schema ?TABLE? Show the CREATE statements
If TABLE specified, only show tables matching
LIKE pattern TABLE.
%separator STRING ?NL? Change separator used by output mode and .import
NL is the end-of-line mark for CSV
%shell CMD ARGS... Run CMD ARGS... in a system shell
%show Show the current values for various settings
%stats on|off Turn stats on or off
%system CMD ARGS... Run CMD ARGS... in a system shell
%tables ?TABLE? List names of tables
If TABLE specified, only list tables matching
LIKE pattern TABLE.
%timeout MS Try opening locked tables for MS milliseconds
%timer on|off Turn SQL timer on or off
%trace FILE|off Output each SQL statement as it is run
%vfsname ?AUX? Print the name of the VFS stack
%width NUM1 NUM2 ... Set column widths for "column" mode
Negative values right-justify
sqlite>
...
.sp
.fi
.SH OPTIONS
.B sqlite3
has the following options:
.TP
.B \-bail
Stop after hitting an error.
.TP
.B \-batch
Force batch I/O.
.TP
.B \-column
Query results will be displayed in a table like form, using
whitespace characters to separate the columns and align the
output.
.TP
.BI \-cmd\ command
run
.I command
before reading stdin
.TP
.B \-csv
Set output mode to CSV (comma separated values).
.TP
.B \-echo
Print commands before execution.
.TP
.BI \-init\ file
Read and execute commands from
.I file
, which can contain a mix of SQL statements and meta-commands.
.TP
.B \-[no]header
Turn headers on or off.
.TP
.B \-help
Show help on options and exit.
.TP
.B \-html
Query results will be output as simple HTML tables.
.TP
.B \-interactive
Force interactive I/O.
.TP
.B \-line
Query results will be displayed with one value per line, rows
separated by a blank line. Designed to be easily parsed by
scripts or other programs
.TP
.B \-list
Query results will be displayed with the separator (|, by default)
character between each field value. The default.
.TP
.BI \-mmap\ N
Set default mmap size to
.I N
\.
.TP
.BI \-nullvalue\ string
Set string used to represent NULL values. Default is ''
(empty string).
.TP
.BI \-separator\ separator
Set output field separator. Default is '|'.
.TP
.B \-stats
Print memory stats before each finalize.
.TP
.B \-version
Show SQLite version.
.TP
.BI \-vfs\ name
Use
.I name
as the default VFS.
The available commands differ by version and build options, so they
are not listed here. Please refer to your local copy for all available
options.
.SH INIT FILE
@@ -265,22 +137,25 @@ continue prompt = " ...> "
.sp
.fi
o If the file
o If the file
.B ${XDG_CONFIG_HOME}/sqlite3/sqliterc
or
.B ~/.sqliterc
exists, it is processed first.
can be found in the user's home directory, it is
read and processed. It should generally only contain meta-commands.
exists, the first of those to be found is processed during startup.
It should generally only contain meta-commands.
o If the -init option is present, the specified file is processed.
o All other command line options are processed.
.SH SEE ALSO
http://www.sqlite.org/cli.html
https://sqlite.org/cli.html
.br
https://sqlite.org/fiddle (a WebAssembly build of the CLI app)
.br
The sqlite3-doc package.
.SH AUTHOR
This manual page was originally written by Andreas Rottmann
<rotty@debian.org>, for the Debian GNU/Linux system (but may be used
by others). It was subsequently revised by Bill Bumgarner <bbum@mac.com> and
further updated by Laszlo Boszormenyi <gcs@debian.hu> .
by others). It was subsequently revised by Bill Bumgarner <bbum@mac.com>,
Laszlo Boszormenyi <gcs@debian.hu>, and the sqlite3 developers.

View File

@@ -2156,8 +2156,10 @@ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){
** sensitive.
*/
void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
FuncDef *pDef;
struct compareInfo *pInfo;
int flags;
int nArg;
if( caseSensitive ){
pInfo = (struct compareInfo*)&likeInfoAlt;
flags = SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE;
@@ -2165,10 +2167,13 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
pInfo = (struct compareInfo*)&likeInfoNorm;
flags = SQLITE_FUNC_LIKE;
}
sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0);
sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0);
sqlite3FindFunction(db, "like", 2, SQLITE_UTF8, 0)->funcFlags |= flags;
sqlite3FindFunction(db, "like", 3, SQLITE_UTF8, 0)->funcFlags |= flags;
for(nArg=2; nArg<=3; nArg++){
sqlite3CreateFunc(db, "like", nArg, SQLITE_UTF8, pInfo, likeFunc,
0, 0, 0, 0, 0);
pDef = sqlite3FindFunction(db, "like", nArg, SQLITE_UTF8, 0);
pDef->funcFlags |= flags;
pDef->funcFlags &= ~SQLITE_FUNC_UNSAFE;
}
}
/*

View File

@@ -512,7 +512,9 @@ static const sqlite3_api_routines sqlite3Apis = {
/* Version 3.40.0 and later */
sqlite3_value_encoding,
/* Version 3.41.0 and later */
sqlite3_is_interrupted
sqlite3_is_interrupted,
/* Version 3.43.0 and later */
sqlite3_stmt_explain
};
/* True if x is the directory separator character

View File

@@ -4747,6 +4747,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
size_t i, j;
DWORD pid;
int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX);
int nMax, nBuf, nDir, nLen;
char *zBuf;
@@ -4959,7 +4960,10 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
j = sqlite3Strlen30(zBuf);
sqlite3_randomness(15, &zBuf[j]);
pid = osGetCurrentProcessId();
for(i=0; i<15; i++, j++){
zBuf[j] += pid & 0xff;
pid >>= 8;
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;

View File

@@ -274,7 +274,7 @@ int sqlite3PagerWalInfo(Pager*, u32 *pnPrior, u32 *pnFrame);
# define enable_simulated_io_errors()
#endif
#ifdef SQLITE_USE_SEH
#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
int sqlite3PagerWalSystemErrno(Pager*);
#endif

View File

@@ -4799,7 +4799,6 @@ static const char *(azHelp[]) = {
" --async Write to FILE without journal and fsync()",
#endif
".bail on|off Stop after hitting an error. Default OFF",
".binary on|off Turn binary output on or off. Default OFF",
#ifndef SQLITE_SHELL_FIDDLE
".cd DIRECTORY Change the working directory to DIRECTORY",
#endif
@@ -4809,6 +4808,9 @@ static const char *(azHelp[]) = {
".clone NEWDB Clone data into NEWDB from the existing database",
#endif
".connection [close] [#] Open or close an auxiliary database connection",
#if defined(_WIN32) || defined(WIN32)
".crnl on|off Translate \\n to \\r\\n. Default ON",
#endif
".databases List names and files of attached databases",
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
#if SQLITE_SHELL_HAVE_RECOVER
@@ -8164,6 +8166,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
/* Undocumented. Legacy only. See "crnl" below */
if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
if( nArg==2 ){
if( booleanValue(azArg[1]) ){
@@ -8172,6 +8175,8 @@ static int do_meta_command(char *zLine, ShellState *p){
setTextMode(p->out, 1);
}
}else{
raw_printf(stderr, "The \".binary\" command is deprecated."
" Use \".crnl\" instead.\n");
raw_printf(stderr, "Usage: .binary on|off\n");
rc = 1;
}
@@ -8299,6 +8304,22 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='c' && n==4 && cli_strncmp(azArg[0], "crnl", n)==0 ){
if( nArg==2 ){
if( booleanValue(azArg[1]) ){
setTextMode(p->out, 1);
}else{
setBinaryMode(p->out, 1);
}
}else{
#if !defined(_WIN32) && !defined(WIN32)
raw_printf(stderr, "The \".crnl\" is a no-op on non-Windows machines.\n");
#endif
raw_printf(stderr, "Usage: .crnl on|off\n");
rc = 1;
}
}else
if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
char **azName = 0;
int nName = 0;
@@ -11283,6 +11304,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif /* SQLITE_USER_AUTHENTICATION */
if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
char *zPtrSz = sizeof(void*)==8 ? "64-bit" : "32-bit";
utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
sqlite3_libversion(), sqlite3_sourceid());
#if SQLITE_HAVE_ZLIB
@@ -11293,11 +11315,11 @@ static int do_meta_command(char *zLine, ShellState *p){
#if defined(__clang__) && defined(__clang_major__)
utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
CTIMEOPT_VAL(__clang_minor__) "."
CTIMEOPT_VAL(__clang_patchlevel__) "\n");
CTIMEOPT_VAL(__clang_patchlevel__) " (%s)\n", zPtrSz);
#elif defined(_MSC_VER)
utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz);
#elif defined(__GNUC__) && defined(__VERSION__)
utf8_printf(p->out, "gcc-" __VERSION__ "\n");
utf8_printf(p->out, "gcc-" __VERSION__ " (%s)\n", zPtrSz);
#endif
}else
@@ -12471,7 +12493,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
}else if( cli_strcmp(z,"-bail")==0 ){
/* No-op. The bail_on_error flag should already be set. */
}else if( cli_strcmp(z,"-version")==0 ){
printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
printf("%s %s (%d-bit)\n", sqlite3_libversion(), sqlite3_sourceid(),
8*(int)sizeof(char*));
return 0;
}else if( cli_strcmp(z,"-interactive")==0 ){
stdin_is_interactive = 1;

View File

@@ -361,6 +361,8 @@ struct sqlite3_api_routines {
int (*value_encoding)(sqlite3_value*);
/* Version 3.41.0 and later */
int (*is_interrupted)(sqlite3*);
/* Version 3.43.0 and later */
int (*stmt_explain)(sqlite3_stmt*,int);
};
/*
@@ -689,6 +691,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_value_encoding sqlite3_api->value_encoding
/* Version 3.41.0 and later */
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
/* Version 3.43.0 and later */
#define sqlite3_stmt_explain sqlite3_api->stmt_explain
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)

View File

@@ -608,7 +608,7 @@ static int faultSimCallback(int x){
zInt[i] = (x%10) + '0';
}
if( isNeg ) zInt[i--] = '-';
memcpy(faultSimScript+faultSimScriptSize, zInt+i+1, sizeof(zInt)-i);
memcpy(faultSimScript+faultSimScriptSize, zInt+i+1, sizeof(zInt)-i-1);
}
rc = Tcl_Eval(faultSimInterp, faultSimScript);
if( rc ){

View File

@@ -1270,9 +1270,9 @@ static void updateVirtualTable(
sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0)
);
}else{
Expr *pRow = exprRowColumn(pParse, i);
if( pRow ) pRow->op2 = OPFLAG_NOCHNG;
pList = sqlite3ExprListAppend(pParse, pList, pRow);
Expr *pRowExpr = exprRowColumn(pParse, i);
if( pRowExpr ) pRowExpr->op2 = OPFLAG_NOCHNG;
pList = sqlite3ExprListAppend(pParse, pList, pRowExpr);
}
}

View File

@@ -178,7 +178,7 @@ int sqlite3UpsertAnalyzeTarget(
pExpr = &sCol[0];
}
for(jj=0; jj<nn; jj++){
if( sqlite3ExprCompare(pParse,pTarget->a[jj].pExpr,pExpr,iCursor)<2 ){
if( sqlite3ExprCompare(0,pTarget->a[jj].pExpr,pExpr,iCursor)<2 ){
break; /* Column ii of the index matches column jj of target */
}
}

View File

@@ -610,7 +610,11 @@ do_atof_calc:
}
assert( r>=0.0 );
if( r>+1.7976931348623157081452742373e+308L ){
#ifdef INFINITY
*pResult = +INFINITY;
#else
*pResult = 1.0e308*10.0;
#endif
}else{
*pResult = (double)r;
}
@@ -1016,7 +1020,7 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
** The error terms on constants like 1.0e+100 computed using the
** decimal extension, for example as follows:
**
** SELECT decimal_sci(decimal_sub('1.0e+100',decimal(1.0e+100)));
** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
*/
double rr[2];
rr[0] = r;

View File

@@ -1864,7 +1864,7 @@ int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode){
Vdbe *v = (Vdbe*)pStmt;
int rc;
sqlite3_mutex_enter(v->db->mutex);
if( v->explain==eMode ){
if( ((int)v->explain)==eMode ){
rc = SQLITE_OK;
}else if( eMode<0 || eMode>2 ){
rc = SQLITE_ERROR;

View File

@@ -795,6 +795,8 @@ struct Wal {
#ifdef SQLITE_USE_SEH
u32 lockMask; /* Mask of locks held */
void *pFree; /* Pointer to sqlite3_free() if exception thrown */
u32 *pWiValue; /* Value to write into apWiData[iWiPg] */
int iWiPg; /* Write pWiValue into apWiData[iWiPg] */
int iSysErrno; /* System error code following exception */
#endif
#ifdef SQLITE_DEBUG
@@ -969,11 +971,24 @@ static void sehInjectFault(Wal *pWal){
#define SEH_FREE_ON_ERROR(X,Y) \
assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y
/*
** There are two ways to use this macro. To arrange for pWal->apWiData[iPg]
** to be set to pValue if an exception is thrown:
**
** SEH_SET_ON_ERROR(iPg, pValue);
**
** and to cancel the same:
**
** SEH_SET_ON_ERROR(0, 0);
*/
#define SEH_SET_ON_ERROR(X,Y) pWal->iWiPg = X; pWal->pWiValue = Y
#else
# define SEH_TRY VVA_ONLY(pWal->nSehTry++);
# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 );
# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 );
# define SEH_FREE_ON_ERROR(X,Y)
# define SEH_SET_ON_ERROR(X,Y)
#endif /* ifdef SQLITE_USE_SEH */
/*
@@ -1782,6 +1797,7 @@ static int walIndexRecoverOne(Wal *pWal, int iWal, u32 *pnCkpt, int *pbZero){
rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
assert( aShare!=0 || rc!=SQLITE_OK );
if( aShare==0 ) break;
SEH_SET_ON_ERROR(iPg, aShare);
pWal->apWiData[iPg] = aPrivate;
if( iWal ){
@@ -1820,6 +1836,7 @@ static int walIndexRecoverOne(Wal *pWal, int iWal, u32 *pnCkpt, int *pbZero){
}
}
pWal->apWiData[iPg] = aShare;
SEH_SET_ON_ERROR(0, 0);
nHdr = (iPg==0 ? WALINDEX_HDR_SIZE : 0);
nHdr32 = nHdr / sizeof(u32);
#ifndef SQLITE_SAFER_WALINDEX_RECOVERY
@@ -3001,7 +3018,9 @@ static void walLimitSize(Wal *pWal, i64 nMax){
**
** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free().
**
** 3) Returns SQLITE_IOERR.
** 3) Set pWal->apWiData[pWal->iWiPg] to pWal->pWiValue if not NULL
**
** 4) Returns SQLITE_IOERR.
*/
static int walHandleException(Wal *pWal){
if( pWal->exclusiveMode==0 ){
@@ -3020,6 +3039,10 @@ static int walHandleException(Wal *pWal){
}
sqlite3_free(pWal->pFree);
pWal->pFree = 0;
if( pWal->pWiValue ){
pWal->apWiData[pWal->iWiPg] = pWal->pWiValue;
pWal->pWiValue = 0;
}
return SQLITE_IOERR_IN_PAGE;
}
@@ -3834,7 +3857,8 @@ static int walSnapshotRecover(
rc = walHashGet(pWal, walFramePage(i), &sLoc);
if( rc!=SQLITE_OK ) break;
pgno = sLoc.aPgno[i-sLoc.iZero];
assert( i - sLoc.iZero - 1 >=0 );
pgno = sLoc.aPgno[i-sLoc.iZero-1];
iDbOff = (i64)(pgno-1) * szPage;
if( iDbOff+szPage<=szDb ){

View File

@@ -46,6 +46,7 @@
# define sqlite3WalFindFrame(x,y,z) 0
# define sqlite3WalFile(x) 0
# define sqlite3WalJournalMode(x) 0
# undef SQLITE_USE_SEH
#else
#define WAL_SAVEPOINT_NDATA 4

View File

@@ -49,7 +49,7 @@ do_execsql_test 1080 {
SELECT decimal('+123e+4');
} {1230000}
do_execsql_test 1081 {
SELECT decimal_sci('+123e+4');
SELECT decimal_exp('+123e+4');
} {+1.23e+06}

View File

@@ -1205,10 +1205,12 @@ int runCombinedDbSqlInput(
iSql = decodeDatabase((unsigned char*)aData, (int)nByte, &aDb, &nDb);
if( iSql<0 ) return 0;
if( nDb>=75 ){
dbFlags = (aDb[72]<<24) + (aDb[73]<<16) + (aDb[74]<<8) + aDb[75];
dbFlags = ((unsigned int)aDb[72]<<24) + ((unsigned int)aDb[73]<<16) +
((unsigned int)aDb[74]<<8) + (unsigned int)aDb[75];
}
if( nDb>=79 ){
dbOpt = (aDb[76]<<24) + (aDb[77]<<16) + (aDb[78]<<8) + aDb[79];
dbOpt = ((unsigned int)aDb[76]<<24) + ((unsigned int)aDb[77]<<16) +
((unsigned int)aDb[78]<<8) + (unsigned int)aDb[79];
}
nSql = (int)(nByte - iSql);
if( bScript ){
@@ -2031,7 +2033,9 @@ int main(int argc, char **argv){
if( strcmp(z,"version")==0 ){
int ii;
const char *zz;
printf("SQLite %s %s\n", sqlite3_libversion(), sqlite3_sourceid());
printf("SQLite %s %s (%d-bit)\n",
sqlite3_libversion(), sqlite3_sourceid(),
8*(int)sizeof(char*));
for(ii=0; (zz = sqlite3_compileoption_get(ii))!=0; ii++){
printf("%s\n", zz);
}
@@ -2536,9 +2540,10 @@ int main(int argc, char **argv){
printf("fuzzcheck: %u query invariants checked\n", g.nInvariant);
}
printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\n"
"SQLite %s %s\n",
"SQLite %s %s (%d-bit)\n",
nTest, (int)(iElapse/1000), (int)(iElapse%1000),
sqlite3_libversion(), sqlite3_sourceid());
sqlite3_libversion(), sqlite3_sourceid(),
8*(int)sizeof(char*));
}
free(azSrcDb);
free(pHeap);

View File

@@ -122,14 +122,14 @@ do_execsql_test json101-4.8 {
# json_extract(JSON,'$') will return objects and arrays without change.
#
do_execsql_test json-4.10 {
do_execsql_test json101-4.10 {
SELECT count(*) FROM j1 WHERE json_type(x) IN ('object','array');
SELECT x FROM j1
WHERE json_extract(x,'$')<>x
AND json_type(x) IN ('object','array');
} {4}
do_execsql_test json-5.1 {
do_execsql_test json101-5.1 {
CREATE TABLE j2(id INTEGER PRIMARY KEY, json, src);
INSERT INTO j2(id,json,src)
VALUES(1,'{
@@ -257,7 +257,7 @@ do_execsql_test json-5.1 {
SELECT count(*) FROM j2;
} {3}
do_execsql_test json-5.2 {
do_execsql_test json101-5.2 {
SELECT id, json_valid(json), json_type(json), '|' FROM j2 ORDER BY id;
} {1 1 object | 2 1 object | 3 1 array |}
@@ -268,13 +268,13 @@ ifcapable !vtab {
# fullkey is always the same as path+key (with appropriate formatting)
#
do_execsql_test json-5.3 {
do_execsql_test json101-5.3 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_tree(j2.json) AS jx
WHERE fullkey!=(path || CASE WHEN typeof(key)=='integer' THEN '['||key||']'
ELSE '.'||key END);
} {}
do_execsql_test json-5.4 {
do_execsql_test json101-5.4 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_each(j2.json) AS jx
WHERE fullkey!=(path || CASE WHEN typeof(key)=='integer' THEN '['||key||']'
@@ -285,58 +285,58 @@ do_execsql_test json-5.4 {
# Verify that the json_each.json and json_tree.json output is always the
# same as input.
#
do_execsql_test json-5.5 {
do_execsql_test json101-5.5 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_each(j2.json) AS jx
WHERE jx.json<>j2.json;
} {}
do_execsql_test json-5.6 {
do_execsql_test json101-5.6 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_tree(j2.json) AS jx
WHERE jx.json<>j2.json;
} {}
do_execsql_test json-5.7 {
do_execsql_test json101-5.7 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_each(j2.json) AS jx
WHERE jx.value<>jx.atom AND type NOT IN ('array','object');
} {}
do_execsql_test json-5.8 {
do_execsql_test json101-5.8 {
SELECT j2.rowid, jx.rowid, fullkey, path, key
FROM j2, json_tree(j2.json) AS jx
WHERE jx.value<>jx.atom AND type NOT IN ('array','object');
} {}
do_execsql_test json-6.1 {
do_execsql_test json101-6.1 {
SELECT json_valid('{"a":55,"b":72,}');
} {0}
do_execsql_test json-6.2 {
do_execsql_test json101-6.2 {
SELECT json_error_position('{"a":55,"b":72,}');
} {0}
do_execsql_test json-6.3 {
do_execsql_test json101-6.3 {
SELECT json_valid(json('{"a":55,"b":72,}'));
} {1}
do_execsql_test json-6.4 {
do_execsql_test json101-6.4 {
SELECT json_valid('{"a":55,"b":72 , }');
} {0}
do_execsql_test json-6.5 {
do_execsql_test json101-6.5 {
SELECT json_error_position('{"a":55,"b":72 , }');
} {0}
do_execsql_test json-6.6 {
do_execsql_test json101-6.6 {
SELECT json_error_position('{"a":55,"b":72,,}');
} {16}
do_execsql_test json-6.7 {
do_execsql_test json101-6.7 {
SELECT json_valid('{"a":55,"b":72}');
} {1}
do_execsql_test json-6.8 {
do_execsql_test json101-6.8 {
SELECT json_error_position('["a",55,"b",72,]');
} {0}
do_execsql_test json-6.9 {
do_execsql_test json101-6.9 {
SELECT json_error_position('["a",55,"b",72 , ]');
} {0}
do_execsql_test json-6.10 {
do_execsql_test json101-6.10 {
SELECT json_error_position('["a",55,"b",72,,]');
} {16}
do_execsql_test json-6.11 {
do_execsql_test json101-6.11 {
SELECT json_valid('["a",55,"b",72]');
} {1}
@@ -352,7 +352,7 @@ foreach {tn isvalid ws} {
7.6 1 char(0x20,0x09,0x0a,0x0d,0x20)
7.7 0 char(0x20,0x09,0x0a,0x0c,0x0d,0x20)
} {
do_execsql_test json-$tn.1 \
do_execsql_test json101-$tn.1 \
"SELECT json_valid(printf('%s{%s\"x\"%s:%s9%s}%s',
$::ws,$::ws,$::ws,$::ws,$::ws,$::ws));" \
$isvalid
@@ -361,23 +361,23 @@ foreach {tn isvalid ws} {
# Ticket https://www.sqlite.org/src/info/ad2559db380abf8e
# Control characters must be escaped in JSON strings.
#
do_execsql_test json-8.1 {
do_execsql_test json101-8.1 {
DROP TABLE IF EXISTS t8;
CREATE TABLE t8(a,b);
INSERT INTO t8(a) VALUES('abc' || char(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) || 'xyz');
UPDATE t8 SET b=json_array(a);
SELECT b FROM t8;
} {{["abc\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#xyz"]}}
do_execsql_test json-8.2 {
do_execsql_test json101-8.2 {
SELECT a=json_extract(b,'$[0]') FROM t8;
} {1}
# 2017-04-12. Regression reported on the mailing list by Rolf Ade
#
do_execsql_test json-8.3 {
do_execsql_test json101-8.3 {
SELECT json_valid(char(0x22,0xe4,0x22));
} {1}
do_execsql_test json-8.4 {
do_execsql_test json101-8.4 {
SELECT unicode(json_extract(char(0x22,228,0x22),'$'));
} {228}
@@ -385,331 +385,331 @@ do_execsql_test json-8.4 {
# String values are quoted and interior quotes are escaped. NULL values
# are rendered as the unquoted string "null".
#
do_execsql_test json-9.1 {
do_execsql_test json101-9.1 {
SELECT json_quote('abc"xyz');
} {{"abc\"xyz"}}
do_execsql_test json-9.2 {
do_execsql_test json101-9.2 {
SELECT json_quote(3.14159);
} {3.14159}
do_execsql_test json-9.3 {
do_execsql_test json101-9.3 {
SELECT json_quote(12345);
} {12345}
do_execsql_test json-9.4 {
do_execsql_test json101-9.4 {
SELECT json_quote(null);
} {"null"}
do_catchsql_test json-9.5 {
do_catchsql_test json101-9.5 {
SELECT json_quote(x'30313233');
} {1 {JSON cannot hold BLOB values}}
do_catchsql_test json-9.6 {
do_catchsql_test json101-9.6 {
SELECT json_quote(123,456)
} {1 {wrong number of arguments to function json_quote()}}
do_catchsql_test json-9.7 {
do_catchsql_test json101-9.7 {
SELECT json_quote()
} {1 {wrong number of arguments to function json_quote()}}
# Make sure only valid backslash-escapes are accepted.
#
do_execsql_test json-10.1 {
do_execsql_test json101-10.1 {
SELECT json_valid('" \ "');
} {0}
do_execsql_test json-10.2 {
do_execsql_test json101-10.2 {
SELECT json_valid('" \! "');
} {0}
do_execsql_test json-10.3 {
do_execsql_test json101-10.3 {
SELECT json_valid('" \" "');
} {1}
do_execsql_test json-10.4 {
do_execsql_test json101-10.4 {
SELECT json_valid('" \# "');
} {0}
do_execsql_test json-10.5 {
do_execsql_test json101-10.5 {
SELECT json_valid('" \$ "');
} {0}
do_execsql_test json-10.6 {
do_execsql_test json101-10.6 {
SELECT json_valid('" \% "');
} {0}
do_execsql_test json-10.7 {
do_execsql_test json101-10.7 {
SELECT json_valid('" \& "');
} {0}
do_execsql_test json-10.8 {
do_execsql_test json101-10.8 {
SELECT json_valid('" \'' "');
} {0}
do_execsql_test json-10.9 {
do_execsql_test json101-10.9 {
SELECT json_valid('" \( "');
} {0}
do_execsql_test json-10.10 {
do_execsql_test json101-10.10 {
SELECT json_valid('" \) "');
} {0}
do_execsql_test json-10.11 {
do_execsql_test json101-10.11 {
SELECT json_valid('" \* "');
} {0}
do_execsql_test json-10.12 {
do_execsql_test json101-10.12 {
SELECT json_valid('" \+ "');
} {0}
do_execsql_test json-10.13 {
do_execsql_test json101-10.13 {
SELECT json_valid('" \, "');
} {0}
do_execsql_test json-10.14 {
do_execsql_test json101-10.14 {
SELECT json_valid('" \- "');
} {0}
do_execsql_test json-10.15 {
do_execsql_test json101-10.15 {
SELECT json_valid('" \. "');
} {0}
do_execsql_test json-10.16 {
do_execsql_test json101-10.16 {
SELECT json_valid('" \/ "');
} {1}
do_execsql_test json-10.17 {
do_execsql_test json101-10.17 {
SELECT json_valid('" \0 "');
} {0}
do_execsql_test json-10.18 {
do_execsql_test json101-10.18 {
SELECT json_valid('" \1 "');
} {0}
do_execsql_test json-10.19 {
do_execsql_test json101-10.19 {
SELECT json_valid('" \2 "');
} {0}
do_execsql_test json-10.20 {
do_execsql_test json101-10.20 {
SELECT json_valid('" \3 "');
} {0}
do_execsql_test json-10.21 {
do_execsql_test json101-10.21 {
SELECT json_valid('" \4 "');
} {0}
do_execsql_test json-10.22 {
do_execsql_test json101-10.22 {
SELECT json_valid('" \5 "');
} {0}
do_execsql_test json-10.23 {
do_execsql_test json101-10.23 {
SELECT json_valid('" \6 "');
} {0}
do_execsql_test json-10.24 {
do_execsql_test json101-10.24 {
SELECT json_valid('" \7 "');
} {0}
do_execsql_test json-10.25 {
do_execsql_test json101-10.25 {
SELECT json_valid('" \8 "');
} {0}
do_execsql_test json-10.26 {
do_execsql_test json101-10.26 {
SELECT json_valid('" \9 "');
} {0}
do_execsql_test json-10.27 {
do_execsql_test json101-10.27 {
SELECT json_valid('" \: "');
} {0}
do_execsql_test json-10.28 {
do_execsql_test json101-10.28 {
SELECT json_valid('" \; "');
} {0}
do_execsql_test json-10.29 {
do_execsql_test json101-10.29 {
SELECT json_valid('" \< "');
} {0}
do_execsql_test json-10.30 {
do_execsql_test json101-10.30 {
SELECT json_valid('" \= "');
} {0}
do_execsql_test json-10.31 {
do_execsql_test json101-10.31 {
SELECT json_valid('" \> "');
} {0}
do_execsql_test json-10.32 {
do_execsql_test json101-10.32 {
SELECT json_valid('" \? "');
} {0}
do_execsql_test json-10.33 {
do_execsql_test json101-10.33 {
SELECT json_valid('" \@ "');
} {0}
do_execsql_test json-10.34 {
do_execsql_test json101-10.34 {
SELECT json_valid('" \A "');
} {0}
do_execsql_test json-10.35 {
do_execsql_test json101-10.35 {
SELECT json_valid('" \B "');
} {0}
do_execsql_test json-10.36 {
do_execsql_test json101-10.36 {
SELECT json_valid('" \C "');
} {0}
do_execsql_test json-10.37 {
do_execsql_test json101-10.37 {
SELECT json_valid('" \D "');
} {0}
do_execsql_test json-10.38 {
do_execsql_test json101-10.38 {
SELECT json_valid('" \E "');
} {0}
do_execsql_test json-10.39 {
do_execsql_test json101-10.39 {
SELECT json_valid('" \F "');
} {0}
do_execsql_test json-10.40 {
do_execsql_test json101-10.40 {
SELECT json_valid('" \G "');
} {0}
do_execsql_test json-10.41 {
do_execsql_test json101-10.41 {
SELECT json_valid('" \H "');
} {0}
do_execsql_test json-10.42 {
do_execsql_test json101-10.42 {
SELECT json_valid('" \I "');
} {0}
do_execsql_test json-10.43 {
do_execsql_test json101-10.43 {
SELECT json_valid('" \J "');
} {0}
do_execsql_test json-10.44 {
do_execsql_test json101-10.44 {
SELECT json_valid('" \K "');
} {0}
do_execsql_test json-10.45 {
do_execsql_test json101-10.45 {
SELECT json_valid('" \L "');
} {0}
do_execsql_test json-10.46 {
do_execsql_test json101-10.46 {
SELECT json_valid('" \M "');
} {0}
do_execsql_test json-10.47 {
do_execsql_test json101-10.47 {
SELECT json_valid('" \N "');
} {0}
do_execsql_test json-10.48 {
do_execsql_test json101-10.48 {
SELECT json_valid('" \O "');
} {0}
do_execsql_test json-10.49 {
do_execsql_test json101-10.49 {
SELECT json_valid('" \P "');
} {0}
do_execsql_test json-10.50 {
do_execsql_test json101-10.50 {
SELECT json_valid('" \Q "');
} {0}
do_execsql_test json-10.51 {
do_execsql_test json101-10.51 {
SELECT json_valid('" \R "');
} {0}
do_execsql_test json-10.52 {
do_execsql_test json101-10.52 {
SELECT json_valid('" \S "');
} {0}
do_execsql_test json-10.53 {
do_execsql_test json101-10.53 {
SELECT json_valid('" \T "');
} {0}
do_execsql_test json-10.54 {
do_execsql_test json101-10.54 {
SELECT json_valid('" \U "');
} {0}
do_execsql_test json-10.55 {
do_execsql_test json101-10.55 {
SELECT json_valid('" \V "');
} {0}
do_execsql_test json-10.56 {
do_execsql_test json101-10.56 {
SELECT json_valid('" \W "');
} {0}
do_execsql_test json-10.57 {
do_execsql_test json101-10.57 {
SELECT json_valid('" \X "');
} {0}
do_execsql_test json-10.58 {
do_execsql_test json101-10.58 {
SELECT json_valid('" \Y "');
} {0}
do_execsql_test json-10.59 {
do_execsql_test json101-10.59 {
SELECT json_valid('" \Z "');
} {0}
do_execsql_test json-10.60 {
do_execsql_test json101-10.60 {
SELECT json_valid('" \[ "');
} {0}
do_execsql_test json-10.61 {
do_execsql_test json101-10.61 {
SELECT json_valid('" \\ "');
} {1}
do_execsql_test json-10.62 {
do_execsql_test json101-10.62 {
SELECT json_valid('" \] "');
} {0}
do_execsql_test json-10.63 {
do_execsql_test json101-10.63 {
SELECT json_valid('" \^ "');
} {0}
do_execsql_test json-10.64 {
do_execsql_test json101-10.64 {
SELECT json_valid('" \_ "');
} {0}
do_execsql_test json-10.65 {
do_execsql_test json101-10.65 {
SELECT json_valid('" \` "');
} {0}
do_execsql_test json-10.66 {
do_execsql_test json101-10.66 {
SELECT json_valid('" \a "');
} {0}
do_execsql_test json-10.67 {
do_execsql_test json101-10.67 {
SELECT json_valid('" \b "');
} {1}
do_execsql_test json-10.68 {
do_execsql_test json101-10.68 {
SELECT json_valid('" \c "');
} {0}
do_execsql_test json-10.69 {
do_execsql_test json101-10.69 {
SELECT json_valid('" \d "');
} {0}
do_execsql_test json-10.70 {
do_execsql_test json101-10.70 {
SELECT json_valid('" \e "');
} {0}
do_execsql_test json-10.71 {
do_execsql_test json101-10.71 {
SELECT json_valid('" \f "');
} {1}
do_execsql_test json-10.72 {
do_execsql_test json101-10.72 {
SELECT json_valid('" \g "');
} {0}
do_execsql_test json-10.73 {
do_execsql_test json101-10.73 {
SELECT json_valid('" \h "');
} {0}
do_execsql_test json-10.74 {
do_execsql_test json101-10.74 {
SELECT json_valid('" \i "');
} {0}
do_execsql_test json-10.75 {
do_execsql_test json101-10.75 {
SELECT json_valid('" \j "');
} {0}
do_execsql_test json-10.76 {
do_execsql_test json101-10.76 {
SELECT json_valid('" \k "');
} {0}
do_execsql_test json-10.77 {
do_execsql_test json101-10.77 {
SELECT json_valid('" \l "');
} {0}
do_execsql_test json-10.78 {
do_execsql_test json101-10.78 {
SELECT json_valid('" \m "');
} {0}
do_execsql_test json-10.79 {
do_execsql_test json101-10.79 {
SELECT json_valid('" \n "');
} {1}
do_execsql_test json-10.80 {
do_execsql_test json101-10.80 {
SELECT json_valid('" \o "');
} {0}
do_execsql_test json-10.81 {
do_execsql_test json101-10.81 {
SELECT json_valid('" \p "');
} {0}
do_execsql_test json-10.82 {
do_execsql_test json101-10.82 {
SELECT json_valid('" \q "');
} {0}
do_execsql_test json-10.83 {
do_execsql_test json101-10.83 {
SELECT json_valid('" \r "');
} {1}
do_execsql_test json-10.84 {
do_execsql_test json101-10.84 {
SELECT json_valid('" \s "');
} {0}
do_execsql_test json-10.85 {
do_execsql_test json101-10.85 {
SELECT json_valid('" \t "');
} {1}
do_execsql_test json-10.86.0 {
do_execsql_test json101-10.86.0 {
SELECT json_valid('" \u "');
} {0}
do_execsql_test json-10.86.1 {
do_execsql_test json101-10.86.1 {
SELECT json_valid('" \ua "');
} {0}
do_execsql_test json-10.86.2 {
do_execsql_test json101-10.86.2 {
SELECT json_valid('" \uab "');
} {0}
do_execsql_test json-10.86.3 {
do_execsql_test json101-10.86.3 {
SELECT json_valid('" \uabc "');
} {0}
do_execsql_test json-10.86.4 {
do_execsql_test json101-10.86.4 {
SELECT json_valid('" \uabcd "');
} {1}
do_execsql_test json-10.86.5 {
do_execsql_test json101-10.86.5 {
SELECT json_valid('" \uFEDC "');
} {1}
do_execsql_test json-10.86.6 {
do_execsql_test json101-10.86.6 {
SELECT json_valid('" \u1234 "');
} {1}
do_execsql_test json-10.87 {
do_execsql_test json101-10.87 {
SELECT json_valid('" \v "');
} {0}
do_execsql_test json-10.88 {
do_execsql_test json101-10.88 {
SELECT json_valid('" \w "');
} {0}
do_execsql_test json-10.89 {
do_execsql_test json101-10.89 {
SELECT json_valid('" \x "');
} {0}
do_execsql_test json-10.90 {
do_execsql_test json101-10.90 {
SELECT json_valid('" \y "');
} {0}
do_execsql_test json-10.91 {
do_execsql_test json101-10.91 {
SELECT json_valid('" \z "');
} {0}
do_execsql_test json-10.92 {
do_execsql_test json101-10.92 {
SELECT json_valid('" \{ "');
} {0}
do_execsql_test json-10.93 {
do_execsql_test json101-10.93 {
SELECT json_valid('" \| "');
} {0}
do_execsql_test json-10.94 {
do_execsql_test json101-10.94 {
SELECT json_valid('" \} "');
} {0}
do_execsql_test json-10.95 {
do_execsql_test json101-10.95 {
SELECT json_valid('" \~ "');
} {0}
@@ -719,20 +719,20 @@ do_execsql_test json-10.95 {
#
# The following tests confirm that deeply nested JSON is considered invalid.
#
do_execsql_test json-11.0 {
do_execsql_test json101-11.0 {
/* Shallow enough to be parsed */
SELECT json_valid(printf('%.1000c0%.1000c','[',']'));
} {1}
do_execsql_test json-11.1 {
do_execsql_test json101-11.1 {
/* Too deep by one */
SELECT json_valid(printf('%.1001c0%.1001c','[',']'));
} {0}
do_execsql_test json-11.2 {
do_execsql_test json101-11.2 {
/* Shallow enough to be parsed { */
SELECT json_valid(replace(printf('%.1000c0%.1000c','[','}'),'[','{"a":'));
/* } */
} {1}
do_execsql_test json-11.3 {
do_execsql_test json101-11.3 {
/* Too deep by one { */
SELECT json_valid(replace(printf('%.1001c0%.1001c','[','}'),'[','{"a":'));
/* } */
@@ -742,7 +742,7 @@ do_execsql_test json-11.3 {
# a json structure even though the element name constains a "."
# character, by quoting the element name in the path.
#
do_execsql_test json-12.100 {
do_execsql_test json101-12.100 {
CREATE TABLE t12(x);
INSERT INTO t12(x) VALUES(
'{"settings":
@@ -766,11 +766,11 @@ do_execsql_test json-12.100 {
}
}');
} {}
do_execsql_test json-12.110 {
do_execsql_test json101-12.110 {
SELECT json_remove(x, '$.settings.layer2."dis.legomenon".forceDisplay')
FROM t12;
} {{{"settings":{"layer2":{"hapax.legomenon":{"forceDisplay":true,"transliterate":true,"add.footnote":true,"summary.report":true},"dis.legomenon":{"transliterate":false,"add.footnote":false,"summary.report":true},"tris.legomenon":{"forceDisplay":true,"transliterate":false,"add.footnote":false,"summary.report":false}}}}}}
do_execsql_test json-12.120 {
do_execsql_test json101-12.120 {
SELECT json_extract(x, '$.settings.layer2."tris.legomenon"."summary.report"')
FROM t12;
} {0}
@@ -779,7 +779,7 @@ do_execsql_test json-12.120 {
# ticket https://www.sqlite.org/src/tktview/80177f0c226ff54f6ddd41
# Make sure the query planner knows about the arguments to table-valued functions.
#
do_execsql_test json-13.100 {
do_execsql_test json101-13.100 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1(id, json);
@@ -794,7 +794,7 @@ do_execsql_test json-13.100 {
WHERE EXISTS(SELECT 1 FROM json_each(t1.json,'$.items') AS Z
WHERE Z.value==t2.id);
} {1 {{"items":[3,5]}} 3 {{"value":3}} 1 {{"items":[3,5]}} 5 {{"value":5}}}
do_execsql_test json-13.110 {
do_execsql_test json101-13.110 {
SELECT * FROM t2 CROSS JOIN t1
WHERE EXISTS(SELECT 1 FROM json_each(t1.json,'$.items') AS Z
WHERE Z.value==t2.id);
@@ -804,28 +804,28 @@ do_execsql_test json-13.110 {
# Incorrect fullkey output from json_each()
# when the input JSON is not an array or object.
#
do_execsql_test json-14.100 {
do_execsql_test json101-14.100 {
SELECT fullkey FROM json_each('123');
} {$}
do_execsql_test json-14.110 {
do_execsql_test json101-14.110 {
SELECT fullkey FROM json_each('123.56');
} {$}
do_execsql_test json-14.120 {
do_execsql_test json101-14.120 {
SELECT fullkey FROM json_each('"hello"');
} {$}
do_execsql_test json-14.130 {
do_execsql_test json101-14.130 {
SELECT fullkey FROM json_each('null');
} {$}
do_execsql_test json-14.140 {
do_execsql_test json101-14.140 {
SELECT fullkey FROM json_tree('123');
} {$}
do_execsql_test json-14.150 {
do_execsql_test json101-14.150 {
SELECT fullkey FROM json_tree('123.56');
} {$}
do_execsql_test json-14.160 {
do_execsql_test json101-14.160 {
SELECT fullkey FROM json_tree('"hello"');
} {$}
do_execsql_test json-14.170 {
do_execsql_test json101-14.170 {
SELECT fullkey FROM json_tree('null');
} {$}
@@ -835,16 +835,16 @@ do_execsql_test json-14.170 {
#
# Bug reported via private email. See TH3 for more information.
#
do_execsql_test json-15.100 {
do_execsql_test json101-15.100 {
SELECT * FROM JSON_EACH('{"a":1, "b":2}');
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
do_execsql_test json-15.110 {
do_execsql_test json101-15.110 {
SELECT xyz.* FROM JSON_EACH('{"a":1, "b":2}') AS xyz;
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
do_execsql_test json-15.120 {
do_execsql_test json101-15.120 {
SELECT * FROM (JSON_EACH('{"a":1, "b":2}'));
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
do_execsql_test json-15.130 {
do_execsql_test json101-15.130 {
SELECT xyz.* FROM (JSON_EACH('{"a":1, "b":2}')) AS xyz;
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
@@ -852,18 +852,18 @@ do_execsql_test json-15.130 {
# Mailing list bug report on the handling of surrogate pairs
# in JSON.
#
do_execsql_test json-16.10 {
do_execsql_test json101-16.10 {
SELECT length(json_extract('"abc\uD834\uDD1Exyz"','$'));
} {7}
do_execsql_test json-16.20 {
do_execsql_test json101-16.20 {
SELECT length(json_extract('"\uD834\uDD1E"','$'));
} {1}
do_execsql_test json-16.30 {
do_execsql_test json101-16.30 {
SELECT unicode(json_extract('"\uD834\uDD1E"','$'));
} {119070}
# 2022-01-30 dbsqlfuzz 4678cf825d27f87c9b8343720121e12cf944b71a
do_execsql_test json-17.1 {
do_execsql_test json101-17.1 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1(a,b,c);
@@ -872,19 +872,19 @@ do_execsql_test json-17.1 {
} {}
# 2022-04-04 forum post https://sqlite.org/forum/forumpost/c082aeab43
do_execsql_test json-18.1 {
do_execsql_test json101-18.1 {
SELECT json_valid('{"":5}');
} {1}
do_execsql_test json-18.2 {
do_execsql_test json101-18.2 {
SELECT json_extract('{"":5}', '$.""');
} {5}
do_execsql_test json-18.3 {
do_execsql_test json101-18.3 {
SELECT json_extract('[3,{"a":4,"":[5,{"hi":6},7]},8]', '$[1].""[1].hi');
} {6}
do_execsql_test json-18.4 {
do_execsql_test json101-18.4 {
SELECT json_extract('[3,{"a":4,"":[5,{"hi":6},7]},8]', '$[1].""[1]."hi"');
} {6}
do_catchsql_test json-18.5 {
do_catchsql_test json101-18.5 {
SELECT json_extract('{"":8}', '$.');
} {1 {JSON path error near ''}}
@@ -893,28 +893,28 @@ do_catchsql_test json-18.5 {
# a problem with transaction control. But the json() function makes
# the problem more easily accessible, so it is tested here.
#
do_execsql_test json-19.1 {
do_execsql_test json101-19.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(x);
} {}
do_catchsql_test json-19.2 {
do_catchsql_test json101-19.2 {
BEGIN;
INSERT INTO t1 VALUES(0), (json('not-valid-json'));
} {1 {malformed JSON}}
do_execsql_test json-19.3 {
do_execsql_test json101-19.3 {
COMMIT;
SELECT * FROM t1;
} {}
# 2023-03-17 positive and negative infinities
#
do_execsql_test json-20.1 {
do_execsql_test json101-20.1 {
SELECT json_object('a',2e370,'b',-3e380);
} {{{"a":9.0e+999,"b":-9.0e+999}}}
do_execsql_test json-20.2 {
do_execsql_test json101-20.2 {
SELECT json_object('a',2e370,'b',-3e380)->>'a';
} Inf
do_execsql_test json-20.3 {
do_execsql_test json101-20.3 {
SELECT json_object('a',2e370,'b',-3e380)->>'b';
} {-Inf}
@@ -924,91 +924,91 @@ do_execsql_test json-20.3 {
#
db null NULL
if {[db exists {SELECT * FROM pragma_compile_options WHERE compile_options LIKE '%legacy_json_valid%'}]} {
do_execsql_test json-21.1-legacy {
do_execsql_test json101-21.1-legacy {
SELECT json_valid(NULL);
} 0
} else {
do_execsql_test json-21.1-correct {
do_execsql_test json101-21.1-correct {
SELECT json_valid(NULL);
} NULL
}
do_execsql_test json-21.2 {
do_execsql_test json101-21.2 {
SELECT json_error_position(NULL);
} NULL
do_execsql_test json-21.3 {
do_execsql_test json101-21.3 {
SELECT json(NULL);
} NULL
do_execsql_test json-21.4 {
do_execsql_test json101-21.4 {
SELECT json_array(NULL);
} {[null]}
do_execsql_test json-21.5 {
do_execsql_test json101-21.5 {
SELECT json_extract(NULL);
} NULL
do_execsql_test json-21.6 {
do_execsql_test json101-21.6 {
SELECT json_insert(NULL,'$',123);
} NULL
do_execsql_test json-21.7 {
do_execsql_test json101-21.7 {
SELECT NULL->0;
} NULL
do_execsql_test json-21.8 {
do_execsql_test json101-21.8 {
SELECT NULL->>0;
} NULL
do_execsql_test json-21.9 {
do_execsql_test json101-21.9 {
SELECT '{a:5}'->NULL;
} NULL
do_execsql_test json-21.10 {
do_execsql_test json101-21.10 {
SELECT '{a:5}'->>NULL;
} NULL
do_catchsql_test json-21.11 {
do_catchsql_test json101-21.11 {
SELECT json_object(NULL,5);
} {1 {json_object() labels must be TEXT}}
do_execsql_test json-21.12 {
do_execsql_test json101-21.12 {
SELECT json_patch(NULL,'{a:5}');
} NULL
do_execsql_test json-21.13 {
do_execsql_test json101-21.13 {
SELECT json_patch('{a:5}',NULL);
} NULL
do_execsql_test json-21.14 {
do_execsql_test json101-21.14 {
SELECT json_patch(NULL,NULL);
} NULL
do_execsql_test json-21.15 {
do_execsql_test json101-21.15 {
SELECT json_remove(NULL,'$');
} NULL
do_execsql_test json-21.16 {
do_execsql_test json101-21.16 {
SELECT json_remove('{a:5,b:7}',NULL);
} NULL
do_execsql_test json-21.17 {
do_execsql_test json101-21.17 {
SELECT json_replace(NULL,'$.a',123);
} NULL
do_execsql_test json-21.18 {
do_execsql_test json101-21.18 {
SELECT json_replace('{a:5,b:7}',NULL,NULL);
} {{{"a":5,"b":7}}}
do_execsql_test json-21.19 {
do_execsql_test json101-21.19 {
SELECT json_set(NULL,'$.a',123);
} NULL
do_execsql_test json-21.20 {
do_execsql_test json101-21.20 {
SELECT json_set('{a:5,b:7}',NULL,NULL);
} {{{"a":5,"b":7}}}
do_execsql_test json-21.21 {
do_execsql_test json101-21.21 {
SELECT json_type(NULL);
} NULL
do_execsql_test json-21.22 {
do_execsql_test json101-21.22 {
SELECT json_type('{a:5,b:7}',NULL);
} NULL
do_execsql_test json-21.23 {
do_execsql_test json101-21.23 {
SELECT json_quote(NULL);
} null
do_execsql_test json-21.24 {
do_execsql_test json101-21.24 {
SELECT count(*) FROM json_each(NULL);
} 0
do_execsql_test json-21.25 {
do_execsql_test json101-21.25 {
SELECT count(*) FROM json_tree(NULL);
} 0
do_execsql_test json-21.26 {
do_execsql_test json101-21.26 {
WITH c(x) AS (VALUES(1),(2.0),(NULL),('three'))
SELECT json_group_array(x) FROM c;
} {[1,2.0,null,"three"]}
do_execsql_test json-21.27 {
do_execsql_test json101-21.27 {
WITH c(x,y) AS (VALUES('a',1),('b',2.0),('c',NULL),(NULL,'three'),('e','four'))
SELECT json_group_object(x,y) FROM c;
} {{{"a":1,"b":2.0,"c":null,:"three","e":"four"}}}

View File

@@ -1140,4 +1140,24 @@ do_execsql_test 17.1 {
} {1}
# 2023-08-15 https://sqlite.org/forum/forumpost/925dc9f67804c540
#
reset_db
sqlite3_db_config db DEFENSIVE 1
db eval {PRAGMA trusted_schema=OFF}
do_execsql_test 18.0 {
CREATE TABLE t1(x INT, y TEXT);
INSERT INTO t1 VALUES(1,'abc'),(2,'ABC'),(3,'Abc');
CREATE VIEW t2 AS SELECT * FROM t1 WHERE y LIKE 'a%';
SELECT * FROM t2;
} {1 abc 2 ABC 3 Abc}
do_execsql_test 18.1 {
PRAGMA case_sensitive_like=OFF;
SELECT * FROM t2;
} {1 abc 2 ABC 3 Abc}
do_execsql_test 18.2 {
PRAGMA case_sensitive_like=ON;
SELECT * FROM t2;
} {1 abc}
finish_test

View File

@@ -10,9 +10,11 @@
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
db close
if {[info vars ::trd::tcltest]==""} {
set testdir [file dirname $argv0]
source $testdir/tester.tcl
db close
}
#-------------------------------------------------------------------------
# test_suite NAME OPTIONS
@@ -832,117 +834,111 @@ test_suite "inmemory_journal" -description {
recoverpgsz.test
}]
ifcapable mem3 {
test_suite "memsys3" -description {
Run tests using the allocator in mem3.c.
} -files [test_set $::allquicktests -exclude {
autovacuum.test delete3.test manydb.test
bigrow.test incrblob2.test memdb.test
bitvec.test index2.test memsubsys1.test
capi3c.test ioerr.test memsubsys2.test
capi3.test join3.test pagesize.test
collate5.test limit.test backup_ioerr.test
backup_malloc.test
}] -initialize {
catch {db close}
sqlite3_reset_auto_extension
sqlite3_shutdown
sqlite3_config_heap 25000000 0
sqlite3_config_lookaside 0 0
ifcapable mem5 {
# If both memsys3 and memsys5 are enabled in the build, the call to
# [sqlite3_config_heap] will initialize the system to use memsys5.
# The following overrides this preference and installs the memsys3
# allocator.
sqlite3_install_memsys3
}
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
} -shutdown {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 0 0
sqlite3_config_lookaside 100 500
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
test_suite "memsys3" -description {
Run tests using the allocator in mem3.c.
} -files [test_set $::allquicktests -exclude {
autovacuum.test delete3.test manydb.test
bigrow.test incrblob2.test memdb.test
bitvec.test index2.test memsubsys1.test
capi3c.test ioerr.test memsubsys2.test
capi3.test join3.test pagesize.test
collate5.test limit.test backup_ioerr.test
backup_malloc.test
}] -initialize {
catch {db close}
sqlite3_reset_auto_extension
sqlite3_shutdown
sqlite3_config_heap 25000000 0
sqlite3_config_lookaside 0 0
ifcapable mem5 {
# If both memsys3 and memsys5 are enabled in the build, the call to
# [sqlite3_config_heap] will initialize the system to use memsys5.
# The following overrides this preference and installs the memsys3
# allocator.
sqlite3_install_memsys3
}
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
} -shutdown {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 0 0
sqlite3_config_lookaside 100 500
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
}
ifcapable mem5 {
test_suite "memsys5" -description {
Run tests using the allocator in mem5.c.
} -files [test_set $::allquicktests -exclude {
autovacuum.test delete3.test manydb.test
bigrow.test incrblob2.test memdb.test
bitvec.test index2.test memsubsys1.test
capi3c.test ioerr.test memsubsys2.test
capi3.test join3.test pagesize.test
collate5.test limit.test zeroblob.test
}] -initialize {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 25000000 64
sqlite3_config_lookaside 0 0
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
} -shutdown {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 0 0
sqlite3_config_lookaside 100 500
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
}
test_suite "memsys5-2" -description {
Run tests using the allocator in mem5.c in a different configuration.
} -files {
select1.test
} -initialize {
catch {db close}
sqlite3_shutdown
sqlite3_config_memstatus 0
sqlite3_config_heap 40000000 16
sqlite3_config_lookaside 0 0
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
} -shutdown {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 0 0
sqlite3_config_lookaside 100 500
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
}
test_suite "memsys5" -description {
Run tests using the allocator in mem5.c.
} -files [test_set $::allquicktests -exclude {
autovacuum.test delete3.test manydb.test
bigrow.test incrblob2.test memdb.test
bitvec.test index2.test memsubsys1.test
capi3c.test ioerr.test memsubsys2.test
capi3.test join3.test pagesize.test
collate5.test limit.test zeroblob.test
}] -initialize {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 25000000 64
sqlite3_config_lookaside 0 0
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
} -shutdown {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 0 0
sqlite3_config_lookaside 100 500
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
}
ifcapable threadsafe {
test_suite "no_mutex_try" -description {
The sqlite3_mutex_try() interface always fails
} -files [
test_set $::allquicktests -exclude mutex1.test mutex2.test
] -initialize {
catch {db close}
sqlite3_shutdown
install_mutex_counters 1
set ::disable_mutex_try 1
sqlite3_initialize
autoinstall_test_functions
} -shutdown {
catch {db close}
catch {db2 close}
catch {db3 close}
sqlite3_shutdown
install_mutex_counters 0
sqlite3_initialize
autoinstall_test_functions
}
test_suite "memsys5-2" -description {
Run tests using the allocator in mem5.c in a different configuration.
} -files {
select1.test
} -initialize {
catch {db close}
sqlite3_shutdown
sqlite3_config_memstatus 0
sqlite3_config_heap 40000000 16
sqlite3_config_lookaside 0 0
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
} -shutdown {
catch {db close}
sqlite3_shutdown
sqlite3_config_heap 0 0
sqlite3_config_lookaside 100 500
install_malloc_faultsim 1
sqlite3_initialize
autoinstall_test_functions
}
test_suite "no_mutex_try" -description {
The sqlite3_mutex_try() interface always fails
} -files [
test_set $::allquicktests -exclude mutex1.test mutex2.test
] -initialize {
catch {db close}
sqlite3_shutdown
install_mutex_counters 1
set ::disable_mutex_try 1
sqlite3_initialize
autoinstall_test_functions
} -shutdown {
catch {db close}
catch {db2 close}
catch {db3 close}
sqlite3_shutdown
install_mutex_counters 0
sqlite3_initialize
autoinstall_test_functions
}
# run_tests "crash_safe_append" -description {

View File

@@ -53,6 +53,12 @@ array set ::Configs [strip_comments {
--enable-session
-DSQLITE_ENABLE_RBU
}
"All-Debug" {
--enable-debug --enable-all
}
"All-O0" {
-O0 --enable-all
}
"Sanitize" {
CC=clang -fsanitize=address,undefined
-DSQLITE_ENABLE_STAT4
@@ -672,6 +678,12 @@ proc main_trscript {args} {
lappend opts -DSQLITE_ENABLE_PREUPDATE_HOOK
lappend opts -DSQLITE_ENABLE_SESSION
}
--enable-all {
}
--enable-debug {
# lappend makeOpts OPTIMIZATIONS=0
lappend opts -DSQLITE_DEBUG
}
default {
error "Cannot translate $param for MSVC"
}
@@ -717,7 +729,12 @@ proc main_trscript {args} {
puts " \$SRCDIR/configure --with-tcl=\$TCL $configOpts"
puts {fi}
puts {}
puts {OPTS=" -DSQLITE_NO_SYNC=1"}
if {[info exists ::env(OPTS)]} {
puts "# From environment variable:"
puts "OPTS=$::env(OPTS)"
puts ""
}
puts {OPTS="$OPTS -DSQLITE_NO_SYNC=1"}
foreach o $opts {
puts "OPTS=\"\$OPTS $o\""
}

View File

@@ -69,7 +69,7 @@ foreach {tn script} {
# Because it uses so much data, this test can take 12-13 seconds even on
# a modern workstation. So it is omitted from "veryquick" and other
# permutations.test tests.
if {[isquick]==0} {
if {[isquick]==0 && [clang_sanitize_address]==0} {
do_execsql_test $tn.3 {
PRAGMA cache_size = 5;
WITH r(x,y) AS (

View File

@@ -1,6 +1,6 @@
set dir [pwd]
set testdir [file dirname $argv0]
set testdir [file normalize [file dirname $argv0]]
set saved $argv
set argv [list]
source [file join $testdir testrunner_data.tcl]
@@ -8,6 +8,42 @@ source [file join $testdir permutations.test]
set argv $saved
cd $dir
# This script requires an interpreter that supports [package require sqlite3]
# to run. If this is not such an intepreter, see if there is a [testfixture]
# in the current directory. If so, run the command using it. If not,
# recommend that the user build one.
#
proc find_interpreter {} {
set interpreter [file tail [info nameofexec]]
set rc [catch { package require sqlite3 }]
if {$rc} {
if { [string match -nocase testfixture* $interpreter]==0
&& [file executable ./testfixture]
} {
puts "Failed to find tcl package sqlite3. Restarting with ./testfixture.."
set status [catch {
exec ./testfixture [info script] {*}$::argv >@ stdout
} msg]
exit $status
}
}
if {$rc} {
puts stderr "Failed to find tcl package sqlite3"
puts stderr "Run \"make testfixture\" and then try again..."
exit 1
}
}
find_interpreter
# Usually this script is run by [testfixture]. But it can also be run
# by a regular [tclsh]. For these cases, emulate the [clock_milliseconds]
# command.
if {[info commands clock_milliseconds]==""} {
proc clock_milliseconds {} {
clock milliseconds
}
}
#-------------------------------------------------------------------------
# Usage:
#
@@ -74,16 +110,20 @@ proc guess_number_of_cores {} {
if {[catch {number_of_cores} ret]} {
set ret 4
if {$::tcl_platform(os)=="Darwin"} {
set cmd "sysctl -n hw.logicalcpu"
if {$::tcl_platform(platform)=="windows"} {
catch { set ret $::env(NUMBER_OF_PROCESSORS) }
} else {
set cmd "nproc"
}
catch {
set fd [open "|$cmd" r]
set ret [gets $fd]
close $fd
set ret [expr $ret]
if {$::tcl_platform(os)=="Darwin"} {
set cmd "sysctl -n hw.logicalcpu"
} else {
set cmd "nproc"
}
catch {
set fd [open "|$cmd" r]
set ret [gets $fd]
close $fd
set ret [expr $ret]
}
}
}
return $ret
@@ -152,10 +192,8 @@ set TRG(schema) {
state TEXT CHECK( state IN ('', 'ready', 'running', 'done', 'failed') ),
time INTEGER, -- Time in ms
output TEXT, -- full output of test script
priority AS ((config='make') + ((config='build')*2) + (slow*4)),
jobtype AS (
CASE WHEN config IN ('build', 'make') THEN config ELSE 'script' END
),
priority INTEGER,
jobtype TEXT CHECK( jobtype IN ('script', 'build', 'make') ),
PRIMARY KEY(build, config, filename)
);
@@ -181,10 +219,11 @@ if {[llength $argv]==2
set script [file normalize [lindex $argv 1]]
set ::argv [list]
set testdir [file dirname $argv0]
source $::testdir/tester.tcl
if {$permutation=="full"} {
set testdir [file dirname $argv0]
source $::testdir/tester.tcl
unset -nocomplain ::G(isquick)
reset_db
@@ -241,6 +280,22 @@ if {([llength $argv]==2 || [llength $argv]==1)
}
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# Check if this is the "script" command:
#
if {[string compare -nocase script [lindex $argv 0]]==0} {
if {[llength $argv]!=2 && !([llength $argv]==3&&[lindex $argv 1]=="-msvc")} {
usage
}
set bMsvc [expr ([llength $argv]==3)]
set config [lindex $argv [expr [llength $argv]-1]]
puts [trd_buildscript $config [file dirname $testdir] $bMsvc]
exit
}
#--------------------------------------------------------------------------
# Check if this is the "status" command:
#
@@ -289,9 +344,13 @@ if {[llength $argv]==1
set cmdline [mydb one { SELECT value FROM config WHERE name='cmdline' }]
set nJob [mydb one { SELECT value FROM config WHERE name='njob' }]
set tm [expr [clock_milliseconds] - [mydb one {
SELECT value FROM config WHERE name='start'
}]]
set now [clock_milliseconds]
set tm [mydb one {
SELECT
COALESCE((SELECT value FROM config WHERE name='end'), $now) -
(SELECT value FROM config WHERE name='start')
}]
set total 0
foreach s {"" ready running done failed} { set S($s) 0 }
@@ -315,7 +374,6 @@ if {[llength $argv]==1
set srcdir [file dirname [file dirname $TRG(info_script)]]
if {$S(running)>0} {
puts "Running: "
set now [clock_milliseconds]
mydb eval {
SELECT build, config, filename, time FROM script WHERE state='running'
ORDER BY time
@@ -411,8 +469,6 @@ proc dirs_allocDir {} {
return $iRet
}
set testdir [file dirname $argv0]
# Check that directory $dir exists. If it does not, create it. If
# it does, delete its contents.
#
@@ -449,7 +505,16 @@ proc testset_patternlist {patternlist} {
set first [lindex $patternlist 0]
if {$first=="release"} {
if {$first=="mdevtest"} {
set patternlist [lrange $patternlist 1 end]
foreach b {All-Debug All-O0} {
lappend testset [list $b build testfixture]
lappend testset [list $b make fuzztest]
testset_append testset $b veryquick $patternlist
}
} elseif {$first=="release"} {
set platform $::TRG(platform)
set patternlist [lrange $patternlist 1 end]
@@ -634,9 +699,20 @@ proc make_new_testset {} {
set state ""
}
set priority [expr {$slow*2}]
if {$c=="make"} { incr priority 3 }
if {$c=="build"} { incr priority 1 }
if {$c=="make" || $c=="build"} {
set jobtype $c
} else {
set jobtype "script"
}
trdb eval {
INSERT INTO script(build, config, filename, slow, state)
VALUES ($b, $c, $s, $slow, $state)
INSERT INTO script
(build, config, filename, slow, state, priority, jobtype)
VALUES ($b, $c, $s, $slow, $state, $priority, $jobtype)
}
}
}
@@ -721,12 +797,7 @@ proc launch_another_job {iJob} {
if {$b=="Zipvfs"} {
set script [zipvfs_testrunner_script]
} else {
set cmd [info nameofexec]
lappend cmd [file join $testdir releasetest_data.tcl]
lappend cmd trscript
if {$TRG(platform)=="win"} { lappend cmd -msvc }
lappend cmd $b $srcdir
set script [exec {*}$cmd]
set script [trd_buildscript $b $srcdir [expr {$TRG(platform)=="win"}]]
}
set fd [open [file join $builddir $TRG(make)] w]
@@ -865,6 +936,8 @@ proc run_testset {} {
one_line_report
r_write_db {
set tm [clock_milliseconds]
trdb eval { REPLACE INTO config VALUES('end', $tm ); }
set nErr [trdb one {SELECT count(*) FROM script WHERE state='failed'}]
if {$nErr>0} {
puts "$nErr failures:"

View File

@@ -5,6 +5,7 @@ namespace eval trd {
variable tcltest
variable extra
variable all_configs
variable build
# Tcl tests to run for various builds.
@@ -35,6 +36,7 @@ namespace eval trd {
set tcltest(win.Have-Not) veryquick
set tcltest(win.Windows-Memdebug) veryquick
set tcltest(win.Windows-Win32Heap) veryquick
set tcltest(win.Windows-Sanitize) veryquick
set tcltest(win.Default) full
# Extra [make xyz] tests that should be run for various builds.
@@ -63,6 +65,7 @@ namespace eval trd {
set extra(win.Stdcall) {fuzztest sourcetest}
set extra(win.Windows-Memdebug) {fuzztest sourcetest}
set extra(win.Windows-Win32Heap) {fuzztest sourcetest}
set extra(win.Windows-Sanitize) fuzztest
set extra(win.Have-Not) {fuzztest sourcetest}
# The following mirrors the set of test suites invoked by "all.test".
@@ -75,6 +78,245 @@ namespace eval trd {
inmemory_journal pcache0 pcache10 pcache50 pcache90
pcache100 prepare mmap
}
#-----------------------------------------------------------------------
# Start of build() definitions.
#
set build(Default) {
-O2
--disable-amalgamation --disable-shared
--enable-session
-DSQLITE_ENABLE_RBU
}
# These two are used by [testrunner.tcl mdevtest].
#
set build(All-Debug) {
--enable-debug --enable-all
}
set build(All-O0) {
-O0 --enable-all
}
set build(Sanitize) {
CC=clang -fsanitize=address,undefined
-DSQLITE_ENABLE_STAT4
-DCONFIG_SLOWDOWN_FACTOR=5.0
--enable-debug
--enable-all
}
set build(Stdcall) {
-DUSE_STDCALL=1
-O2
}
# The "Have-Not" configuration sets all possible -UHAVE_feature options
# in order to verify that the code works even on platforms that lack
# these support services.
set build(Have-Not) {
-DHAVE_FDATASYNC=0
-DHAVE_GMTIME_R=0
-DHAVE_ISNAN=0
-DHAVE_LOCALTIME_R=0
-DHAVE_LOCALTIME_S=0
-DHAVE_MALLOC_USABLE_SIZE=0
-DHAVE_STRCHRNUL=0
-DHAVE_USLEEP=0
-DHAVE_UTIME=0
}
set build(Unlock-Notify) {
-O2
-DSQLITE_ENABLE_UNLOCK_NOTIFY
-DSQLITE_THREADSAFE
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
}
set build(User-Auth) {
-O2
-DSQLITE_USER_AUTHENTICATION=1
}
set build(Secure-Delete) {
-O2
-DSQLITE_SECURE_DELETE=1
-DSQLITE_SOUNDEX=1
}
set build(Update-Delete-Limit) {
-O2
-DSQLITE_DEFAULT_FILE_FORMAT=4
-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
-DSQLITE_ENABLE_STMT_SCANSTATUS
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS
-DSQLITE_ENABLE_CURSOR_HINTS
}
set build(Check-Symbols) {
-DSQLITE_MEMDEBUG=1
-DSQLITE_ENABLE_FTS3_PARENTHESIS=1
-DSQLITE_ENABLE_FTS3=1
-DSQLITE_ENABLE_RTREE=1
-DSQLITE_ENABLE_MEMSYS5=1
-DSQLITE_ENABLE_MEMSYS3=1
-DSQLITE_ENABLE_COLUMN_METADATA=1
-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
-DSQLITE_SECURE_DELETE=1
-DSQLITE_SOUNDEX=1
-DSQLITE_ENABLE_ATOMIC_WRITE=1
-DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
-DSQLITE_ENABLE_STAT4
-DSQLITE_ENABLE_STMT_SCANSTATUS
--enable-fts5 --enable-session
}
set build(Debug-One) {
--disable-shared
-O2 -funsigned-char
-DSQLITE_DEBUG=1
-DSQLITE_MEMDEBUG=1
-DSQLITE_MUTEX_NOOP=1
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
-DSQLITE_ENABLE_FTS3=1
-DSQLITE_ENABLE_RTREE=1
-DSQLITE_ENABLE_MEMSYS5=1
-DSQLITE_ENABLE_COLUMN_METADATA=1
-DSQLITE_ENABLE_STAT4
-DSQLITE_ENABLE_HIDDEN_COLUMNS
-DSQLITE_MAX_ATTACHED=125
-DSQLITE_MUTATION_TEST
--enable-fts5
}
set build(Debug-Two) {
-DSQLITE_DEFAULT_MEMSTATUS=0
-DSQLITE_MAX_EXPR_DEPTH=0
--enable-debug
}
set build(Fast-One) {
-O6
-DSQLITE_ENABLE_FTS4=1
-DSQLITE_ENABLE_RTREE=1
-DSQLITE_ENABLE_STAT4
-DSQLITE_ENABLE_RBU
-DSQLITE_MAX_ATTACHED=125
-DSQLITE_MAX_MMAP_SIZE=12884901888
-DSQLITE_ENABLE_SORTER_MMAP=1
-DLONGDOUBLE_TYPE=double
--enable-session
}
set build(Device-One) {
-O2
-DSQLITE_DEBUG=1
-DSQLITE_DEFAULT_AUTOVACUUM=1
-DSQLITE_DEFAULT_CACHE_SIZE=64
-DSQLITE_DEFAULT_PAGE_SIZE=1024
-DSQLITE_DEFAULT_TEMP_CACHE_SIZE=32
-DSQLITE_DISABLE_LFS=1
-DSQLITE_ENABLE_ATOMIC_WRITE=1
-DSQLITE_ENABLE_IOTRACE=1
-DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
-DSQLITE_MAX_PAGE_SIZE=4096
-DSQLITE_OMIT_LOAD_EXTENSION=1
-DSQLITE_OMIT_PROGRESS_CALLBACK=1
-DSQLITE_OMIT_VIRTUALTABLE=1
-DSQLITE_ENABLE_HIDDEN_COLUMNS
-DSQLITE_TEMP_STORE=3
}
set build(Device-Two) {
-DSQLITE_4_BYTE_ALIGNED_MALLOC=1
-DSQLITE_DEFAULT_AUTOVACUUM=1
-DSQLITE_DEFAULT_CACHE_SIZE=1000
-DSQLITE_DEFAULT_LOCKING_MODE=0
-DSQLITE_DEFAULT_PAGE_SIZE=1024
-DSQLITE_DEFAULT_TEMP_CACHE_SIZE=1000
-DSQLITE_DISABLE_LFS=1
-DSQLITE_ENABLE_FTS3=1
-DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
-DSQLITE_ENABLE_RTREE=1
-DSQLITE_MAX_COMPOUND_SELECT=50
-DSQLITE_MAX_PAGE_SIZE=32768
-DSQLITE_OMIT_TRACE=1
-DSQLITE_TEMP_STORE=3
-DSQLITE_THREADSAFE=2
--enable-fts5 --enable-session
}
set build(Locking-Style) {
-O2
-DSQLITE_ENABLE_LOCKING_STYLE=1
}
set build(Apple) {
-Os
-DHAVE_GMTIME_R=1
-DHAVE_ISNAN=1
-DHAVE_LOCALTIME_R=1
-DHAVE_PREAD=1
-DHAVE_PWRITE=1
-DHAVE_UTIME=1
-DSQLITE_DEFAULT_CACHE_SIZE=1000
-DSQLITE_DEFAULT_CKPTFULLFSYNC=1
-DSQLITE_DEFAULT_MEMSTATUS=1
-DSQLITE_DEFAULT_PAGE_SIZE=1024
-DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS=1
-DSQLITE_ENABLE_API_ARMOR=1
-DSQLITE_ENABLE_AUTO_PROFILE=1
-DSQLITE_ENABLE_FLOCKTIMEOUT=1
-DSQLITE_ENABLE_FTS3=1
-DSQLITE_ENABLE_FTS3_PARENTHESIS=1
-DSQLITE_ENABLE_FTS3_TOKENIZER=1
-DSQLITE_ENABLE_PERSIST_WAL=1
-DSQLITE_ENABLE_PURGEABLE_PCACHE=1
-DSQLITE_ENABLE_RTREE=1
-DSQLITE_ENABLE_SNAPSHOT=1
-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
-DSQLITE_MAX_LENGTH=2147483645
-DSQLITE_MAX_VARIABLE_NUMBER=500000
-DSQLITE_NO_SYNC=1
-DSQLITE_OMIT_AUTORESET=1
-DSQLITE_OMIT_LOAD_EXTENSION=1
-DSQLITE_PREFER_PROXY_LOCKING=1
-DSQLITE_SERIES_CONSTRAINT_VERIFY=1
-DSQLITE_THREADSAFE=2
-DSQLITE_USE_URI=1
-DSQLITE_WRITE_WALFRAME_PREBUFFERED=1
-DUSE_GUARDED_FD=1
-DUSE_PREAD=1
--enable-fts5
}
set build(Extra-Robustness) {
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
-DSQLITE_MAX_ATTACHED=62
}
set build(Devkit) {
-DSQLITE_DEFAULT_FILE_FORMAT=4
-DSQLITE_MAX_ATTACHED=30
-DSQLITE_ENABLE_COLUMN_METADATA
-DSQLITE_ENABLE_FTS4
-DSQLITE_ENABLE_FTS5
-DSQLITE_ENABLE_FTS4_PARENTHESIS
-DSQLITE_DISABLE_FTS4_DEFERRED
-DSQLITE_ENABLE_RTREE
--enable-fts5
}
set build(No-lookaside) {
-DSQLITE_TEST_REALLOC_STRESS=1
-DSQLITE_OMIT_LOOKASIDE=1
}
set build(Valgrind) {
-DSQLITE_ENABLE_STAT4
-DSQLITE_ENABLE_FTS4
-DSQLITE_ENABLE_RTREE
-DSQLITE_ENABLE_HIDDEN_COLUMNS
-DLONGDOUBLE_TYPE=double
-DCONFIG_SLOWDOWN_FACTOR=8.0
}
set build(Windows-Memdebug) {
MEMDEBUG=1
DEBUG=3
}
set build(Windows-Win32Heap) {
WIN32HEAP=1
DEBUG=4
}
set build(Windows-Sanitize) {
ASAN=1
}
}
@@ -84,6 +326,7 @@ proc trd_import {} {
variable ::trd::tcltest
variable ::trd::extra
variable ::trd::all_configs
variable ::trd::build
}
}
@@ -106,13 +349,13 @@ proc trd_builds {platform} {
set ret
}
proc trd_configs {platform build} {
proc trd_configs {platform bld} {
trd_import
set clist [list]
if {[info exists tcltest($platform.$build)]} {
set clist $tcltest($platform.$build)
if {[info exists tcltest($platform.$bld)]} {
set clist $tcltest($platform.$bld)
if {$clist=="all"} {
set clist $all_configs
} elseif {$clist=="all_plus_autovacuum_crash"} {
@@ -123,12 +366,12 @@ proc trd_configs {platform build} {
set clist
}
proc trd_extras {platform build} {
proc trd_extras {platform bld} {
trd_import
set elist [list]
if {[info exists extra($platform.$build)]} {
set elist $extra($platform.$build)
if {[info exists extra($platform.$bld)]} {
set elist $extra($platform.$bld)
}
set elist
@@ -139,5 +382,180 @@ proc trd_all_configs {} {
set all_configs
}
proc trimscript {text} {
set text [string map {"\n " "\n"} [string trim $text]]
}
proc make_sh_script {srcdir opts cflags makeOpts configOpts} {
set tcldir [::tcl::pkgconfig get libdir,install]
set myopts ""
if {[info exists ::env(OPTS)]} {
append myopts "# From environment variable:\n"
append myopts "OPTS=$::env(OPTS)\n"
}
foreach o [lsort $opts] {
append myopts "OPTS=\"\$OPTS $o\"\n"
}
return [trimscript [subst -nocommands {
set -e
if [ "\$#" -ne 1 ] ; then
echo "Usage: \$0 <target>"
exit -1
fi
SRCDIR="$srcdir"
TCLDIR="$tcldir"
if [ ! -f Makefile ] ; then
\$SRCDIR/configure --with-tcl=\$TCL $configOpts
fi
$myopts
CFLAGS="$cflags"
make \$1 "CFLAGS=\$CFLAGS" "OPTS=\$OPTS" $makeOpts
}]]
}
# Generate the text of a *.bat script.
#
proc make_bat_file {srcdir opts cflags makeOpts} {
set srcdir [file nativename [file normalize $srcdir]]
return [trimscript [subst -nocommands {
set TARGET=%1
set TMP=%CD%
nmake /f $srcdir\\Makefile.msc TOP="$srcdir" %TARGET% "CCOPTS=$cflags" "OPTS=$opts" $makeOpts
}]]
}
# Generate the text of a shell script.
#
proc make_script {cfg srcdir bMsvc} {
set opts [list] ;# OPTS value
set cflags [expr {$bMsvc ? "-Zi" : "-g"}] ;# CFLAGS value
set makeOpts [list] ;# Extra args for [make]
set configOpts [list] ;# Extra args for [configure]
# Define either SQLITE_OS_WIN or SQLITE_OS_UNIX, as appropriate.
if {$::tcl_platform(platform)=="windows"} {
lappend opts -DSQLITE_OS_WIN=1
} else {
lappend opts -DSQLITE_OS_UNIX=1
}
# Unless the configuration specifies -DHAVE_USLEEP=0, set -DHAVE_USLEEP=1.
#
if {[lsearch $cfg "-DHAVE_USLEEP=0"]<0} {
lappend cfg -DHAVE_USLEEP=1
}
# Loop through the parameters of the nominated configuration, updating
# $opts, $cflags, $makeOpts and $configOpts along the way. Rules are as
# follows:
#
# 1. If the parameter begins with "-D", add it to $opts.
#
# 2. If the parameter begins with "--" add it to $configOpts. Unless
# this command is preparing a script for MSVC - then add an
# equivalent to $makeOpts or $opts.
#
# 3. If the parameter begins with "-" add it to $cflags. If in MSVC
# mode and the parameter is an -O<integer> option, instead add
# an OPTIMIZATIONS=<integer> switch to $makeOpts.
#
# 4. If none of the above apply, add the parameter to $makeOpts
#
foreach param $cfg {
if {[string range $param 0 1]=="-D"} {
lappend opts $param
continue
}
if {[string range $param 0 1]=="--"} {
if {$bMsvc==0} {
lappend configOpts $param
} else {
switch -- $param {
--disable-amalgamation {
lappend makeOpts USE_AMALGAMATION=0
}
--disable-shared {
lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0
}
--enable-fts5 {
lappend opts -DSQLITE_ENABLE_FTS5
}
--enable-shared {
lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1
}
--enable-session {
lappend opts -DSQLITE_ENABLE_PREUPDATE_HOOK
lappend opts -DSQLITE_ENABLE_SESSION
}
--enable-all {
}
--enable-debug {
# lappend makeOpts OPTIMIZATIONS=0
lappend opts -DSQLITE_DEBUG
}
default {
error "Cannot translate $param for MSVC"
}
}
}
continue
}
if {[string range $param 0 0]=="-"} {
if {$bMsvc && [regexp -- {^-O(\d+)$} $param -> level]} {
lappend makeOpts OPTIMIZATIONS=$level
} else {
lappend cflags $param
}
continue
}
lappend makeOpts $param
}
if {$bMsvc==0} {
set zRet [make_sh_script $srcdir $opts $cflags $makeOpts $configOpts]
} else {
set zRet [make_bat_file $srcdir $opts $cflags $makeOpts]
}
}
# Usage:
#
# trd_buildscript CONFIG SRCDIR MSVC
#
# This command returns the full text of a script (either a shell script or
# an ms-dos bat file) that may be used to build SQLite source code according
# to a nominated configuration.
#
# Parameter CONFIG must be a configuration defined above in the ::trd::build
# array. SRCDIR is the root directory of an SQLite source tree (the parent
# directory of that containing this script). MSVC is a boolean - true to
# use the MSVC compiler, false otherwise.
#
proc trd_buildscript {config srcdir bMsvc} {
trd_import
# Ensure that the named configuration exists.
if {![info exists build($config)]} {
error "No such build config: $config"
}
# Generate and return the script.
return [make_script $build($config) $srcdir $bMsvc]
}

View File

@@ -255,4 +255,17 @@ do_execsql_test upsert1-1100 {
SELECT * FROM t1;
} {1 22}
# 2023-08-17 dbsqlfuzz 9983e2c77634a8ccf33b5c91fa9982599de5f9e9
# Bound parameters in the ON CONFLICT clause of an UPSERT.
#
reset_db
do_execsql_test upsert1-1200 {
CREATE TABLE t1(a INT, b INT);
CREATE UNIQUE INDEX t1x ON t1(b+3);
}
sqlite3_db_config db ENABLE_QPSG 1
do_catchsql_test upsert1-1210 {
INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(b+?1) DO NOTHING;
} {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}}
finish_test

View File

@@ -47,8 +47,12 @@
# include <unistd.h>
#else
# include <io.h>
# define R_OK 04
# define access(f,m) _access((f),(m))
# ifndef R_OK
# define R_OK 04
# endif
# ifndef access
# define access(f,m) _access((f),(m))
# endif
#endif
typedef unsigned long long int u64;