Compare commits
307 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 66795962b5 | |||
| 7394a6ef57 | |||
| ad27c437ff | |||
| bfc7e62be4 | |||
| 694beecf2b | |||
| da2578391d | |||
| 6d7afd8ba8 | |||
| 2ba5534101 | |||
| 4b54d6cdaf | |||
| 748178a9fb | |||
| 1f8c7c7053 | |||
| 1ef232c0e1 | |||
| 1cab41e290 | |||
| ef97f8360a | |||
| 940b23bc3a | |||
| b8950e0f45 | |||
| 26cd4b57df | |||
| ec1f59f0cd | |||
| 5026ddb83d | |||
| f46f89df97 | |||
| eb04a0bb7b | |||
| bae2d0f2eb | |||
| e52854a9e6 | |||
| 8a3034add8 | |||
| 821a4c9f8c | |||
| 85eafe6f3b | |||
| b4e5bc6cdb | |||
| 15c0b03c5d | |||
| 50b37832b2 | |||
| e09a38c2e8 | |||
| 796abda538 | |||
| aea2d23121 | |||
| c2474105ca | |||
| b7d5cb711a | |||
| 5e6500c81c | |||
| 48cca2422e | |||
| abbdbdfc1f | |||
| 88a61ff8ba | |||
| f5232b3a97 | |||
| ab70266698 | |||
| c0f8d58b21 | |||
| d47719ee02 | |||
| ac8b6e70c9 | |||
| 77044f30a2 | |||
| 226aebae07 | |||
| 5d175eb020 | |||
| a328c42724 | |||
| 92752a31d9 | |||
| c0314bc01d | |||
| cf72606a7d | |||
| 27fea97e44 | |||
| e1df37b947 | |||
| d9f3d6d753 | |||
| 664fe310b5 | |||
| e97f295783 | |||
| 8a4cecaea2 | |||
| e788255681 | |||
| a4050f1434 | |||
| 4f77a27032 | |||
| 0fcaf16f20 | |||
| 56bb07bad6 | |||
| 033127af75 | |||
| 4c9a02c9f0 | |||
| 73e3e0c21f | |||
| 046a7f9493 | |||
| 52c41ed41b | |||
| b8688e131e | |||
| 11c512d631 | |||
| f9ae48b9ed | |||
| 003d419b33 | |||
| 735e7ee62a | |||
| e416251725 | |||
| f2bb6ab3fb | |||
| c15133e82a | |||
| e1edecf5d3 | |||
| 11e8242e2e | |||
| 5e3ae1ec76 | |||
| 91c8e65dd4 | |||
| 8c96d3c104 | |||
| af0c9ffb4a | |||
| 0399994759 | |||
| 9eb7694d58 | |||
| fb57c8a932 | |||
| 5cc4ab93f2 | |||
| 1b963102b7 | |||
| bd06d8672d | |||
| 4d6b10cdbe | |||
| 6b36312e8a | |||
| 973011432b | |||
| d7ef0e8f87 | |||
| 253727b33d | |||
| 7df044633d | |||
| 5d59669711 | |||
| d928e78088 | |||
| cb3a0b1b67 | |||
| 34ccd18d65 | |||
| 4ce5bc2836 | |||
| bdfc51dfef | |||
| f695620e46 | |||
| adcd13d243 | |||
| b481413d95 | |||
| ce2edab088 | |||
| 87c407da18 | |||
| 5ed4ba0f7d | |||
| 7f7d7bea01 | |||
| 41d4b7bdee | |||
| c270dad95d | |||
| 14a08730de | |||
| fdbd9119d4 | |||
| 782c9f2e9e | |||
| cc2b3c2051 | |||
| ea80462c10 | |||
| 1bcb7c4902 | |||
| 56e1610f7a | |||
| 307f95c1e4 | |||
| d2c8658024 | |||
| 1229f8e6bd | |||
| fb28a93f75 | |||
| 88dcfe56da | |||
| 10c815a55d | |||
| e8d4fd59e4 | |||
| 5a81e6e5ce | |||
| 53381132be | |||
| 0eed27d38b | |||
| 9d60c3c256 | |||
| 828a00c287 | |||
| af65e7d21f | |||
| 6db0b11e07 | |||
| 3839dcf973 | |||
| 2009a5acba | |||
| beb06e6b0a | |||
| cb1f190ed2 | |||
| b10c3d32e0 | |||
| 752722e8d1 | |||
| 6eb381ff4a | |||
| b9050dcec7 | |||
| b18bb822dc | |||
| 194b8d514b | |||
| ec427813ac | |||
| c060b5f3a8 | |||
| 243f2ec6a1 | |||
| 2cbe14098b | |||
| a4cf38ca9b | |||
| b494366370 | |||
| 6234b33478 | |||
| e445586630 | |||
| 0ad5301378 | |||
| 8657eddcdb | |||
| 86b1898cb4 | |||
| c78d3b5963 | |||
| ec8f893e06 | |||
| d7b0b5ec6f | |||
| 275234e320 | |||
| 344255e5aa | |||
| 73f03276d9 | |||
| 17a3295387 | |||
| 637922acac | |||
| 488125d4ce | |||
| 6dc368e632 | |||
| 6ca0cfd87a | |||
| 4c78cb50bf | |||
| 23056b608e | |||
| a3e8822c4b | |||
| d0046388a0 | |||
| eb1898d6f3 | |||
| 56fba47850 | |||
| e3a6a60901 | |||
| a0cd392979 | |||
| 8dd4697e48 | |||
| ff39634625 | |||
| ed99e7493a | |||
| 546db3f14a | |||
| 88c90a793e | |||
| 9a26589940 | |||
| 557297ae77 | |||
| 0ee7ae72a1 | |||
| 2c930e3b86 | |||
| b02ca781ad | |||
| 15d38c0dde | |||
| dc8a684c11 | |||
| ffdb479e7c | |||
| d4677f192f | |||
| 1b199243cb | |||
| 348e192ea8 | |||
| 5f3b13d136 | |||
| aad6808efc | |||
| a501791d59 | |||
| 5189ef98d3 | |||
| ab8a4b2bb0 | |||
| b945183195 | |||
| 7b5123c796 | |||
| 073f8f5458 | |||
| 1d5f2af063 | |||
| 24f7f5923d | |||
| d706adba48 | |||
| dcd6d21fe9 | |||
| 792103a0f2 | |||
| 5e4233a9e4 | |||
| 78fee3f738 | |||
| 7b0fd0c564 | |||
| 06af40b2e1 | |||
| e186fe20f5 | |||
| 845a2e0cc2 | |||
| 8a93ce7458 | |||
| 57a7fdd814 | |||
| 7d52262889 | |||
| 0577cdec5f | |||
| 54e7a0f360 | |||
| 2158864585 | |||
| 66476771b7 | |||
| 5ba99da869 | |||
| ddd1c97500 | |||
| 739edb99ee | |||
| 793e872803 | |||
| 95c11b1158 | |||
| 26422f823f | |||
| 334b6fe418 | |||
| 90a5617b55 | |||
| 96aa4d344d | |||
| 166c8d0067 | |||
| 32a0d6129f | |||
| 4598b6e5ae | |||
| 4bcde614d8 | |||
| f5e487d168 | |||
| c7ad9f65fa | |||
| 7d1c9da62d | |||
| 86db4555ca | |||
| 2b7a1f5926 | |||
| 33b56217cb | |||
| 2a96a1584d | |||
| 71dc3c714b | |||
| 6b7b23c580 | |||
| 59ded6b5f1 | |||
| d88f378c7d | |||
| 064c1688da | |||
| cc5e612db4 | |||
| f32aa34346 | |||
| 0dead8d3d1 | |||
| a7e9386e88 | |||
| de8ccf00fb | |||
| 3efb2c4791 | |||
| f26833d783 | |||
| 1244b6cbf6 | |||
| 502b11c6d3 | |||
| bae197c175 | |||
| 522e880bc2 | |||
| 11aa2adca3 | |||
| 6b8aa95c3c | |||
| 7b4349735f | |||
| 98dbfa69d3 | |||
| e690d5ad80 | |||
| e1e2f2dcc5 | |||
| 91f3cd9874 | |||
| dd7f09e6c0 | |||
| 27401d38d8 | |||
| f7af8f3270 | |||
| dac2707152 | |||
| 51d507d432 | |||
| 5b6cfb7906 | |||
| 14fce24a9b | |||
| 0585d9f08f | |||
| 01acfd5805 | |||
| 9061e22a05 | |||
| 0f921e2bac | |||
| 4500d87e76 | |||
| f362731c1c | |||
| 51cc3041fe | |||
| 6e737b9252 | |||
| f0c129f247 | |||
| ee0f6777f9 | |||
| 8405e1140a | |||
| 313336f90b | |||
| e5c384e9a5 | |||
| dee29e8c7a | |||
| c97407fdba | |||
| 8eeafb7544 | |||
| 5624b0b4cd | |||
| 9b176f863b | |||
| d8f26350a0 | |||
| 7e86d3fc69 | |||
| 5736ba5ac3 | |||
| ee50aad865 | |||
| a99e2fb576 | |||
| ae5f55e227 | |||
| ecce6022d5 | |||
| 8cdab14286 | |||
| 0a19bb078d | |||
| edbc44c5a1 | |||
| 77e00f24d7 | |||
| 6b1db92228 | |||
| 59862e6d22 | |||
| 2dc60ec57f | |||
| 1854837b5a | |||
| 733da8d31a | |||
| 676bcf7457 | |||
| 42156fd90c | |||
| 219e7f7986 | |||
| 09f23d2a36 | |||
| 5933581cf0 | |||
| e367e453e1 | |||
| c1c1d4d4a6 | |||
| 90189be7ce | |||
| 8c55945220 | |||
| 769a8dea81 | |||
| 6831cad03b | |||
| 4ffaa7c5de | |||
| 5289c51050 |
+27
-10
@@ -710,6 +710,21 @@ fuzzcheck-asan$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP)
|
||||
fuzzcheck-ubsan$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP)
|
||||
$(LTLINK) -o $@ -fsanitize=undefined $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS)
|
||||
|
||||
# Usage: FUZZDB=filename make run-fuzzcheck
|
||||
#
|
||||
# Where filename is a fuzzcheck database, this target builds and runs
|
||||
# fuzzcheck, fuzzcheck-asan, and fuzzcheck-ubsan on that database.
|
||||
#
|
||||
# FUZZDB can be a glob pattern of two or more databases. Example:
|
||||
#
|
||||
# FUZZDB=test/fuzzdata*.db make run-fuzzcheck
|
||||
#
|
||||
run-fuzzcheck: fuzzcheck$(TEXE) fuzzcheck-asan$(TEXE) fuzzcheck-ubsan$(TEXE)
|
||||
@if test "$(FUZZDB)" = ""; then echo 'ERROR: No FUZZDB specified. Rerun with FUZZDB=filename'; exit 1; fi
|
||||
./fuzzcheck$(TEXE) --spinner $(FUZZDB)
|
||||
./fuzzcheck-asan$(TEXE) --spinner $(FUZZDB)
|
||||
./fuzzcheck-ubsan$(TEXE) --spinner $(FUZZDB)
|
||||
|
||||
ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \
|
||||
$(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
|
||||
@@ -1135,19 +1150,21 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
# Source files that go into making shell.c
|
||||
SHELL_SRC = \
|
||||
$(TOP)/src/shell.c.in \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/consio/console_io.c \
|
||||
$(TOP)/ext/consio/console_io.h \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/basexx.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/basexx.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
@@ -1156,7 +1173,7 @@ SHELL_SRC = \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.h \
|
||||
$(TOP)/src/test_windirent.c
|
||||
$(TOP)/src/test_windirent.c
|
||||
|
||||
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl has_tclsh84
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c
|
||||
|
||||
+4
-1
@@ -1610,7 +1610,8 @@ TESTSRC2 = \
|
||||
$(SRC01) \
|
||||
$(SRC07) \
|
||||
$(SRC10) \
|
||||
$(TOP)\ext\async\sqlite3async.c
|
||||
$(TOP)\ext\async\sqlite3async.c \
|
||||
fts5.c
|
||||
|
||||
# Header files used by all library source files.
|
||||
#
|
||||
@@ -2260,6 +2261,8 @@ keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
# Source files that go into making shell.c
|
||||
SHELL_SRC = \
|
||||
$(TOP)\src\shell.c.in \
|
||||
$(TOP)\ext\consio\console_io.c \
|
||||
$(TOP)\ext\consio\console_io.h \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\completion.c \
|
||||
$(TOP)\ext\misc\base64.c \
|
||||
|
||||
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so that we create the export library with the dll.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite],[3.44.0])
|
||||
AC_INIT([sqlite],[3.45.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.44.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.45.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.44.0'
|
||||
PACKAGE_STRING='sqlite 3.44.0'
|
||||
PACKAGE_VERSION='3.45.0'
|
||||
PACKAGE_STRING='sqlite 3.45.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1472,7 +1472,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.44.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.45.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1537,7 +1537,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.44.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.45.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1668,7 +1668,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.44.0
|
||||
sqlite configure 3.45.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2087,7 +2087,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.44.0, which was
|
||||
It was created by sqlite $as_me 3.45.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -12481,7 +12481,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.44.0, which was
|
||||
This file was extended by sqlite $as_me 3.45.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12547,7 +12547,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.44.0
|
||||
sqlite config.status 3.45.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@
|
||||
# you don't need (for example BLT) by erasing or commenting out
|
||||
# the corresponding code.
|
||||
#
|
||||
AC_INIT([sqlite],[m4_esyscmd(cat VERSION | tr -d '\n')])
|
||||
AC_INIT([sqlite],m4_esyscmd(cat VERSION | tr -d '\n'))
|
||||
|
||||
dnl Make sure the local VERSION file matches this configure script
|
||||
sqlite_version_sanity_check=`cat $srcdir/VERSION | tr -d '\n'`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 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:
|
||||
canonical source on a new Windows 11 PC, as of 2023-11-01:
|
||||
|
||||
1. Install Microsoft Visual Studio. The free "community edition"
|
||||
will work fine. Do a standard install for C++ development.
|
||||
@@ -84,6 +84,18 @@ following minor changes:
|
||||
<li> `set PATH=c:\tcl32\bin;%PATH%`
|
||||
</ul>
|
||||
|
||||
## Building a DLL
|
||||
|
||||
The command the developers use for building the deliverable DLL on the
|
||||
[download page](https://sqlite.org/download.html) is as follows:
|
||||
|
||||
> ~~~~
|
||||
nmake /f Makefile.msc sqlite3.dll USE_NATIVE_LIBPATHS=1 "OPTS=-DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_ENABLE_SERIALIZE=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1"
|
||||
~~~~
|
||||
|
||||
That command generates both the sqlite3.dll and sqlite3.def files. The same
|
||||
command works for both 32-bit and 64-bit builds.
|
||||
|
||||
## Statically Linking The TCL Library
|
||||
|
||||
Some utility programs associated with SQLite need to be linked
|
||||
|
||||
+69
-9
@@ -2,6 +2,26 @@
|
||||
|
||||
# The testrunner.tcl Script
|
||||
|
||||
<ul type=none>
|
||||
<li> 1. <a href=#overview>Overview</a>
|
||||
<li> 2. <a href=#binary_tests>Binary Tests</a>
|
||||
<ul type=none>
|
||||
<li> 2.1. <a href=#organization_tests>Organization of Tcl Tests</a>
|
||||
<li> 2.2. <a href=#run_tests>Commands to Run Tests</a>
|
||||
<li> 2.3. <a href=#binary_test_failures>Investigating Binary Test Failures</a>
|
||||
</ul>
|
||||
<li> 3. <a href=#source_code_tests>Source Tests</a>
|
||||
<ul type=none>
|
||||
<li> 3.1. <a href=#commands_to_run_tests>Commands to Run SQLite Tests</a>
|
||||
<li> 3.2. <a href=#zipvfs_tests>Running ZipVFS Tests</a>
|
||||
<li> 3.3. <a href=#source_code_test_failures>Investigating Source Code Test Failures</a>
|
||||
</ul>
|
||||
<li> 4. <a href=#testrunner_options>Extra testrunner.tcl Options</a>
|
||||
# 4. Extra testrunner.tcl Options
|
||||
<li> 5. <a href=#cpu_cores>Controlling CPU Core Utilization</a>
|
||||
</ul>
|
||||
|
||||
<a name=overview></a>
|
||||
# 1. Overview
|
||||
|
||||
testrunner.tcl is a Tcl script used to run multiple SQLite tests using
|
||||
@@ -44,6 +64,7 @@ Sometimes testrunner.tcl uses the [testfixture] binary that it is run with
|
||||
to run tests (see "Binary Tests" below). Sometimes it builds testfixture and
|
||||
other binaries in specific configurations to test (see "Source Tests").
|
||||
|
||||
<a name=binary_tests></a>
|
||||
# 2. Binary Tests
|
||||
|
||||
The commands described in this section all run various combinations of the Tcl
|
||||
@@ -61,6 +82,7 @@ these tests is therefore:
|
||||
The following sub-sections describe the various options that can be
|
||||
passed to testrunner.tcl to test binary testfixture builds.
|
||||
|
||||
<a name=organization_tests></a>
|
||||
## 2.1. Organization of Tcl Tests
|
||||
|
||||
Tcl tests are stored in files that match the pattern *\*.test*. They are
|
||||
@@ -91,6 +113,7 @@ Running **all** tests is to run all tests in the full test set, plus a dozen
|
||||
or so permutations. The specific permutations that are run as part of "all"
|
||||
are defined in file *testrunner_data.tcl*.
|
||||
|
||||
<a name=run_tests></a>
|
||||
## 2.2. Commands to Run Tests
|
||||
|
||||
To run the "veryquick" test set, use either of the following:
|
||||
@@ -114,6 +137,12 @@ a specified pattern (e.g. all tests that start with "fts5"), either of:
|
||||
./testfixture $TESTDIR/testrunner.tcl 'fts5*'
|
||||
```
|
||||
|
||||
Strictly speaking, for a test to be run the pattern must match the script
|
||||
filename, not including the directory, using the rules of Tcl's
|
||||
\[string match\] command. Except that before the matching is done, any "%"
|
||||
characters specified as part of the pattern are transformed to "\*".
|
||||
|
||||
|
||||
To run "all" tests (full + permutations):
|
||||
|
||||
```
|
||||
@@ -141,6 +170,7 @@ Or, if the failure occured as part of a permutation:
|
||||
|
||||
TODO: An example instead of "$PERMUTATION" and $PATH\_TO\_SCRIPT?
|
||||
|
||||
<a name=source_code_tests></a>
|
||||
# 3. Source Code Tests
|
||||
|
||||
The commands described in this section invoke the C compiler to build
|
||||
@@ -159,7 +189,8 @@ shell that supports SQLite 3.31.1 or newer via "package require sqlite3".
|
||||
|
||||
TODO: ./configure + Makefile.msc build systems.
|
||||
|
||||
## Commands to Run SQLite Tests
|
||||
<a name=commands_to_run_tests></a>
|
||||
## 3.1. Commands to Run SQLite Tests
|
||||
|
||||
The **mdevtest** command is equivalent to running the veryquick tests and
|
||||
the [make fuzztest] target once for each of two --enable-all builds - one
|
||||
@@ -201,7 +232,18 @@ of the specific tests run.
|
||||
tclsh $TESTDIR/testrunner.tcl release
|
||||
```
|
||||
|
||||
## Running ZipVFS Tests
|
||||
As with <a href=#source code tests>source code tests</a>, one or more patterns
|
||||
may be appended to any of the above commands (mdevtest, sdevtest or release).
|
||||
In that case only Tcl tests (no fuzz or other tests) that match the specified
|
||||
pattern are run. For example, to run the just the Tcl rtree tests in all
|
||||
builds and configurations supported by "release":
|
||||
|
||||
```
|
||||
tclsh $TESTDIR/testrunner.tcl release rtree%
|
||||
```
|
||||
|
||||
<a name=zipvfs_tests></a>
|
||||
## 3.2. Running ZipVFS Tests
|
||||
|
||||
testrunner.tcl can build a zipvfs-enabled testfixture and use it to run
|
||||
tests from the Zipvfs project with the following command:
|
||||
@@ -217,7 +259,8 @@ test both SQLite and Zipvfs with a single command:
|
||||
tclsh $TESTDIR/testrunner.tcl --zipvfs $PATH_TO_ZIPVFS mdevtest
|
||||
```
|
||||
|
||||
## Investigating Source Code Test Failures
|
||||
<a name=source_code_test_failures></a>
|
||||
## 3.3. Investigating Source Code Test Failures
|
||||
|
||||
Investigating a test failure that occurs during source code testing is a
|
||||
two step process:
|
||||
@@ -244,9 +287,31 @@ target to build. This may be used either to run a [make] command test directly,
|
||||
or else to build a testfixture (or testfixture.exe) binary with which to
|
||||
run a Tcl test script, as <a href=#binary_test_failures>described above</a>.
|
||||
|
||||
<a name=testrunner_options></a>
|
||||
# 4. Extra testrunner.tcl Options
|
||||
|
||||
The testrunner.tcl script options in this section may be used with both source
|
||||
code and binary tests.
|
||||
|
||||
# 4. Controlling CPU Core Utilization
|
||||
The **--buildonly** option instructs testrunner.tcl just to build the binaries
|
||||
required by a test, not to run any actual tests. For example:
|
||||
|
||||
```
|
||||
# Build binaries required by release test.
|
||||
tclsh $TESTDIR/testrunner.tcl --buildonly release"
|
||||
```
|
||||
|
||||
The **--dryrun** option prevents testrunner.tcl from building any binaries
|
||||
or running any tests. Instead, it just writes the shell commands that it
|
||||
would normally execute into the testrunner.log file. Example:
|
||||
|
||||
```
|
||||
# Log the shell commmands that make up the mdevtest test.
|
||||
tclsh $TESTDIR/testrunner.tcl --dryrun mdevtest"
|
||||
```
|
||||
|
||||
<a name=cpu_cores></a>
|
||||
# 5. Controlling CPU Core Utilization
|
||||
|
||||
When running either binary or source code tests, testrunner.tcl reports the
|
||||
number of jobs it intends to use to stdout. e.g.
|
||||
@@ -277,8 +342,3 @@ testrunner.log and testrunner.db files:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+678
@@ -0,0 +1,678 @@
|
||||
/*
|
||||
** 2023 November 4
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
********************************************************************************
|
||||
** This file implements various interfaces used for console and stream I/O
|
||||
** by the SQLite project command-line tools, as explained in console_io.h .
|
||||
** Functions prefixed by "SQLITE_INTERNAL_LINKAGE" behave as described there.
|
||||
*/
|
||||
|
||||
#ifndef SQLITE_CDECL
|
||||
# define SQLITE_CDECL
|
||||
#endif
|
||||
|
||||
#ifndef SHELL_NO_SYSINC
|
||||
# include <stdarg.h>
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
# include <assert.h>
|
||||
# include "console_io.h"
|
||||
# include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
|
||||
# ifndef SHELL_NO_SYSINC
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# define CIO_WIN_WC_XLATE 1 /* Use WCHAR Windows APIs for console I/O */
|
||||
# else
|
||||
# ifndef SHELL_NO_SYSINC
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# define CIO_WIN_WC_XLATE 0 /* Use plain C library stream I/O at console */
|
||||
# endif
|
||||
#else
|
||||
# define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
/* Character used to represent a known-incomplete UTF-8 char group (�) */
|
||||
static WCHAR cBadGroup = 0xfffd;
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
static HANDLE handleOfFile(FILE *pf){
|
||||
int fileDesc = _fileno(pf);
|
||||
union { intptr_t osfh; HANDLE fh; } fid = {
|
||||
(fileDesc>=0)? _get_osfhandle(fileDesc) : (intptr_t)INVALID_HANDLE_VALUE
|
||||
};
|
||||
return fid.fh;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
typedef struct PerStreamTags {
|
||||
# if CIO_WIN_WC_XLATE
|
||||
HANDLE hx;
|
||||
DWORD consMode;
|
||||
char acIncomplete[4];
|
||||
# else
|
||||
short reachesConsole;
|
||||
# endif
|
||||
FILE *pf;
|
||||
} PerStreamTags;
|
||||
|
||||
/* Define NULL-like value for things which can validly be 0. */
|
||||
# define SHELL_INVALID_FILE_PTR ((FILE *)~0)
|
||||
# if CIO_WIN_WC_XLATE
|
||||
# define SHELL_INVALID_CONS_MODE 0xFFFF0000
|
||||
# endif
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
# define PST_INITIALIZER { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, \
|
||||
{0,0,0,0}, SHELL_INVALID_FILE_PTR }
|
||||
# else
|
||||
# define PST_INITIALIZER { 0, SHELL_INVALID_FILE_PTR }
|
||||
# endif
|
||||
|
||||
/* Quickly say whether a known output is going to the console. */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static short pstReachesConsole(PerStreamTags *ppst){
|
||||
return (ppst->hx != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
# else
|
||||
# define pstReachesConsole(ppst) 0
|
||||
# endif
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void restoreConsoleArb(PerStreamTags *ppst){
|
||||
if( pstReachesConsole(ppst) ) SetConsoleMode(ppst->hx, ppst->consMode);
|
||||
}
|
||||
# else
|
||||
# define restoreConsoleArb(ppst)
|
||||
# endif
|
||||
|
||||
/* Say whether FILE* appears to be a console, collect associated info. */
|
||||
static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){
|
||||
# if CIO_WIN_WC_XLATE
|
||||
short rv = 0;
|
||||
DWORD dwCM = SHELL_INVALID_CONS_MODE;
|
||||
HANDLE fh = handleOfFile(pf);
|
||||
ppst->pf = pf;
|
||||
if( INVALID_HANDLE_VALUE != fh ){
|
||||
rv = (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwCM));
|
||||
}
|
||||
ppst->hx = (rv)? fh : INVALID_HANDLE_VALUE;
|
||||
ppst->consMode = dwCM;
|
||||
return rv;
|
||||
# else
|
||||
ppst->pf = pf;
|
||||
ppst->reachesConsole = ( (short)isatty(fileno(pf)) );
|
||||
return ppst->reachesConsole;
|
||||
# endif
|
||||
}
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
/* Define console modes for use with the Windows Console API. */
|
||||
# define SHELL_CONI_MODE \
|
||||
(ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \
|
||||
| ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT)
|
||||
# define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \
|
||||
| ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
# endif
|
||||
|
||||
typedef struct ConsoleInfo {
|
||||
PerStreamTags pstSetup[3];
|
||||
PerStreamTags pstDesignated[3];
|
||||
StreamsAreConsole sacSetup;
|
||||
} ConsoleInfo;
|
||||
|
||||
static short isValidStreamInfo(PerStreamTags *ppst){
|
||||
return (ppst->pf != SHELL_INVALID_FILE_PTR);
|
||||
}
|
||||
|
||||
static ConsoleInfo consoleInfo = {
|
||||
{ /* pstSetup */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
|
||||
{ /* pstDesignated[] */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
|
||||
SAC_NoConsole /* sacSetup */
|
||||
};
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE FILE* invalidFileStream = (FILE *)~0;
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void maybeSetupAsConsole(PerStreamTags *ppst, short odir){
|
||||
if( pstReachesConsole(ppst) ){
|
||||
DWORD cm = odir? SHELL_CONO_MODE : SHELL_CONI_MODE;
|
||||
SetConsoleMode(ppst->hx, cm);
|
||||
}
|
||||
}
|
||||
# else
|
||||
# define maybeSetupAsConsole(ppst,odir)
|
||||
# endif
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void){
|
||||
# if CIO_WIN_WC_XLATE
|
||||
int ix = 0;
|
||||
while( ix < 6 ){
|
||||
PerStreamTags *ppst = (ix<3)?
|
||||
&consoleInfo.pstSetup[ix] : &consoleInfo.pstDesignated[ix-3];
|
||||
maybeSetupAsConsole(ppst, (ix % 3)>0);
|
||||
++ix;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE StreamsAreConsole
|
||||
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){
|
||||
StreamsAreConsole rv = SAC_NoConsole;
|
||||
FILE* apf[3] = { pfIn, pfOut, pfErr };
|
||||
int ix;
|
||||
for( ix = 2; ix >= 0; --ix ){
|
||||
PerStreamTags *ppst = &consoleInfo.pstSetup[ix];
|
||||
if( streamOfConsole(apf[ix], ppst) ){
|
||||
rv |= (SAC_InConsole<<ix);
|
||||
}
|
||||
consoleInfo.pstDesignated[ix] = *ppst;
|
||||
if( ix > 0 ) fflush(apf[ix]);
|
||||
}
|
||||
consoleInfo.sacSetup = rv;
|
||||
consoleRenewSetup();
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ){
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static ConsoleInfo *pci = &consoleInfo;
|
||||
if( pci->sacSetup ){
|
||||
int ix;
|
||||
for( ix=0; ix<3; ++ix ){
|
||||
if( pci->sacSetup & (SAC_InConsole<<ix) ){
|
||||
PerStreamTags *ppst = &pci->pstSetup[ix];
|
||||
SetConsoleMode(ppst->hx, ppst->consMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#ifdef SQLITE_CIO_INPUT_REDIR
|
||||
/* Say whether given FILE* is among those known, via either
|
||||
** consoleClassifySetup() or set{Output,Error}Stream, as
|
||||
** readable, and return an associated PerStreamTags pointer
|
||||
** if so. Otherwise, return 0.
|
||||
*/
|
||||
static PerStreamTags * isKnownReadable(FILE *pf){
|
||||
static PerStreamTags *apst[] = {
|
||||
&consoleInfo.pstDesignated[0], &consoleInfo.pstSetup[0], 0
|
||||
};
|
||||
int ix = 0;
|
||||
do {
|
||||
if( apst[ix]->pf == pf ) break;
|
||||
} while( apst[++ix] != 0 );
|
||||
return apst[ix];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
/* Say whether given FILE* is among those known, via either
|
||||
** consoleClassifySetup() or set{Output,Error}Stream, as
|
||||
** writable, and return an associated PerStreamTags pointer
|
||||
** if so. Otherwise, return 0.
|
||||
*/
|
||||
static PerStreamTags * isKnownWritable(FILE *pf){
|
||||
static PerStreamTags *apst[] = {
|
||||
&consoleInfo.pstDesignated[1], &consoleInfo.pstDesignated[2],
|
||||
&consoleInfo.pstSetup[1], &consoleInfo.pstSetup[2], 0
|
||||
};
|
||||
int ix = 0;
|
||||
do {
|
||||
if( apst[ix]->pf == pf ) break;
|
||||
} while( apst[++ix] != 0 );
|
||||
return apst[ix];
|
||||
}
|
||||
|
||||
static FILE *designateEmitStream(FILE *pf, unsigned chix){
|
||||
FILE *rv = consoleInfo.pstDesignated[chix].pf;
|
||||
if( pf == invalidFileStream ) return rv;
|
||||
else{
|
||||
/* Setting a possibly new output stream. */
|
||||
PerStreamTags *ppst = isKnownWritable(pf);
|
||||
if( ppst != 0 ){
|
||||
PerStreamTags pst = *ppst;
|
||||
consoleInfo.pstDesignated[chix] = pst;
|
||||
}else streamOfConsole(pf, &consoleInfo.pstDesignated[chix]);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf){
|
||||
return designateEmitStream(pf, 1);
|
||||
}
|
||||
# ifdef CONSIO_SET_ERROR_STREAM
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf){
|
||||
return designateEmitStream(pf, 2);
|
||||
}
|
||||
# endif
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_SETMODE
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void setModeFlushQ(FILE *pf, short bFlush, int mode){
|
||||
if( bFlush ) fflush(pf);
|
||||
_setmode(_fileno(pf), mode);
|
||||
}
|
||||
# else
|
||||
# define setModeFlushQ(f, b, m) if(b) fflush(f)
|
||||
# endif
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *pf, short bFlush){
|
||||
setModeFlushQ(pf, bFlush, _O_BINARY);
|
||||
}
|
||||
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *pf, short bFlush){
|
||||
setModeFlushQ(pf, bFlush, _O_TEXT);
|
||||
}
|
||||
# undef setModeFlushQ
|
||||
|
||||
#else /* defined(SQLITE_CIO_NO_SETMODE) */
|
||||
# define setBinaryMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
|
||||
# define setTextMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
|
||||
#endif /* defined(SQLITE_CIO_NO_SETMODE) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# if CIO_WIN_WC_XLATE
|
||||
/* Write buffer cBuf as output to stream known to reach console,
|
||||
** limited to ncTake char's. Return ncTake on success, else 0. */
|
||||
static int conZstrEmit(PerStreamTags *ppst, const char *z, int ncTake){
|
||||
int rv = 0;
|
||||
if( z!=NULL ){
|
||||
int nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, 0,0);
|
||||
if( nwc > 0 ){
|
||||
WCHAR *zw = sqlite3_malloc64(nwc*sizeof(WCHAR));
|
||||
if( zw!=NULL ){
|
||||
nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, zw,nwc);
|
||||
if( nwc > 0 ){
|
||||
/* Translation from UTF-8 to UTF-16, then WCHARs out. */
|
||||
if( WriteConsoleW(ppst->hx, zw,nwc, 0, NULL) ){
|
||||
rv = ncTake;
|
||||
}
|
||||
}
|
||||
sqlite3_free(zw);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For {f,o,e}PrintfUtf8() when stream is known to reach console. */
|
||||
static int conioVmPrintf(PerStreamTags *ppst, const char *zFormat, va_list ap){
|
||||
char *z = sqlite3_vmprintf(zFormat, ap);
|
||||
if( z ){
|
||||
int rv = conZstrEmit(ppst, z, (int)strlen(z));
|
||||
sqlite3_free(z);
|
||||
return rv;
|
||||
}else return 0;
|
||||
}
|
||||
# endif /* CIO_WIN_WC_XLATE */
|
||||
|
||||
# ifdef CONSIO_GET_EMIT_STREAM
|
||||
static PerStreamTags * getDesignatedEmitStream(FILE *pf, unsigned chix,
|
||||
PerStreamTags *ppst){
|
||||
PerStreamTags *rv = isKnownWritable(pf);
|
||||
short isValid = (rv!=0)? isValidStreamInfo(rv) : 0;
|
||||
if( rv != 0 && isValid ) return rv;
|
||||
streamOfConsole(pf, ppst);
|
||||
return ppst;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Get stream info, either for designated output or error stream when
|
||||
** chix equals 1 or 2, or for an arbitrary stream when chix == 0.
|
||||
** In either case, ppst references a caller-owned PerStreamTags
|
||||
** struct which may be filled in if none of the known writable
|
||||
** streams is being held by consoleInfo. The ppf parameter is a
|
||||
** byref output when chix!=0 and a byref input when chix==0.
|
||||
*/
|
||||
static PerStreamTags *
|
||||
getEmitStreamInfo(unsigned chix, PerStreamTags *ppst,
|
||||
/* in/out */ FILE **ppf){
|
||||
PerStreamTags *ppstTry;
|
||||
FILE *pfEmit;
|
||||
if( chix > 0 ){
|
||||
ppstTry = &consoleInfo.pstDesignated[chix];
|
||||
if( !isValidStreamInfo(ppstTry) ){
|
||||
ppstTry = &consoleInfo.pstSetup[chix];
|
||||
pfEmit = ppst->pf;
|
||||
}else pfEmit = ppstTry->pf;
|
||||
if( !isValidStreamInfo(ppstTry) ){
|
||||
pfEmit = (chix > 1)? stderr : stdout;
|
||||
ppstTry = ppst;
|
||||
streamOfConsole(pfEmit, ppstTry);
|
||||
}
|
||||
*ppf = pfEmit;
|
||||
}else{
|
||||
ppstTry = isKnownWritable(*ppf);
|
||||
if( ppstTry != 0 ) return ppstTry;
|
||||
streamOfConsole(*ppf, ppst);
|
||||
return ppst;
|
||||
}
|
||||
return ppstTry;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rv;
|
||||
FILE *pfOut;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# else
|
||||
getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# endif
|
||||
assert(zFormat!=0);
|
||||
va_start(ap, zFormat);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
rv = conioVmPrintf(ppst, zFormat, ap);
|
||||
}else{
|
||||
# endif
|
||||
rv = vfprintf(pfOut, zFormat, ap);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rv;
|
||||
FILE *pfErr;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# else
|
||||
getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# endif
|
||||
assert(zFormat!=0);
|
||||
va_start(ap, zFormat);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
rv = conioVmPrintf(ppst, zFormat, ap);
|
||||
}else{
|
||||
# endif
|
||||
rv = vfprintf(pfErr, zFormat, ap);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rv;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
|
||||
# else
|
||||
getEmitStreamInfo(0, &pst, &pfO);
|
||||
# endif
|
||||
assert(zFormat!=0);
|
||||
va_start(ap, zFormat);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
maybeSetupAsConsole(ppst, 1);
|
||||
rv = conioVmPrintf(ppst, zFormat, ap);
|
||||
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
|
||||
}else{
|
||||
# endif
|
||||
rv = vfprintf(pfO, zFormat, ap);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO){
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
|
||||
# else
|
||||
getEmitStreamInfo(0, &pst, &pfO);
|
||||
# endif
|
||||
assert(z!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
int rv;
|
||||
maybeSetupAsConsole(ppst, 1);
|
||||
rv = conZstrEmit(ppst, z, (int)strlen(z));
|
||||
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
|
||||
return rv;
|
||||
}else {
|
||||
# endif
|
||||
return (fputs(z, pfO)<0)? 0 : (int)strlen(z);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z){
|
||||
FILE *pfErr;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# else
|
||||
getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# endif
|
||||
assert(z!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
|
||||
else {
|
||||
# endif
|
||||
return (fputs(z, pfErr)<0)? 0 : (int)strlen(z);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z){
|
||||
FILE *pfOut;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# else
|
||||
getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# endif
|
||||
assert(z!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
|
||||
else {
|
||||
# endif
|
||||
return (fputs(z, pfOut)<0)? 0 : (int)strlen(z);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#if !(defined(SQLITE_CIO_NO_UTF8SCAN) && defined(SQLITE_CIO_NO_TRANSLATE))
|
||||
/* Skip over as much z[] input char sequence as is valid UTF-8,
|
||||
** limited per nAccept char's or whole characters and containing
|
||||
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
|
||||
** sequence z:return (inclusive:exclusive) is validated UTF-8.
|
||||
** Limit: nAccept>=0 => char count, nAccept<0 => character
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE const char*
|
||||
zSkipValidUtf8(const char *z, int nAccept, long ccm){
|
||||
int ng = (nAccept<0)? -nAccept : 0;
|
||||
const char *pcLimit = (nAccept>=0)? z+nAccept : 0;
|
||||
assert(z!=0);
|
||||
while( (pcLimit)? (z<pcLimit) : (ng-- != 0) ){
|
||||
char c = *z;
|
||||
if( (c & 0x80) == 0 ){
|
||||
if( ccm != 0L && c < 0x20 && ((1L<<c) & ccm) != 0 ) return z;
|
||||
++z; /* ASCII */
|
||||
}else if( (c & 0xC0) != 0xC0 ) return z; /* not a lead byte */
|
||||
else{
|
||||
const char *zt = z+1; /* Got lead byte, look at trail bytes.*/
|
||||
do{
|
||||
if( pcLimit && zt >= pcLimit ) return z;
|
||||
else{
|
||||
char ct = *zt++;
|
||||
if( ct==0 || (zt-z)>4 || (ct & 0xC0)!=0x80 ){
|
||||
/* Trailing bytes are too few, too many, or invalid. */
|
||||
return z;
|
||||
}
|
||||
}
|
||||
} while( ((c <<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */
|
||||
z = zt;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
#endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# ifdef CONSIO_SPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fPutbUtf8(FILE *pfO, const char *cBuf, int nAccept){
|
||||
assert(pfO!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
|
||||
if( pstReachesConsole(ppst) ){
|
||||
int rv;
|
||||
maybeSetupAsConsole(ppst, 1);
|
||||
rv = conZstrEmit(ppst, cBuf, nAccept);
|
||||
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
|
||||
return rv;
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfO);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
oPutbUtf8(const char *cBuf, int nAccept){
|
||||
FILE *pfOut;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# else
|
||||
getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# endif
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
return conZstrEmit(ppst, cBuf, nAccept);
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfOut);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef CONSIO_EPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept){
|
||||
FILE *pfErr;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
return conZstrEmit(ppst, cBuf, nAccept);
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfErr);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
# endif /* defined(CONSIO_EPUTB) */
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
|
||||
if( pfIn==0 ) pfIn = stdin;
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pfIn == consoleInfo.pstSetup[0].pf
|
||||
&& (consoleInfo.sacSetup & SAC_InConsole)!=0 ){
|
||||
# if CIO_WIN_WC_XLATE==1
|
||||
# define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */
|
||||
WCHAR wcBuf[SHELL_GULP+1];
|
||||
int lend = 0, noc = 0;
|
||||
if( ncMax > 0 ) cBuf[0] = 0;
|
||||
while( noc < ncMax-8-1 && !lend ){
|
||||
/* There is room for at least 2 more characters and a 0-terminator. */
|
||||
int na = (ncMax > SHELL_GULP*4+1 + noc)? SHELL_GULP : (ncMax-1 - noc)/4;
|
||||
# undef SHELL_GULP
|
||||
DWORD nbr = 0;
|
||||
BOOL bRC = ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf, na, &nbr, 0);
|
||||
if( bRC && nbr>0 && (wcBuf[nbr-1]&0xF800)==0xD800 ){
|
||||
/* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */
|
||||
DWORD nbrx;
|
||||
bRC &= ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf+nbr, 1, &nbrx, 0);
|
||||
if( bRC ) nbr += nbrx;
|
||||
}
|
||||
if( !bRC || (noc==0 && nbr==0) ) return 0;
|
||||
if( nbr > 0 ){
|
||||
int nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,0,0,0,0);
|
||||
if( nmb != 0 && noc+nmb <= ncMax ){
|
||||
int iseg = noc;
|
||||
nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,cBuf+noc,nmb,0,0);
|
||||
noc += nmb;
|
||||
/* Fixup line-ends as coded by Windows for CR (or "Enter".)
|
||||
** This is done without regard for any setMode{Text,Binary}()
|
||||
** call that might have been done on the interactive input.
|
||||
*/
|
||||
if( noc > 0 ){
|
||||
if( cBuf[noc-1]=='\n' ){
|
||||
lend = 1;
|
||||
if( noc > 1 && cBuf[noc-2]=='\r' ) cBuf[--noc-1] = '\n';
|
||||
}
|
||||
}
|
||||
/* Check for ^Z (anywhere in line) too, to act as EOF. */
|
||||
while( iseg < noc ){
|
||||
if( cBuf[iseg]=='\x1a' ){
|
||||
noc = iseg; /* Chop ^Z and anything following. */
|
||||
lend = 1; /* Counts as end of line too. */
|
||||
break;
|
||||
}
|
||||
++iseg;
|
||||
}
|
||||
}else break; /* Drop apparent garbage in. (Could assert.) */
|
||||
}else break;
|
||||
}
|
||||
/* If got nothing, (after ^Z chop), must be at end-of-file. */
|
||||
if( noc > 0 ){
|
||||
cBuf[noc] = 0;
|
||||
return cBuf;
|
||||
}else return 0;
|
||||
# endif
|
||||
}else{
|
||||
# endif
|
||||
return fgets(cBuf, ncMax, pfIn);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#undef SHELL_INVALID_FILE_PTR
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
** 2023 November 1
|
||||
**
|
||||
** 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 exposes various interfaces used for console and other I/O
|
||||
** by the SQLite project command-line tools. These interfaces are used
|
||||
** at either source conglomeration time, compilation time, or run time.
|
||||
** This source provides for either inclusion into conglomerated,
|
||||
** "single-source" forms or separate compilation then linking.
|
||||
**
|
||||
** Platform dependencies are "hidden" here by various stratagems so
|
||||
** that, provided certain conditions are met, the programs using this
|
||||
** source or object code compiled from it need no explicit conditional
|
||||
** compilation in their source for their console and stream I/O.
|
||||
**
|
||||
** The symbols and functionality exposed here are not a public API.
|
||||
** This code may change in tandem with other project code as needed.
|
||||
**
|
||||
** When this .h file and its companion .c are directly incorporated into
|
||||
** a source conglomeration (such as shell.c), the preprocessor symbol
|
||||
** CIO_WIN_WC_XLATE is defined as 0 or 1, reflecting whether console I/O
|
||||
** translation for Windows is effected for the build.
|
||||
*/
|
||||
|
||||
#ifndef SQLITE_INTERNAL_LINKAGE
|
||||
# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */
|
||||
# include <stdio.h>
|
||||
#else
|
||||
# define SHELL_NO_SYSINC /* Better yet, modify mkshellc.tcl for this. */
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE3_H
|
||||
# include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_CLASSIFY
|
||||
|
||||
/* Define enum for use with following function. */
|
||||
typedef enum StreamsAreConsole {
|
||||
SAC_NoConsole = 0,
|
||||
SAC_InConsole = 1, SAC_OutConsole = 2, SAC_ErrConsole = 4,
|
||||
SAC_AnyConsole = 0x7
|
||||
} StreamsAreConsole;
|
||||
|
||||
/*
|
||||
** Classify the three standard I/O streams according to whether
|
||||
** they are connected to a console attached to the process.
|
||||
**
|
||||
** Returns the bit-wise OR of SAC_{In,Out,Err}Console values,
|
||||
** or SAC_NoConsole if none of the streams reaches a console.
|
||||
**
|
||||
** This function should be called before any I/O is done with
|
||||
** the given streams. As a side-effect, the given inputs are
|
||||
** recorded so that later I/O operations on them may be done
|
||||
** differently than the C library FILE* I/O would be done,
|
||||
** iff the stream is used for the I/O functions that follow,
|
||||
** and to support the ones that use an implicit stream.
|
||||
**
|
||||
** On some platforms, stream or console mode alteration (aka
|
||||
** "Setup") may be made which is undone by consoleRestore().
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE StreamsAreConsole
|
||||
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr );
|
||||
/* A usual call for convenience: */
|
||||
#define SQLITE_STD_CONSOLE_INIT() consoleClassifySetup(stdin,stdout,stderr)
|
||||
|
||||
/*
|
||||
** After an initial call to consoleClassifySetup(...), renew
|
||||
** the same setup it effected. (A call not after is an error.)
|
||||
** This will restore state altered by consoleRestore();
|
||||
**
|
||||
** Applications which run an inferior (child) process which
|
||||
** inherits the same I/O streams may call this function after
|
||||
** such a process exits to guard against console mode changes.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void);
|
||||
|
||||
/*
|
||||
** Undo any side-effects left by consoleClassifySetup(...).
|
||||
**
|
||||
** This should be called after consoleClassifySetup() and
|
||||
** before the process terminates normally. It is suitable
|
||||
** for use with the atexit() C library procedure. After
|
||||
** this call, no console I/O should be done until one of
|
||||
** console{Classify or Renew}Setup(...) is called again.
|
||||
**
|
||||
** Applications which run an inferior (child) process that
|
||||
** inherits the same I/O streams might call this procedure
|
||||
** before so that said process will have a console setup
|
||||
** however users have configured it or come to expect.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void );
|
||||
|
||||
#else /* defined(SQLITE_CIO_NO_CLASSIFY) */
|
||||
# define consoleClassifySetup(i,o,e)
|
||||
# define consoleRenewSetup()
|
||||
# define consoleRestore()
|
||||
#endif /* defined(SQLITE_CIO_NO_CLASSIFY) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_REDIRECT
|
||||
/*
|
||||
** Set stream to be used for the functions below which write
|
||||
** to "the designated X stream", where X is Output or Error.
|
||||
** Returns the previous value.
|
||||
**
|
||||
** Alternatively, pass the special value, invalidFileStream,
|
||||
** to get the designated stream value without setting it.
|
||||
**
|
||||
** Before the designated streams are set, they default to
|
||||
** those passed to consoleClassifySetup(...), and before
|
||||
** that is called they default to stdout and stderr.
|
||||
**
|
||||
** It is error to close a stream so designated, then, without
|
||||
** designating another, use the corresponding {o,e}Emit(...).
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE FILE *invalidFileStream;
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf);
|
||||
# ifdef CONSIO_SET_ERROR_STREAM
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf);
|
||||
# endif
|
||||
#else
|
||||
# define setOutputStream(pf)
|
||||
# define setErrorStream(pf)
|
||||
#endif /* !defined(SQLITE_CIO_NO_REDIRECT) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
/*
|
||||
** Emit output like fprintf(). If the output is going to the
|
||||
** console and translation from UTF-8 is necessary, perform
|
||||
** the needed translation. Otherwise, write formatted output
|
||||
** to the provided stream almost as-is, possibly with newline
|
||||
** translation as specified by set{Binary,Text}Mode().
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...);
|
||||
/* Like fPrintfUtf8 except stream is always the designated output. */
|
||||
SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...);
|
||||
/* Like fPrintfUtf8 except stream is always the designated error. */
|
||||
SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...);
|
||||
|
||||
/*
|
||||
** Emit output like fputs(). If the output is going to the
|
||||
** console and translation from UTF-8 is necessary, perform
|
||||
** the needed translation. Otherwise, write given text to the
|
||||
** provided stream almost as-is, possibly with newline
|
||||
** translation as specified by set{Binary,Text}Mode().
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO);
|
||||
/* Like fPutsUtf8 except stream is always the designated output. */
|
||||
SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z);
|
||||
/* Like fPutsUtf8 except stream is always the designated error. */
|
||||
SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z);
|
||||
|
||||
/*
|
||||
** Emit output like fPutsUtf8(), except that the length of the
|
||||
** accepted char or character sequence is limited by nAccept.
|
||||
**
|
||||
** Returns the number of accepted char values.
|
||||
*/
|
||||
#ifdef CONSIO_SPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fPutbUtf8(FILE *pfOut, const char *cBuf, int nAccept);
|
||||
/* Like fPutbUtf8 except stream is always the designated output. */
|
||||
#endif
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
oPutbUtf8(const char *cBuf, int nAccept);
|
||||
/* Like fPutbUtf8 except stream is always the designated error. */
|
||||
#ifdef CONSIO_EPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Collect input like fgets(...) with special provisions for input
|
||||
** from the console on platforms that require same. Defers to the
|
||||
** C library fgets() when input is not from the console. Newline
|
||||
** translation may be done as set by set{Binary,Text}Mode(). As a
|
||||
** convenience, pfIn==NULL is treated as stdin.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn);
|
||||
/* Like fGetsUtf8 except stream is always the designated input. */
|
||||
/* SQLITE_INTERNAL_LINKAGE char* iGetsUtf8(char *cBuf, int ncMax); */
|
||||
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_SETMODE
|
||||
/*
|
||||
** Set given stream for binary mode, where newline translation is
|
||||
** not done, or for text mode where, for some platforms, newlines
|
||||
** are translated to the platform's conventional char sequence.
|
||||
** If bFlush true, flush the stream.
|
||||
**
|
||||
** An additional side-effect is that if the stream is one passed
|
||||
** to consoleClassifySetup() as an output, it is flushed first.
|
||||
**
|
||||
** Note that binary/text mode has no effect on console I/O
|
||||
** translation. On all platforms, newline to the console starts
|
||||
** a new line and CR,LF chars from the console become a newline.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *, short bFlush);
|
||||
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *, short bFlush);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_CIO_PROMPTED_IN
|
||||
typedef struct Prompts {
|
||||
int numPrompts;
|
||||
const char **azPrompts;
|
||||
} Prompts;
|
||||
|
||||
/*
|
||||
** Macros for use of a line editor.
|
||||
**
|
||||
** The following macros define operations involving use of a
|
||||
** line-editing library or simple console interaction.
|
||||
** A "T" argument is a text (char *) buffer or filename.
|
||||
** A "N" argument is an integer.
|
||||
**
|
||||
** SHELL_ADD_HISTORY(T) // Record text as line(s) of history.
|
||||
** SHELL_READ_HISTORY(T) // Read history from file named by T.
|
||||
** SHELL_WRITE_HISTORY(T) // Write history to file named by T.
|
||||
** SHELL_STIFLE_HISTORY(N) // Limit history to N entries.
|
||||
**
|
||||
** A console program which does interactive console input is
|
||||
** expected to call:
|
||||
** SHELL_READ_HISTORY(T) before collecting such input;
|
||||
** SHELL_ADD_HISTORY(T) as record-worthy input is taken;
|
||||
** SHELL_STIFLE_HISTORY(N) after console input ceases; then
|
||||
** SHELL_WRITE_HISTORY(T) before the program exits.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Retrieve a single line of input text from an input stream.
|
||||
**
|
||||
** If pfIn is the input stream passed to consoleClassifySetup(),
|
||||
** and azPrompt is not NULL, then a prompt is issued before the
|
||||
** line is collected, as selected by the isContinuation flag.
|
||||
** Array azPrompt[{0,1}] holds the {main,continuation} prompt.
|
||||
**
|
||||
** If zBufPrior is not NULL then it is a buffer from a prior
|
||||
** call to this routine that can be reused, or will be freed.
|
||||
**
|
||||
** The result is stored in space obtained from malloc() and
|
||||
** must either be freed by the caller or else passed back to
|
||||
** this function as zBufPrior for reuse.
|
||||
**
|
||||
** This function may call upon services of a line-editing
|
||||
** library to interactively collect line edited input.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char *
|
||||
shellGetLine(FILE *pfIn, char *zBufPrior, int nLen,
|
||||
short isContinuation, Prompts azPrompt);
|
||||
#endif /* defined(SQLITE_CIO_PROMPTED_IN) */
|
||||
/*
|
||||
** TBD: Define an interface for application(s) to generate
|
||||
** completion candidates for use by the line-editor.
|
||||
**
|
||||
** This may be premature; the CLI is the only application
|
||||
** that does this. Yet, getting line-editing melded into
|
||||
** console I/O is desirable because a line-editing library
|
||||
** may have to establish console operating mode, possibly
|
||||
** in a way that interferes with the above functionality.
|
||||
*/
|
||||
|
||||
#if !(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))
|
||||
/* Skip over as much z[] input char sequence as is valid UTF-8,
|
||||
** limited per nAccept char's or whole characters and containing
|
||||
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
|
||||
** sequence z:return (inclusive:exclusive) is validated UTF-8.
|
||||
** Limit: nAccept>=0 => char count, nAccept<0 => character
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE const char*
|
||||
zSkipValidUtf8(const char *z, int nAccept, long ccm);
|
||||
|
||||
#endif
|
||||
@@ -211,6 +211,14 @@ static int fts5HighlightCb(
|
||||
}
|
||||
|
||||
if( iPos==p->iRangeEnd ){
|
||||
if( p->bOpen ){
|
||||
if( p->iter.iStart>=0 && iPos>=p->iter.iStart ){
|
||||
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
|
||||
p->iOff = iEndOff;
|
||||
}
|
||||
fts5HighlightAppend(&rc, p, p->zClose, -1);
|
||||
p->bOpen = 0;
|
||||
}
|
||||
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
|
||||
p->iOff = iEndOff;
|
||||
}
|
||||
|
||||
@@ -432,10 +432,8 @@ static Fts5HashEntry *fts5HashEntryMerge(
|
||||
}
|
||||
|
||||
/*
|
||||
** Extract all tokens from hash table iHash and link them into a list
|
||||
** in sorted order. The hash table is cleared before returning. It is
|
||||
** the responsibility of the caller to free the elements of the returned
|
||||
** list.
|
||||
** Link all tokens from hash table iHash into a list in sorted order. The
|
||||
** tokens are not removed from the hash table.
|
||||
*/
|
||||
static int fts5HashEntrySort(
|
||||
Fts5Hash *pHash,
|
||||
|
||||
+26
-11
@@ -2719,6 +2719,14 @@ static void fts5SegIterHashInit(
|
||||
pLeaf->p = (u8*)pList;
|
||||
}
|
||||
}
|
||||
|
||||
/* The call to sqlite3Fts5HashScanInit() causes the hash table to
|
||||
** fill the size field of all existing position lists. This means they
|
||||
** can no longer be appended to. Since the only scenario in which they
|
||||
** can be appended to is if the previous operation on this table was
|
||||
** a DELETE, by clearing the Fts5Index.bDelete flag we can avoid this
|
||||
** possibility altogether. */
|
||||
p->bDelete = 0;
|
||||
}else{
|
||||
p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data),
|
||||
(const char*)pTerm, nTerm, (void**)&pLeaf, &nList
|
||||
@@ -4396,7 +4404,7 @@ static void fts5WriteAppendPoslistData(
|
||||
const u8 *a = aData;
|
||||
int n = nData;
|
||||
|
||||
assert( p->pConfig->pgsz>0 );
|
||||
assert( p->pConfig->pgsz>0 || p->rc!=SQLITE_OK );
|
||||
while( p->rc==SQLITE_OK
|
||||
&& (pPage->buf.n + pPage->pgidx.n + n)>=p->pConfig->pgsz
|
||||
){
|
||||
@@ -5129,18 +5137,24 @@ static void fts5DoSecureDelete(
|
||||
|
||||
iOff = iStart;
|
||||
|
||||
/* Set variable bLastInDoclist to true if this entry happens to be
|
||||
** the last rowid in the doclist for its term. */
|
||||
/* If the position-list for the entry being removed flows over past
|
||||
** the end of this page, delete the portion of the position-list on the
|
||||
** next page and beyond.
|
||||
**
|
||||
** Set variable bLastInDoclist to true if this entry happens
|
||||
** to be the last rowid in the doclist for its term. */
|
||||
if( iNextOff>=iPgIdx ){
|
||||
int pgno = pSeg->iLeafPgno+1;
|
||||
fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist);
|
||||
iNextOff = iPgIdx;
|
||||
}
|
||||
|
||||
if( pSeg->bDel==0 ){
|
||||
if( iNextOff>=iPgIdx ){
|
||||
int pgno = pSeg->iLeafPgno+1;
|
||||
fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist);
|
||||
iNextOff = iPgIdx;
|
||||
}else{
|
||||
if( iNextOff!=iPgIdx ){
|
||||
/* Loop through the page-footer. If iNextOff (offset of the
|
||||
** entry following the one we are removing) is equal to the
|
||||
** offset of a key on this page, then the entry is the last
|
||||
** in its doclist. */
|
||||
** in its doclist. */
|
||||
int iKeyOff = 0;
|
||||
for(iIdx=0; iIdx<nIdx; /* no-op */){
|
||||
u32 iVal = 0;
|
||||
@@ -5656,8 +5670,9 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){
|
||||
|
||||
assert( p->rc==SQLITE_OK );
|
||||
fts5IndexFlush(p);
|
||||
assert( p->nContentlessDelete==0 );
|
||||
assert( p->rc!=SQLITE_OK || p->nContentlessDelete==0 );
|
||||
pStruct = fts5StructureRead(p);
|
||||
assert( p->rc!=SQLITE_OK || pStruct!=0 );
|
||||
fts5StructureInvalidate(p);
|
||||
|
||||
if( pStruct ){
|
||||
@@ -6204,7 +6219,7 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
|
||||
/* Flush the hash table to disk if required */
|
||||
if( iRowid<p->iWriteRowid
|
||||
|| (iRowid==p->iWriteRowid && p->bDelete==0)
|
||||
|| (p->nPendingData > p->pConfig->nHashSize)
|
||||
|| (p->nPendingData > p->pConfig->nHashSize)
|
||||
){
|
||||
fts5IndexFlush(p);
|
||||
}
|
||||
|
||||
+70
-27
@@ -229,6 +229,12 @@ static const unsigned char sqlite3Utf8Trans1[] = {
|
||||
|
||||
#endif /* ifndef SQLITE_AMALGAMATION */
|
||||
|
||||
#define FTS5_SKIP_UTF8(zIn) { \
|
||||
if( ((unsigned char)(*(zIn++)))>=0xc0 ){ \
|
||||
while( (((unsigned char)*zIn) & 0xc0)==0x80 ){ zIn++; } \
|
||||
} \
|
||||
}
|
||||
|
||||
typedef struct Unicode61Tokenizer Unicode61Tokenizer;
|
||||
struct Unicode61Tokenizer {
|
||||
unsigned char aTokenChar[128]; /* ASCII range token characters */
|
||||
@@ -1264,6 +1270,7 @@ static int fts5PorterTokenize(
|
||||
typedef struct TrigramTokenizer TrigramTokenizer;
|
||||
struct TrigramTokenizer {
|
||||
int bFold; /* True to fold to lower-case */
|
||||
int iFoldParam; /* Parameter to pass to Fts5UnicodeFold() */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1290,6 +1297,7 @@ static int fts5TriCreate(
|
||||
}else{
|
||||
int i;
|
||||
pNew->bFold = 1;
|
||||
pNew->iFoldParam = 0;
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
|
||||
@@ -1298,10 +1306,21 @@ static int fts5TriCreate(
|
||||
}else{
|
||||
pNew->bFold = (zArg[0]=='0');
|
||||
}
|
||||
}else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0;
|
||||
}
|
||||
}else{
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
fts5TriDelete((Fts5Tokenizer*)pNew);
|
||||
pNew = 0;
|
||||
@@ -1324,40 +1343,62 @@ static int fts5TriTokenize(
|
||||
TrigramTokenizer *p = (TrigramTokenizer*)pTok;
|
||||
int rc = SQLITE_OK;
|
||||
char aBuf[32];
|
||||
char *zOut = aBuf;
|
||||
int ii;
|
||||
const unsigned char *zIn = (const unsigned char*)pText;
|
||||
const unsigned char *zEof = &zIn[nText];
|
||||
u32 iCode;
|
||||
int aStart[3]; /* Input offset of each character in aBuf[] */
|
||||
|
||||
UNUSED_PARAM(unusedFlags);
|
||||
while( 1 ){
|
||||
char *zOut = aBuf;
|
||||
int iStart = zIn - (const unsigned char*)pText;
|
||||
const unsigned char *zNext;
|
||||
|
||||
READ_UTF8(zIn, zEof, iCode);
|
||||
if( iCode==0 ) break;
|
||||
zNext = zIn;
|
||||
if( zIn<zEof ){
|
||||
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
|
||||
WRITE_UTF8(zOut, iCode);
|
||||
/* Populate aBuf[] with the characters for the first trigram. */
|
||||
for(ii=0; ii<3; ii++){
|
||||
do {
|
||||
aStart[ii] = zIn - (const unsigned char*)pText;
|
||||
READ_UTF8(zIn, zEof, iCode);
|
||||
if( iCode==0 ) return SQLITE_OK;
|
||||
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
|
||||
}while( iCode==0 );
|
||||
WRITE_UTF8(zOut, iCode);
|
||||
}
|
||||
|
||||
/* At the start of each iteration of this loop:
|
||||
**
|
||||
** aBuf: Contains 3 characters. The 3 characters of the next trigram.
|
||||
** zOut: Points to the byte following the last character in aBuf.
|
||||
** aStart[3]: Contains the byte offset in the input text corresponding
|
||||
** to the start of each of the three characters in the buffer.
|
||||
*/
|
||||
assert( zIn<=zEof );
|
||||
while( 1 ){
|
||||
int iNext; /* Start of character following current tri */
|
||||
const char *z1;
|
||||
|
||||
/* Read characters from the input up until the first non-diacritic */
|
||||
do {
|
||||
iNext = zIn - (const unsigned char*)pText;
|
||||
READ_UTF8(zIn, zEof, iCode);
|
||||
if( iCode==0 ) break;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
if( zIn<zEof ){
|
||||
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
|
||||
WRITE_UTF8(zOut, iCode);
|
||||
READ_UTF8(zIn, zEof, iCode);
|
||||
if( iCode==0 ) break;
|
||||
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
|
||||
WRITE_UTF8(zOut, iCode);
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
rc = xToken(pCtx, 0, aBuf, zOut-aBuf, iStart, iStart + zOut-aBuf);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
zIn = zNext;
|
||||
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
|
||||
}while( iCode==0 );
|
||||
|
||||
/* Pass the current trigram back to fts5 */
|
||||
rc = xToken(pCtx, 0, aBuf, zOut-aBuf, aStart[0], iNext);
|
||||
if( iCode==0 || rc!=SQLITE_OK ) break;
|
||||
|
||||
/* Remove the first character from buffer aBuf[]. Append the character
|
||||
** with codepoint iCode. */
|
||||
z1 = aBuf;
|
||||
FTS5_SKIP_UTF8(z1);
|
||||
memmove(aBuf, z1, zOut - z1);
|
||||
zOut -= (z1 - aBuf);
|
||||
WRITE_UTF8(zOut, iCode);
|
||||
|
||||
/* Update the aStart[] array */
|
||||
aStart[0] = aStart[1];
|
||||
aStart[1] = aStart[2];
|
||||
aStart[2] = iNext;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -1380,7 +1421,9 @@ int sqlite3Fts5TokenizerPattern(
|
||||
){
|
||||
if( xCreate==fts5TriCreate ){
|
||||
TrigramTokenizer *p = (TrigramTokenizer*)pTok;
|
||||
return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
|
||||
if( p->iFoldParam==0 ){
|
||||
return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
|
||||
}
|
||||
}
|
||||
return FTS5_PATTERN_NONE;
|
||||
}
|
||||
|
||||
@@ -880,6 +880,91 @@ do_catchsql_test 5.4 {
|
||||
UPDATE t1 SET content=randomblob(500);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 6.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 32768 pagesize 4096 filename crash-42fa37b694d45a.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 07 .....@ ........
|
||||
| 96: 00 00 00 00 0d 00 00 00 07 0d d2 00 0f c4 0f 6d ...............m
|
||||
| 112: 0f 02 0e ab 0e 4e 0d f6 0d d2 00 00 00 00 00 00 .....N..........
|
||||
| 3536: 00 00 22 07 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
|
||||
| 3552: 32 74 32 07 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
|
||||
| 3568: 20 74 32 28 78 29 56 06 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
|
||||
| 3584: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
|
||||
| 3600: 6f 6e 66 69 67 06 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
|
||||
| 3616: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
|
||||
| 3632: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
|
||||
| 3648: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 05 WITHOUT ROWID[.
|
||||
| 3664: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
|
||||
| 3680: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
|
||||
| 3696: 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
|
||||
| 3712: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
|
||||
| 3728: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
|
||||
| 3744: 59 2c 20 73 7a 20 42 4c 4f 42 29 55 04 06 17 21 Y, sz BLOB)U...!
|
||||
| 3760: 21 01 77 74 61 62 6c 65 74 31 5f 63 6f 6e 74 65 !.wtablet1_conte
|
||||
| 3776: 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 04 43 52 45 ntt1_content.CRE
|
||||
| 3792: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f ATE TABLE 't1_co
|
||||
| 3808: 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 45 ntent'(id INTEGE
|
||||
| 3824: 52 20 50 52 49 4d 41 52 49 20 4b 45 59 2c 20 63 R PRIMARI KEY, c
|
||||
| 3840: 30 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 0)i.......-table
|
||||
| 3856: 74 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 t1_idxt1_idx.CRE
|
||||
| 3872: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 ATE TABLE 't1_id
|
||||
| 3888: 78 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 x'(segid, term,
|
||||
| 3904: 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 pgno, PRIMARY KE
|
||||
| 3920: 59 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 Y(segid, term))
|
||||
| 3936: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 WITHOUT ROWIDU..
|
||||
| 3952: 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 ......tablet1_da
|
||||
| 3968: 74 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 tat1_data.CREATE
|
||||
| 3984: 20 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 TABLE 't1_data'
|
||||
| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
|
||||
| 4016: 41 52 b9 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 AR. KEY, block B
|
||||
| 4032: 4c 4f 42 29 3a 01 06 17 11 11 08 63 74 61 62 6c LOB):......ctabl
|
||||
| 4048: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT
|
||||
| 4064: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI
|
||||
| 4080: 4e 47 20 66 74 73 35 28 63 6f 6e 74 65 6e 74 29 NG fts5(content)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 00 00 00 03 0f bd 00 0f e8 0f ef 0f bd f0 00 ................
|
||||
| 16: 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 24 84 80 .............$..
|
||||
| 4032: 80 80 80 01 03 00 4e 00 10 00 1e 06 30 61 62 61 ......N.....0aba
|
||||
| 4048: 63 6c 01 02 02 04 02 66 74 02 5f 02 04 04 6e 64 cl.....ft._...nd
|
||||
| 4064: 6f 6e 02 02 02 04 0a 07 05 01 03 00 10 03 03 0f on..............
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 11 ...$............
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 01 0f 00 01 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 03 0f e0 00 0f f6 0f ec 0f e0 00 00 ................
|
||||
| 4064: 0a 03 03 00 1b 61 62 61 6e 64 6f 6e 08 02 03 00 .....abandon....
|
||||
| 4080: 17 61 62 61 66 74 08 01 03 00 17 61 62 61 63 6b .abaft.....aback
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 03 0f ee 00 0f fa 0f 00 00 00 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 03 ................
|
||||
| 4080: 03 00 0e 01 04 02 03 00 0e 01 04 01 03 00 0e 01 ................
|
||||
| page 6 offset 20480
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 7 offset 24576
|
||||
| 0: 0d 00 00 10 03 0f d6 00 0f 00 00 00 00 00 00 00 ................
|
||||
| 4048: 00 00 00 00 00 00 09 03 02 1b 72 65 62 75 69 6c ..........rebuil
|
||||
| 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c
|
||||
| 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 00 00 00 heck....optim...
|
||||
| page 8 offset 28672
|
||||
| 0: 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| end crash-42fa37b694d45a.db
|
||||
}]} {}
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
INSERT INTO t1(t1,rank) VALUES('secure-delete',1);
|
||||
}
|
||||
do_catchsql_test 6.2 {
|
||||
UPDATE t1 SET content=randomblob(500) WHERE t1;
|
||||
} {1 {constraint failed}}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
@@ -46,5 +46,31 @@ do_faultsim_test 1 -faults oom* -prep {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, content=, contentless_delete=1);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES('here''s some text');
|
||||
INSERT INTO t1 VALUES('useful stuff, text');
|
||||
INSERT INTO t1 VALUES('what would we do without text!');
|
||||
COMMIT;
|
||||
}
|
||||
faultsim_save_and_close
|
||||
do_faultsim_test 2 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql {
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE rowid=2;
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO t1(t1) VALUES('optimize');
|
||||
}
|
||||
} -test {
|
||||
faultsim_integrity_check
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -52,6 +52,36 @@ do_execsql_test 2.1 {
|
||||
SELECT * FROM t2('to*');
|
||||
} {top to tommy}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
foreach {tn newrowid} {
|
||||
1 122
|
||||
2 123
|
||||
3 124
|
||||
} {
|
||||
reset_db
|
||||
do_execsql_test 3.$tn.0 {
|
||||
CREATE VIRTUAL TABLE t12 USING fts5(x);
|
||||
INSERT INTO t12(rowid, x) VALUES(123, 'wwww');
|
||||
}
|
||||
do_execsql_test 3.$tn.1 {
|
||||
BEGIN;
|
||||
DELETE FROM t12 WHERE rowid=123;
|
||||
SELECT * FROM t12('wwww*');
|
||||
INSERT INTO t12(rowid, x) VALUES($newrowid, 'wwww');
|
||||
SELECT * FROM t12('wwww*');
|
||||
END;
|
||||
} {wwww}
|
||||
do_execsql_test 3.$tn.2 {
|
||||
INSERT INTO t12(t12) VALUES('integrity-check');
|
||||
}
|
||||
do_execsql_test 3.$tn.3 {
|
||||
SELECT rowid FROM t12('wwww*');
|
||||
} $newrowid
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# 2023 Nov 23
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
ifcapable !fts5 { finish_test ; return }
|
||||
set ::testprefix fts5secure8
|
||||
|
||||
proc sql_repeat {txt n} {
|
||||
string repeat $txt $n
|
||||
}
|
||||
db func repeat sql_repeat
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(x);
|
||||
|
||||
INSERT INTO ft(ft, rank) VALUES('pgsz', 64);
|
||||
|
||||
INSERT INTO ft(rowid, x) VALUES(100, 'hello world');
|
||||
INSERT INTO ft(rowid, x) VALUES(200, 'one day');
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO ft(rowid, x) VALUES(45, 'one two three');
|
||||
UPDATE ft SET x = repeat('hello world ', 500) WHERE rowid=100;
|
||||
COMMIT
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
INSERT INTO ft(ft, rank) VALUES('secure-delete', 1);
|
||||
DELETE FROM ft WHERE rowid=100;
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
# 2023 Nov 03
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests focusing on the built-in fts5 tokenizers.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5tokenizer2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
sqlite3_fts5_create_tokenizer db tst get_tst_tokenizer
|
||||
proc get_tst_tokenizer {args} {
|
||||
return "tst_tokenizer"
|
||||
}
|
||||
proc tst_tokenizer {flags txt} {
|
||||
set token ""
|
||||
set lTok [list]
|
||||
|
||||
foreach c [split $txt {}] {
|
||||
if {$token==""} {
|
||||
append token $c
|
||||
} else {
|
||||
set t1 [string is upper $token]
|
||||
set t2 [string is upper $c]
|
||||
|
||||
if {$t1!=$t2} {
|
||||
lappend lTok $token
|
||||
set token ""
|
||||
}
|
||||
append token $c
|
||||
}
|
||||
}
|
||||
if {$token!=""} { lappend lTok $token }
|
||||
|
||||
set iOff 0
|
||||
foreach t $lTok {
|
||||
set n [string length $t]
|
||||
sqlite3_fts5_token $t $iOff [expr $iOff+$n]
|
||||
incr iOff $n
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(t, tokenize=tst);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
INSERT INTO t1 VALUES('AAdontBBmess');
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT snippet(t1, 0, '>', '<', '...', 4) FROM t1('BB');
|
||||
} {AAdont>BB<mess}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT highlight(t1, 0, '>', '<') FROM t1('BB');
|
||||
} {AAdont>BB<mess}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT highlight(t1, 0, '>', '<') FROM t1('AA');
|
||||
} {>AA<dontBBmess}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
SELECT highlight(t1, 0, '>', '<') FROM t1('dont');
|
||||
} {AA>dont<BBmess}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
SELECT highlight(t1, 0, '>', '<') FROM t1('mess');
|
||||
} {AAdontBB>mess<}
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
SELECT highlight(t1, 0, '>', '<') FROM t1('BB mess');
|
||||
} {AAdont>BBmess<}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,109 @@
|
||||
# 2023 October 24
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
# Tests for the fts5 "trigram" tokenizer.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
ifcapable !fts5 { finish_test ; return }
|
||||
set ::testprefix fts5trigram2
|
||||
|
||||
do_execsql_test 1.0 "
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(y, tokenize='trigram remove_diacritics 1');
|
||||
INSERT INTO t1 VALUES('abc\u0303defghijklm');
|
||||
INSERT INTO t1 VALUES('a\u0303b\u0303c\u0303defghijklm');
|
||||
"
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT highlight(t1, 0, '(', ')') FROM t1('abc');
|
||||
} [list \
|
||||
"(abc\u0303)defghijklm" \
|
||||
"(a\u0303b\u0303c\u0303)defghijklm" \
|
||||
]
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT highlight(t1, 0, '(', ')') FROM t1('bcde');
|
||||
} [list \
|
||||
"a(bc\u0303de)fghijklm" \
|
||||
"a\u0303(b\u0303c\u0303de)fghijklm" \
|
||||
]
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT highlight(t1, 0, '(', ')') FROM t1('cdef');
|
||||
} [list \
|
||||
"ab(c\u0303def)ghijklm" \
|
||||
"a\u0303b\u0303(c\u0303def)ghijklm" \
|
||||
]
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT highlight(t1, 0, '(', ')') FROM t1('def');
|
||||
} [list \
|
||||
"abc\u0303(def)ghijklm" \
|
||||
"a\u0303b\u0303c\u0303(def)ghijklm" \
|
||||
]
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_catchsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(
|
||||
z, tokenize='trigram case_sensitive 1 remove_diacritics 1'
|
||||
);
|
||||
} {1 {error in tokenizer constructor}}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(
|
||||
z, tokenize='trigram case_sensitive 0 remove_diacritics 1'
|
||||
);
|
||||
}
|
||||
do_execsql_test 2.2 "
|
||||
INSERT INTO t2 VALUES('\u00E3bcdef');
|
||||
INSERT INTO t2 VALUES('b\u00E3cdef');
|
||||
INSERT INTO t2 VALUES('bc\u00E3def');
|
||||
INSERT INTO t2 VALUES('bcd\u00E3ef');
|
||||
"
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
SELECT highlight(t2, 0, '(', ')') FROM t2('abc');
|
||||
} "(\u00E3bc)def"
|
||||
do_execsql_test 2.4 {
|
||||
SELECT highlight(t2, 0, '(', ')') FROM t2('bac');
|
||||
} "(b\u00E3c)def"
|
||||
do_execsql_test 2.5 {
|
||||
SELECT highlight(t2, 0, '(', ')') FROM t2('bca');
|
||||
} "(bc\u00E3)def"
|
||||
do_execsql_test 2.6 "
|
||||
SELECT highlight(t2, 0, '(', ')') FROM t2('\u00E3bc');
|
||||
" "(\u00E3bc)def"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5(
|
||||
z, tokenize='trigram remove_diacritics 1'
|
||||
);
|
||||
} {}
|
||||
do_execsql_test 3.1 "
|
||||
INSERT INTO t3 VALUES ('\u0303abc\u0303');
|
||||
"
|
||||
do_execsql_test 3.2 {
|
||||
SELECT highlight(t3, 0, '(', ')') FROM t3('abc');
|
||||
} "\u0303(abc\u0303)"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts5(z, tokenize=trigram);
|
||||
} {}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 4.1 {
|
||||
INSERT INTO t4 VALUES('ABCD');
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
+11
-4
@@ -35,6 +35,8 @@ $(dir.bld.c):
|
||||
|
||||
javac.flags ?= -Xlint:unchecked -Xlint:deprecation
|
||||
java.flags ?=
|
||||
javac.flags += -encoding utf8
|
||||
# -------------^^^^^^^^^^^^^^ required for Windows builds
|
||||
jnicheck ?= 1
|
||||
ifeq (1,$(jnicheck))
|
||||
java.flags += -Xcheck:jni
|
||||
@@ -79,6 +81,7 @@ $(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
||||
# 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)/annotation/%,\
|
||||
Experimental.java \
|
||||
NotNull.java \
|
||||
Nullable.java \
|
||||
) $(patsubst %,$(dir.src.capi)/%,\
|
||||
@@ -91,7 +94,7 @@ JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/annotation/%,\
|
||||
CollationNeededCallback.java \
|
||||
CommitHookCallback.java \
|
||||
ConfigLogCallback.java \
|
||||
ConfigSqllogCallback.java \
|
||||
ConfigSqlLogCallback.java \
|
||||
NativePointerHolder.java \
|
||||
OutputPointer.java \
|
||||
PrepareMultiCallback.java \
|
||||
@@ -110,6 +113,7 @@ JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/annotation/%,\
|
||||
WindowFunction.java \
|
||||
XDestroyCallback.java \
|
||||
sqlite3.java \
|
||||
sqlite3_blob.java \
|
||||
sqlite3_context.java \
|
||||
sqlite3_stmt.java \
|
||||
sqlite3_value.java \
|
||||
@@ -120,6 +124,7 @@ JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/annotation/%,\
|
||||
Sqlite.java \
|
||||
SqliteException.java \
|
||||
ValueHolder.java \
|
||||
WindowFunction.java \
|
||||
)
|
||||
|
||||
JAVA_FILES.unittest := $(patsubst %,$(dir.src.jni)/%,\
|
||||
@@ -159,12 +164,13 @@ endif
|
||||
CLASS_FILES :=
|
||||
define CLASSFILE_DEPS
|
||||
all: $(1).class
|
||||
$(1).class: $(1).java
|
||||
CLASS_FILES += $(1).class
|
||||
endef
|
||||
$(foreach B,$(basename \
|
||||
$(JAVA_FILES.main) $(JAVA_FILES.unittest) $(JAVA_FILES.tester)),\
|
||||
$(eval $(call CLASSFILE_DEPS,$(B))))
|
||||
$(CLASS_FILES): $(JAVA_FILES) $(MAKEFILE)
|
||||
$(CLASS_FILES): $(MAKEFILE)
|
||||
$(bin.javac) $(javac.flags) -h $(dir.bld.c) -cp $(classpath) $(JAVA_FILES)
|
||||
|
||||
#.PHONY: classfiles
|
||||
@@ -226,7 +232,8 @@ SQLITE_OPT += -DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_ENABLE_OFFSET_SQL_FUNC \
|
||||
-DSQLITE_ENABLE_PREUPDATE_HOOK \
|
||||
-DSQLITE_ENABLE_NORMALIZE \
|
||||
-DSQLITE_ENABLE_SQLLOG
|
||||
-DSQLITE_ENABLE_SQLLOG \
|
||||
-DSQLITE_ENABLE_COLUMN_METADATA
|
||||
endif
|
||||
|
||||
ifeq (1,$(opt.debug))
|
||||
@@ -316,7 +323,7 @@ test-one: $(test.deps)
|
||||
$(bin.java) $(test.flags.jvm) org.sqlite.jni.wrapper1.Tester2 $(Tester2.flags)
|
||||
test-sqllog: $(test.deps)
|
||||
@echo "Testing with -sqllog..."
|
||||
$(bin.java) $(test.flags.jvm) -sqllog
|
||||
$(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 $(Tester1.flags) -sqllog
|
||||
test-mt: $(test.deps)
|
||||
@echo "Testing in multi-threaded mode:";
|
||||
$(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 \
|
||||
|
||||
+22
-19
@@ -16,9 +16,8 @@ Technical support is available in the 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. The JNI
|
||||
bindings released with version 3.43 are a "tech preview" and 3.44
|
||||
will be "final," at which point strong backward compatibility
|
||||
guarantees will apply.
|
||||
bindings released with version 3.43 are a "tech preview." Once
|
||||
finalized, strong backward compatibility guarantees will apply.
|
||||
|
||||
Project goals/requirements:
|
||||
|
||||
@@ -43,11 +42,13 @@ Non-goals:
|
||||
- Creation of high-level OO wrapper APIs. Clients are free to create
|
||||
them off of the C-style API.
|
||||
|
||||
- Virtual tables are unlikely to be supported due to the amount of
|
||||
glue code needed to fit them into Java.
|
||||
|
||||
- Support for mixed-mode operation, where client code accesses SQLite
|
||||
both via the Java-side API and the C API via their own native
|
||||
code. In such cases, proxy functionalities (primarily callback
|
||||
handler wrappers of all sorts) may fail because the C-side use of
|
||||
the SQLite APIs will bypass those proxies.
|
||||
code. Such cases would be a minefield of potential mis-interactions
|
||||
between this project's JNI bindings and mixed-mode client code.
|
||||
|
||||
|
||||
Hello World
|
||||
@@ -123,15 +124,13 @@ sensible default argument values. In all such cases they are thin
|
||||
proxies around the corresponding C APIs and do not introduce new
|
||||
semantics.
|
||||
|
||||
In some very few cases, Java-specific capabilities have been added in
|
||||
In a few cases, Java-specific capabilities have been added in
|
||||
new APIs, all of which have "_java" somewhere in their names.
|
||||
Examples include:
|
||||
|
||||
- `sqlite3_result_java_object()`
|
||||
- `sqlite3_column_java_object()`
|
||||
- `sqlite3_column_java_casted()`
|
||||
- `sqlite3_value_java_object()`
|
||||
- `sqlite3_value_java_casted()`
|
||||
|
||||
which, as one might surmise, collectively enable the passing of
|
||||
arbitrary Java objects from user-defined SQL functions through to the
|
||||
@@ -150,6 +149,9 @@ pending statements have been closed. Be aware that Java garbage
|
||||
collection _cannot_ close a database or finalize a prepared statement.
|
||||
Those things require explicit API calls.
|
||||
|
||||
Classes for which it is sensible support Java's `AutoCloseable`
|
||||
interface so can be used with try-with-resources constructs.
|
||||
|
||||
|
||||
Golden Rule #2: _Never_ Throw from Callbacks (Unless...)
|
||||
------------------------------------------------------------------------
|
||||
@@ -159,14 +161,15 @@ retain C-like semantics. For example, they are not permitted to throw
|
||||
or propagate exceptions and must return error information (if any) via
|
||||
result codes or `null`. The only cases where the C-style APIs may
|
||||
throw is through client-side misuse, e.g. passing in a null where it
|
||||
shouldn't be used. The APIs clearly mark function parameters which
|
||||
should not be null, but does not actively defend itself against such
|
||||
misuse. Some C-style APIs explicitly accept `null` as a no-op for
|
||||
usability's sake, and some of the JNI APIs deliberately return an
|
||||
error code, instead of segfaulting, when passed a `null`.
|
||||
may cause a `NullPointerException`. The APIs clearly mark function
|
||||
parameters which should not be null, but does not generally actively
|
||||
defend itself against such misuse. Some C-style APIs explicitly accept
|
||||
`null` as a no-op for usability's sake, and some of the JNI APIs
|
||||
deliberately return an error code, instead of segfaulting, when passed
|
||||
a `null`.
|
||||
|
||||
Client-defined callbacks _must never throw exceptions_ unless _very
|
||||
explicitly documented_ as being throw-safe. Exceptions are generally
|
||||
explitly 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. In some cases, callback handlers are permitted to throw, in
|
||||
@@ -292,14 +295,14 @@ int sqlite3_create_function(sqlite3 db, String funcName, int nArgs,
|
||||
`SQLFunction` is not used directly, but is instead instantiated via
|
||||
one of its three subclasses:
|
||||
|
||||
- `SQLFunction.Scalar` implements simple scalar functions using but a
|
||||
- `ScalarFunction` implements simple scalar functions using but a
|
||||
single callback.
|
||||
- `SQLFunction.Aggregate` implements aggregate functions using two
|
||||
- `AggregateFunction` implements aggregate functions using two
|
||||
callbacks.
|
||||
- `SQLFunction.Window` implements window functions using four
|
||||
- `WindowFunction` implements window functions using four
|
||||
callbacks.
|
||||
|
||||
Search [`Tester1.java`](/file/ext/jni/src/org/sqlite/jni/Tester1.java) for
|
||||
Search [`Tester1.java`](/file/ext/jni/src/org/sqlite/jni/capi/Tester1.java) for
|
||||
`SQLFunction` for how it's used.
|
||||
|
||||
Reminder: see the disclaimer at the top of this document regarding the
|
||||
|
||||
+579
-141
File diff suppressed because it is too large
Load Diff
+108
-26
@@ -427,8 +427,6 @@ extern "C" {
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_OPEN_EXRESCODE 33554432L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_PREPARE_PERSISTENT
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_PREPARE_PERSISTENT 1L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_PREPARE_NORMALIZE
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_PREPARE_NORMALIZE 2L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_PREPARE_NO_VTAB
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_PREPARE_NO_VTAB 4L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_OK
|
||||
@@ -707,8 +705,12 @@ extern "C" {
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_DETERMINISTIC 2048L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_DIRECTONLY
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_DIRECTONLY 524288L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_SUBTYPE
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_SUBTYPE 1048576L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_INNOCUOUS
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_INNOCUOUS 2097152L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_RESULT_SUBTYPE
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_RESULT_SUBTYPE 16777216L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_INDEX_SCAN_UNIQUE
|
||||
#define org_sqlite_jni_capi_CApi_SQLITE_INDEX_SCAN_UNIQUE 1L
|
||||
#undef org_sqlite_jni_capi_CApi_SQLITE_INDEX_CONSTRAINT_EQ
|
||||
@@ -775,6 +777,22 @@ JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_init
|
||||
JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1java_1uncache_1thread
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_jni_supports_nio
|
||||
* Signature: ()Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1jni_1supports_1nio
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_jni_db_error
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3;ILjava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1jni_1db_1error
|
||||
(JNIEnv *, jclass, jobject, jint, jstring);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_aggregate_context
|
||||
@@ -871,6 +889,14 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1bind_1int64
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1bind_1java_1object
|
||||
(JNIEnv *, jclass, jlong, jint, jobject);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_bind_nio_buffer
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3_stmt;ILjava/nio/ByteBuffer;II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1bind_1nio_1buffer
|
||||
(JNIEnv *, jclass, jobject, jint, jobject, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_bind_null
|
||||
@@ -975,6 +1001,14 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1blob_1open
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1blob_1read
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_blob_read_nio_buffer
|
||||
* Signature: (JILjava/nio/ByteBuffer;II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1blob_1read_1nio_1buffer
|
||||
(JNIEnv *, jclass, jlong, jint, jobject, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_blob_reopen
|
||||
@@ -991,6 +1025,14 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1blob_1reopen
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1blob_1write
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_blob_write_nio_buffer
|
||||
* Signature: (JILjava/nio/ByteBuffer;II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1blob_1write_1nio_1buffer
|
||||
(JNIEnv *, jclass, jlong, jint, jobject, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_busy_handler
|
||||
@@ -1087,6 +1129,14 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1column_1bytes16
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1column_1count
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_column_database_name
|
||||
* Signature: (JI)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1column_1database_1name
|
||||
(JNIEnv *, jclass, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_column_decltype
|
||||
@@ -1119,6 +1169,14 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1column_1int
|
||||
JNIEXPORT jlong JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1column_1int64
|
||||
(JNIEnv *, jclass, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_column_java_object
|
||||
* Signature: (JI)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1column_1java_1object
|
||||
(JNIEnv *, jclass, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_column_name
|
||||
@@ -1129,11 +1187,11 @@ JNIEXPORT jstring JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1column_1name
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_column_database_name
|
||||
* Signature: (JI)Ljava/lang/String;
|
||||
* Method: sqlite3_column_nio_buffer
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3_stmt;I)Ljava/nio/ByteBuffer;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1column_1database_1name
|
||||
(JNIEnv *, jclass, jlong, jint);
|
||||
JNIEXPORT jobject JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1column_1nio_1buffer
|
||||
(JNIEnv *, jclass, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
@@ -1225,26 +1283,26 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1complete
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_config
|
||||
* Method: sqlite3_config__enable
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config__I
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config_1_1enable
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_config
|
||||
* Signature: (Lorg/sqlite/jni/capi/ConfigSqllogCallback;)I
|
||||
* Method: sqlite3_config__CONFIG_LOG
|
||||
* Signature: (Lorg/sqlite/jni/capi/ConfigLogCallback;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config__Lorg_sqlite_jni_capi_ConfigSqllogCallback_2
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config_1_1CONFIG_1LOG
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_config
|
||||
* Signature: (Lorg/sqlite/jni/capi/ConfigLogCallback;)I
|
||||
* Method: sqlite3_config__SQLLOG
|
||||
* Signature: (Lorg/sqlite/jni/capi/ConfigSqlLogCallback;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config__Lorg_sqlite_jni_capi_ConfigLogCallback_2
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config_1_1SQLLOG
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
@@ -1394,9 +1452,9 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1extended_1errcode
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_extended_result_codes
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3;Z)Z
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3;Z)I
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1extended_1result_1codes
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1extended_1result_1codes
|
||||
(JNIEnv *, jclass, jobject, jboolean);
|
||||
|
||||
/*
|
||||
@@ -1679,14 +1737,6 @@ JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1error_1nom
|
||||
JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1error_1code
|
||||
(JNIEnv *, jclass, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_result_null
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3_context;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1null
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_result_int
|
||||
@@ -1711,6 +1761,30 @@ JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1int64
|
||||
JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1java_1object
|
||||
(JNIEnv *, jclass, jobject, jobject);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_result_nio_buffer
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3_context;Ljava/nio/ByteBuffer;II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1nio_1buffer
|
||||
(JNIEnv *, jclass, jobject, jobject, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_result_null
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3_context;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1null
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_result_subtype
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3_context;I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1subtype
|
||||
(JNIEnv *, jclass, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_result_value
|
||||
@@ -1850,10 +1924,10 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1status64
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_step
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3_stmt;)I
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1step
|
||||
(JNIEnv *, jclass, jobject);
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
@@ -2063,6 +2137,14 @@ JNIEXPORT jlong JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1value_1int64
|
||||
JNIEXPORT jobject JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1value_1java_1object
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_value_nio_buffer
|
||||
* Signature: (Lorg/sqlite/jni/capi/sqlite3_value;)Ljava/nio/ByteBuffer;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1value_1nio_1buffer
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: org_sqlite_jni_capi_CApi
|
||||
* Method: sqlite3_value_nochange
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
** 2023-09-27
|
||||
**
|
||||
** 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 houses the Experimental annotation for the sqlite3 C API.
|
||||
*/
|
||||
package org.sqlite.jni.annotation;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
This annotation is for flagging methods, constructors, and types
|
||||
which are expressly experimental and subject to any amount of
|
||||
change or outright removal. Client code should not rely on such
|
||||
features.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({
|
||||
ElementType.METHOD,
|
||||
ElementType.CONSTRUCTOR,
|
||||
ElementType.TYPE
|
||||
})
|
||||
public @interface Experimental{}
|
||||
@@ -9,21 +9,22 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file houses the NotNull annotaion for the sqlite3 C API.
|
||||
** This file houses the NotNull annotation for the sqlite3 C API.
|
||||
*/
|
||||
package org.sqlite.jni.annotation;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
This annotation is for flagging parameters which may not legally be
|
||||
null or point to closed/finalized C-side resources.
|
||||
|
||||
<p>In the case of Java types which map directly to C struct types
|
||||
(e.g. {@link org.sqlite.jni.sqlite3}, {@link
|
||||
org.sqlite.jni.sqlite3_stmt}, and {@link
|
||||
org.sqlite.jni.sqlite3_context}), a closed/finalized resource is
|
||||
also considered to be null for purposes this annotation because the
|
||||
C-side effect of passing such a handle is the same as if null is
|
||||
passed.</p>
|
||||
(e.g. {@link org.sqlite.jni.capi.sqlite3}, {@link
|
||||
org.sqlite.jni.capi.sqlite3_stmt}, and {@link
|
||||
org.sqlite.jni.capi.sqlite3_context}), a closed/finalized resource
|
||||
is also considered to be null for purposes this annotation because
|
||||
the C-side effect of passing such a handle is the same as if null
|
||||
is passed.</p>
|
||||
|
||||
<p>When used in the context of Java interfaces which are called
|
||||
from the C APIs, this annotation communicates that the C API will
|
||||
@@ -31,12 +32,23 @@ package org.sqlite.jni.annotation;
|
||||
|
||||
<p>Passing a null, for this annotation's definition of null, for
|
||||
any parameter marked with this annoation specifically invokes
|
||||
undefined behavior.</p>
|
||||
undefined behavior (see below).</p>
|
||||
|
||||
<p>Passing 0 (i.e. C NULL) or a negative value for any long-type
|
||||
parameter marked with this annoation specifically invokes undefined
|
||||
behavior. Such values are treated as C pointers in the JNI
|
||||
layer.</p>
|
||||
behavior (see below). Such values are treated as C pointers in the
|
||||
JNI layer.</p>
|
||||
|
||||
<p><b>Undefined behaviour:</b> the JNI build uses the {@code
|
||||
SQLITE_ENABLE_API_ARMOR} build flag, meaning that the C code
|
||||
invoked with invalid NULL pointers and the like will not invoke
|
||||
undefined behavior in the conventional C sense, but may, for
|
||||
example, return result codes which are not documented for the
|
||||
affected APIs or may otherwise behave unpredictably. In no known
|
||||
cases will such arguments result in C-level code dereferencing a
|
||||
NULL pointer or accessing out-of-bounds (or otherwise invalid)
|
||||
memory. In other words, they may cause unexpected behavior but
|
||||
should never cause an outright crash or security issue.</p>
|
||||
|
||||
<p>Note that the C-style API does not throw any exceptions on its
|
||||
own because it has a no-throw policy in order to retain its C-style
|
||||
@@ -48,12 +60,12 @@ package org.sqlite.jni.annotation;
|
||||
code.</p>
|
||||
|
||||
<p>This annotation is solely for the use by the classes in the
|
||||
org.sqlite package and subpackages, but is made public so that
|
||||
org.sqlite.jni package and subpackages, but is made public so that
|
||||
javadoc will link to it from the annotated functions. It is not
|
||||
part of the public API and client-level code must not rely on
|
||||
it.</p>
|
||||
*/
|
||||
@java.lang.annotation.Documented
|
||||
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
|
||||
@java.lang.annotation.Target(java.lang.annotation.ElementType.PARAMETER)
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.PARAMETER)
|
||||
public @interface NotNull{}
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file houses the Nullable annotaion for the sqlite3 C API.
|
||||
** This file houses the Nullable annotation for the sqlite3 C API.
|
||||
*/
|
||||
package org.sqlite.jni.annotation;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
This annotation is for flagging parameters which may legally be
|
||||
@@ -26,7 +27,7 @@ package org.sqlite.jni.annotation;
|
||||
annotated functions. It is not part of the public API and
|
||||
client-level code must not rely on it.
|
||||
*/
|
||||
@java.lang.annotation.Documented
|
||||
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
|
||||
@java.lang.annotation.Target(java.lang.annotation.ElementType.PARAMETER)
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.PARAMETER)
|
||||
public @interface Nullable{}
|
||||
|
||||
@@ -42,9 +42,75 @@ public abstract class AggregateFunction<T> implements SQLFunction {
|
||||
*/
|
||||
public void xDestroy() {}
|
||||
|
||||
/**
|
||||
PerContextState assists aggregate and window functions in
|
||||
managing their accumulator state across calls to the UDF's
|
||||
callbacks.
|
||||
|
||||
<p>T must be of a type which can be legally stored as a value in
|
||||
java.util.HashMap<KeyType,T>.
|
||||
|
||||
<p>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.
|
||||
|
||||
<p>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.
|
||||
|
||||
<p>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 {@link AggregateFunction} and {@link
|
||||
WindowFunction} 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 the given context 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.
|
||||
|
||||
<p>The caller is obligated to eventually call
|
||||
takeAggregateState() to clear the mapping.
|
||||
*/
|
||||
public ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
|
||||
final Long key = cx.getAggregateContext(true);
|
||||
ValueHolder<T> rc = null==key ? null : map.get(key);
|
||||
if( null==rc ){
|
||||
map.put(key, 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(false));
|
||||
return null==h ? null : h.value;
|
||||
}
|
||||
}
|
||||
|
||||
/** Per-invocation state for the UDF. */
|
||||
private final SQLFunction.PerContextState<T> map =
|
||||
new SQLFunction.PerContextState<>();
|
||||
private final PerContextState<T> map = new PerContextState<>();
|
||||
|
||||
/**
|
||||
To be called from the implementation's xStep() method, as well
|
||||
|
||||
@@ -20,7 +20,8 @@ import org.sqlite.jni.annotation.*;
|
||||
public interface AuthorizerCallback extends CallbackProxy {
|
||||
/**
|
||||
Must function as described for the C-level
|
||||
sqlite3_set_authorizer() callback.
|
||||
sqlite3_set_authorizer() callback. If it throws, the error is
|
||||
converted to a db-level error and the exception is suppressed.
|
||||
*/
|
||||
int call(int opId, @Nullable String s1, @Nullable String s2,
|
||||
@Nullable String s3, @Nullable String s4);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,8 +24,9 @@ package org.sqlite.jni.capi;
|
||||
propagated. For callback interfaces which support returning error
|
||||
info to the core, the JNI binding will convert any exceptions to
|
||||
C-level error information. For callback interfaces which do not
|
||||
support, all exceptions will necessarily be suppressed in order to
|
||||
retain the C-style no-throw semantics.
|
||||
support returning error information, all exceptions will
|
||||
necessarily be suppressed in order to retain the C-style no-throw
|
||||
semantics and avoid invoking undefined behavior in the C layer.
|
||||
|
||||
<p>Callbacks of this style follow a common naming convention:
|
||||
|
||||
|
||||
@@ -21,8 +21,9 @@ public interface CollationNeededCallback extends CallbackProxy {
|
||||
Has the same semantics as the C-level sqlite3_create_collation()
|
||||
callback.
|
||||
|
||||
<p>If it throws, the exception message is passed on to the db and
|
||||
the exception is suppressed.
|
||||
<p>Because the C API has no mechanism for reporting errors
|
||||
from this callbacks, any exceptions thrown by this callback
|
||||
are suppressed.
|
||||
*/
|
||||
int call(sqlite3 db, int eTextRep, String collationName);
|
||||
void call(sqlite3 db, int eTextRep, String collationName);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ package org.sqlite.jni.capi;
|
||||
public interface CommitHookCallback extends CallbackProxy {
|
||||
/**
|
||||
Works as documented for the C-level sqlite3_commit_hook()
|
||||
callback. Must not throw.
|
||||
callback. If it throws, the exception is translated into
|
||||
a db-level error.
|
||||
*/
|
||||
int call();
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,10 +16,10 @@ package org.sqlite.jni.capi;
|
||||
/**
|
||||
A callback for use with sqlite3_config().
|
||||
*/
|
||||
public interface ConfigSqllogCallback {
|
||||
public interface ConfigSqlLogCallback {
|
||||
/**
|
||||
Must function as described for a C-level callback for
|
||||
{@link CApi#sqlite3_config(ConfigSqllogCallback)}, with the slight signature change.
|
||||
{@link CApi#sqlite3_config(ConfigSqlLogCallback)}, with the slight signature change.
|
||||
*/
|
||||
void call(sqlite3 db, String msg, int msgType );
|
||||
}
|
||||
@@ -228,4 +228,26 @@ public final class OutputPointer {
|
||||
/** Sets the current value. */
|
||||
public final void set(byte[] v){value = v;}
|
||||
}
|
||||
|
||||
/**
|
||||
Output pointer for use with native routines which return
|
||||
blobs via java.nio.ByteBuffer.
|
||||
|
||||
See {@link org.sqlite.jni.capi.CApi#sqlite3_jni_supports_nio}
|
||||
*/
|
||||
public static final class ByteBuffer {
|
||||
/**
|
||||
This is public for ease of use. Accessors are provided for
|
||||
consistency with the higher-level types.
|
||||
*/
|
||||
public java.nio.ByteBuffer value;
|
||||
/** Initializes with the value null. */
|
||||
public ByteBuffer(){this(null);}
|
||||
/** Initializes with the value v. */
|
||||
public ByteBuffer(java.nio.ByteBuffer v){value = v;}
|
||||
/** Returns the current value. */
|
||||
public final java.nio.ByteBuffer get(){return value;}
|
||||
/** Sets the current value. */
|
||||
public final void set(java.nio.ByteBuffer v){value = v;}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,10 @@ public interface PrepareMultiCallback extends CallbackProxy {
|
||||
sqlite3_prepare_multi() will _not_ finalize st - it is up
|
||||
to the call() implementation how st is handled.
|
||||
|
||||
Must return 0 on success or an SQLITE_... code on error.
|
||||
Must return 0 on success or an SQLITE_... code on error. If it
|
||||
throws, sqlite3_prepare_multi() will transform the exception into
|
||||
a db-level error in order to retain the C-style error semantics
|
||||
of the API.
|
||||
|
||||
See the {@link Finalize} class for a wrapper which finalizes the
|
||||
statement after calling a proxy PrepareMultiCallback.
|
||||
@@ -37,7 +40,7 @@ public interface PrepareMultiCallback extends CallbackProxy {
|
||||
any sqlite3_stmt passed to its callback.
|
||||
*/
|
||||
public static final class Finalize implements PrepareMultiCallback {
|
||||
private PrepareMultiCallback p;
|
||||
private final PrepareMultiCallback p;
|
||||
/**
|
||||
p is the proxy to call() when this.call() is called.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,8 @@ package org.sqlite.jni.capi;
|
||||
public interface PreupdateHookCallback extends CallbackProxy {
|
||||
/**
|
||||
Must function as described for the C-level sqlite3_preupdate_hook()
|
||||
callback.
|
||||
callback. If it throws, the exception is translated to a
|
||||
db-level error and the exception is suppressed.
|
||||
*/
|
||||
void call(sqlite3 db, int op, String dbName, String dbTable,
|
||||
long iKey1, long iKey2 );
|
||||
|
||||
@@ -18,8 +18,9 @@ package org.sqlite.jni.capi;
|
||||
*/
|
||||
public interface RollbackHookCallback extends CallbackProxy {
|
||||
/**
|
||||
Works as documented for the C-level sqlite3_rollback_hook()
|
||||
callback.
|
||||
Must function as documented for the C-level sqlite3_rollback_hook()
|
||||
callback. If it throws, the exception is translated into
|
||||
a db-level error.
|
||||
*/
|
||||
void call();
|
||||
}
|
||||
|
||||
@@ -33,71 +33,4 @@ package org.sqlite.jni.capi;
|
||||
*/
|
||||
public interface SQLFunction {
|
||||
|
||||
/**
|
||||
PerContextState assists aggregate and window functions in
|
||||
managing their accumulator state across calls to the UDF's
|
||||
callbacks.
|
||||
|
||||
<p>T must be of a type which can be legally stored as a value in
|
||||
java.util.HashMap<KeyType,T>.
|
||||
|
||||
<p>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.
|
||||
|
||||
<p>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.
|
||||
|
||||
<p>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 {@link AggregateFunction} and {@link
|
||||
WindowFunction} 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 the given context 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.
|
||||
|
||||
<p>The caller is obligated to eventually call
|
||||
takeAggregateState() to clear the mapping.
|
||||
*/
|
||||
public ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
|
||||
final Long key = cx.getAggregateContext(true);
|
||||
ValueHolder<T> rc = null==key ? null : map.get(key);
|
||||
if( null==rc ){
|
||||
map.put(key, 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(false));
|
||||
return null==h ? null : h.value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,14 @@ import java.util.concurrent.Future;
|
||||
@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
|
||||
@interface SingleThreadOnly{}
|
||||
|
||||
/**
|
||||
Annotation for Tester1 tests which must only be run if
|
||||
sqlite3_jni_supports_nio() is true.
|
||||
*/
|
||||
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
|
||||
@interface RequiresJniNio{}
|
||||
|
||||
public class Tester1 implements Runnable {
|
||||
//! True when running in multi-threaded mode.
|
||||
private static boolean mtMode = false;
|
||||
@@ -46,7 +54,7 @@ public class Tester1 implements Runnable {
|
||||
//! True to shuffle the order of the tests.
|
||||
private static boolean shuffle = false;
|
||||
//! True to dump the list of to-run tests to stdout.
|
||||
private static boolean listRunTests = false;
|
||||
private static int listRunTests = 0;
|
||||
//! True to squelch all out() and outln() output.
|
||||
private static boolean quietMode = false;
|
||||
//! Total number of runTests() calls.
|
||||
@@ -327,7 +335,7 @@ public class Tester1 implements Runnable {
|
||||
|
||||
|
||||
rc = sqlite3_prepare_v3(db, "INSERT INTO t2(a) VALUES(1),(2),(3)",
|
||||
SQLITE_PREPARE_NORMALIZE, outStmt);
|
||||
0, outStmt);
|
||||
affirm(0 == rc);
|
||||
stmt = outStmt.get();
|
||||
affirm(0 != stmt.getNativePointer());
|
||||
@@ -382,6 +390,15 @@ public class Tester1 implements Runnable {
|
||||
stmt = prepare(db, "SELECT a FROM t ORDER BY a DESC;");
|
||||
affirm( sqlite3_stmt_readonly(stmt) );
|
||||
affirm( !sqlite3_stmt_busy(stmt) );
|
||||
if( sqlite3_compileoption_used("ENABLE_COLUMN_METADATA") ){
|
||||
/* Unlike in native C code, JNI won't trigger an
|
||||
UnsatisfiedLinkError until these are called (on Linux, at
|
||||
least). */
|
||||
affirm("t".equals(sqlite3_column_table_name(stmt,0)));
|
||||
affirm("main".equals(sqlite3_column_database_name(stmt,0)));
|
||||
affirm("a".equals(sqlite3_column_origin_name(stmt,0)));
|
||||
}
|
||||
|
||||
int total2 = 0;
|
||||
while( SQLITE_ROW == sqlite3_step(stmt) ){
|
||||
affirm( sqlite3_stmt_busy(stmt) );
|
||||
@@ -477,6 +494,7 @@ public class Tester1 implements Runnable {
|
||||
stmt = prepare(db, "SELECT a FROM t ORDER BY a DESC;");
|
||||
StringBuilder sbuf = new StringBuilder();
|
||||
n = 0;
|
||||
final boolean tryNio = sqlite3_jni_supports_nio();
|
||||
while( SQLITE_ROW == sqlite3_step(stmt) ){
|
||||
final sqlite3_value sv = sqlite3_value_dup(sqlite3_column_value(stmt,0));
|
||||
final String txt = sqlite3_column_text16(stmt, 0);
|
||||
@@ -491,6 +509,15 @@ public class Tester1 implements Runnable {
|
||||
StandardCharsets.UTF_8)) );
|
||||
affirm( txt.length() == sqlite3_value_bytes16(sv)/2 );
|
||||
affirm( txt.equals(sqlite3_value_text16(sv)) );
|
||||
if( tryNio ){
|
||||
java.nio.ByteBuffer bu = sqlite3_value_nio_buffer(sv);
|
||||
byte ba[] = sqlite3_value_blob(sv);
|
||||
affirm( ba.length == bu.capacity() );
|
||||
int i = 0;
|
||||
for( byte b : ba ){
|
||||
affirm( b == bu.get(i++) );
|
||||
}
|
||||
}
|
||||
sqlite3_value_free(sv);
|
||||
++n;
|
||||
}
|
||||
@@ -548,6 +575,79 @@ public class Tester1 implements Runnable {
|
||||
sqlite3_close_v2(db);
|
||||
}
|
||||
|
||||
@RequiresJniNio
|
||||
private void testBindByteBuffer(){
|
||||
/* TODO: these tests need to be much more extensive to check the
|
||||
begin/end range handling. */
|
||||
|
||||
java.nio.ByteBuffer zeroCheck =
|
||||
java.nio.ByteBuffer.allocateDirect(0);
|
||||
affirm( null != zeroCheck );
|
||||
zeroCheck = null;
|
||||
sqlite3 db = createNewDb();
|
||||
execSql(db, "CREATE TABLE t(a)");
|
||||
|
||||
final java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocateDirect(10);
|
||||
buf.put((byte)0x31)/*note that we'll skip this one*/
|
||||
.put((byte)0x32)
|
||||
.put((byte)0x33)
|
||||
.put((byte)0x34)
|
||||
.put((byte)0x35)/*we'll skip this one too*/;
|
||||
|
||||
final int expectTotal = buf.get(1) + buf.get(2) + buf.get(3);
|
||||
sqlite3_stmt stmt = prepare(db, "INSERT INTO t(a) VALUES(?);");
|
||||
affirm( SQLITE_ERROR == sqlite3_bind_blob(stmt, 1, buf, -1, 0),
|
||||
"Buffer offset may not be negative." );
|
||||
affirm( 0 == sqlite3_bind_blob(stmt, 1, buf, 1, 3) );
|
||||
affirm( SQLITE_DONE == sqlite3_step(stmt) );
|
||||
sqlite3_finalize(stmt);
|
||||
stmt = prepare(db, "SELECT a FROM t;");
|
||||
int total = 0;
|
||||
affirm( SQLITE_ROW == sqlite3_step(stmt) );
|
||||
byte blob[] = sqlite3_column_blob(stmt, 0);
|
||||
java.nio.ByteBuffer nioBlob =
|
||||
sqlite3_column_nio_buffer(stmt, 0);
|
||||
affirm(3 == blob.length);
|
||||
affirm(blob.length == nioBlob.capacity());
|
||||
affirm(blob.length == nioBlob.limit());
|
||||
int i = 0;
|
||||
for(byte b : blob){
|
||||
affirm( i<=3 );
|
||||
affirm(b == buf.get(1 + i));
|
||||
affirm(b == nioBlob.get(i));
|
||||
++i;
|
||||
total += b;
|
||||
}
|
||||
affirm( SQLITE_DONE == sqlite3_step(stmt) );
|
||||
sqlite3_finalize(stmt);
|
||||
affirm(total == expectTotal);
|
||||
|
||||
SQLFunction func =
|
||||
new ScalarFunction(){
|
||||
public void xFunc(sqlite3_context cx, sqlite3_value[] args){
|
||||
sqlite3_result_blob(cx, buf, 1, 3);
|
||||
}
|
||||
};
|
||||
|
||||
affirm( 0 == sqlite3_create_function(db, "myfunc", -1, SQLITE_UTF8, func) );
|
||||
stmt = prepare(db, "SELECT myfunc()");
|
||||
affirm( SQLITE_ROW == sqlite3_step(stmt) );
|
||||
blob = sqlite3_column_blob(stmt, 0);
|
||||
affirm(3 == blob.length);
|
||||
i = 0;
|
||||
total = 0;
|
||||
for(byte b : blob){
|
||||
affirm( i<=3 );
|
||||
affirm(b == buf.get(1 + i++));
|
||||
total += b;
|
||||
}
|
||||
affirm( SQLITE_DONE == sqlite3_step(stmt) );
|
||||
sqlite3_finalize(stmt);
|
||||
affirm(total == expectTotal);
|
||||
|
||||
sqlite3_close_v2(db);
|
||||
}
|
||||
|
||||
private void testSql(){
|
||||
sqlite3 db = createNewDb();
|
||||
sqlite3_stmt stmt = prepare(db, "SELECT 1");
|
||||
@@ -593,9 +693,9 @@ public class Tester1 implements Runnable {
|
||||
};
|
||||
final CollationNeededCallback collLoader = new CollationNeededCallback(){
|
||||
@Override
|
||||
public int call(sqlite3 dbArg, int eTextRep, String collationName){
|
||||
public void call(sqlite3 dbArg, int eTextRep, String collationName){
|
||||
affirm(dbArg == db/* as opposed to a temporary object*/);
|
||||
return sqlite3_create_collation(dbArg, "reversi", eTextRep, myCollation);
|
||||
sqlite3_create_collation(dbArg, "reversi", eTextRep, myCollation);
|
||||
}
|
||||
};
|
||||
int rc = sqlite3_collation_needed(db, collLoader);
|
||||
@@ -803,13 +903,17 @@ public class Tester1 implements Runnable {
|
||||
affirm( 0==rc );
|
||||
int n = 0;
|
||||
if( SQLITE_ROW == sqlite3_step(stmt) ){
|
||||
affirm( testResult.value == sqlite3_column_java_object(stmt, 0) );
|
||||
affirm( testResult.value == sqlite3_column_java_object(stmt, 0, sqlite3.class) );
|
||||
affirm( null == sqlite3_column_java_object(stmt, 0, sqlite3_stmt.class) );
|
||||
affirm( null == sqlite3_column_java_object(stmt,1) );
|
||||
final sqlite3_value v = sqlite3_column_value(stmt, 0);
|
||||
affirm( testResult.value == sqlite3_value_java_object(v) );
|
||||
affirm( testResult.value == sqlite3_value_java_casted(v, sqlite3.class) );
|
||||
affirm( testResult.value == sqlite3_value_java_object(v, sqlite3.class) );
|
||||
affirm( testResult.value ==
|
||||
sqlite3_value_java_casted(v, testResult.value.getClass()) );
|
||||
affirm( testResult.value == sqlite3_value_java_casted(v, Object.class) );
|
||||
affirm( null == sqlite3_value_java_casted(v, String.class) );
|
||||
sqlite3_value_java_object(v, testResult.value.getClass()) );
|
||||
affirm( testResult.value == sqlite3_value_java_object(v, Object.class) );
|
||||
affirm( null == sqlite3_value_java_object(v, String.class) );
|
||||
++n;
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
@@ -824,15 +928,28 @@ public class Tester1 implements Runnable {
|
||||
// To confirm that xFinal() is called with no aggregate state
|
||||
// when the corresponding result set is empty.
|
||||
new ValueHolder<>(false);
|
||||
final ValueHolder<sqlite3_value[]> neverEverDoThisInClientCode = new ValueHolder<>(null);
|
||||
final ValueHolder<sqlite3_context> neverEverDoThisInClientCode2 = new ValueHolder<>(null);
|
||||
SQLFunction func = new AggregateFunction<Integer>(){
|
||||
@Override
|
||||
public void xStep(sqlite3_context cx, sqlite3_value[] args){
|
||||
if( null==neverEverDoThisInClientCode.value ){
|
||||
/* !!!NEVER!!! hold a reference to an sqlite3_value or
|
||||
sqlite3_context object like this in client code! They
|
||||
are ONLY legal for the duration of their single
|
||||
call. We do it here ONLY to test that the defenses
|
||||
against clients doing this are working. */
|
||||
neverEverDoThisInClientCode.value = args;
|
||||
}
|
||||
final ValueHolder<Integer> agg = this.getAggregateState(cx, 0);
|
||||
agg.value += sqlite3_value_int(args[0]);
|
||||
affirm( agg == this.getAggregateState(cx, 0) );
|
||||
}
|
||||
@Override
|
||||
public void xFinal(sqlite3_context cx){
|
||||
if( null==neverEverDoThisInClientCode2.value ){
|
||||
neverEverDoThisInClientCode2.value = cx;
|
||||
}
|
||||
final Integer v = this.takeAggregateState(cx);
|
||||
if(null == v){
|
||||
xFinalNull.value = true;
|
||||
@@ -857,6 +974,10 @@ public class Tester1 implements Runnable {
|
||||
}
|
||||
affirm( 1==n );
|
||||
affirm(!xFinalNull.value);
|
||||
affirm( null!=neverEverDoThisInClientCode.value );
|
||||
affirm( null!=neverEverDoThisInClientCode2.value );
|
||||
affirm( 0<neverEverDoThisInClientCode.value.length );
|
||||
affirm( 0==neverEverDoThisInClientCode2.value.getNativePointer() );
|
||||
sqlite3_reset(stmt);
|
||||
affirm( 1==sqlite3_stmt_status(stmt, SQLITE_STMTSTATUS_RUN, false) );
|
||||
// Ensure that the accumulator is reset on subsequent calls...
|
||||
@@ -925,7 +1046,6 @@ public class Tester1 implements Runnable {
|
||||
"ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING"+
|
||||
") AS sum_y "+
|
||||
"FROM twin ORDER BY x;");
|
||||
affirm( 0 == rc );
|
||||
int n = 0;
|
||||
while( SQLITE_ROW == sqlite3_step(stmt) ){
|
||||
final String s = sqlite3_column_text16(stmt, 0);
|
||||
@@ -1028,48 +1148,48 @@ public class Tester1 implements Runnable {
|
||||
@SingleThreadOnly /* because threads inherently break this test */
|
||||
private static void testBusy(){
|
||||
final String dbName = "_busy-handler.db";
|
||||
final OutputPointer.sqlite3 outDb = new OutputPointer.sqlite3();
|
||||
final OutputPointer.sqlite3_stmt outStmt = new OutputPointer.sqlite3_stmt();
|
||||
|
||||
int rc = sqlite3_open(dbName, outDb);
|
||||
++metrics.dbOpen;
|
||||
affirm( 0 == rc );
|
||||
final sqlite3 db1 = outDb.get();
|
||||
execSql(db1, "CREATE TABLE IF NOT EXISTS t(a)");
|
||||
rc = sqlite3_open(dbName, outDb);
|
||||
++metrics.dbOpen;
|
||||
affirm( 0 == rc );
|
||||
affirm( outDb.get() != db1 );
|
||||
final sqlite3 db2 = outDb.get();
|
||||
|
||||
affirm( "main".equals( sqlite3_db_name(db1, 0) ) );
|
||||
rc = sqlite3_db_config(db1, SQLITE_DBCONFIG_MAINDBNAME, "foo");
|
||||
affirm( sqlite3_db_filename(db1, "foo").endsWith(dbName) );
|
||||
affirm( "foo".equals( sqlite3_db_name(db1, 0) ) );
|
||||
|
||||
final ValueHolder<Integer> xBusyCalled = new ValueHolder<>(0);
|
||||
BusyHandlerCallback handler = new BusyHandlerCallback(){
|
||||
@Override public int call(int n){
|
||||
//outln("busy handler #"+n);
|
||||
return n > 2 ? 0 : ++xBusyCalled.value;
|
||||
}
|
||||
};
|
||||
rc = sqlite3_busy_handler(db2, handler);
|
||||
affirm(0 == rc);
|
||||
|
||||
// Force a locked condition...
|
||||
execSql(db1, "BEGIN EXCLUSIVE");
|
||||
rc = sqlite3_prepare_v2(db2, "SELECT * from t", outStmt);
|
||||
affirm( SQLITE_BUSY == rc);
|
||||
affirm( null == outStmt.get() );
|
||||
affirm( 3 == xBusyCalled.value );
|
||||
sqlite3_close_v2(db1);
|
||||
sqlite3_close_v2(db2);
|
||||
try{
|
||||
final java.io.File f = new java.io.File(dbName);
|
||||
f.delete();
|
||||
}catch(Exception e){
|
||||
/* ignore */
|
||||
final OutputPointer.sqlite3 outDb = new OutputPointer.sqlite3();
|
||||
final OutputPointer.sqlite3_stmt outStmt = new OutputPointer.sqlite3_stmt();
|
||||
|
||||
int rc = sqlite3_open(dbName, outDb);
|
||||
++metrics.dbOpen;
|
||||
affirm( 0 == rc );
|
||||
final sqlite3 db1 = outDb.get();
|
||||
execSql(db1, "CREATE TABLE IF NOT EXISTS t(a)");
|
||||
rc = sqlite3_open(dbName, outDb);
|
||||
++metrics.dbOpen;
|
||||
affirm( 0 == rc );
|
||||
affirm( outDb.get() != db1 );
|
||||
final sqlite3 db2 = outDb.get();
|
||||
|
||||
affirm( "main".equals( sqlite3_db_name(db1, 0) ) );
|
||||
rc = sqlite3_db_config(db1, SQLITE_DBCONFIG_MAINDBNAME, "foo");
|
||||
affirm( sqlite3_db_filename(db1, "foo").endsWith(dbName) );
|
||||
affirm( "foo".equals( sqlite3_db_name(db1, 0) ) );
|
||||
affirm( SQLITE_MISUSE == sqlite3_db_config(db1, 0, 0, null) );
|
||||
|
||||
final ValueHolder<Integer> xBusyCalled = new ValueHolder<>(0);
|
||||
BusyHandlerCallback handler = new BusyHandlerCallback(){
|
||||
@Override public int call(int n){
|
||||
//outln("busy handler #"+n);
|
||||
return n > 2 ? 0 : ++xBusyCalled.value;
|
||||
}
|
||||
};
|
||||
rc = sqlite3_busy_handler(db2, handler);
|
||||
affirm(0 == rc);
|
||||
|
||||
// Force a locked condition...
|
||||
execSql(db1, "BEGIN EXCLUSIVE");
|
||||
rc = sqlite3_prepare_v2(db2, "SELECT * from t", outStmt);
|
||||
affirm( SQLITE_BUSY == rc);
|
||||
affirm( null == outStmt.get() );
|
||||
affirm( 3 == xBusyCalled.value );
|
||||
sqlite3_close_v2(db1);
|
||||
sqlite3_close_v2(db2);
|
||||
}finally{
|
||||
try{(new java.io.File(dbName)).delete();}
|
||||
catch(Exception e){/* ignore */}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1093,6 +1213,7 @@ public class Tester1 implements Runnable {
|
||||
|
||||
private void testCommitHook(){
|
||||
final sqlite3 db = createNewDb();
|
||||
sqlite3_extended_result_codes(db, true);
|
||||
final ValueHolder<Integer> counter = new ValueHolder<>(0);
|
||||
final ValueHolder<Integer> hookResult = new ValueHolder<>(0);
|
||||
final CommitHookCallback theHook = new CommitHookCallback(){
|
||||
@@ -1135,7 +1256,7 @@ public class Tester1 implements Runnable {
|
||||
affirm( 5 == counter.value );
|
||||
hookResult.value = SQLITE_ERROR;
|
||||
int rc = execSql(db, false, "BEGIN; update t set a='j' where a='i'; COMMIT;");
|
||||
affirm( SQLITE_CONSTRAINT == rc );
|
||||
affirm( SQLITE_CONSTRAINT_COMMITHOOK == rc );
|
||||
affirm( 6 == counter.value );
|
||||
sqlite3_close_v2(db);
|
||||
}
|
||||
@@ -1354,6 +1475,9 @@ public class Tester1 implements Runnable {
|
||||
authRc.value = SQLITE_DENY;
|
||||
int rc = execSql(db, false, "UPDATE t SET a=2");
|
||||
affirm( SQLITE_AUTH==rc );
|
||||
sqlite3_set_authorizer(db, null);
|
||||
rc = execSql(db, false, "UPDATE t SET a=2");
|
||||
affirm( 0==rc );
|
||||
// TODO: expand these tests considerably
|
||||
sqlite3_close(db);
|
||||
}
|
||||
@@ -1415,7 +1539,7 @@ public class Tester1 implements Runnable {
|
||||
|
||||
val.value = 0;
|
||||
final AutoExtensionCallback ax2 = new AutoExtensionCallback(){
|
||||
@Override public synchronized int call(sqlite3 db){
|
||||
@Override public int call(sqlite3 db){
|
||||
++val.value;
|
||||
return 0;
|
||||
}
|
||||
@@ -1626,7 +1750,7 @@ public class Tester1 implements Runnable {
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
b = sqlite3_blob_open(db, "main", "t", "a",
|
||||
sqlite3_last_insert_rowid(db), 1);
|
||||
sqlite3_last_insert_rowid(db), 0);
|
||||
affirm( null!=b );
|
||||
rc = sqlite3_blob_reopen(b, 2);
|
||||
affirm( 0==rc );
|
||||
@@ -1636,6 +1760,86 @@ public class Tester1 implements Runnable {
|
||||
affirm( 100==tgt[0] && 101==tgt[1] && 102==tgt[2], "DEF" );
|
||||
rc = sqlite3_blob_close(b);
|
||||
affirm( 0==rc );
|
||||
|
||||
if( !sqlite3_jni_supports_nio() ){
|
||||
outln("WARNING: skipping tests for ByteBuffer-using sqlite3_blob APIs ",
|
||||
"because this platform lacks that support.");
|
||||
sqlite3_close_v2(db);
|
||||
return;
|
||||
}
|
||||
/* Sanity checks for the java.nio.ByteBuffer-taking overloads of
|
||||
sqlite3_blob_read/write(). */
|
||||
execSql(db, "UPDATE t SET a=zeroblob(10)");
|
||||
b = sqlite3_blob_open(db, "main", "t", "a", 1, 1);
|
||||
affirm( null!=b );
|
||||
java.nio.ByteBuffer bb = java.nio.ByteBuffer.allocateDirect(10);
|
||||
for( byte i = 0; i < 10; ++i ){
|
||||
bb.put((int)i, (byte)(48+i & 0xff));
|
||||
}
|
||||
rc = sqlite3_blob_write(b, 1, bb, 1, 10);
|
||||
affirm( rc==SQLITE_ERROR, "b length < (srcOffset + bb length)" );
|
||||
rc = sqlite3_blob_write(b, -1, bb);
|
||||
affirm( rc==SQLITE_ERROR, "Target offset may not be negative" );
|
||||
rc = sqlite3_blob_write(b, 0, bb, -1, -1);
|
||||
affirm( rc==SQLITE_ERROR, "Source offset may not be negative" );
|
||||
rc = sqlite3_blob_write(b, 1, bb, 1, 8);
|
||||
affirm( rc==0 );
|
||||
// b's contents: 0 49 50 51 52 53 54 55 56 0
|
||||
// ascii: 0 '1' '2' '3' '4' '5' '6' '7' '8' 0
|
||||
byte br[] = new byte[10];
|
||||
java.nio.ByteBuffer bbr =
|
||||
java.nio.ByteBuffer.allocateDirect(bb.limit());
|
||||
rc = sqlite3_blob_read( b, br, 0 );
|
||||
affirm( rc==0 );
|
||||
rc = sqlite3_blob_read( b, bbr );
|
||||
affirm( rc==0 );
|
||||
java.nio.ByteBuffer bbr2 = sqlite3_blob_read_nio_buffer(b, 0, 12);
|
||||
affirm( null==bbr2, "Read size is too big");
|
||||
bbr2 = sqlite3_blob_read_nio_buffer(b, -1, 3);
|
||||
affirm( null==bbr2, "Source offset is negative");
|
||||
bbr2 = sqlite3_blob_read_nio_buffer(b, 5, 6);
|
||||
affirm( null==bbr2, "Read pos+size is too big");
|
||||
bbr2 = sqlite3_blob_read_nio_buffer(b, 4, 7);
|
||||
affirm( null==bbr2, "Read pos+size is too big");
|
||||
bbr2 = sqlite3_blob_read_nio_buffer(b, 4, 6);
|
||||
affirm( null!=bbr2 );
|
||||
java.nio.ByteBuffer bbr3 =
|
||||
java.nio.ByteBuffer.allocateDirect(2 * bb.limit());
|
||||
java.nio.ByteBuffer bbr4 =
|
||||
java.nio.ByteBuffer.allocateDirect(5);
|
||||
rc = sqlite3_blob_read( b, bbr3 );
|
||||
affirm( rc==0 );
|
||||
rc = sqlite3_blob_read( b, bbr4 );
|
||||
affirm( rc==0 );
|
||||
affirm( sqlite3_blob_bytes(b)==bbr3.limit() );
|
||||
affirm( 5==bbr4.limit() );
|
||||
sqlite3_blob_close(b);
|
||||
affirm( 0==br[0] );
|
||||
affirm( 0==br[9] );
|
||||
affirm( 0==bbr.get(0) );
|
||||
affirm( 0==bbr.get(9) );
|
||||
affirm( bbr2.limit() == 6 );
|
||||
affirm( 0==bbr3.get(0) );
|
||||
{
|
||||
Exception ex = null;
|
||||
try{ bbr3.get(11); }
|
||||
catch(Exception e){ex = e;}
|
||||
affirm( ex instanceof IndexOutOfBoundsException,
|
||||
"bbr3.limit() was reset by read()" );
|
||||
ex = null;
|
||||
}
|
||||
affirm( 0==bbr4.get(0) );
|
||||
for( int i = 1; i < 9; ++i ){
|
||||
affirm( br[i] == 48 + i );
|
||||
affirm( br[i] == bbr.get(i) );
|
||||
affirm( br[i] == bbr3.get(i) );
|
||||
if( i>3 ){
|
||||
affirm( br[i] == bbr2.get(i-4) );
|
||||
}
|
||||
if( i < bbr4.limit() ){
|
||||
affirm( br[i] == bbr4.get(i) );
|
||||
}
|
||||
}
|
||||
sqlite3_close_v2(db);
|
||||
}
|
||||
|
||||
@@ -1648,9 +1852,13 @@ public class Tester1 implements Runnable {
|
||||
};
|
||||
final List<sqlite3_stmt> liStmt = new ArrayList<sqlite3_stmt>();
|
||||
final PrepareMultiCallback proxy = new PrepareMultiCallback.StepAll();
|
||||
final ValueHolder<String> toss = new ValueHolder<>(null);
|
||||
PrepareMultiCallback m = new PrepareMultiCallback() {
|
||||
@Override public int call(sqlite3_stmt st){
|
||||
liStmt.add(st);
|
||||
if( null!=toss.value ){
|
||||
throw new RuntimeException(toss.value);
|
||||
}
|
||||
return proxy.call(st);
|
||||
}
|
||||
};
|
||||
@@ -1660,6 +1868,10 @@ public class Tester1 implements Runnable {
|
||||
for( sqlite3_stmt st : liStmt ){
|
||||
sqlite3_finalize(st);
|
||||
}
|
||||
toss.value = "This is an exception.";
|
||||
rc = sqlite3_prepare_multi(db, "SELECT 1", m);
|
||||
affirm( SQLITE_ERROR==rc );
|
||||
affirm( sqlite3_errmsg(db).indexOf(toss.value)>0 );
|
||||
sqlite3_close_v2(db);
|
||||
}
|
||||
|
||||
@@ -1698,7 +1910,7 @@ public class Tester1 implements Runnable {
|
||||
mlist = new ArrayList<>( testMethods.subList(0, testMethods.size()) );
|
||||
java.util.Collections.shuffle(mlist);
|
||||
}
|
||||
if( listRunTests ){
|
||||
if( (!fromThread && listRunTests>0) || listRunTests>1 ){
|
||||
synchronized(this.getClass()){
|
||||
if( !fromThread ){
|
||||
out("Initial test"," list: ");
|
||||
@@ -1760,8 +1972,11 @@ public class Tester1 implements Runnable {
|
||||
-naps: sleep small random intervals between tests in order to add
|
||||
some chaos for cross-thread contention.
|
||||
|
||||
|
||||
-list-tests: outputs the list of tests being run, minus some
|
||||
which are hard-coded. This is noisy in multi-threaded mode.
|
||||
which are hard-coded. In multi-threaded mode, use this twice to
|
||||
to emit the list run by each thread (which may differ from the initial
|
||||
list, in particular if -shuffle is used).
|
||||
|
||||
-fail: forces an exception to be thrown during the test run. Use
|
||||
with -shuffle to make its appearance unpredictable.
|
||||
@@ -1790,7 +2005,7 @@ public class Tester1 implements Runnable {
|
||||
}else if(arg.equals("shuffle")){
|
||||
shuffle = true;
|
||||
}else if(arg.equals("list-tests")){
|
||||
listRunTests = true;
|
||||
++listRunTests;
|
||||
}else if(arg.equals("fail")){
|
||||
forceFail = true;
|
||||
}else if(arg.equals("sqllog")){
|
||||
@@ -1809,7 +2024,7 @@ public class Tester1 implements Runnable {
|
||||
|
||||
if( sqlLog ){
|
||||
if( sqlite3_compileoption_used("ENABLE_SQLLOG") ){
|
||||
final ConfigSqllogCallback log = new ConfigSqllogCallback() {
|
||||
final ConfigSqlLogCallback log = new ConfigSqlLogCallback() {
|
||||
@Override public void call(sqlite3 db, String msg, int op){
|
||||
switch(op){
|
||||
case 0: outln("Opening db: ",db); break;
|
||||
@@ -1820,7 +2035,7 @@ public class Tester1 implements Runnable {
|
||||
};
|
||||
int rc = sqlite3_config( log );
|
||||
affirm( 0==rc );
|
||||
rc = sqlite3_config( (ConfigSqllogCallback)null );
|
||||
rc = sqlite3_config( (ConfigSqlLogCallback)null );
|
||||
affirm( 0==rc );
|
||||
rc = sqlite3_config( log );
|
||||
affirm( 0==rc );
|
||||
@@ -1858,18 +2073,20 @@ public class Tester1 implements Runnable {
|
||||
if( forceFail ){
|
||||
testMethods.add(m);
|
||||
}
|
||||
}else if( m.isAnnotationPresent( RequiresJniNio.class )
|
||||
&& !sqlite3_jni_supports_nio() ){
|
||||
outln("Skipping test for lack of JNI java.nio.ByteBuffer support: ",
|
||||
name,"()\n");
|
||||
++nSkipped;
|
||||
}else if( !m.isAnnotationPresent( ManualTest.class ) ){
|
||||
if( nThread>1 && m.isAnnotationPresent( SingleThreadOnly.class ) ){
|
||||
if( 0==nSkipped++ ){
|
||||
out("Skipping tests in multi-thread mode:");
|
||||
}
|
||||
out(" "+name+"()");
|
||||
out("Skipping test in multi-thread mode: ",name,"()\n");
|
||||
++nSkipped;
|
||||
}else if( name.startsWith("test") ){
|
||||
testMethods.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( nSkipped>0 ) out("\n");
|
||||
}
|
||||
|
||||
final long timeStart = System.currentTimeMillis();
|
||||
@@ -1901,6 +2118,7 @@ public class Tester1 implements Runnable {
|
||||
sqlite3_libversion_number(),"\n",
|
||||
sqlite3_libversion(),"\n",SQLITE_SOURCE_ID,"\n",
|
||||
"SQLITE_THREADSAFE=",sqlite3_threadsafe());
|
||||
outln("JVM NIO support? ",sqlite3_jni_supports_nio() ? "YES" : "NO");
|
||||
final boolean showLoopCount = (nRepeat>1 && nThread>1);
|
||||
if( showLoopCount ){
|
||||
outln("Running ",nRepeat," loop(s) with ",nThread," thread(s) each.");
|
||||
|
||||
@@ -19,7 +19,8 @@ package org.sqlite.jni.capi;
|
||||
public interface UpdateHookCallback extends CallbackProxy {
|
||||
/**
|
||||
Must function as described for the C-level sqlite3_update_hook()
|
||||
callback.
|
||||
callback. If it throws, the exception is translated into
|
||||
a db-level error.
|
||||
*/
|
||||
void call(int opId, String dbName, String tableName, long rowId);
|
||||
}
|
||||
|
||||
@@ -9,14 +9,16 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains a set of tests for the sqlite3 JNI bindings.
|
||||
** This file contains the ValueHolder utility class for the sqlite3
|
||||
** JNI bindings.
|
||||
*/
|
||||
package org.sqlite.jni.capi;
|
||||
|
||||
/**
|
||||
A helper class which simply holds a single value. Its primary use
|
||||
is for communicating values out of anonymous classes, as doing so
|
||||
requires a "final" reference.
|
||||
requires a "final" reference, as well as communicating aggregate
|
||||
SQL function state across calls to such functions.
|
||||
*/
|
||||
public class ValueHolder<T> {
|
||||
public T value;
|
||||
|
||||
@@ -38,6 +38,6 @@ public final class sqlite3 extends NativePointerHolder<sqlite3>
|
||||
}
|
||||
|
||||
@Override public void close(){
|
||||
CApi.sqlite3_close_v2(this.clearNativePointer());
|
||||
CApi.sqlite3_close_v2(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ public final class sqlite3_blob extends NativePointerHolder<sqlite3_blob>
|
||||
private sqlite3_blob(){}
|
||||
|
||||
@Override public void close(){
|
||||
CApi.sqlite3_blob_close(this.clearNativePointer());
|
||||
CApi.sqlite3_blob_close(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,6 @@ public final class sqlite3_stmt extends NativePointerHolder<sqlite3_stmt>
|
||||
private sqlite3_stmt(){}
|
||||
|
||||
@Override public void close(){
|
||||
CApi.sqlite3_finalize(this.clearNativePointer());
|
||||
CApi.sqlite3_finalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
** This file is part of the wrapper1 interface for sqlite3.
|
||||
*/
|
||||
package org.sqlite.jni.wrapper1;
|
||||
import org.sqlite.jni.capi.CApi;
|
||||
import org.sqlite.jni.annotation.*;
|
||||
import org.sqlite.jni.capi.sqlite3_context;
|
||||
import org.sqlite.jni.capi.sqlite3_value;
|
||||
|
||||
/**
|
||||
EXPERIMENTAL/INCOMPLETE/UNTESTED
|
||||
@@ -51,9 +47,75 @@ public abstract class AggregateFunction<T> implements SqlFunction {
|
||||
*/
|
||||
public void xDestroy() {}
|
||||
|
||||
/**
|
||||
PerContextState assists aggregate and window functions in
|
||||
managing their accumulator state across calls to the UDF's
|
||||
callbacks.
|
||||
|
||||
<p>T must be of a type which can be legally stored as a value in
|
||||
java.util.HashMap<KeyType,T>.
|
||||
|
||||
<p>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.
|
||||
|
||||
<p>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.
|
||||
|
||||
<p>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 {@link AggregateFunction} and {@link
|
||||
WindowFunction} 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 the given context 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.
|
||||
|
||||
<p>The caller is obligated to eventually call
|
||||
takeAggregateState() to clear the mapping.
|
||||
*/
|
||||
public ValueHolder<T> getAggregateState(SqlFunction.Arguments args, T initialValue){
|
||||
final Long key = args.getContext().getAggregateContext(true);
|
||||
ValueHolder<T> rc = null==key ? null : map.get(key);
|
||||
if( null==rc ){
|
||||
map.put(key, 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 with the arguments' aggregate context 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(SqlFunction.Arguments args){
|
||||
final ValueHolder<T> h = map.remove(args.getContext().getAggregateContext(false));
|
||||
return null==h ? null : h.value;
|
||||
}
|
||||
}
|
||||
|
||||
/** Per-invocation state for the UDF. */
|
||||
private final SqlFunction.PerContextState<T> map =
|
||||
new SqlFunction.PerContextState<>();
|
||||
private final PerContextState<T> map = new PerContextState<>();
|
||||
|
||||
/**
|
||||
To be called from the implementation's xStep() method, as well
|
||||
|
||||
@@ -22,6 +22,14 @@ import org.sqlite.jni.capi.sqlite3_value;
|
||||
*/
|
||||
public interface SqlFunction {
|
||||
|
||||
public static final int DETERMINISTIC = CApi.SQLITE_DETERMINISTIC;
|
||||
public static final int INNOCUOUS = CApi.SQLITE_INNOCUOUS;
|
||||
public static final int DIRECTONLY = CApi.SQLITE_DIRECTONLY;
|
||||
public static final int SUBTYPE = CApi.SQLITE_SUBTYPE;
|
||||
public static final int RESULT_SUBTYPE = CApi.SQLITE_RESULT_SUBTYPE;
|
||||
public static final int UTF8 = CApi.SQLITE_UTF8;
|
||||
public static final int UTF16 = CApi.SQLITE_UTF16;
|
||||
|
||||
/**
|
||||
The Arguments type is an abstraction on top of the lower-level
|
||||
UDF function argument types. It provides _most_ of the functionality
|
||||
@@ -45,12 +53,118 @@ public interface SqlFunction {
|
||||
*/
|
||||
Arguments(sqlite3_context cx, sqlite3_value args[]){
|
||||
this.cx = cx;
|
||||
this.args = args==null ? new sqlite3_value[0] : args;;
|
||||
this.args = args==null ? new sqlite3_value[0] : args;
|
||||
this.length = this.args.length;
|
||||
}
|
||||
|
||||
/**
|
||||
Wrapper for a single SqlFunction argument. Primarily intended
|
||||
Returns the sqlite3_value at the given argument index or throws
|
||||
an IllegalArgumentException exception if ndx is out of range.
|
||||
*/
|
||||
private sqlite3_value valueAt(int ndx){
|
||||
if(ndx<0 || ndx>=args.length){
|
||||
throw new IllegalArgumentException(
|
||||
"SQL function argument index "+ndx+" is out of range."
|
||||
);
|
||||
}
|
||||
return args[ndx];
|
||||
}
|
||||
|
||||
//! Returns the underlying sqlite3_context for these arguments.
|
||||
sqlite3_context getContext(){return cx;}
|
||||
|
||||
/**
|
||||
Returns the Sqlite (db) object associated with this UDF call,
|
||||
or null if the UDF is somehow called without such an object or
|
||||
the db has been closed in an untimely manner (e.g. closed by a
|
||||
UDF call).
|
||||
*/
|
||||
public Sqlite getDb(){
|
||||
return Sqlite.fromNative( CApi.sqlite3_context_db_handle(cx) );
|
||||
}
|
||||
|
||||
public int getArgCount(){ return args.length; }
|
||||
|
||||
public int getInt(int argNdx){return CApi.sqlite3_value_int(valueAt(argNdx));}
|
||||
public long getInt64(int argNdx){return CApi.sqlite3_value_int64(valueAt(argNdx));}
|
||||
public double getDouble(int argNdx){return CApi.sqlite3_value_double(valueAt(argNdx));}
|
||||
public byte[] getBlob(int argNdx){return CApi.sqlite3_value_blob(valueAt(argNdx));}
|
||||
public byte[] getText(int argNdx){return CApi.sqlite3_value_text(valueAt(argNdx));}
|
||||
public String getText16(int argNdx){return CApi.sqlite3_value_text16(valueAt(argNdx));}
|
||||
public int getBytes(int argNdx){return CApi.sqlite3_value_bytes(valueAt(argNdx));}
|
||||
public int getBytes16(int argNdx){return CApi.sqlite3_value_bytes16(valueAt(argNdx));}
|
||||
public Object getObject(int argNdx){return CApi.sqlite3_value_java_object(valueAt(argNdx));}
|
||||
public <T> T getObject(int argNdx, Class<T> type){
|
||||
return CApi.sqlite3_value_java_object(valueAt(argNdx), type);
|
||||
}
|
||||
|
||||
public int getType(int argNdx){return CApi.sqlite3_value_type(valueAt(argNdx));}
|
||||
public int getSubtype(int argNdx){return CApi.sqlite3_value_subtype(valueAt(argNdx));}
|
||||
public int getNumericType(int argNdx){return CApi.sqlite3_value_numeric_type(valueAt(argNdx));}
|
||||
public int getNoChange(int argNdx){return CApi.sqlite3_value_nochange(valueAt(argNdx));}
|
||||
public boolean getFromBind(int argNdx){return CApi.sqlite3_value_frombind(valueAt(argNdx));}
|
||||
public int getEncoding(int argNdx){return CApi.sqlite3_value_encoding(valueAt(argNdx));}
|
||||
|
||||
public void resultInt(int v){ CApi.sqlite3_result_int(cx, v); }
|
||||
public void resultInt64(long v){ CApi.sqlite3_result_int64(cx, v); }
|
||||
public void resultDouble(double v){ CApi.sqlite3_result_double(cx, v); }
|
||||
public void resultError(String msg){CApi.sqlite3_result_error(cx, msg);}
|
||||
public void resultError(Exception e){CApi.sqlite3_result_error(cx, e);}
|
||||
public void resultErrorTooBig(){CApi.sqlite3_result_error_toobig(cx);}
|
||||
public void resultErrorCode(int rc){CApi.sqlite3_result_error_code(cx, rc);}
|
||||
public void resultObject(Object o){CApi.sqlite3_result_java_object(cx, o);}
|
||||
public void resultNull(){CApi.sqlite3_result_null(cx);}
|
||||
/**
|
||||
Analog to sqlite3_result_value(), using the Value object at the
|
||||
given argument index.
|
||||
*/
|
||||
public void resultArg(int argNdx){CApi.sqlite3_result_value(cx, valueAt(argNdx));}
|
||||
public void resultSubtype(int subtype){CApi.sqlite3_result_subtype(cx, subtype);}
|
||||
public void resultZeroBlob(long n){
|
||||
// Throw on error? If n is too big,
|
||||
// sqlite3_result_error_toobig() is automatically called.
|
||||
CApi.sqlite3_result_zeroblob64(cx, n);
|
||||
}
|
||||
|
||||
public void resultBlob(byte[] blob){CApi.sqlite3_result_blob(cx, blob);}
|
||||
public void resultText(byte[] utf8){CApi.sqlite3_result_text(cx, utf8);}
|
||||
public void resultText(String txt){CApi.sqlite3_result_text(cx, txt);}
|
||||
public void resultText16(byte[] utf16){CApi.sqlite3_result_text16(cx, utf16);}
|
||||
public void resultText16(String txt){CApi.sqlite3_result_text16(cx, txt);}
|
||||
|
||||
/**
|
||||
Callbacks should invoke this on OOM errors, instead of throwing
|
||||
OutOfMemoryError, because the latter cannot be propagated
|
||||
through the C API.
|
||||
*/
|
||||
public void resultNoMem(){CApi.sqlite3_result_error_nomem(cx);}
|
||||
|
||||
/**
|
||||
Analog to sqlite3_set_auxdata() but throws if argNdx is out of
|
||||
range.
|
||||
*/
|
||||
public void setAuxData(int argNdx, Object o){
|
||||
/* From the API docs: https://www.sqlite.org/c3ref/get_auxdata.html
|
||||
|
||||
The value of the N parameter to these interfaces should be
|
||||
non-negative. Future enhancements may make use of negative N
|
||||
values to define new kinds of function caching behavior.
|
||||
*/
|
||||
valueAt(argNdx);
|
||||
CApi.sqlite3_set_auxdata(cx, argNdx, o);
|
||||
}
|
||||
|
||||
/**
|
||||
Analog to sqlite3_get_auxdata() but throws if argNdx is out of
|
||||
range.
|
||||
*/
|
||||
public Object getAuxData(int argNdx){
|
||||
valueAt(argNdx);
|
||||
return CApi.sqlite3_get_auxdata(cx, argNdx);
|
||||
}
|
||||
|
||||
/**
|
||||
Represents a single SqlFunction argument. Primarily intended
|
||||
for use with the Arguments class's Iterable interface.
|
||||
*/
|
||||
public final static class Arg {
|
||||
@@ -72,7 +186,7 @@ public interface SqlFunction {
|
||||
public int getBytes(){return a.getBytes(ndx);}
|
||||
public int getBytes16(){return a.getBytes16(ndx);}
|
||||
public Object getObject(){return a.getObject(ndx);}
|
||||
public <T> T getObjectCasted(Class<T> type){ return a.getObjectCasted(ndx, type); }
|
||||
public <T> T getObject(Class<T> type){ return a.getObject(ndx, type); }
|
||||
public int getType(){return a.getType(ndx);}
|
||||
public Object getAuxData(){return a.getAuxData(ndx);}
|
||||
public void setAuxData(Object o){a.setAuxData(ndx, o);}
|
||||
@@ -87,147 +201,6 @@ public interface SqlFunction {
|
||||
return java.util.Arrays.stream(proxies).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the sqlite3_value at the given argument index or throws
|
||||
an IllegalArgumentException exception if ndx is out of range.
|
||||
*/
|
||||
private sqlite3_value valueAt(int ndx){
|
||||
if(ndx<0 || ndx>=args.length){
|
||||
throw new IllegalArgumentException(
|
||||
"SQL function argument index "+ndx+" is out of range."
|
||||
);
|
||||
}
|
||||
return args[ndx];
|
||||
}
|
||||
|
||||
sqlite3_context getContext(){return cx;}
|
||||
|
||||
public int getArgCount(){ return args.length; }
|
||||
|
||||
public int getInt(int arg){return CApi.sqlite3_value_int(valueAt(arg));}
|
||||
public long getInt64(int arg){return CApi.sqlite3_value_int64(valueAt(arg));}
|
||||
public double getDouble(int arg){return CApi.sqlite3_value_double(valueAt(arg));}
|
||||
public byte[] getBlob(int arg){return CApi.sqlite3_value_blob(valueAt(arg));}
|
||||
public byte[] getText(int arg){return CApi.sqlite3_value_text(valueAt(arg));}
|
||||
public String getText16(int arg){return CApi.sqlite3_value_text16(valueAt(arg));}
|
||||
public int getBytes(int arg){return CApi.sqlite3_value_bytes(valueAt(arg));}
|
||||
public int getBytes16(int arg){return CApi.sqlite3_value_bytes16(valueAt(arg));}
|
||||
public Object getObject(int arg){return CApi.sqlite3_value_java_object(valueAt(arg));}
|
||||
public <T> T getObjectCasted(int arg, Class<T> type){
|
||||
return CApi.sqlite3_value_java_casted(valueAt(arg), type);
|
||||
}
|
||||
|
||||
public int getType(int arg){return CApi.sqlite3_value_type(valueAt(arg));}
|
||||
public int getSubtype(int arg){return CApi.sqlite3_value_subtype(valueAt(arg));}
|
||||
public int getNumericType(int arg){return CApi.sqlite3_value_numeric_type(valueAt(arg));}
|
||||
public int getNoChange(int arg){return CApi.sqlite3_value_nochange(valueAt(arg));}
|
||||
public boolean getFromBind(int arg){return CApi.sqlite3_value_frombind(valueAt(arg));}
|
||||
public int getEncoding(int arg){return CApi.sqlite3_value_encoding(valueAt(arg));}
|
||||
|
||||
public void resultInt(int v){ CApi.sqlite3_result_int(cx, v); }
|
||||
public void resultInt64(long v){ CApi.sqlite3_result_int64(cx, v); }
|
||||
public void resultDouble(double v){ CApi.sqlite3_result_double(cx, v); }
|
||||
public void resultError(String msg){CApi.sqlite3_result_error(cx, msg);}
|
||||
public void resultError(Exception e){CApi.sqlite3_result_error(cx, e);}
|
||||
public void resultErrorTooBig(){CApi.sqlite3_result_error_toobig(cx);}
|
||||
public void resultErrorCode(int rc){CApi.sqlite3_result_error_code(cx, rc);}
|
||||
public void resultObject(Object o){CApi.sqlite3_result_java_object(cx, o);}
|
||||
public void resultNull(){CApi.sqlite3_result_null(cx);}
|
||||
public void resultArg(int argNdx){CApi.sqlite3_result_value(cx, valueAt(argNdx));}
|
||||
public void resultZeroBlob(long n){
|
||||
// Throw on error? If n is too big,
|
||||
// sqlite3_result_error_toobig() is automatically called.
|
||||
CApi.sqlite3_result_zeroblob64(cx, n);
|
||||
}
|
||||
|
||||
public void resultBlob(byte[] blob){CApi.sqlite3_result_blob(cx, blob);}
|
||||
public void resultText(byte[] utf8){CApi.sqlite3_result_text(cx, utf8);}
|
||||
public void resultText(String txt){CApi.sqlite3_result_text(cx, txt);}
|
||||
public void resultText16(byte[] utf16){CApi.sqlite3_result_text16(cx, utf16);}
|
||||
public void resultText16(String txt){CApi.sqlite3_result_text16(cx, txt);}
|
||||
|
||||
public void setAuxData(int arg, Object o){
|
||||
/* From the API docs: https://www.sqlite.org/c3ref/get_auxdata.html
|
||||
|
||||
The value of the N parameter to these interfaces should be
|
||||
non-negative. Future enhancements may make use of negative N
|
||||
values to define new kinds of function caching behavior.
|
||||
*/
|
||||
valueAt(arg);
|
||||
CApi.sqlite3_set_auxdata(cx, arg, o);
|
||||
}
|
||||
|
||||
public Object getAuxData(int arg){
|
||||
valueAt(arg);
|
||||
return CApi.sqlite3_get_auxdata(cx, arg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
PerContextState assists aggregate and window functions in
|
||||
managing their accumulator state across calls to the UDF's
|
||||
callbacks.
|
||||
|
||||
<p>T must be of a type which can be legally stored as a value in
|
||||
java.util.HashMap<KeyType,T>.
|
||||
|
||||
<p>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.
|
||||
|
||||
<p>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.
|
||||
|
||||
<p>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 {@link AggregateFunction} and {@link
|
||||
WindowFunction} 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 the given context 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.
|
||||
|
||||
<p>The caller is obligated to eventually call
|
||||
takeAggregateState() to clear the mapping.
|
||||
*/
|
||||
public ValueHolder<T> getAggregateState(SqlFunction.Arguments args, T initialValue){
|
||||
final Long key = args.getContext().getAggregateContext(true);
|
||||
ValueHolder<T> rc = null==key ? null : map.get(key);
|
||||
if( null==rc ){
|
||||
map.put(key, 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 with the arguments' aggregate context 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(SqlFunction.Arguments args){
|
||||
final ValueHolder<T> h = map.remove(args.getContext().getAggregateContext(false));
|
||||
return null==h ? null : h.value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,7 +208,7 @@ public interface SqlFunction {
|
||||
for use with the org.sqlite.jni.capi.ScalarFunction interface.
|
||||
*/
|
||||
static final class ScalarAdapter extends org.sqlite.jni.capi.ScalarFunction {
|
||||
final ScalarFunction impl;
|
||||
private final ScalarFunction impl;
|
||||
ScalarAdapter(ScalarFunction impl){
|
||||
this.impl = impl;
|
||||
}
|
||||
@@ -261,8 +234,9 @@ public interface SqlFunction {
|
||||
Internal-use adapter for wrapping this package's AggregateFunction
|
||||
for use with the org.sqlite.jni.capi.AggregateFunction interface.
|
||||
*/
|
||||
static final class AggregateAdapter extends org.sqlite.jni.capi.AggregateFunction {
|
||||
final AggregateFunction impl;
|
||||
static /*cannot be final without duplicating the whole body in WindowAdapter*/
|
||||
class AggregateAdapter extends org.sqlite.jni.capi.AggregateFunction {
|
||||
private final AggregateFunction impl;
|
||||
AggregateAdapter(AggregateFunction impl){
|
||||
this.impl = impl;
|
||||
}
|
||||
@@ -282,8 +256,9 @@ public interface SqlFunction {
|
||||
}
|
||||
|
||||
/**
|
||||
As for the xFinal() argument of the C API's sqlite3_create_function().
|
||||
If the proxied function throws, it is translated into a sqlite3_result_error().
|
||||
As for the xFinal() argument of the C API's
|
||||
sqlite3_create_function(). If the proxied function throws, it
|
||||
is translated into a sqlite3_result_error().
|
||||
*/
|
||||
public void xFinal(sqlite3_context cx){
|
||||
try{
|
||||
@@ -298,4 +273,46 @@ public interface SqlFunction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Internal-use adapter for wrapping this package's WindowFunction
|
||||
for use with the org.sqlite.jni.capi.WindowFunction interface.
|
||||
*/
|
||||
static final class WindowAdapter extends AggregateAdapter {
|
||||
private final WindowFunction impl;
|
||||
WindowAdapter(WindowFunction impl){
|
||||
super(impl);
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
/**
|
||||
Proxies this.impl.xInverse(), adapting the call arguments to that
|
||||
function's signature. If the proxied function throws, it is
|
||||
translated to sqlite_result_error() with the exception's
|
||||
message.
|
||||
*/
|
||||
public void xInverse(sqlite3_context cx, sqlite3_value[] args){
|
||||
try{
|
||||
impl.xInverse( new SqlFunction.Arguments(cx, args) );
|
||||
}catch(Exception e){
|
||||
CApi.sqlite3_result_error(cx, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
As for the xValue() argument of the C API's sqlite3_create_window_function().
|
||||
If the proxied function throws, it is translated into a sqlite3_result_error().
|
||||
*/
|
||||
public void xValue(sqlite3_context cx){
|
||||
try{
|
||||
impl.xValue( new SqlFunction.Arguments(cx, null) );
|
||||
}catch(Exception e){
|
||||
CApi.sqlite3_result_error(cx, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void xDestroy(){
|
||||
impl.xDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
||||
** This file is part of the wrapper1 interface for sqlite3.
|
||||
*/
|
||||
package org.sqlite.jni.wrapper1;
|
||||
import static org.sqlite.jni.capi.CApi.*;
|
||||
import org.sqlite.jni.capi.CApi;
|
||||
import org.sqlite.jni.capi.sqlite3;
|
||||
|
||||
/**
|
||||
@@ -22,10 +22,10 @@ import org.sqlite.jni.capi.sqlite3;
|
||||
and C via JNI.
|
||||
*/
|
||||
public final class SqliteException extends java.lang.RuntimeException {
|
||||
int errCode = SQLITE_ERROR;
|
||||
int xerrCode = SQLITE_ERROR;
|
||||
int errOffset = -1;
|
||||
int sysErrno = 0;
|
||||
private int errCode = CApi.SQLITE_ERROR;
|
||||
private int xerrCode = CApi.SQLITE_ERROR;
|
||||
private int errOffset = -1;
|
||||
private int sysErrno = 0;
|
||||
|
||||
/**
|
||||
Records the given error string and uses SQLITE_ERROR for both the
|
||||
@@ -38,28 +38,31 @@ public final class SqliteException extends java.lang.RuntimeException {
|
||||
/**
|
||||
Uses sqlite3_errstr(sqlite3ResultCode) for the error string and
|
||||
sets both the error code and extended error code to the given
|
||||
value.
|
||||
value. This approach includes no database-level information and
|
||||
systemErrno() will be 0, so is intended only for use with sqlite3
|
||||
APIs for which a result code is not an error but which the
|
||||
higher-level wrapper should treat as one.
|
||||
*/
|
||||
public SqliteException(int sqlite3ResultCode){
|
||||
super(sqlite3_errstr(sqlite3ResultCode));
|
||||
super(CApi.sqlite3_errstr(sqlite3ResultCode));
|
||||
errCode = xerrCode = sqlite3ResultCode;
|
||||
}
|
||||
|
||||
/**
|
||||
Records the current error state of db (which must not be null and
|
||||
must refer to an opened db object). Note that this does NOT close
|
||||
must refer to an opened db object). Note that this does not close
|
||||
the db.
|
||||
|
||||
Design note: closing the db on error is likely only useful during
|
||||
Design note: closing the db on error is really only useful during
|
||||
a failed db-open operation, and the place(s) where that can
|
||||
happen are inside this library, not client-level code.
|
||||
*/
|
||||
SqliteException(sqlite3 db){
|
||||
super(sqlite3_errmsg(db));
|
||||
errCode = sqlite3_errcode(db);
|
||||
xerrCode = sqlite3_extended_errcode(db);
|
||||
errOffset = sqlite3_error_offset(db);
|
||||
sysErrno = sqlite3_system_errno(db);
|
||||
super(CApi.sqlite3_errmsg(db));
|
||||
errCode = CApi.sqlite3_errcode(db);
|
||||
xerrCode = CApi.sqlite3_extended_errcode(db);
|
||||
errOffset = CApi.sqlite3_error_offset(db);
|
||||
sysErrno = CApi.sqlite3_system_errno(db);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +74,7 @@ public final class SqliteException extends java.lang.RuntimeException {
|
||||
}
|
||||
|
||||
public SqliteException(Sqlite.Stmt stmt){
|
||||
this( stmt.db() );
|
||||
this(stmt.getDb());
|
||||
}
|
||||
|
||||
public int errcode(){ return errCode; }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,13 +9,13 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains a set of tests for the sqlite3 JNI bindings.
|
||||
** This file contains the ValueHolder utility class.
|
||||
*/
|
||||
package org.sqlite.jni.wrapper1;
|
||||
|
||||
/**
|
||||
A helper class which simply holds a single value. Its primary use
|
||||
is for communicating values out of anonymous classes, as doing so
|
||||
is for communicating values out of anonymous callbacks, as doing so
|
||||
requires a "final" reference.
|
||||
*/
|
||||
public class ValueHolder<T> {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
** 2023-10-16
|
||||
**
|
||||
** 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 wrapper1 interface for sqlite3.
|
||||
*/
|
||||
package org.sqlite.jni.wrapper1;
|
||||
|
||||
/**
|
||||
A SqlFunction implementation for window functions. The T type
|
||||
represents the type of data accumulated by this function while it
|
||||
works. e.g. a SUM()-like UDF might use Integer or Long and a
|
||||
CONCAT()-like UDF might use a StringBuilder or a List<String>.
|
||||
*/
|
||||
public abstract class WindowFunction<T> extends AggregateFunction<T> {
|
||||
|
||||
/**
|
||||
As for the xInverse() argument of the C API's
|
||||
sqlite3_create_window_function(). If this function throws, the
|
||||
exception is reported via sqlite3_result_error().
|
||||
*/
|
||||
public abstract void xInverse(SqlFunction.Arguments args);
|
||||
|
||||
/**
|
||||
As for the xValue() argument of the C API's
|
||||
sqlite3_create_window_function(). If this function throws, it is
|
||||
translated into sqlite3_result_error().
|
||||
|
||||
Note that the passed-in object will not actually contain any
|
||||
arguments for xValue() but will contain the context object needed
|
||||
for setting the call's result or error state.
|
||||
*/
|
||||
public abstract void xValue(SqlFunction.Arguments args);
|
||||
|
||||
}
|
||||
@@ -392,7 +392,6 @@ static int SQLITE_TCLAPI test_session_cmd(
|
||||
};
|
||||
size_t sz = sizeof(aOpt[0]);
|
||||
|
||||
int rc;
|
||||
int iArg;
|
||||
int iOpt;
|
||||
if( Tcl_GetIndexFromObjStruct(interp,objv[2],aOpt,sz,"option",0,&iOpt) ){
|
||||
|
||||
@@ -63,6 +63,7 @@ _sqlite3_file_control
|
||||
_sqlite3_finalize
|
||||
_sqlite3_free
|
||||
_sqlite3_get_auxdata
|
||||
_sqlite3_get_autocommit
|
||||
_sqlite3_initialize
|
||||
_sqlite3_keyword_count
|
||||
_sqlite3_keyword_name
|
||||
|
||||
@@ -188,6 +188,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
|
||||
["sqlite3_finalize", "int", "sqlite3_stmt*"],
|
||||
["sqlite3_free", undefined,"*"],
|
||||
["sqlite3_get_autocommit", "int", "sqlite3*"],
|
||||
["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"],
|
||||
["sqlite3_initialize", undefined],
|
||||
/*["sqlite3_interrupt", undefined, "sqlite3*"
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
```
|
||||
{
|
||||
type: string, // one of: 'open', 'close', 'exec', 'config-get'
|
||||
type: string, // one of: 'open', 'close', 'exec', 'export', 'config-get'
|
||||
|
||||
messageId: OPTIONAL arbitrary value. The worker will copy it as-is
|
||||
into response messages to assist in client-side dispatching.
|
||||
@@ -325,6 +325,37 @@
|
||||
passed only a string), noting that options.resultRows and
|
||||
options.columnNames may be populated by the call to db.exec().
|
||||
|
||||
|
||||
====================================================================
|
||||
"export" the current db
|
||||
|
||||
To export the underlying database as a byte array...
|
||||
|
||||
Message format:
|
||||
|
||||
```
|
||||
{
|
||||
type: "export",
|
||||
messageId: ...as above...,
|
||||
dbId: ...as above...
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```
|
||||
{
|
||||
type: "export",
|
||||
messageId: ...as above...,
|
||||
dbId: ...as above...
|
||||
result: {
|
||||
byteArray: Uint8Array (as per sqlite3_js_db_export()),
|
||||
filename: the db filename,
|
||||
mimetype: "application/x-sqlite3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*/
|
||||
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
sqlite3.initWorker1API = function(){
|
||||
|
||||
@@ -877,7 +877,7 @@ const char * sqlite3_wasm_enum_json(void){
|
||||
DefInt(SQLITE_STMTSTATUS_FILTER_HIT);
|
||||
DefInt(SQLITE_STMTSTATUS_MEMUSED);
|
||||
} _DefGroup;
|
||||
|
||||
|
||||
DefGroup(syncFlags) {
|
||||
DefInt(SQLITE_SYNC_NORMAL);
|
||||
DefInt(SQLITE_SYNC_FULL);
|
||||
@@ -901,6 +901,8 @@ const char * sqlite3_wasm_enum_json(void){
|
||||
DefInt(SQLITE_DETERMINISTIC);
|
||||
DefInt(SQLITE_DIRECTONLY);
|
||||
DefInt(SQLITE_INNOCUOUS);
|
||||
DefInt(SQLITE_SUBTYPE);
|
||||
DefInt(SQLITE_RESULT_SUBTYPE);
|
||||
} _DefGroup;
|
||||
|
||||
DefGroup(version) {
|
||||
|
||||
@@ -247,9 +247,8 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
|
||||
globalThis.sqlite3Worker1Promiser.defaultConfig = {
|
||||
worker: function(){
|
||||
//#if target=es6-bundler-friendly
|
||||
return new Worker("sqlite3-worker1-bundler-friendly.mjs",{
|
||||
type: 'module' /* Noting that neither Firefox nor Safari suppor this,
|
||||
as of this writing. */
|
||||
return new Worker(new URL("sqlite3-worker1-bundler-friendly.mjs", import.meta.url),{
|
||||
type: 'module'
|
||||
});
|
||||
//#else
|
||||
let theJs = "sqlite3-worker1.js";
|
||||
@@ -267,8 +266,12 @@ globalThis.sqlite3Worker1Promiser.defaultConfig = {
|
||||
}
|
||||
return new Worker(theJs + globalThis.location.search);
|
||||
//#endif
|
||||
}.bind({
|
||||
}
|
||||
//#ifnot target=es6-bundler-friendly
|
||||
.bind({
|
||||
currentScript: globalThis?.document?.currentScript
|
||||
}),
|
||||
})
|
||||
//#endif
|
||||
,
|
||||
onerror: (...args)=>console.error('worker1 promiser error',...args)
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ const tryOpfsVfs = async function(sqlite3){
|
||||
const opfs = sqlite3.opfs;
|
||||
log("tryOpfsVfs()");
|
||||
if(!sqlite3.opfs){
|
||||
const e = toss("OPFS is not available.");
|
||||
const e = new Error("OPFS is not available.");
|
||||
error(e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -1688,7 +1688,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
wasm.sqlite3_wasm_vfs_unlink(0, filename);
|
||||
}
|
||||
}
|
||||
}/*sqlite3_js_vfs_create_file()*/)
|
||||
}/*sqlite3_js_posix_create_file()*/)
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
.t({
|
||||
@@ -2605,28 +2605,6 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
}
|
||||
}
|
||||
}/*kvvfs sanity checks*/)
|
||||
.t({
|
||||
name: 'kvvfs sqlite3_js_vfs_create_file()',
|
||||
predicate: ()=>"kvvfs does not currently support this",
|
||||
test: function(sqlite3){
|
||||
let db;
|
||||
try {
|
||||
db = new this.JDb(this.kvvfsDbFile);
|
||||
const exp = capi.sqlite3_js_db_export(db);
|
||||
db.close();
|
||||
this.kvvfsUnlink();
|
||||
capi.sqlite3_js_vfs_create_file("kvvfs", this.kvvfsDbFile, exp);
|
||||
db = new this.JDb(filename);
|
||||
T.assert(6 === db.selectValue('select count(*) from kvvfs'));
|
||||
}finally{
|
||||
db.close();
|
||||
this.kvvfsUnlink();
|
||||
}
|
||||
delete this.kvvfsDbFile;
|
||||
delete this.kvvfsUnlink;
|
||||
delete this.JDb;
|
||||
}
|
||||
}/*kvvfs sqlite3_js_vfs_create_file()*/)
|
||||
;/* end kvvfs tests */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -2644,13 +2622,17 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
T.assert( 0 === rc /*void pointer*/ );
|
||||
|
||||
// Commit hook...
|
||||
T.assert( 0!=capi.sqlite3_get_autocommit(db) );
|
||||
db.exec("BEGIN; SELECT 1; COMMIT");
|
||||
T.assert(0 === countCommit,
|
||||
"No-op transactions (mostly) do not trigger commit hook.");
|
||||
db.exec("BEGIN EXCLUSIVE; SELECT 1; COMMIT");
|
||||
T.assert(1 === countCommit,
|
||||
"But EXCLUSIVE transactions do.");
|
||||
db.transaction((d)=>{d.exec("create table t(a)");});
|
||||
db.transaction((d)=>{
|
||||
T.assert( 0==capi.sqlite3_get_autocommit(db) );
|
||||
d.exec("create table t(a)");
|
||||
});
|
||||
T.assert(2 === countCommit);
|
||||
|
||||
// Rollback hook:
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
C Remedy\sCLI\snon-UTF8\shandling\sdetection\sflaw\s[forum:/forumpost/fa0e00d36db5fe0a|noted\sin\sa\sforum\spost].
|
||||
D 2023-10-30T23:04:27.173
|
||||
C Enhance\sjson_set()\sand\sjson_insert()\sso\sthat\sthey\screate\smissing\nsubstructure.
|
||||
D 2023-11-30T19:06:27.003
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 8b59912fc1538f96a08555605c5886cdcc733696ae7f22e374b2a4752196ca20
|
||||
F Makefile.in 890caf094636c308bc981032baf8f9208bf307755f9197ae4218a9fbcec2e449
|
||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||
F Makefile.msc 2309c96119271c76f25c5a1bb012b7b8d6716ff47918fc172eed84ab386f0897
|
||||
F Makefile.msc 59bb36dba001f0b38212be0794fb838f25371008b180929bcf08aa799694c168
|
||||
F README.md 963d30019abf0cc06b263cd2824bce022893f3f93a531758f6f04ff2194a16a8
|
||||
F VERSION 4c09b629c03b8ae32317cb336a32f3aa3252841d6dcd51184cecc4278d08f21e
|
||||
F VERSION 73573d4545343f001bf5dc5461173a7c78c203dd046cabcf99153878cf25d3a6
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
@@ -22,7 +22,7 @@ F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d
|
||||
F autoconf/tea/Makefile.in 106a96f2f745d41a0f6193f1de98d7355830b65d45032c18cd7c90295ec24196
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
F autoconf/tea/configure.ac 1ee185f2f8c2e9bed69d0113222724202f962d04eafd57197e65c662d2d9b180
|
||||
F autoconf/tea/configure.ac 4c32b08691a5b296206b38422b53b92b65be3d3f6b3dd6552a50981a61f5acda
|
||||
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
|
||||
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
|
||||
F autoconf/tea/pkgIndex.tcl.in b9eb6dd37f64e08e637d576b3c83259814b9cddd78bec4af2e5abfc6c5c750ce
|
||||
@@ -33,15 +33,15 @@ F autoconf/tea/win/nmakehlp.c b01f822eabbe1ed2b64e70882d97d48402b42d2689a1ea0034
|
||||
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
|
||||
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
|
||||
F configure 1d9cbcb416cb5387b3f750ae6db63cfedb703a2e46bf8ca61daecff31d208252 x
|
||||
F configure.ac de31fea7d975bb7ebafbe0e2190a855cc80d48558bf0c9a6578a1836daf1cd3a
|
||||
F configure bcb1042e92775424a1021d2f4c89c78a699a6225df01fa8c593df7df0be6ad10 x
|
||||
F configure.ac f25bd7843120f2c2b8bc9db5a92b0502bbdd28e68907415c3d42fc8e57c657b9
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
F doc/compile-for-windows.md 922ba580d210a1f1bd3ef9d0413121556f9b5714fb5c01e664d980f85fa4ac8c
|
||||
F doc/compile-for-windows.md 50b27d77be96195c66031a3181cb8684ed822327ea834e07f9c014213e5e3bcf
|
||||
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
|
||||
F doc/lemon.html 44a53a1d2b42d7751f7b2f478efb23c978e258d794bfd172442307a755b9fa44
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/testrunner.md 2434864be2219d4f0b6ffc99d0a2172d531c4ca4345340776f67ad4edd90dc90
|
||||
F doc/testrunner.md 8d36ec692cf4994bb66d84a4645b9afa1ce9d47dc12cbf8d437c5a5fb6ddeedb
|
||||
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
|
||||
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
@@ -50,6 +50,8 @@ F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
|
||||
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
|
||||
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
|
||||
F ext/consio/console_io.c 097323f60037d70523421f0248958d2280851f8ff2f9a443d4ee1474c4769118 x
|
||||
F ext/consio/console_io.h 3228dff1717481202a24f6dcf45ce0b75e7a778bf6877089518a44e1473b76a3
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test 0dd5cb096d66bed593e33053a3b364f6ef52ed72064bf5cf298364636dbf3cd6
|
||||
@@ -89,18 +91,18 @@ F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a0
|
||||
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
||||
F ext/fts5/fts5.h 05501612cc655504c5dce8ba765ab621d50fc478490089beaa0d75e00b23e520
|
||||
F ext/fts5/fts5Int.h 78a63cc0795186cde5384816a9403a68c65774b35d952e05b81a1b4b158e07c8
|
||||
F ext/fts5/fts5_aux.c 35c4101613eff86902877a4dedd9400b07922e412cbdd637b45041dce2fd5388
|
||||
F ext/fts5/fts5_aux.c ee770eec0af8646db9e18fc01a0dad7345b5f5e8cbba236704cfae2d777022ad
|
||||
F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b729225eeaf6a5
|
||||
F ext/fts5/fts5_config.c 054359543566cbff1ba65a188330660a5457299513ac71c53b3a07d934c7b081
|
||||
F ext/fts5/fts5_expr.c bd3b81ce669c4104e34ffe66570af1999a317b142c15fccb112de9fb0caa57a6
|
||||
F ext/fts5/fts5_hash.c 65e7707bc8774706574346d18c20218facf87de3599b995963c3e6d6809f203d
|
||||
F ext/fts5/fts5_index.c 730c9c32ada18ce1eb7ff847b36507f4b005d88d47af7b47db521e695a8ea4c7
|
||||
F ext/fts5/fts5_hash.c 076058f93327051952a752dc765df1acfe783eb11b419b30652aa1fc1f987902
|
||||
F ext/fts5/fts5_index.c 458cbed8a3e17617cbf7e80cdfb7612000b9bb3781f286b345fb9655858658cf
|
||||
F ext/fts5/fts5_main.c a07ed863b8bd9e6fefb62db2fd40a3518eb30a5f7dcfda5be915dd2db45efa2f
|
||||
F ext/fts5/fts5_storage.c 5d10b9bdcce5b90656cad13c7d12ad4148677d4b9e3fca0481fca56d6601426d
|
||||
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
|
||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
|
||||
F ext/fts5/fts5_tokenize.c 5e251efb0f1af99a25ed50010ba6b1ad1250aca5921af1988fdcabe5ebc3cb43
|
||||
F ext/fts5/fts5_tokenize.c 83cfcede3898001cab84432a36ce1503e3080cf9b1c682b022ec82e267ea4c13
|
||||
F ext/fts5/fts5_unicode2.c eca63dbc797f8ff0572e97caf4631389c0ab900d6364861b915bdd4735973f00
|
||||
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
|
||||
F ext/fts5/fts5_vocab.c aed56169ae5c1aa9b8189c779ffeef04ed516d3c712c06914e6d91a6759f4e4a
|
||||
@@ -143,7 +145,7 @@ F ext/fts5/test/fts5corrupt.test b6d4034b682bb3387bc44c510c71b3c67d4349e4df13949
|
||||
F ext/fts5/test/fts5corrupt2.test 99e7e23a58b4d89eb7167c6de1669cbc595cd3c79ab333e0eb56405473319e77
|
||||
F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36fe2689801bba2ccd78
|
||||
F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
|
||||
F ext/fts5/test/fts5corrupt5.test eb6ba5ca28ef7c4c6b01e850d388cdb3dacc8c4c2f383f79d0a98128257742b4
|
||||
F ext/fts5/test/fts5corrupt5.test 38a238df26c4de471e1c4b98f8de6c902bc692577a1c08d0ff4f2251f3559644
|
||||
F ext/fts5/test/fts5corrupt6.test bf8eeae07825b088b9665d9d8e4accbd8dc9bf3cb85b6c64cf6c9e18ccc420a4
|
||||
F ext/fts5/test/fts5corrupt7.test 80ad7f683a8bda2404731bb77e8c3dbbb620c1f6cc583cca8239f6accd6338c0
|
||||
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
|
||||
@@ -167,7 +169,7 @@ F ext/fts5/test/fts5faultB.test d606bdb8e81aaeb6f41de3fc9fc7ae315733f0903fbff05c
|
||||
F ext/fts5/test/fts5faultD.test e7ed7895abfe6bc98a5e853826f6b74956e7ba7f594f1860bbf9e504b9647996
|
||||
F ext/fts5/test/fts5faultE.test 844586ce71dab4be85bb86880e87b624d089f851654cd22e4710c77eb8ce7075
|
||||
F ext/fts5/test/fts5faultF.test 4abef99f86e99d9f0c6460dd68c586a766b6b9f1f660ada55bf2e8266bd1bbc1
|
||||
F ext/fts5/test/fts5faultG.test 340e59d2c2c1c7c379224f3968ee8d09b0f64bf56c5194217d1ded887b9d47c4
|
||||
F ext/fts5/test/fts5faultG.test d2e5a4d9a34e08dcaadcaeafef74d10cbc2abdd11aa2659a18af0294bf2812d3
|
||||
F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079
|
||||
F ext/fts5/test/fts5full.test e1701a112354e0ff9a1fdffb0c940c576530c33732ee20ac5e8361777070d717
|
||||
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
|
||||
@@ -193,7 +195,7 @@ F ext/fts5/test/fts5plan.test b65cfcca9ddd6fdaa118c61e17aeec8e8433bc5b6bb307abd1
|
||||
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
|
||||
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
|
||||
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
|
||||
F ext/fts5/test/fts5prefix2.test 3847ce46f70b82d61c6095103a9d7c53f2952c40a4704157bc079c04d9c8b18b
|
||||
F ext/fts5/test/fts5prefix2.test ad751d4a5b029726ee908a7664e27d27bde7584218b8d7944c2a323afd381432
|
||||
F ext/fts5/test/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728
|
||||
F ext/fts5/test/fts5rank.test 30f29e278cd7fb8831ba4f082feb74d8eb90c463bf07113ae200afc2b467ef32
|
||||
F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7
|
||||
@@ -207,6 +209,7 @@ F ext/fts5/test/fts5secure4.test 0d10a80590c07891478700af7793b232962042677432b98
|
||||
F ext/fts5/test/fts5secure5.test c07a68ced5951567ac116c22f2d2aafae497e47fe9fcb6a335c22f9c7a4f2c3a
|
||||
F ext/fts5/test/fts5secure6.test 74bf04733cc523bccca519bb03d3b4e2ed6f6e3db7c59bf6be82c88a0ac857fd
|
||||
F ext/fts5/test/fts5secure7.test fd03d0868d64340a1db8615b02e5508fea409de13910114e4f19eaefc120777a
|
||||
F ext/fts5/test/fts5secure8.test eb3579e9d58b0acad97e8082dee1f99b2d393198f03500b453c2b25761c0c298
|
||||
F ext/fts5/test/fts5securefault.test dbca2b6a1c16700017f5051138991b705410889933f2a37c57ae8a23b296b10b
|
||||
F ext/fts5/test/fts5simple.test a298670508c1458b88ce6030440f26a30673931884eb5f4094ac1773b3ba217b
|
||||
F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0
|
||||
@@ -216,7 +219,9 @@ F ext/fts5/test/fts5synonym2.test 8f891fc49cc1e8daed727051e77e1f42849c784a6a54be
|
||||
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
|
||||
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
|
||||
F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
|
||||
F ext/fts5/test/fts5tokenizer2.test cb5428c7cfb3b6a74b7adfcde65506e329112003e8dffa7501d01c2d18d02569
|
||||
F ext/fts5/test/fts5trigram.test 6c4e37864f3e7d90673db5563d9736d7e40080ab94d10ebdffa94c1b77941da0
|
||||
F ext/fts5/test/fts5trigram2.test 9fe4207f8a4241747aff1005258b564958588d21bfd240d6cd4c2e955d31c156
|
||||
F ext/fts5/test/fts5ubsan.test 783d5a8d13ebfa169e634940228db54540780e3ba7a87ad1e4510e61440bf64b
|
||||
F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d05926482cc0bccac9ad602
|
||||
F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
|
||||
@@ -236,49 +241,50 @@ 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 5c3ac326bf3853486ebe0d70819abc790cc65c412182ce4ebd5012b008d9b059
|
||||
F ext/jni/README.md ef9ac115e97704ea995d743b4a8334e23c659e5534c3b64065a5405256d5f2f4
|
||||
F ext/jni/GNUmakefile 59eb05f2a363bdfac8d15d66bed624bfe1ff289229184f3861b95f98a19cf4b2
|
||||
F ext/jni/README.md d899789a9082a07b99bf30b1bbb6204ae57c060efcaa634536fa669323918f42
|
||||
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
|
||||
F ext/jni/src/c/sqlite3-jni.c 6f6df9657989e9ca2cfdcc2fe9a71c279de56d5c941adfd09a0f24256de35c8f
|
||||
F ext/jni/src/c/sqlite3-jni.h b4c413a0d0c734683da1049cfcf89e35ae2719759d0656ec0f8c57188f18cab8
|
||||
F ext/jni/src/org/sqlite/jni/annotation/NotNull.java a99341e88154e70447596b1af6a27c586317df41a7e0f246fd41370cd7b723b2
|
||||
F ext/jni/src/org/sqlite/jni/annotation/Nullable.java 0b1879852707f752512d4db9d7edd0d8db2f0c2612316ce1c832715e012ff6ba
|
||||
F ext/jni/src/c/sqlite3-jni.c 6040c0de97644a1fb14bb589ee9f2f4208f6e6b165d14a0e33ed24945b118838
|
||||
F ext/jni/src/c/sqlite3-jni.h 913ab8e8fee432ae40f0e387c8231118d17053714703f5ded18202912a8a3fbf
|
||||
F ext/jni/src/org/sqlite/jni/annotation/Experimental.java 8603498634e41d0f7c70f661f64e05df64376562ea8f126829fd1e0cdd47e82b
|
||||
F ext/jni/src/org/sqlite/jni/annotation/NotNull.java 38e7e58a69b26dc100e458b31dfa3b2a7d67bc36d051325526ef1987d5bc8a24
|
||||
F ext/jni/src/org/sqlite/jni/annotation/Nullable.java 56e3dee1f3f703a545dfdeddc1c3d64d1581172b1ad01ffcae95c18547fafd90
|
||||
F ext/jni/src/org/sqlite/jni/annotation/package-info.java 977b374aed9d5853cbf3438ba3b0940abfa2ea4574f702a2448ee143b98ac3ca
|
||||
F ext/jni/src/org/sqlite/jni/capi/AbstractCollationCallback.java 1afa90d3f236f79cc7fcd2497e111992644f7596fbc8e8bcf7f1908ae00acd6c
|
||||
F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java bc29e986c866c2ddbbb9f935f5b7264c1c1026864e50a4a735192864f75e37c0
|
||||
F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java 7ed409d5449684616cc924534e22ff6b07d361f12ad904b69ecb10e0568a8013
|
||||
F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0b72cdff61533b564d65b63418129656daa9a9f30e7e7be982bd5ab394b1dbd0
|
||||
F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java c045a5b47e02bb5f1af91973814a905f12048c428a3504fbc5266d1c1be3de5a
|
||||
F ext/jni/src/org/sqlite/jni/capi/AutoExtensionCallback.java 74cc4998a73d6563542ecb90804a3c4f4e828cb4bd69e61226d1a51f4646e759
|
||||
F ext/jni/src/org/sqlite/jni/capi/BusyHandlerCallback.java 7b8e19810c42b0ad21a04b5d8c804b32ee5905d137148703f16a75b612c380ca
|
||||
F ext/jni/src/org/sqlite/jni/capi/CApi.java bccb442ca81cd4decb1adae99006a60b7a9f54e5153842e738c01104e97d1de0
|
||||
F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 0bfd6e56e8265c2f05c9207665707285534d78f8466ef0e0430c65677f00943d
|
||||
F ext/jni/src/org/sqlite/jni/capi/CApi.java d428a1fd3b827f01c55d10d21ff35e33e7dac9e8a1d92a8b5c7d7255e67407d8
|
||||
F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 57e2d275dcebe690b1fc1f3d34eb96879b2d7039bce30b563aee547bf45d8a8b
|
||||
F ext/jni/src/org/sqlite/jni/capi/CollationCallback.java e29bcfc540fdd343e2f5cca4d27235113f2886acb13380686756d5cabdfd065a
|
||||
F ext/jni/src/org/sqlite/jni/capi/CollationNeededCallback.java f81cf10b79c52f9b2e9247d523d29ae48863935f60420eae35f257c38c80ce95
|
||||
F ext/jni/src/org/sqlite/jni/capi/CommitHookCallback.java 29c002f3c638cc80f7db1594564a262d1beb32637824c3dca2d60a224d1f71d7
|
||||
F ext/jni/src/org/sqlite/jni/capi/CollationNeededCallback.java 5bfa226a8e7a92e804fd52d6e42b4c7b875fa7a94f8e2c330af8cc244a8920ab
|
||||
F ext/jni/src/org/sqlite/jni/capi/CommitHookCallback.java 482f53dfec9e3ac2a9070d3fceebd56250932aaaf7c4f5bc8de29fc011416e0c
|
||||
F ext/jni/src/org/sqlite/jni/capi/ConfigLogCallback.java b995ca412f59b631803b93aa5b3684fce62e335d1e123207084c054abfd488d4
|
||||
F ext/jni/src/org/sqlite/jni/capi/ConfigSqllogCallback.java 701f2e4d8bdeb27cfbeeb56315d15b13d8752b0fdbca705f31bd4366c58d8a33
|
||||
F ext/jni/src/org/sqlite/jni/capi/ConfigSqlLogCallback.java e5723900b6458bc6288f52187090a78ebe0a20f403ac7c887ec9061dfe51aba7
|
||||
F ext/jni/src/org/sqlite/jni/capi/NativePointerHolder.java b7036dcb1ef1b39f1f36ac605dde0ff1a24a9a01ade6aa1a605039443e089a61
|
||||
F ext/jni/src/org/sqlite/jni/capi/OutputPointer.java 68f60aec7aeb5cd4e5fb83449037f668c63cb99f682ee1036cc226d0cbd909b9
|
||||
F ext/jni/src/org/sqlite/jni/capi/PrepareMultiCallback.java aca8f9fa72e3b6602bc9a7dd3ae9f5b2808103fbbee9b2749dc96c19cdc261a1
|
||||
F ext/jni/src/org/sqlite/jni/capi/PreupdateHookCallback.java 819d938e26208adde17ca4b7ddde1d8cd6915b6ab7b708249a9787beca6bd6b6
|
||||
F ext/jni/src/org/sqlite/jni/capi/OutputPointer.java 246b0e66c4603f41c567105a21189d138aaf8c58203ecd4928802333da553e7c
|
||||
F ext/jni/src/org/sqlite/jni/capi/PrepareMultiCallback.java 97352091abd7556167f4799076396279a51749fdae2b72a6ba61cd39b3df0359
|
||||
F ext/jni/src/org/sqlite/jni/capi/PreupdateHookCallback.java efcf57545c5e282d1dd332fa63329b3b218d98f356ef107a9dbe3979be82213a
|
||||
F ext/jni/src/org/sqlite/jni/capi/ProgressHandlerCallback.java 01bc0c238eed2d5f93c73522cb7849a445cc9098c2ed1e78248fa20ed1cfde5b
|
||||
F ext/jni/src/org/sqlite/jni/capi/ResultCode.java 8141171f1bcf9f46eef303b9d3c5dc2537a25ad1628f3638398d8a60cacefa7f
|
||||
F ext/jni/src/org/sqlite/jni/capi/RollbackHookCallback.java 105e324d09c207100485e7667ad172e64322c62426bb49b547e9b0dc9c33f5f0
|
||||
F ext/jni/src/org/sqlite/jni/capi/SQLFunction.java fef556adbc3624292423083a648bdf97fa8a4f6b3b6577c9660dd7bd6a6d3c4a
|
||||
F ext/jni/src/org/sqlite/jni/capi/RollbackHookCallback.java e172210a2080e851ebb694c70e9f0bf89284237795e38710a7f5f1b61e3f6787
|
||||
F ext/jni/src/org/sqlite/jni/capi/SQLFunction.java 0d1e9afc9ff8a2adb94a155b72385155fa3b8011a5cca0bb3c28468c7131c1a5
|
||||
F ext/jni/src/org/sqlite/jni/capi/SQLTester.java 09bee15aa0eedac68d767ae21d9a6a62a31ade59182a3ccbf036d6463d9e30b1
|
||||
F ext/jni/src/org/sqlite/jni/capi/ScalarFunction.java 93b9700fca4c68075ccab12fe0fbbc76c91cafc9f368e835b9bd7cd7732c8615
|
||||
F ext/jni/src/org/sqlite/jni/capi/TableColumnMetadata.java addf120e0e76e5be1ff2260daa7ce305ff9b5fafd64153a7a28e9d8f000a815f
|
||||
F ext/jni/src/org/sqlite/jni/capi/Tester1.java ca195521b6bda3e0cd00e76bb71ec8060d1fab76a2f13b1af9feea40789f44bb
|
||||
F ext/jni/src/org/sqlite/jni/capi/Tester1.java e5fa17301b7266c1cbe4bcce67788e08e45871c7c72c153d515abb37e501de0a
|
||||
F ext/jni/src/org/sqlite/jni/capi/TraceV2Callback.java 0a25e117a0daae3394a77f24713e36d7b44c67d6e6d30e9e1d56a63442eef723
|
||||
F ext/jni/src/org/sqlite/jni/capi/UpdateHookCallback.java 2766b8526bbffc4f1045f70e79f1bc1b1efe1c3e95ca06cdb8a7391032dda3b4
|
||||
F ext/jni/src/org/sqlite/jni/capi/ValueHolder.java 9f9e151f1da017b706c0ee5f40f4c86b54e773d6ae4339723e0cc85a456251ab
|
||||
F ext/jni/src/org/sqlite/jni/capi/UpdateHookCallback.java c8bdf7848e6599115d601bcc9427ff902cb33129b9be32870ac6808e04b6ae56
|
||||
F ext/jni/src/org/sqlite/jni/capi/ValueHolder.java 2ce069f3e007fdbbe1f4e507a5a407fc9679da31a0aa40985e6317ed4d5ec7b5
|
||||
F ext/jni/src/org/sqlite/jni/capi/WindowFunction.java caf4396f91b2567904cf94bc538a069fd62260d975bd037d15a02a890ed1ef9e
|
||||
F ext/jni/src/org/sqlite/jni/capi/XDestroyCallback.java f3abb8dd7381f53ebba909437090caf68200f06717b8a7d6aa96fa3e8133117d
|
||||
F ext/jni/src/org/sqlite/jni/capi/package-info.java 08ff986a65d2be9162442c82d28a65ce431d826f188520717c2ecb1484d0a50e
|
||||
F ext/jni/src/org/sqlite/jni/capi/sqlite3.java 4010bbebc5bf44e2044e610786088cdee7dc155da2b333c0551492ff1cedf33b
|
||||
F ext/jni/src/org/sqlite/jni/capi/sqlite3.java c6a5c555d163d76663534f2b2cce7cab15325b9852d0f58c6688a85e73ae52f0
|
||||
F ext/jni/src/org/sqlite/jni/capi/sqlite3_backup.java 6742b431cd4d77e8000c1f92ec66265a58414c86bf3b0b5fbcb1164e08477227
|
||||
F ext/jni/src/org/sqlite/jni/capi/sqlite3_blob.java f204ab6ab1263e119fe43730141a00662d80972129a5351dfb11aae5d282df36
|
||||
F ext/jni/src/org/sqlite/jni/capi/sqlite3_blob.java 59e26ca5254cd4771f467237bcfe2d8deed30a77152fabcd4574fd406c301d63
|
||||
F ext/jni/src/org/sqlite/jni/capi/sqlite3_context.java f0ef982009c335c4393ffcb68051809ca1711e4f47bcb8d1d46952f22c01bc22
|
||||
F ext/jni/src/org/sqlite/jni/capi/sqlite3_stmt.java ff579621e9bd5ffbc6b2ef9f996c12db4df6e0c8cc5697c91273e5fca279fcf8
|
||||
F ext/jni/src/org/sqlite/jni/capi/sqlite3_stmt.java 293b5fa7d5b5724c87de544654aca1103d76f3092bc2c8f4360102a65ba25dff
|
||||
F ext/jni/src/org/sqlite/jni/capi/sqlite3_value.java e1d62a257c13504b46d39d5c21c49cf157ad73fda00cc5f34c931aa008c37049
|
||||
F ext/jni/src/org/sqlite/jni/fts5/Fts5.java e94681023785f1eff5399f0ddc82f46b035977d350f14838db659236ebdf6b41
|
||||
F ext/jni/src/org/sqlite/jni/fts5/Fts5Context.java 338637e6e5a2cc385d962b220f3c1f475cc371d12ae43d18ef27327b6e6225f7
|
||||
@@ -291,13 +297,14 @@ F ext/jni/src/org/sqlite/jni/fts5/fts5_api.java a8e88c3783d21cec51b0748568a96653
|
||||
F ext/jni/src/org/sqlite/jni/fts5/fts5_extension_function.java 9e2b954d210d572552b28aca523b272fae14bd41e318921b22f65b728d5bf978
|
||||
F ext/jni/src/org/sqlite/jni/fts5/fts5_tokenizer.java 92bdaa3893bd684533004d64ade23d329843f809cd0d0f4f1a2856da6e6b4d90
|
||||
F ext/jni/src/org/sqlite/jni/test-script-interpreter.md f9f25126127045d051e918fe59004a1485311c50a13edbf18c79a6ff9160030e
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/AggregateFunction.java 5ad99bd74c85f56bbef324d9ec29b4048f4620547c9a80093d8586c3557f9f9a
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/AggregateFunction.java d5c108b02afd3c63c9e5e53f71f85273c1bfdc461ae526e0a0bb2b25e4df6483
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/ScalarFunction.java 43c43adfb7866098aadaaca1620028a6ec82d5193149970019b1cce9eb59fb03
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java 004394eeb944baa56e36cd7ae69ba6d4a52b52db3c49439db16e98270b861421
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java a9ddc6a9e8c113168cc67592ae24c0e56d30dd06226eeab012f2761a0889d7bb
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 1386f7b753134fc12253ce2fbbc448ba8c970567fac01a3356cb672e14408d73
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java c24b510ebe801c30533cc62efdf69a4a5e2da9ec4b49f8d403f2060693f060a0
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/ValueHolder.java 7b89a7391f771692c5b83b0a5b86266abe8d59f1c77d7a0eccc9b79f259d79af
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java 27b141f5914c7cb0e40e90a301d5e05b77f3bd42236834a68031b7086381fafd
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java ada39f18e4e3e9d4868dadbc3f7bfe1c6c7fde74fb1fb2954c3f0f70120b805c
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 982538ddb4c0719ef87dfa664cd137b09890b546029a7477810bd64d4c47ee35
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java ce45f2ec85facbb73690096547ed166e7be82299e3d92eaa206f82b60a6ec969
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/ValueHolder.java a84e90c43724a69c2ecebd601bc8e5139f869b7d08cb705c77ef757dacdd0593
|
||||
F ext/jni/src/org/sqlite/jni/wrapper1/WindowFunction.java c7d1452f9ff26175b3c19bbf273116cc2846610af68e01756d755f037fe7319f
|
||||
F ext/jni/src/tests/000-000-sanity.test c3427a0e0ac84d7cbe4c95fdc1cd4b61f9ddcf43443408f3000139478c4dc745
|
||||
F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
|
||||
F ext/jni/src/tests/900-001-fts.test bf0ce17a8d082773450e91f2388f5bbb2dfa316d0b676c313c637a91198090f0
|
||||
@@ -556,7 +563,7 @@ F ext/session/sessionstat1.test b039e38e2ba83767b464baf39b297cc0b1cc6f3292255cb4
|
||||
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
|
||||
F ext/session/sqlite3session.c 7b0f9bf6479aebd49e5f34cdaeb1479cde843cf5189bca6f32db4f36c130b414
|
||||
F ext/session/sqlite3session.h 4cf19a51975746d7cff2fdd74db8b769c570958e1c3639ac150d824ac1553b3e
|
||||
F ext/session/test_session.c 73e9921205633a08c1497770beecf3dcbc9b826dd4358f7f8152f706eaac5d71
|
||||
F ext/session/test_session.c 7b94ad945cd4afe6c73ee935aeb3d44b4446186e1729362af616c7695a5283d9
|
||||
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
||||
@@ -569,7 +576,7 @@ F ext/wasm/SQLTester/SQLTester.mjs ec2f6ba63a0f2f0562941a0fb8e46b7dc55589711513f
|
||||
F ext/wasm/SQLTester/SQLTester.run.mjs c72b7fe2072d05992f7a3d8c6a1d34e95712513ceabe40849784e24e41c84638
|
||||
F ext/wasm/SQLTester/index.html 3f8a016df0776be76605abf20e815ecaafbe055abac0e1fe5ea080e7846b760d
|
||||
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api f442460ed9a109e637dd3ea1caa4489553ad9414e8988118b208bb7a4bbece6b
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
|
||||
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
||||
F ext/wasm/api/README.md 5eb44fa02e9c693a1884a3692428647894b0380b24bca120866b7a24c8786134
|
||||
@@ -579,17 +586,17 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
|
||||
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
|
||||
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
||||
F ext/wasm/api/sqlite3-api-glue.js 26aedfb27915f4f316f6eac84078443e4f0d2dfe5f012310014923ed4b77b2b6
|
||||
F ext/wasm/api/sqlite3-api-glue.js 119b91c8a7ce6648679eb66fcdd1ed07ef7fd892eb501d658fbfefcc962012d9
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 9aeba7b45cf41b3a26d34d7fb2525633cd1adfc544888c1ea8dbb077496f4ce9
|
||||
F ext/wasm/api/sqlite3-api-worker1.js f941382f21006b4a817754184e2661b0a63ce650201f3419cd60f4758b6fd60e
|
||||
F ext/wasm/api/sqlite3-api-worker1.js 88770ac01fc756f89a3e060eec17111d6c1688e89ebfd34cb9d9e54d25affbb9
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
||||
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 595953994aa3ae2287c889c4da39ab3d6f17b6461ecf4bec334b7a3faafddb02
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 46c4afa6c50d7369252c104f274ad977a97e91ccfafc38b400fe36e90bdda88e
|
||||
F ext/wasm/api/sqlite3-wasm.c 038de1b6d40b2cc0f41a143a0451db60b2a6f1b5bc06de67da255c54ea1661b7
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
||||
F ext/wasm/api/sqlite3-wasm.c d0e09eb5ed3743c00294e30019e591c3aa150572ae7ffe8a8994568a7377589f
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 569d4e859968e65f55dec5fac0b879828a23c8b179162cc7812fec19f844dd21
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js a541112aa51e16705f13a99bb943c64efe178aa28c86704a955f8fd9afe4ba37
|
||||
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
||||
F ext/wasm/batch-runner.js 0dad6a02ad796f1003d3b7048947d275c4d6277f63767b8e685c27df8fdac93e
|
||||
@@ -630,10 +637,10 @@ F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f129
|
||||
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
|
||||
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
|
||||
F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555e685bce3da8c3f
|
||||
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
|
||||
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
|
||||
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
||||
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
||||
F ext/wasm/tester1.c-pp.js fb20d9e1c308ea34a29d8afdda1a6c5edc406241b5560fa23c19c14747ee41bc
|
||||
F ext/wasm/tester1.c-pp.js a92dc256738dbd1b50f142d1fd0c835294ba09b7bb6526650360e942f88cb63f
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
|
||||
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||
@@ -662,16 +669,16 @@ F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
|
||||
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
|
||||
F src/btree.c f3b09c5414de3a11db73e11e1d66f4c5e53c9e89876ff3b531a887ab656ca303 x
|
||||
F src/btree.h 03e3356f5208bcab8eed4e094240fdac4a7f9f5ddf5e91045ce589f67d47c240
|
||||
F src/btreeInt.h ef12a72b708677e48d6bc8dcd66fed25434740568b89e2cfa368093cfc5b9d15
|
||||
F src/btreeInt.h 3e2589726c4f105e653461814f65857465da68be1fac688de340c43b873f4062
|
||||
F src/build.c 189e4517d67f09f0a3e0d8e1faa6e2ef0c2e95f6ac82e33c912cb7efa2a359cc
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 23331529e654be40ca97d171cbbffe9b3d4c71cc53b78fe5501230675952da8b
|
||||
F src/date.c eebc54a00e888d3c56147779e9f361b77d62fd69ff2008c5373946aa1ba1d574
|
||||
F src/date.c 3b8d02977d160e128469de38493b4085f7c5cf4073193459909a6af3cf6d7c91
|
||||
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
||||
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
|
||||
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
|
||||
F src/expr.c 2ad50ae13cc6402973593eebd1f9af2c0915d5f7cc2c2f4f2f3472a9a7aeddce
|
||||
F src/expr.c e9a491c7f156e5b25641c28af11b735a424e108a21b9f83b6f3e51c99a8141d9
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
|
||||
F src/func.c 472f6dcfa39cf54f89a6aec76c79c225fb880a6c14469c15d361331662b9bf43
|
||||
@@ -681,10 +688,10 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
|
||||
F src/json.c d69c6e28ff7b602877bda68cd20583b8487c059759aa4d154dd21b3fd99c6238
|
||||
F src/json.c 92cc05dcf87cdace6fbf2a76e0cb2b030f04ddb1819e024af4ce8885261b4cef
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c e1bc8864834697503d370d94613be945d05ca1c5ebdda43e7d5c8ee8c48d433c
|
||||
F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9
|
||||
F src/malloc.c f016922435dc7d1f1f5083a03338a3e91f8c67ce2c5bdcfa4cdef62e612f5fcc
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -698,35 +705,35 @@ F src/mutex.c 1b4c7e5e3621b510e0c18397210be27cd54c8084141144fbbafd003fde948e88
|
||||
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c f7ee5a2061a4c11815a2bf4fc0e2bfa6fb8d9dc89390eb613ca0cec32fc9a3d1
|
||||
F src/mutex_w32.c 38b56d0bc8d54c17c20cbaaad3719b0c36b92fd07a7e34360d0c6a18d5589912
|
||||
F src/mutex_w32.c 28f8d480387db5b2ef5248705dd4e19db0cfc12c3ba426695a7d2c45c48e6885
|
||||
F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
|
||||
F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
|
||||
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
|
||||
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
|
||||
F src/os_unix.c cb116fde9e3ca3c1bbfdf89d6928f776a2a34da168e2667426523a4db353b271
|
||||
F src/os_unix.c 97bdcd43315da7aaec9fea2da1ff7c9de458f93dd363e073f2742403a7f2e011
|
||||
F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 699aab8dfc88056d796b03b40c0ab979040d58dfc3ae9db207f1be91e4880bbf
|
||||
F src/pager.c 987ab3a2cd9065d62e9955474470ff733445e2357432a67e3d0f5a8f9313e334
|
||||
F src/pager.h f4d33fec8052603758792045493423b8871a996da2d0973927b7d36cd6070473
|
||||
F src/parse.y 020d80386eb216ec9520549106353c517d2bbc89be28752ffdca649a9eaf56ec
|
||||
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
|
||||
F src/pragma.c b3b4ad9c0298d63098a067acca613c21a5f56b4d176d5842922bcd0b07b7164e
|
||||
F src/pragma.c b5b4cff830575e6188cd56a295a57448d2b9dbc53f0dae58e22b97354cda3781
|
||||
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
|
||||
F src/prepare.c bde74add20fc0e8ce0c4e937a1f70a36d17413afe4f71d3e103f5cb74b17c8d9
|
||||
F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
|
||||
F src/printf.c 9da63b9ae1c14789bcae12840f5d800fd9302500cd2d62733fac77f0041b4750
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 31229276a8eb5b5de1428cd2d80f6f1cf8ffc5248be25e47cf575df12f1b8f23
|
||||
F src/resolve.c d017bad7ba8e778617701a0e986fdeb393d67d6afa84fb28ef4e8b8ad2acf916
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c a19daa26e95f7245106a31f288b2f50c72d1f2cc156703f04c8c91450e111515
|
||||
F src/shell.c.in 3e9371ca6a93294931a8ed8b098bc3cb15d57567aa9a1f2ade72db7f5c572795
|
||||
F src/sqlite.h.in ef0e41e83ad1ac0dcc9ec9939bf541a44b1c5de821bee2d6c61754c3252f3276
|
||||
F src/select.c 85857bedd2913d888aa571755b48c54cd2e6e7fcb0087e19b226ee0368cfda1e
|
||||
F src/shell.c.in 7bb83293775e1a5586d65212997442bc7acc70a2f1b781745da64ec3c2e4ea97
|
||||
F src/sqlite.h.in d93a4821d2f792467a60f7dc81268d1bb8634f40c31694ef254cab4f9921f96a
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 567e317f8631883897b7d3da43fce778b7c30dd0dd7f714558c9725fc1c1196c
|
||||
F src/sqliteInt.h 6b82eb99a9d2887e873fb29e56befb7c50cf4624df615d23a28f071dc8abf5f6
|
||||
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
|
||||
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -784,43 +791,43 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 23d9f4539880b40226254ad9072f4ecf12eb1902e62aea47aac29928afafcfd5
|
||||
F src/treeview.c 62fafcd31eea60b718f8daf448116b7b19f90134ebc6c20777ddbb07f56a3d28
|
||||
F src/treeview.c c6fc972683fd00f975d8b32a81c1f25d2fb7d4035366bf45c9f5622d3ccd70ee
|
||||
F src/trigger.c 0905b96b04bb6658509f711a8207287f1315cdbc3df1a1b13ba6483c8e341c81
|
||||
F src/update.c 6904814dd62a7a93bbb86d9f1419c7f134a9119582645854ab02b36b676d9f92
|
||||
F src/upsert.c fa125a8d3410ce9a97b02cb50f7ae68a2476c405c76aa692d3acf6b8586e9242
|
||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
F src/util.c b22cc9f203a8c0b9ee5338a67f8860347d14845864c10248bebe84518a781677
|
||||
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
||||
F src/vdbe.c 14479441337135eed8e290fb1d4abb7db657d93217a3b1ea8a2f031d3895536a
|
||||
F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
|
||||
F src/vdbe.c f73bead140670fac1aa4227188827ada52387a5fe0ccff0dd5af2a906754d904
|
||||
F src/vdbe.h 88e19a982df9027ec1c177c793d1a5d34dc23d8f06e3b2d997f43688b05ee0eb
|
||||
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
||||
F src/vdbeapi.c fe654b1f54e1feebcaed6c2ae3ed035cc65bfeb9a1169bed866abc42bfc63ff6
|
||||
F src/vdbeaux.c dffcf79e7e415fcd6e4c8ac1ec7124cae5257018443adf09551c807655b04993
|
||||
F src/vdbeapi.c 8f57d60c89da0b60e6d4e272358c511f6bae4e24330bdb11f8b42f986d1bf21b
|
||||
F src/vdbeaux.c c5a471b34e9c4cfc0295a3e10734fd197670ffaebcb742f284c8e17e8026ceea
|
||||
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
|
||||
F src/vdbemem.c c936e9002af4993b84c4eb7133d6b1190efe46d391cc86117ecd67ba17b1a04b
|
||||
F src/vdbemem.c 0012d5f01cc866833847c2f3ae4c318ac53a1cb3d28acad9c35e688039464cf0
|
||||
F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7
|
||||
F src/vtab.c 154725ebecd3bc02f7fbd7ad3974334f73fff76e02a964e828e48a7c5fb7efff
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 01e051a1e713d9eabdb25df38602837cec8f4c2cae448ce2cf6accc87af903e9
|
||||
F src/wal.c e5247a3406531b705b44630e9ccf9ca0e5c74955ef19c06fbb146d765c500c20
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||
F src/where.c 313ce81270d2a414672370e1ee74e65949ad620519193d4cac2986d073cbc8a0
|
||||
F src/where.c 1fdc69ce1333e9bd6d7d3df9fa5af1373a3f5bfdd52108d1dbc0ca85a55f777e
|
||||
F src/whereInt.h 4b38c5889514e3aead3f27d0ee9a26e47c3f150efc59e2a8b4e3bc8835e4d7a1
|
||||
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
|
||||
F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00
|
||||
F src/window.c ad21e2b73ec75acc79dde2576c573f54a338b0c49e9de847ce984f9b9595b5e2
|
||||
F src/window.c 5b1387d59df30d481ed14cceef5f4d1dab1f8752aa106ba72c8b62777bd139d2
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggfault.test 777f269d0da5b0c2524c7ff6d99ae9a93db4f1b1839a914dd2a12e3035c29829
|
||||
F test/aggnested.test 2e738bfe2980df301a782f6e7bbf9459266f64f7e72f58f3b5c843bf897c568c
|
||||
F test/aggnested.test ce85a6af7d59c3109e35c5f03b2cd11da1a9b1417371e2f942102d0f0d77fd62
|
||||
F test/aggorderby.test e6b98dbbf3ababa96892435d387de2dcf602ef02c2b848d2d817473066f154ba
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
|
||||
F test/alter.test 403a7f8842457044a994d0ffb42963d6e84fcfbf5e8f54556063b25d966cd454
|
||||
F test/alter.test 3c00eff1e2036b9f93e9cd0f3d3e63750ac87ecb5bc71b9d7bd07cbf2ac4c494
|
||||
F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687
|
||||
F test/alter3.test ffc4ab29ce78a3517a66afd69b2730667e3471622509c283b2bd4c46f680fba3
|
||||
F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707
|
||||
@@ -1013,7 +1020,7 @@ F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c47
|
||||
F test/cursorhint.test 05cf0febe5c5f8a31f199401fd1c9322249e753950d55f26f9d5aca61408a270
|
||||
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
|
||||
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
|
||||
F test/date.test c0d17cdfd89395bc78087b131e3538d96f864b5029c335318011accc7c0d0934
|
||||
F test/date.test ff2341a1ef71b9a27979494d299222f9a293aa22cb9ff6e9c38d88a895317ebf
|
||||
F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1
|
||||
F test/date3.test a1b77abf05c6772fe5ca2337cac1398892f2a41e62bce7e6be0f4a08a0e64ae5
|
||||
F test/date4.test 8aeb3de5b5e9fda968baa9357e4c0fae573724b7904943410195a19e96e31b6a
|
||||
@@ -1266,7 +1273,7 @@ F test/index8.test caa097735c91dbc23d8a402f5e63a2a03c83840ba3928733ed7f9a03f8a91
|
||||
F test/index9.test 2ac891806a4136ef3e91280477e23114e67575207dc331e6797fa0ed9379f997
|
||||
F test/indexA.test 11d84f6995e6e5b9d8315953fb1b6d29772ee7c7803ee9112715e7e4dd3e4974
|
||||
F test/indexedby.test f21eca4f7a6ffe14c8500a7ad6cd53166666c99e5ccd311842a28bc94a195fe0
|
||||
F test/indexexpr1.test 62558b1cfd7ccbe7bc015849cc6d1a13ef124e80cbd5b3a98dc66c3c9cce0cf4
|
||||
F test/indexexpr1.test 833f511213a5e26549186813f0566bd72f978177a7e6e98a2d2dd695de3c670d
|
||||
F test/indexexpr2.test 1c382e81ef996d8ae8b834a74f2a9013dddf59214c32201d7c8a656d739f999a
|
||||
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
@@ -1306,7 +1313,7 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
|
||||
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
|
||||
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
|
||||
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
|
||||
F test/joinH.test 84198ea42bf78b79fe399c0567218cd6df36c50c6dd27d9c4aab221acaad929e
|
||||
F test/joinH.test f69e5b53b7d887914e854b6a131efbed4ea9f5ca52bdab81788bfc3e79299f43
|
||||
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
|
||||
@@ -1315,15 +1322,17 @@ F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd7
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json/README.md 63e3e589e1df8fd3cc1588ba1faaff659214003f8b77a15af5c6452b35e30ee2
|
||||
F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd28656fb261bddc8a3f
|
||||
F test/json/json-q1-b.txt 606818a5fba6d9e418c9f4ea7d8418af026775042dad81439b72447a147a462c
|
||||
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
|
||||
F test/json/json-speed-check.sh 8b7babf530faa58bd59d6d362cec8e9036a68c5457ff46f3b1f1511d21af6737 x
|
||||
F test/json101.test bc05d2476fd6f7ead31ec05b43d1b24b2b193ae112fd8f0d2ed56d9a904f9fa5
|
||||
F test/json102.test 4c69694773a470f1fda34e5f4ba24920b35184fb66050b450fc2ef9ab5ad310b
|
||||
F test/json/json-speed-check.sh b060a9a6c696c0a807d8929400fa11bd7113edc58b0d66b9795f424f8d0db326 x
|
||||
F test/json101.test 70587d7d35ef9e2126364ba70f0c951f70827cfbd28649d779ff3df7e8f87547
|
||||
F test/json102.test 557a46e16df1aa9bdbc4076a71a45814ea0e7503d6621d87d42a8c04cbc2b0ef
|
||||
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
|
||||
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
|
||||
F test/json105.test 11670a4387f4308ae0318cadcbd6a918ea7edcd19fbafde020720a073952675d
|
||||
F test/json501.test f71710f60fa45b19dc336fbaac9e8362f70f80cf81badefdb845ed3f7c7c2ccc
|
||||
F test/json105.test e64a8d73677fbae67886642cd5076e2ef3efe89f8483b87595cf9c030216c9bd
|
||||
F test/json501.test ab168a12eb6eb14d479f8c1cdae3ac062fd5a4679f17f976e96f1af518408330
|
||||
F test/json502.test 98c38e3c4573841028a1381dfb81d4c3f9b105d39668167da10d055e503f6d0b
|
||||
F test/jsonb01.test cace70765b36a36aec9a85a41ea65667d3bbf647d4400ddc3ac76f8fe7d94f90
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
@@ -1484,7 +1493,6 @@ 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 80ef3941bf7ad136f4dc3d8960786f10a4f488797238171bdd757cc6eb4c3efa
|
||||
F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/returning1.test db532cde29d6aebbc48c6ddc3149b30476f8e69ca7a2c4b53986c7635e6fd8ec
|
||||
@@ -1561,7 +1569,7 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
|
||||
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test 2191c892d8256b1b6cccb4fca894cfc2e748450cf422e6ec80a320a0d538b6df
|
||||
F test/shell1.test c7127a5e780ffc9e14c476773127fdf292c6db226529c44c1676f37b3793123f
|
||||
F test/shell2.test 35226c070a8c7f64fd016dfac2a0db2a40f709b3131f61daacd9dad61536c9cb
|
||||
F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
|
||||
F test/shell4.test 9abd0c12a7e20a4c49e84d5be208d2124fa6c09e728f56f1f4bee0f02853935f
|
||||
@@ -1584,7 +1592,7 @@ F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c
|
||||
F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b
|
||||
F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322
|
||||
F test/snapshot_fault.test 129234ceb9b26a0e1000e8563a16e790f5c1412354e70749cbd78c3d5d07d60a
|
||||
F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a393cdd41c
|
||||
F test/snapshot_up.test 77dc7853bfb2b4fa249f76e1714cfa1e596826165d9ef22c06ac3a0b7b778d9a
|
||||
F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c
|
||||
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
|
||||
F test/sort.test f86751134159abb5e5fd4381a0d7038c91013638cd1e3fa1d7850901f6df6196
|
||||
@@ -1647,8 +1655,8 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl 68454ef88508c196d19e8694daa27bff7107a91857799eaa12f417188ae53ede
|
||||
F test/testrunner.tcl 14c8b8ece841b1dd17516a0dc9c7ad9b5f4d4db7987974d3fdf66ae56b2a71fa
|
||||
F test/testrunner_data.tcl 7f73f93634d32dafc857ed491b840f371113d09fde6a8bfb9e47b938d47b8c85
|
||||
F test/testrunner.tcl e18d71f2e797da808ba6d31335e504ed6b2791581b89287a72b697a2f31b1ea1
|
||||
F test/testrunner_data.tcl e4d5017290a6d5c11785e36cc94c67d8bb950c8cdc2dbe4c1db2a3a583812560
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1813,7 +1821,7 @@ F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
|
||||
F test/tpch01.test 4479008f85f6f8f25f7ab2cb305d665752b4727fa28a8df3d8e0ad46520c62ff
|
||||
F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a
|
||||
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
|
||||
F test/trace3.test ae2004df24b585fed9046cc0bae4601762bc6fc4aa321d475f1350bba5047f31
|
||||
F test/trace3.test 4f418ed30d15d9d17dcf13a17f0bd99a92e3038e038798e35db7525f82f4c281
|
||||
F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
@@ -1949,8 +1957,6 @@ F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370
|
||||
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
|
||||
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
|
||||
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
|
||||
F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
|
||||
F test/wapptest.tcl 1bea58a6a8e68a73f542ee4fca28b771b84ed803bd0c9e385087070b3d747b3c x
|
||||
F test/where.test 59abb854eee24f166b5f7ba9d17eb250abc59ce0a66c48912ffb10763648196d
|
||||
F test/where2.test 03c21a11e7b90e2845fc3c8b4002fc44cc2797fa74c86ee47d70bd7ea4f29ed6
|
||||
F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67753
|
||||
@@ -1966,7 +1972,7 @@ F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
|
||||
F test/whereD.test c1c335e914e28b122e000e9310f02d2be83e1c9dbca2e29f46bd732703944d1b
|
||||
F test/whereE.test 7a727b5d5b6bc8fa4cef5206e90cc0363e55ca7f0566f6fbad0206e43170f59e
|
||||
F test/whereF.test 926b65519608e3f2aa28720822b9154fb5c7b13519dd78194f434a511ab3dac5
|
||||
F test/whereG.test b2a479f425f7d0a432df7e842e8484560908ef703fe0fd407888ff85e7097238
|
||||
F test/whereG.test 649d5ad02a87a76ec2ac8de9441e2c83a4dd0f29e459a31215c0533788c6bf07
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581
|
||||
F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf
|
||||
@@ -1982,7 +1988,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
|
||||
F test/win32lock.test e0924eb8daac02bf80e9da88930747bd44dd9b230b7759fed927b1655b467c9c
|
||||
F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/window1.test ccfeaf116afc6a8f748a8122a4f1ee6b69e6bbc5acee61197d3c17167338b100
|
||||
F test/window1.test 5e8abe56a7d667eeddbba6de180086dcf69ed528d046447a25464f945ece101f
|
||||
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
|
||||
F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
|
||||
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
|
||||
@@ -2059,13 +2065,13 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
|
||||
F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl 372452e24267dfe1b496eec3992d10c6e5e7d7870a152560cdcfe5404bc8cc04 x
|
||||
F tool/mkctimec.tcl a16682eae5f01f85e5861b2aa215ca0d46b4230658ee25977e02b4508566fb75 x
|
||||
F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd
|
||||
F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d
|
||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||
F tool/mkopcodeh.tcl 769d9e6a8b462323150dc13a8539d6064664b72974f7894befe2491cc73e05cd
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl bd07bd59d45d0f3448e123d6937e9811195f9908a51e09d774609883055bfd3d
|
||||
F tool/mkpragmatab.tcl 32e359ccb21011958a821955254bd7a5fa7915d01a8c16fed91ffc8b40cb4adf
|
||||
F tool/mkshellc.tcl b7adf08b82de60811d2cb6af05ff59fc17e5cd6f3e98743c14eaaa3f8971fed0
|
||||
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
@@ -2106,7 +2112,7 @@ F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaa
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f
|
||||
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
|
||||
F tool/srctree-check.tcl cef630bc4ff21a460d72479c43a42bf1c1ed61897659305c35c8d72e91bcb176
|
||||
F tool/srctree-check.tcl c15f860a3c97d5f7b4c14b60392d9466af29dd006c4ef18127f502641e2977a8
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/stripccomments.c 20b8aabc4694d0d4af5566e42da1f1a03aff057689370326e9269a9ddcffdc37
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
@@ -2139,8 +2145,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 f89d062f8890fffc957a354e966784031d561d0f8f5c174c1ccdcf77e66c32bd c4f724de279dae1afd10d435ad61ed07c1e4658288457c50e4f9b2f4521bbe12
|
||||
R de3e0925c6135d51477a234fbf85975c
|
||||
U larrybr
|
||||
Z 945c939e9cd689d368ccc6bbe8e3ac11
|
||||
P 04c0d5644372446c924a2e31a26edf51ddc563a1990d170b0ed4739e3e8b239b
|
||||
R 4a2861d7ab7860f80e426ce44e32c50f
|
||||
U drh
|
||||
Z 1fffc27f10fd5ca429d5618946ebb513
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2666b80d2cf64a14d0482ee1ce0e8b2ff9e0c5bb21cd626470241a73a6555a3a
|
||||
cc7a641ab5ae739d31c24f0ad0caeb15a481a63fa8f13720718ea922c25862ff
|
||||
+1
-1
@@ -64,7 +64,7 @@
|
||||
** 22 1 Min embedded payload fraction (must be 32)
|
||||
** 23 1 Min leaf payload fraction (must be 32)
|
||||
** 24 4 File change counter
|
||||
** 28 4 Reserved for future use
|
||||
** 28 4 The size of the database in pages
|
||||
** 32 4 First freelist page
|
||||
** 36 4 Number of freelist pages in the file
|
||||
** 40 60 15 4-byte meta values passed to higher layers
|
||||
|
||||
@@ -1043,6 +1043,12 @@ static int isDate(
|
||||
}
|
||||
computeJD(p);
|
||||
if( p->isError || !validJulianDay(p->iJD) ) return 1;
|
||||
if( argc==1 && p->validYMD && p->D>28 ){
|
||||
/* Make sure a YYYY-MM-DD is normalized.
|
||||
** Example: 2023-02-31 -> 2023-03-03 */
|
||||
assert( p->validJD );
|
||||
p->validYMD = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -1638,7 +1638,8 @@ static Expr *exprDup(
|
||||
memcpy(sEdupBuf.zAlloc, p, nNewSize);
|
||||
}else{
|
||||
u32 nSize = (u32)exprStructSize(p);
|
||||
assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= EXPR_FULLSIZE+nToken );
|
||||
assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >=
|
||||
(int)EXPR_FULLSIZE+nToken );
|
||||
memcpy(sEdupBuf.zAlloc, p, nSize);
|
||||
if( nSize<EXPR_FULLSIZE ){
|
||||
memset(&sEdupBuf.zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
|
||||
@@ -6042,8 +6043,8 @@ int sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB, int iTab){
|
||||
*/
|
||||
int sqlite3ExprCompareSkip(Expr *pA,Expr *pB, int iTab){
|
||||
return sqlite3ExprCompare(0,
|
||||
sqlite3ExprSkipCollateAndLikely(pA),
|
||||
sqlite3ExprSkipCollateAndLikely(pB),
|
||||
sqlite3ExprSkipCollate(pA),
|
||||
sqlite3ExprSkipCollate(pB),
|
||||
iTab);
|
||||
}
|
||||
|
||||
@@ -6768,13 +6769,14 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
case TK_AGG_FUNCTION: {
|
||||
if( (pNC->ncFlags & NC_InAggFunc)==0
|
||||
&& pWalker->walkerDepth==pExpr->op2
|
||||
&& pExpr->pAggInfo==0
|
||||
){
|
||||
/* Check to see if pExpr is a duplicate of another aggregate
|
||||
** function that is already in the pAggInfo structure
|
||||
*/
|
||||
struct AggInfo_func *pItem = pAggInfo->aFunc;
|
||||
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
|
||||
if( pItem->pFExpr==pExpr ) break;
|
||||
if( NEVER(pItem->pFExpr==pExpr) ) break;
|
||||
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
|
||||
break;
|
||||
}
|
||||
|
||||
+3266
-1375
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1914,7 +1914,7 @@ int sqlite3CreateFunc(
|
||||
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
|
||||
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
|
||||
extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
|
||||
SQLITE_SUBTYPE|SQLITE_INNOCUOUS);
|
||||
SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE);
|
||||
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
|
||||
|
||||
/* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ void sqlite3MemoryBarrier(void){
|
||||
SQLITE_MEMORY_BARRIER;
|
||||
#elif defined(__GNUC__)
|
||||
__sync_synchronize();
|
||||
#elif MSVC_VERSION>=1300
|
||||
#elif MSVC_VERSION>=1400
|
||||
_ReadWriteBarrier();
|
||||
#elif defined(MemoryBarrier)
|
||||
MemoryBarrier();
|
||||
|
||||
+219
-96
@@ -4054,7 +4054,13 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
case SQLITE_FCNTL_LOCK_TIMEOUT: {
|
||||
int iOld = pFile->iBusyTimeout;
|
||||
#if SQLITE_ENABLE_SETLK_TIMEOUT==1
|
||||
pFile->iBusyTimeout = *(int*)pArg;
|
||||
#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
|
||||
pFile->iBusyTimeout = !!(*(int*)pArg);
|
||||
#else
|
||||
# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2"
|
||||
#endif
|
||||
*(int*)pArg = iOld;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -4307,6 +4313,25 @@ static int unixGetpagesize(void){
|
||||
** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
|
||||
** unixMutexHeld() is true when reading or writing any other field
|
||||
** in this structure.
|
||||
**
|
||||
** aLock[SQLITE_SHM_NLOCK]:
|
||||
** This array records the various locks held by clients on each of the
|
||||
** SQLITE_SHM_NLOCK slots. If the aLock[] entry is set to 0, then no
|
||||
** locks are held by the process on this slot. If it is set to -1, then
|
||||
** some client holds an EXCLUSIVE lock on the locking slot. If the aLock[]
|
||||
** value is set to a positive value, then it is the number of shared
|
||||
** locks currently held on the slot.
|
||||
**
|
||||
** aMutex[SQLITE_SHM_NLOCK]:
|
||||
** Normally, when SQLITE_ENABLE_SETLK_TIMEOUT is not defined, mutex
|
||||
** pShmMutex is used to protect the aLock[] array and the right to
|
||||
** call fcntl() on unixShmNode.hShm to obtain or release locks.
|
||||
**
|
||||
** If SQLITE_ENABLE_SETLK_TIMEOUT is defined though, we use an array
|
||||
** of mutexes - one for each locking slot. To read or write locking
|
||||
** slot aLock[iSlot], the caller must hold the corresponding mutex
|
||||
** aMutex[iSlot]. Similarly, to call fcntl() to obtain or release a
|
||||
** lock corresponding to slot iSlot, mutex aMutex[iSlot] must be held.
|
||||
*/
|
||||
struct unixShmNode {
|
||||
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
|
||||
@@ -4320,10 +4345,11 @@ struct unixShmNode {
|
||||
char **apRegion; /* Array of mapped shared-memory regions */
|
||||
int nRef; /* Number of unixShm objects pointing to this */
|
||||
unixShm *pFirst; /* All unixShm objects pointing to this */
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
sqlite3_mutex *aMutex[SQLITE_SHM_NLOCK];
|
||||
#endif
|
||||
int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 exclMask; /* Mask of exclusive locks held */
|
||||
u8 sharedMask; /* Mask of shared locks held */
|
||||
u8 nextShmId; /* Next available unixShm.id value */
|
||||
#endif
|
||||
};
|
||||
@@ -4406,16 +4432,29 @@ static int unixShmSystemLock(
|
||||
struct flock f; /* The posix advisory locking structure */
|
||||
int rc = SQLITE_OK; /* Result code form fcntl() */
|
||||
|
||||
/* Access to the unixShmNode object is serialized by the caller */
|
||||
pShmNode = pFile->pInode->pShmNode;
|
||||
assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
|
||||
assert( pShmNode->nRef>0 || unixMutexHeld() );
|
||||
|
||||
/* Assert that the correct mutex or mutexes are held. */
|
||||
if( pShmNode->nRef==0 ){
|
||||
assert( ofst==UNIX_SHM_DMS && n==1 && unixMutexHeld() );
|
||||
}else{
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
int ii;
|
||||
for(ii=ofst-UNIX_SHM_BASE; ii<ofst-UNIX_SHM_BASE+n; ii++){
|
||||
assert( sqlite3_mutex_held(pShmNode->aMutex[ii]) );
|
||||
}
|
||||
#else
|
||||
assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
|
||||
assert( pShmNode->nRef>0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Shared locks never span more than one byte */
|
||||
assert( n==1 || lockType!=F_RDLCK );
|
||||
|
||||
/* Locks are within range */
|
||||
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
|
||||
assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) );
|
||||
|
||||
if( pShmNode->hShm>=0 ){
|
||||
int res;
|
||||
@@ -4426,7 +4465,7 @@ static int unixShmSystemLock(
|
||||
f.l_len = n;
|
||||
res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
|
||||
if( res==-1 ){
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && SQLITE_ENABLE_SETLK_TIMEOUT==1
|
||||
rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
|
||||
#else
|
||||
rc = SQLITE_BUSY;
|
||||
@@ -4434,39 +4473,28 @@ static int unixShmSystemLock(
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the global lock state and do debug tracing */
|
||||
/* Do debug tracing */
|
||||
#ifdef SQLITE_DEBUG
|
||||
{ u16 mask;
|
||||
OSTRACE(("SHM-LOCK "));
|
||||
mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( lockType==F_UNLCK ){
|
||||
OSTRACE(("unlock %d ok", ofst));
|
||||
pShmNode->exclMask &= ~mask;
|
||||
pShmNode->sharedMask &= ~mask;
|
||||
OSTRACE(("unlock %d..%d ok\n", ofst, ofst+n-1));
|
||||
}else if( lockType==F_RDLCK ){
|
||||
OSTRACE(("read-lock %d ok", ofst));
|
||||
pShmNode->exclMask &= ~mask;
|
||||
pShmNode->sharedMask |= mask;
|
||||
OSTRACE(("read-lock %d..%d ok\n", ofst, ofst+n-1));
|
||||
}else{
|
||||
assert( lockType==F_WRLCK );
|
||||
OSTRACE(("write-lock %d ok", ofst));
|
||||
pShmNode->exclMask |= mask;
|
||||
pShmNode->sharedMask &= ~mask;
|
||||
OSTRACE(("write-lock %d..%d ok\n", ofst, ofst+n-1));
|
||||
}
|
||||
}else{
|
||||
if( lockType==F_UNLCK ){
|
||||
OSTRACE(("unlock %d failed", ofst));
|
||||
OSTRACE(("unlock %d..%d failed\n", ofst, ofst+n-1));
|
||||
}else if( lockType==F_RDLCK ){
|
||||
OSTRACE(("read-lock failed"));
|
||||
OSTRACE(("read-lock %d..%d failed\n", ofst, ofst+n-1));
|
||||
}else{
|
||||
assert( lockType==F_WRLCK );
|
||||
OSTRACE(("write-lock %d failed", ofst));
|
||||
OSTRACE(("write-lock %d..%d failed\n", ofst, ofst+n-1));
|
||||
}
|
||||
}
|
||||
OSTRACE((" - afterwards %03x,%03x\n",
|
||||
pShmNode->sharedMask, pShmNode->exclMask));
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
@@ -4503,6 +4531,11 @@ static void unixShmPurge(unixFile *pFd){
|
||||
int i;
|
||||
assert( p->pInode==pFd->pInode );
|
||||
sqlite3_mutex_free(p->pShmMutex);
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
for(i=0; i<SQLITE_SHM_NLOCK; i++){
|
||||
sqlite3_mutex_free(p->aMutex[i]);
|
||||
}
|
||||
#endif
|
||||
for(i=0; i<p->nRegion; i+=nShmPerMap){
|
||||
if( p->hShm>=0 ){
|
||||
osMunmap(p->apRegion[i], p->szRegion);
|
||||
@@ -4562,7 +4595,20 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
|
||||
pShmNode->isUnlocked = 1;
|
||||
rc = SQLITE_READONLY_CANTINIT;
|
||||
}else{
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
/* Do not use a blocking lock here. If the lock cannot be obtained
|
||||
** immediately, it means some other connection is truncating the
|
||||
** *-shm file. And after it has done so, it will not release its
|
||||
** lock, but only downgrade it to a shared lock. So no point in
|
||||
** blocking here. The call below to obtain the shared DMS lock may
|
||||
** use a blocking lock. */
|
||||
int iSaveTimeout = pDbFd->iBusyTimeout;
|
||||
pDbFd->iBusyTimeout = 0;
|
||||
#endif
|
||||
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
pDbFd->iBusyTimeout = iSaveTimeout;
|
||||
#endif
|
||||
/* The first connection to attach must truncate the -shm file. We
|
||||
** truncate to 3 bytes (an arbitrary small number, less than the
|
||||
** -shm header size) rather than 0 as a system debugging aid, to
|
||||
@@ -4683,6 +4729,18 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto shm_open_err;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
{
|
||||
int ii;
|
||||
for(ii=0; ii<SQLITE_SHM_NLOCK; ii++){
|
||||
pShmNode->aMutex[ii] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||
if( pShmNode->aMutex[ii]==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto shm_open_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( pInode->bProcessLock==0 ){
|
||||
@@ -4904,9 +4962,11 @@ shmpage_out:
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
static int assertLockingArrayOk(unixShmNode *pShmNode){
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
return 1;
|
||||
#else
|
||||
unixShm *pX;
|
||||
int aLock[SQLITE_SHM_NLOCK];
|
||||
assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
|
||||
|
||||
memset(aLock, 0, sizeof(aLock));
|
||||
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
||||
@@ -4924,13 +4984,14 @@ static int assertLockingArrayOk(unixShmNode *pShmNode){
|
||||
|
||||
assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) );
|
||||
return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Change the lock state for a shared-memory segment.
|
||||
**
|
||||
** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
|
||||
** Note that the relationship between SHARED and EXCLUSIVE locks is a little
|
||||
** different here than in posix. In xShmLock(), one can go from unlocked
|
||||
** to shared and back or from unlocked to exclusive and back. But one may
|
||||
** not go from shared to exclusive or from exclusive to shared.
|
||||
@@ -4945,7 +5006,7 @@ static int unixShmLock(
|
||||
unixShm *p; /* The shared memory being locked */
|
||||
unixShmNode *pShmNode; /* The underlying file iNode */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
u16 mask; /* Mask of locks to take or release */
|
||||
u16 mask = (1<<(ofst+n)) - (1<<ofst); /* Mask of locks to take or release */
|
||||
int *aLock;
|
||||
|
||||
p = pDbFd->pShm;
|
||||
@@ -4980,88 +5041,150 @@ static int unixShmLock(
|
||||
** It is not permitted to block on the RECOVER lock.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
|
||||
(ofst!=2) /* not RECOVER */
|
||||
&& (ofst!=1 || (p->exclMask|p->sharedMask)==0)
|
||||
&& (ofst!=0 || (p->exclMask|p->sharedMask)<3)
|
||||
&& (ofst<3 || (p->exclMask|p->sharedMask)<(1<<ofst))
|
||||
));
|
||||
{
|
||||
u16 lockMask = (p->exclMask|p->sharedMask);
|
||||
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
|
||||
(ofst!=2) /* not RECOVER */
|
||||
&& (ofst!=1 || lockMask==0 || lockMask==2)
|
||||
&& (ofst!=0 || lockMask<3)
|
||||
&& (ofst<3 || lockMask<(1<<ofst))
|
||||
));
|
||||
}
|
||||
#endif
|
||||
|
||||
mask = (1<<(ofst+n)) - (1<<ofst);
|
||||
assert( n>1 || mask==(1<<ofst) );
|
||||
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
||||
assert( assertLockingArrayOk(pShmNode) );
|
||||
if( flags & SQLITE_SHM_UNLOCK ){
|
||||
if( (p->exclMask|p->sharedMask) & mask ){
|
||||
int ii;
|
||||
int bUnlock = 1;
|
||||
/* Check if there is any work to do. There are three cases:
|
||||
**
|
||||
** a) An unlock operation where there are locks to unlock,
|
||||
** b) An shared lock where the requested lock is not already held
|
||||
** c) An exclusive lock where the requested lock is not already held
|
||||
**
|
||||
** The SQLite core never requests an exclusive lock that it already holds.
|
||||
** This is assert()ed below.
|
||||
*/
|
||||
assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
|
||||
|| 0==(p->exclMask & mask)
|
||||
);
|
||||
if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
|
||||
|| (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
|
||||
|| (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
|
||||
){
|
||||
|
||||
for(ii=ofst; ii<ofst+n; ii++){
|
||||
if( aLock[ii]>((p->sharedMask & (1<<ii)) ? 1 : 0) ){
|
||||
bUnlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( bUnlock ){
|
||||
rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
|
||||
if( rc==SQLITE_OK ){
|
||||
memset(&aLock[ofst], 0, sizeof(int)*n);
|
||||
}
|
||||
}else if( ALWAYS(p->sharedMask & (1<<ofst)) ){
|
||||
assert( n==1 && aLock[ofst]>1 );
|
||||
aLock[ofst]--;
|
||||
}
|
||||
|
||||
/* Undo the local locks */
|
||||
if( rc==SQLITE_OK ){
|
||||
p->exclMask &= ~mask;
|
||||
p->sharedMask &= ~mask;
|
||||
/* Take the required mutexes. In SETLK_TIMEOUT mode (blocking locks), if
|
||||
** this is an attempt on an exclusive lock use sqlite3_mutex_try(). If any
|
||||
** other thread is holding this mutex, then it is either holding or about
|
||||
** to hold a lock exclusive to the one being requested, and we may
|
||||
** therefore return SQLITE_BUSY to the caller.
|
||||
**
|
||||
** Doing this prevents some deadlock scenarios. For example, thread 1 may
|
||||
** be a checkpointer blocked waiting on the WRITER lock. And thread 2
|
||||
** may be a normal SQL client upgrading to a write transaction. In this
|
||||
** case thread 2 does a non-blocking request for the WRITER lock. But -
|
||||
** if it were to use sqlite3_mutex_enter() then it would effectively
|
||||
** become a (doomed) blocking request, as thread 2 would block until thread
|
||||
** 1 obtained WRITER and released the mutex. Since thread 2 already holds
|
||||
** a lock on a read-locking slot at this point, this breaks the
|
||||
** anti-deadlock rules (see above). */
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
int iMutex;
|
||||
for(iMutex=ofst; iMutex<ofst+n; iMutex++){
|
||||
if( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) ){
|
||||
rc = sqlite3_mutex_try(pShmNode->aMutex[iMutex]);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
}else{
|
||||
sqlite3_mutex_enter(pShmNode->aMutex[iMutex]);
|
||||
}
|
||||
}
|
||||
}else if( flags & SQLITE_SHM_SHARED ){
|
||||
assert( n==1 );
|
||||
assert( (p->exclMask & (1<<ofst))==0 );
|
||||
if( (p->sharedMask & mask)==0 ){
|
||||
if( aLock[ofst]<0 ){
|
||||
rc = SQLITE_BUSY;
|
||||
}else if( aLock[ofst]==0 ){
|
||||
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
|
||||
}
|
||||
#else
|
||||
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
||||
#endif
|
||||
|
||||
/* Get the local shared locks */
|
||||
if( rc==SQLITE_OK ){
|
||||
p->sharedMask |= mask;
|
||||
aLock[ofst]++;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* Make sure no sibling connections hold locks that will block this
|
||||
** lock. If any do, return SQLITE_BUSY right away. */
|
||||
int ii;
|
||||
for(ii=ofst; ii<ofst+n; ii++){
|
||||
assert( (p->sharedMask & mask)==0 );
|
||||
if( ALWAYS((p->exclMask & (1<<ii))==0) && aLock[ii] ){
|
||||
rc = SQLITE_BUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the exclusive locks at the system level. Then if successful
|
||||
** also update the in-memory values. */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( flags & SQLITE_SHM_UNLOCK ){
|
||||
/* Case (a) - unlock. */
|
||||
int bUnlock = 1;
|
||||
assert( (p->exclMask & p->sharedMask)==0 );
|
||||
assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
|
||||
assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );
|
||||
|
||||
/* If this is a SHARED lock being unlocked, it is possible that other
|
||||
** clients within this process are holding the same SHARED lock. In
|
||||
** this case, set bUnlock to 0 so that the posix lock is not removed
|
||||
** from the file-descriptor below. */
|
||||
if( flags & SQLITE_SHM_SHARED ){
|
||||
assert( n==1 );
|
||||
assert( aLock[ofst]>=1 );
|
||||
if( aLock[ofst]>1 ){
|
||||
bUnlock = 0;
|
||||
aLock[ofst]--;
|
||||
p->sharedMask &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
if( bUnlock ){
|
||||
rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
|
||||
if( rc==SQLITE_OK ){
|
||||
memset(&aLock[ofst], 0, sizeof(int)*n);
|
||||
p->sharedMask &= ~mask;
|
||||
p->exclMask &= ~mask;
|
||||
}
|
||||
}
|
||||
}else if( flags & SQLITE_SHM_SHARED ){
|
||||
/* Case (b) - a shared lock. */
|
||||
|
||||
if( aLock[ofst]<0 ){
|
||||
/* An exclusive lock is held by some other connection. BUSY. */
|
||||
rc = SQLITE_BUSY;
|
||||
}else if( aLock[ofst]==0 ){
|
||||
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
|
||||
}
|
||||
|
||||
/* Get the local shared locks */
|
||||
if( rc==SQLITE_OK ){
|
||||
p->sharedMask |= mask;
|
||||
aLock[ofst]++;
|
||||
}
|
||||
}else{
|
||||
/* Case (c) - an exclusive lock. */
|
||||
int ii;
|
||||
|
||||
assert( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) );
|
||||
assert( (p->sharedMask & mask)==0 );
|
||||
p->exclMask |= mask;
|
||||
assert( (p->exclMask & mask)==0 );
|
||||
|
||||
/* Make sure no sibling connections hold locks that will block this
|
||||
** lock. If any do, return SQLITE_BUSY right away. */
|
||||
for(ii=ofst; ii<ofst+n; ii++){
|
||||
aLock[ii] = -1;
|
||||
if( aLock[ii] ){
|
||||
rc = SQLITE_BUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the exclusive locks at the system level. Then if successful
|
||||
** also update the in-memory values. */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->exclMask |= mask;
|
||||
for(ii=ofst; ii<ofst+n; ii++){
|
||||
aLock[ii] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert( assertLockingArrayOk(pShmNode) );
|
||||
}
|
||||
|
||||
/* Drop the mutexes acquired above. */
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
for(iMutex--; iMutex>=ofst; iMutex--){
|
||||
sqlite3_mutex_leave(pShmNode->aMutex[iMutex]);
|
||||
}
|
||||
#else
|
||||
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
||||
#endif
|
||||
}
|
||||
assert( assertLockingArrayOk(pShmNode) );
|
||||
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
||||
|
||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
|
||||
p->id, osGetpid(0), p->sharedMask, p->exclMask));
|
||||
return rc;
|
||||
|
||||
+4
-1
@@ -5062,10 +5062,13 @@ act_like_temp_file:
|
||||
*/
|
||||
sqlite3_file *sqlite3_database_file_object(const char *zName){
|
||||
Pager *pPager;
|
||||
const char *p;
|
||||
while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
|
||||
zName--;
|
||||
}
|
||||
pPager = *(Pager**)(zName - 4 - sizeof(Pager*));
|
||||
p = zName - 4 - sizeof(Pager*);
|
||||
assert( EIGHT_BYTE_ALIGNMENT(p) );
|
||||
pPager = *(Pager**)p;
|
||||
return pPager->fd;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -1779,7 +1779,8 @@ void sqlite3Pragma(
|
||||
if( pVTab->pModule->iVersion<4 ) continue;
|
||||
if( pVTab->pModule->xIntegrity==0 ) continue;
|
||||
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
|
||||
sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
|
||||
pTab->nTabRef++;
|
||||
sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
|
||||
a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, a1);
|
||||
|
||||
@@ -868,6 +868,7 @@ static int sqlite3LockAndPrepare(
|
||||
assert( (rc&db->errMask)==rc );
|
||||
db->busyHandler.nBusy = 0;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
assert( rc==SQLITE_OK || (*ppStmt)==0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -1249,11 +1249,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
while( pNC2
|
||||
&& sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
|
||||
){
|
||||
pExpr->op2++;
|
||||
pExpr->op2 += (1 + pNC2->nNestedSelect);
|
||||
pNC2 = pNC2->pNext;
|
||||
}
|
||||
assert( pDef!=0 || IN_RENAME_OBJECT );
|
||||
if( pNC2 && pDef ){
|
||||
pExpr->op2 += pNC2->nNestedSelect;
|
||||
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
|
||||
assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
|
||||
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
|
||||
@@ -1812,6 +1813,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
|
||||
/* Recursively resolve names in all subqueries in the FROM clause
|
||||
*/
|
||||
if( pOuterNC ) pOuterNC->nNestedSelect++;
|
||||
for(i=0; i<p->pSrc->nSrc; i++){
|
||||
SrcItem *pItem = &p->pSrc->a[i];
|
||||
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
|
||||
@@ -1836,6 +1838,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
}
|
||||
}
|
||||
}
|
||||
if( pOuterNC && ALWAYS(pOuterNC->nNestedSelect>0) ){
|
||||
pOuterNC->nNestedSelect--;
|
||||
}
|
||||
|
||||
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
|
||||
** resolve the result-set expression list.
|
||||
|
||||
+7
-6
@@ -2319,7 +2319,8 @@ void sqlite3SubqueryColumnTypes(
|
||||
NameContext sNC;
|
||||
|
||||
assert( pSelect!=0 );
|
||||
assert( (pSelect->selFlags & SF_Resolved)!=0 );
|
||||
testcase( (pSelect->selFlags & SF_Resolved)==0 );
|
||||
assert( (pSelect->selFlags & SF_Resolved)!=0 || IN_RENAME_OBJECT );
|
||||
assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 );
|
||||
assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB );
|
||||
if( db->mallocFailed || IN_RENAME_OBJECT ) return;
|
||||
@@ -6372,10 +6373,11 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
|
||||
SrcList *pTabList;
|
||||
SrcItem *pFrom;
|
||||
|
||||
assert( p->selFlags & SF_Resolved );
|
||||
if( p->selFlags & SF_HasTypeInfo ) return;
|
||||
p->selFlags |= SF_HasTypeInfo;
|
||||
pParse = pWalker->pParse;
|
||||
testcase( (p->selFlags & SF_Resolved)==0 );
|
||||
assert( (p->selFlags & SF_Resolved) || IN_RENAME_OBJECT );
|
||||
pTabList = p->pSrc;
|
||||
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
||||
Table *pTab = pFrom->pTab;
|
||||
@@ -7397,6 +7399,7 @@ int sqlite3Select(
|
||||
TREETRACE(0x1000,pParse,p,
|
||||
("LEFT-JOIN simplifies to JOIN on term %d\n",i));
|
||||
pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER);
|
||||
unsetJoinExpr(p->pWhere, pItem->iCursor, 0);
|
||||
}
|
||||
}
|
||||
if( pItem->fg.jointype & JT_LTORJ ){
|
||||
@@ -7411,17 +7414,15 @@ int sqlite3Select(
|
||||
TREETRACE(0x1000,pParse,p,
|
||||
("RIGHT-JOIN simplifies to JOIN on term %d\n",j));
|
||||
pI2->fg.jointype &= ~(JT_RIGHT|JT_OUTER);
|
||||
unsetJoinExpr(p->pWhere, pI2->iCursor, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(j=pTabList->nSrc-1; j>=i; j--){
|
||||
for(j=pTabList->nSrc-1; j>=0; j--){
|
||||
pTabList->a[j].fg.jointype &= ~JT_LTORJ;
|
||||
if( pTabList->a[j].fg.jointype & JT_RIGHT ) break;
|
||||
}
|
||||
}
|
||||
assert( pItem->iCursor>=0 );
|
||||
unsetJoinExpr(p->pWhere, pItem->iCursor,
|
||||
pTabList->a[0].fg.jointype & JT_LTORJ);
|
||||
}
|
||||
|
||||
/* No further action if this term of the FROM clause is not a subquery */
|
||||
|
||||
+899
-1172
File diff suppressed because it is too large
Load Diff
+57
-12
@@ -3954,15 +3954,17 @@ void sqlite3_free_filename(sqlite3_filename);
|
||||
** </ul>
|
||||
**
|
||||
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
||||
** text that describes the error, as either UTF-8 or UTF-16 respectively.
|
||||
** text that describes the error, as either UTF-8 or UTF-16 respectively,
|
||||
** or NULL if no error message is available.
|
||||
** (See how SQLite handles [invalid UTF] for exceptions to this rule.)
|
||||
** ^(Memory to hold the error message string is managed internally.
|
||||
** The application does not need to worry about freeing the result.
|
||||
** However, the error string might be overwritten or deallocated by
|
||||
** subsequent calls to other SQLite interface functions.)^
|
||||
**
|
||||
** ^The sqlite3_errstr() interface returns the English-language text
|
||||
** that describes the [result code], as UTF-8.
|
||||
** ^The sqlite3_errstr(E) interface returns the English-language text
|
||||
** that describes the [result code] E, as UTF-8, or NULL if E is not an
|
||||
** result code for which a text error message is available.
|
||||
** ^(Memory to hold the error message string is managed internally
|
||||
** and must not be freed by the application)^.
|
||||
**
|
||||
@@ -5573,13 +5575,27 @@ int sqlite3_create_window_function(
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
|
||||
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
|
||||
** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call
|
||||
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
|
||||
** Specifying this flag makes no difference for scalar or aggregate user
|
||||
** functions. However, if it is not specified for a user-defined window
|
||||
** function, then any sub-types belonging to arguments passed to the window
|
||||
** function may be discarded before the window function is called (i.e.
|
||||
** sqlite3_value_subtype() will always return 0).
|
||||
** This flag instructs SQLite to omit some corner-case optimizations that
|
||||
** might disrupt the operation of the [sqlite3_value_subtype()] function,
|
||||
** causing it to return zero rather than the correct subtype().
|
||||
** SQL functions that invokes [sqlite3_value_subtype()] should have this
|
||||
** property. If the SQLITE_SUBTYPE property is omitted, then the return
|
||||
** value from [sqlite3_value_subtype()] might sometimes be zero even though
|
||||
** a non-zero subtype was specified by the function argument expression.
|
||||
**
|
||||
** [[SQLITE_RESULT_SUBTYPE]] <dt>SQLITE_RESULT_SUBTYPE</dt><dd>
|
||||
** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call
|
||||
** [sqlite3_result_subtype()] to cause a sub-type to be associated with its
|
||||
** result.
|
||||
** Every function that invokes [sqlite3_result_subtype()] should have this
|
||||
** property. If it does not, then the call to [sqlite3_result_subtype()]
|
||||
** might become a no-op if the function is used as term in an
|
||||
** [expression index]. On the other hand, SQL functions that never invoke
|
||||
** [sqlite3_result_subtype()] should avoid setting this property, as the
|
||||
** purpose of this property is to disable certain optimizations that are
|
||||
** incompatible with subtypes.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
@@ -5587,6 +5603,7 @@ int sqlite3_create_window_function(
|
||||
#define SQLITE_DIRECTONLY 0x000080000
|
||||
#define SQLITE_SUBTYPE 0x000100000
|
||||
#define SQLITE_INNOCUOUS 0x000200000
|
||||
#define SQLITE_RESULT_SUBTYPE 0x001000000
|
||||
|
||||
/*
|
||||
** CAPI3REF: Deprecated Functions
|
||||
@@ -5783,6 +5800,12 @@ int sqlite3_value_encoding(sqlite3_value*);
|
||||
** information can be used to pass a limited amount of context from
|
||||
** one SQL function to another. Use the [sqlite3_result_subtype()]
|
||||
** routine to set the subtype for the return value of an SQL function.
|
||||
**
|
||||
** Every [application-defined SQL function] that invoke this interface
|
||||
** should include the [SQLITE_SUBTYPE] property in the text
|
||||
** encoding argument when the function is [sqlite3_create_function|registered].
|
||||
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
|
||||
** might return zero instead of the upstream subtype in some corner cases.
|
||||
*/
|
||||
unsigned int sqlite3_value_subtype(sqlite3_value*);
|
||||
|
||||
@@ -5913,14 +5936,22 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
||||
** <li> ^(when sqlite3_set_auxdata() is invoked again on the same
|
||||
** parameter)^, or
|
||||
** <li> ^(during the original sqlite3_set_auxdata() call when a memory
|
||||
** allocation error occurs.)^ </ul>
|
||||
** allocation error occurs.)^
|
||||
** <li> ^(during the original sqlite3_set_auxdata() call if the function
|
||||
** is evaluated during query planning instead of during query execution,
|
||||
** as sometimes happens with [SQLITE_ENABLE_STAT4].)^ </ul>
|
||||
**
|
||||
** Note the last bullet in particular. The destructor X in
|
||||
** Note the last two bullets in particular. The destructor X in
|
||||
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
|
||||
** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
|
||||
** should be called near the end of the function implementation and the
|
||||
** function implementation should not make any use of P after
|
||||
** sqlite3_set_auxdata() has been called.
|
||||
** sqlite3_set_auxdata() has been called. Furthermore, a call to
|
||||
** sqlite3_get_auxdata() that occurs immediately after a corresponding call
|
||||
** to sqlite3_set_auxdata() might still return NULL if an out-of-memory
|
||||
** condition occurred during the sqlite3_set_auxdata() call or if the
|
||||
** function is being evaluated during query planning rather than during
|
||||
** query execution.
|
||||
**
|
||||
** ^(In practice, auxiliary data is preserved between function calls for
|
||||
** function parameters that are compile-time constants, including literal
|
||||
@@ -6194,6 +6225,20 @@ int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
|
||||
** higher order bits are discarded.
|
||||
** The number of subtype bytes preserved by SQLite might increase
|
||||
** in future releases of SQLite.
|
||||
**
|
||||
** Every [application-defined SQL function] that invokes this interface
|
||||
** should include the [SQLITE_RESULT_SUBTYPE] property in its
|
||||
** text encoding argument when the SQL function is
|
||||
** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE]
|
||||
** property is omitted from the function that invokes sqlite3_result_subtype(),
|
||||
** then in some cases the sqlite3_result_subtype() might fail to set
|
||||
** the result subtype.
|
||||
**
|
||||
** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any
|
||||
** SQL function that invokes the sqlite3_result_subtype() interface
|
||||
** and that does not have the SQLITE_RESULT_SUBTYPE property will raise
|
||||
** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1
|
||||
** by default.
|
||||
*/
|
||||
void sqlite3_result_subtype(sqlite3_context*,unsigned int);
|
||||
|
||||
|
||||
+9
-6
@@ -2014,14 +2014,15 @@ struct FuncDestructor {
|
||||
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
|
||||
** single query - might change over time */
|
||||
#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
|
||||
/* 0x8000 -- available for reuse */
|
||||
#define SQLITE_FUNC_RUNONLY 0x8000 /* Cannot be used by valueFromFunction */
|
||||
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
|
||||
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
|
||||
#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
|
||||
#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
|
||||
/* SQLITE_SUBTYPE 0x00100000 // Consumer of subtypes */
|
||||
#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
|
||||
#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
|
||||
#define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */
|
||||
/* SQLITE_RESULT_SUBTYPE 0x01000000 // Generator of subtypes */
|
||||
#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */
|
||||
|
||||
/* Identifier numbers for each in-line function */
|
||||
@@ -2113,10 +2114,11 @@ struct FuncDestructor {
|
||||
#define MFUNCTION(zName, nArg, xPtr, xFunc) \
|
||||
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
|
||||
xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
|
||||
#define JFUNCTION(zName, nArg, iArg, xFunc) \
|
||||
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|\
|
||||
SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
|
||||
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
|
||||
#define JFUNCTION(zName, nArg, bUseCache, bWS, bRS, bJsonB, iArg, xFunc) \
|
||||
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\
|
||||
SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\
|
||||
((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \
|
||||
SQLITE_INT_TO_PTR(iArg|((bJsonB)*JSON_BLOB)),0,xFunc,0, 0, 0, #zName, {0} }
|
||||
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
|
||||
{nArg, SQLITE_FUNC_BUILTIN|\
|
||||
SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
|
||||
@@ -3397,6 +3399,7 @@ struct NameContext {
|
||||
int nRef; /* Number of names resolved by this context */
|
||||
int nNcErr; /* Number of errors encountered while resolving names */
|
||||
int ncFlags; /* Zero or more NC_* flags defined below */
|
||||
u32 nNestedSelect; /* Number of nested selects using this NC */
|
||||
Select *pWinSelect; /* SELECT statement for any window functions */
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -781,7 +781,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
assert( pExpr->x.pList->nExpr==2 );
|
||||
pY = pExpr->x.pList->a[0].pExpr;
|
||||
pZ = pExpr->x.pList->a[1].pExpr;
|
||||
sqlite3TreeViewLine(pView, "BETWEEN");
|
||||
sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs);
|
||||
sqlite3TreeViewExpr(pView, pX, 1);
|
||||
sqlite3TreeViewExpr(pView, pY, 1);
|
||||
sqlite3TreeViewExpr(pView, pZ, 0);
|
||||
|
||||
+10
-6
@@ -132,11 +132,12 @@ int sqlite3_found_count = 0;
|
||||
** sqlite3CantopenError(lineno)
|
||||
*/
|
||||
static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){
|
||||
static int n = 0;
|
||||
static u64 n = 0;
|
||||
(void)pc;
|
||||
(void)pOp;
|
||||
(void)v;
|
||||
n++;
|
||||
if( n==LARGEST_UINT64 ) abort(); /* So that n is used, preventing a warning */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2033,7 +2034,7 @@ case OP_AddImm: { /* in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
memAboutToChange(p, pIn1);
|
||||
sqlite3VdbeMemIntegerify(pIn1);
|
||||
pIn1->u.i += pOp->p2;
|
||||
*(u64*)&pIn1->u.i += (u64)pOp->p2;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -8179,24 +8180,23 @@ case OP_VCheck: { /* out2 */
|
||||
|
||||
pOut = &aMem[pOp->p2];
|
||||
sqlite3VdbeMemSetNull(pOut); /* Innocent until proven guilty */
|
||||
assert( pOp->p4type==P4_TABLE );
|
||||
assert( pOp->p4type==P4_TABLEREF );
|
||||
pTab = pOp->p4.pTab;
|
||||
assert( pTab!=0 );
|
||||
assert( pTab->nTabRef>0 );
|
||||
assert( IsVirtual(pTab) );
|
||||
assert( pTab->u.vtab.p!=0 );
|
||||
if( pTab->u.vtab.p==0 ) break;
|
||||
pVtab = pTab->u.vtab.p->pVtab;
|
||||
assert( pVtab!=0 );
|
||||
pModule = pVtab->pModule;
|
||||
assert( pModule!=0 );
|
||||
assert( pModule->iVersion>=4 );
|
||||
assert( pModule->xIntegrity!=0 );
|
||||
pTab->nTabRef++;
|
||||
sqlite3VtabLock(pTab->u.vtab.p);
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName,
|
||||
pOp->p3, &zErr);
|
||||
sqlite3VtabUnlock(pTab->u.vtab.p);
|
||||
sqlite3DeleteTable(db, pTab);
|
||||
if( rc ){
|
||||
sqlite3_free(zErr);
|
||||
goto abort_due_to_error;
|
||||
@@ -8321,6 +8321,7 @@ case OP_VColumn: { /* ncycle */
|
||||
const sqlite3_module *pModule;
|
||||
Mem *pDest;
|
||||
sqlite3_context sContext;
|
||||
FuncDef nullFunc;
|
||||
|
||||
VdbeCursor *pCur = p->apCsr[pOp->p1];
|
||||
assert( pCur!=0 );
|
||||
@@ -8338,6 +8339,9 @@ case OP_VColumn: { /* ncycle */
|
||||
memset(&sContext, 0, sizeof(sContext));
|
||||
sContext.pOut = pDest;
|
||||
sContext.enc = encoding;
|
||||
nullFunc.pUserData = 0;
|
||||
nullFunc.funcFlags = SQLITE_RESULT_SUBTYPE;
|
||||
sContext.pFunc = &nullFunc;
|
||||
assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
|
||||
if( pOp->p5 & OPFLAG_NOCHNG ){
|
||||
sqlite3VdbeMemSetNull(pDest);
|
||||
|
||||
@@ -126,6 +126,7 @@ typedef struct VdbeOpList VdbeOpList;
|
||||
#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
|
||||
#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
|
||||
#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */
|
||||
#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */
|
||||
|
||||
/* Error message codes for OP_Halt */
|
||||
#define P5_ConstraintNotNull 1
|
||||
|
||||
+22
-3
@@ -152,7 +152,15 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
|
||||
int rc = SQLITE_OK;
|
||||
Vdbe *p = (Vdbe*)pStmt;
|
||||
#if SQLITE_THREADSAFE
|
||||
sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
|
||||
sqlite3_mutex *mutex;
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pStmt==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
#if SQLITE_THREADSAFE
|
||||
mutex = p->db->mutex;
|
||||
#endif
|
||||
sqlite3_mutex_enter(mutex);
|
||||
for(i=0; i<p->nVar; i++){
|
||||
@@ -531,6 +539,18 @@ void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCtx==0 ) return;
|
||||
#endif
|
||||
#if defined(SQLITE_STRICT_SUBTYPE) && SQLITE_STRICT_SUBTYPE+0!=0
|
||||
if( pCtx->pFunc!=0
|
||||
&& (pCtx->pFunc->funcFlags & SQLITE_RESULT_SUBTYPE)==0
|
||||
){
|
||||
char zErr[200];
|
||||
sqlite3_snprintf(sizeof(zErr), zErr,
|
||||
"misuse of sqlite3_result_subtype() by %s()",
|
||||
pCtx->pFunc->zName);
|
||||
sqlite3_result_error(pCtx, zErr, -1);
|
||||
return;
|
||||
}
|
||||
#endif /* SQLITE_STRICT_SUBTYPE */
|
||||
pOut = pCtx->pOut;
|
||||
assert( sqlite3_mutex_held(pOut->db->mutex) );
|
||||
pOut->eSubtype = eSubtype & 0xff;
|
||||
@@ -930,9 +950,8 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
void *sqlite3_user_data(sqlite3_context *p){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( p==0 ) return 0;
|
||||
#else
|
||||
assert( p && p->pFunc );
|
||||
#endif
|
||||
assert( p && p->pFunc );
|
||||
return p->pFunc->pUserData;
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -211,10 +211,11 @@ static int growOpArray(Vdbe *v, int nOp){
|
||||
** sqlite3CantopenError(lineno)
|
||||
*/
|
||||
static void test_addop_breakpoint(int pc, Op *pOp){
|
||||
static int n = 0;
|
||||
static u64 n = 0;
|
||||
(void)pc;
|
||||
(void)pOp;
|
||||
n++;
|
||||
if( n==LARGEST_UINT64 ) abort(); /* so that n is used, preventing a warning */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1399,6 +1400,10 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
|
||||
if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
|
||||
break;
|
||||
}
|
||||
case P4_TABLEREF: {
|
||||
if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1526,7 +1531,7 @@ static void SQLITE_NOINLINE vdbeChangeP4Full(
|
||||
int n
|
||||
){
|
||||
if( pOp->p4type ){
|
||||
freeP4(p->db, pOp->p4type, pOp->p4.p);
|
||||
assert( pOp->p4type > P4_FREE_IF_LE );
|
||||
pOp->p4type = 0;
|
||||
pOp->p4.p = 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1515,7 +1515,7 @@ static int valueFromFunction(
|
||||
#endif
|
||||
assert( pFunc );
|
||||
if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
|
||||
|| (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
|
||||
|| (pFunc->funcFlags & (SQLITE_FUNC_NEEDCOLL|SQLITE_FUNC_RUNONLY))!=0
|
||||
){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -2004,6 +2004,19 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
|
||||
|
||||
/*
|
||||
** Attempt to enable blocking locks that block for nMs ms. Return 1 if
|
||||
** blocking locks are successfully enabled, or 0 otherwise.
|
||||
*/
|
||||
static int walEnableBlockingMs(Wal *pWal, int nMs){
|
||||
int rc = sqlite3OsFileControl(
|
||||
pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&nMs
|
||||
);
|
||||
return (rc==SQLITE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to enable blocking locks. Blocking locks are enabled only if (a)
|
||||
** they are supported by the VFS, and (b) the database handle is configured
|
||||
@@ -2015,11 +2028,7 @@ static int walEnableBlocking(Wal *pWal){
|
||||
if( pWal->db ){
|
||||
int tmout = pWal->db->busyTimeout;
|
||||
if( tmout ){
|
||||
int rc;
|
||||
rc = sqlite3OsFileControl(
|
||||
pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout
|
||||
);
|
||||
res = (rc==SQLITE_OK);
|
||||
res = walEnableBlockingMs(pWal, tmout);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@@ -2068,20 +2077,10 @@ void sqlite3WalDb(Wal *pWal, sqlite3 *db){
|
||||
pWal->db = db;
|
||||
}
|
||||
|
||||
/*
|
||||
** Take an exclusive WRITE lock. Blocking if so configured.
|
||||
*/
|
||||
static int walLockWriter(Wal *pWal){
|
||||
int rc;
|
||||
walEnableBlocking(pWal);
|
||||
rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
||||
walDisableBlocking(pWal);
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
# define walEnableBlocking(x) 0
|
||||
# define walDisableBlocking(x)
|
||||
# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1)
|
||||
# define walEnableBlockingMs(pWal, ms) 0
|
||||
# define sqlite3WalDb(pWal, db)
|
||||
#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */
|
||||
|
||||
@@ -2682,7 +2681,9 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
|
||||
}
|
||||
}else{
|
||||
int bWriteLock = pWal->writeLock;
|
||||
if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
|
||||
if( bWriteLock
|
||||
|| SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1))
|
||||
){
|
||||
pWal->writeLock = 1;
|
||||
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
|
||||
badHdr = walIndexTryHdr(pWal, pChanged);
|
||||
@@ -2690,7 +2691,8 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
|
||||
/* If the wal-index header is still malformed even while holding
|
||||
** a WRITE lock, it can only mean that the header is corrupted and
|
||||
** needs to be reconstructed. So run recovery to do exactly that.
|
||||
*/
|
||||
** Disable blocking locks first. */
|
||||
walDisableBlocking(pWal);
|
||||
rc = walIndexRecover(pWal);
|
||||
*pChanged = 1;
|
||||
}
|
||||
@@ -2957,6 +2959,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
int i; /* Loop counter */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
u32 mxFrame; /* Wal frame to lock to */
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
int nBlockTmout = 0;
|
||||
#endif
|
||||
|
||||
assert( pWal->readLock<0 ); /* Not currently locked */
|
||||
|
||||
@@ -2987,6 +2992,19 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
return SQLITE_PROTOCOL;
|
||||
}
|
||||
if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39;
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
/* In SQLITE_ENABLE_SETLK_TIMEOUT builds, configure the file-descriptor
|
||||
** to block for locks for approximately nDelay us. This affects three
|
||||
** locks: (a) the shared lock taken on the DMS slot in os_unix.c (if
|
||||
** using os_unix.c), (b) the WRITER lock taken in walIndexReadHdr() if the
|
||||
** first attempted read fails, and (c) the shared lock taken on the DMS
|
||||
** slot in os_unix.c. All three of these locks are attempted from within
|
||||
** the call to walIndexReadHdr() below. */
|
||||
nBlockTmout = (nDelay+998) / 1000;
|
||||
if( !useWal && walEnableBlockingMs(pWal, nBlockTmout) ){
|
||||
nDelay = 1;
|
||||
}
|
||||
#endif
|
||||
sqlite3OsSleep(pWal->pVfs, nDelay);
|
||||
}
|
||||
|
||||
@@ -2995,6 +3013,10 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
if( pWal->bShmUnreliable==0 ){
|
||||
rc = walIndexReadHdr(pWal, pChanged);
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
walDisableBlocking(pWal);
|
||||
if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
|
||||
#endif
|
||||
if( rc==SQLITE_BUSY ){
|
||||
/* If there is not a recovery running in another thread or process
|
||||
** then convert BUSY errors to WAL_RETRY. If recovery is known to
|
||||
@@ -3109,9 +3131,12 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
|
||||
}
|
||||
|
||||
(void)walEnableBlockingMs(pWal, nBlockTmout);
|
||||
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
|
||||
walDisableBlocking(pWal);
|
||||
if( rc ){
|
||||
return rc==SQLITE_BUSY ? WAL_RETRY : rc;
|
||||
assert( (rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT );
|
||||
return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
|
||||
}
|
||||
/* Now that the read-lock has been obtained, check that neither the
|
||||
** value in the aReadMark[] array or the contents of the wal-index
|
||||
@@ -4204,10 +4229,9 @@ int sqlite3WalCheckpoint(
|
||||
if( pWal->readOnly ) return SQLITE_READONLY;
|
||||
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
|
||||
|
||||
/* Enable blocking locks, if possible. If blocking locks are successfully
|
||||
** enabled, set xBusy2=0 so that the busy-handler is never invoked. */
|
||||
/* Enable blocking locks, if possible. */
|
||||
sqlite3WalDb(pWal, db);
|
||||
(void)walEnableBlocking(pWal);
|
||||
if( xBusy2 ) (void)walEnableBlocking(pWal);
|
||||
|
||||
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
|
||||
** "checkpoint" lock on the database file.
|
||||
@@ -4248,9 +4272,14 @@ int sqlite3WalCheckpoint(
|
||||
/* Read the wal-index header. */
|
||||
SEH_TRY {
|
||||
if( rc==SQLITE_OK ){
|
||||
/* For a passive checkpoint, do not re-enable blocking locks after
|
||||
** reading the wal-index header. A passive checkpoint should not block
|
||||
** or invoke the busy handler. The only lock such a checkpoint may
|
||||
** attempt to obtain is a lock on a read-slot, and it should give up
|
||||
** immediately and do a partial checkpoint if it cannot obtain it. */
|
||||
walDisableBlocking(pWal);
|
||||
rc = walIndexReadHdr(pWal, &isChanged);
|
||||
(void)walEnableBlocking(pWal);
|
||||
if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal);
|
||||
if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
|
||||
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
|
||||
}
|
||||
|
||||
+24
@@ -678,12 +678,22 @@ static void translateColumnToCopy(
|
||||
for(; iStart<iEnd; iStart++, pOp++){
|
||||
if( pOp->p1!=iTabCur ) continue;
|
||||
if( pOp->opcode==OP_Column ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
printf("TRANSLATE OP_Column to OP_Copy at %d\n", iStart);
|
||||
}
|
||||
#endif
|
||||
pOp->opcode = OP_Copy;
|
||||
pOp->p1 = pOp->p2 + iRegister;
|
||||
pOp->p2 = pOp->p3;
|
||||
pOp->p3 = 0;
|
||||
pOp->p5 = 2; /* Cause the MEM_Subtype flag to be cleared */
|
||||
}else if( pOp->opcode==OP_Rowid ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
printf("TRANSLATE OP_Rowid to OP_Sequence at %d\n", iStart);
|
||||
}
|
||||
#endif
|
||||
pOp->opcode = OP_Sequence;
|
||||
pOp->p1 = iAutoidxCur;
|
||||
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
@@ -5810,6 +5820,20 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
|
||||
continue;
|
||||
}
|
||||
if( sqlite3ExprIsConstant(pExpr) ) continue;
|
||||
if( pExpr->op==TK_FUNCTION ){
|
||||
/* Functions that might set a subtype should not be replaced by the
|
||||
** value taken from an expression index since the index omits the
|
||||
** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */
|
||||
int n;
|
||||
FuncDef *pDef;
|
||||
sqlite3 *db = pParse->db;
|
||||
assert( ExprUseXList(pExpr) );
|
||||
n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
|
||||
if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
|
||||
if( p==0 ) break;
|
||||
p->pIENext = pParse->pIdxEpr;
|
||||
|
||||
+1
-1
@@ -1038,7 +1038,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
assert( pWin->pWFunc!=0 );
|
||||
pArgs = pWin->pOwner->x.pList;
|
||||
if( pWin->pWFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
|
||||
if( pWin->pWFunc->funcFlags & SQLITE_SUBTYPE ){
|
||||
selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
|
||||
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
|
||||
pWin->bExprArgs = 1;
|
||||
|
||||
@@ -358,7 +358,119 @@ do_execsql_test 6.2.2 {
|
||||
FROM t2 GROUP BY 'constant_string';
|
||||
} {{}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 7.0 {
|
||||
CREATE TABLE invoice (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
amount DOUBLE PRECISION DEFAULT NULL,
|
||||
name VARCHAR(100) DEFAULT NULL
|
||||
);
|
||||
|
||||
INSERT INTO invoice (amount, name) VALUES
|
||||
(4.0, 'Michael'), (15.0, 'Bara'), (4.0, 'Michael'), (6.0, 'John');
|
||||
}
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
SELECT sum(amount), name
|
||||
from invoice
|
||||
group by name
|
||||
having (select v > 6 from (select sum(amount) v) t)
|
||||
} {
|
||||
15.0 Bara
|
||||
8.0 Michael
|
||||
}
|
||||
|
||||
do_execsql_test 7.2 {
|
||||
SELECT (select 1 from (select sum(amount))) FROM invoice
|
||||
} {1}
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
CREATE TABLE t1(x INT);
|
||||
INSERT INTO t1 VALUES(100);
|
||||
INSERT INTO t1 VALUES(20);
|
||||
INSERT INTO t1 VALUES(3);
|
||||
SELECT (SELECT y FROM (SELECT sum(x) AS y) AS t2 ) FROM t1;
|
||||
} {123}
|
||||
|
||||
do_execsql_test 8.1 {
|
||||
SELECT (
|
||||
SELECT y FROM (
|
||||
SELECT z AS y FROM (SELECT sum(x) AS z) AS t2
|
||||
)
|
||||
) FROM t1;
|
||||
} {123}
|
||||
|
||||
do_execsql_test 8.2 {
|
||||
SELECT (
|
||||
SELECT a FROM (
|
||||
SELECT y AS a FROM (
|
||||
SELECT z AS y FROM (SELECT sum(x) AS z) AS t2
|
||||
)
|
||||
)
|
||||
) FROM t1;
|
||||
} {123}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# dbsqlfuzz 04408efc51ae46897c4c122b407412045ed221b4
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_execsql_test 9.1 {
|
||||
WITH out(i, j, k) AS (
|
||||
VALUES(1234, 5678, 9012)
|
||||
)
|
||||
SELECT (
|
||||
SELECT (
|
||||
SELECT min(abc) = ( SELECT ( SELECT 1234 fROM (SELECT abc) ) )
|
||||
FROM (
|
||||
SELECT sum( out.i ) + ( SELECT sum( out.i ) ) AS abc FROM (SELECT out.j)
|
||||
)
|
||||
)
|
||||
) FROM out;
|
||||
} {0}
|
||||
|
||||
do_execsql_test 9.2 {
|
||||
CREATE TABLE t1(a);
|
||||
CREATE TABLE t2(b);
|
||||
INSERT INTO t1 VALUES(1), (2), (3);
|
||||
INSERT INTO t2 VALUES(4), (5), (6);
|
||||
|
||||
SELECT (
|
||||
SELECT min(y) + (SELECT x) FROM (
|
||||
SELECT sum(a) AS x, b AS y FROM t2
|
||||
)
|
||||
)
|
||||
FROM t1;
|
||||
} {10}
|
||||
|
||||
do_execsql_test 9.3 {
|
||||
SELECT (
|
||||
SELECT min(y) + (SELECT (SELECT x)) FROM (
|
||||
SELECT sum(a) AS x, b AS y FROM t2
|
||||
)
|
||||
)
|
||||
FROM t1;
|
||||
} {10}
|
||||
|
||||
do_execsql_test 9.4 {
|
||||
SELECT (
|
||||
SELECT (SELECT x) FROM (
|
||||
SELECT sum(a) AS x, b AS y FROM t2
|
||||
) GROUP BY y
|
||||
)
|
||||
FROM t1;
|
||||
} {6}
|
||||
|
||||
do_execsql_test 9.5 {
|
||||
SELECT (
|
||||
SELECT (SELECT (SELECT x)) FROM (
|
||||
SELECT sum(a) AS x, b AS y FROM t2
|
||||
) GROUP BY y
|
||||
)
|
||||
FROM t1;
|
||||
} {6}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -954,4 +954,33 @@ do_catchsql_test alter-20.3 {
|
||||
INSERT INTO t1(a) VALUES(45);
|
||||
} {1 {cannot store BLOB value in TEXT column t1.b}}
|
||||
|
||||
# 2023-11-17 dbsqlfuzz e0900262dadd5c78c2226ad6a435c7f0255be2cd
|
||||
# Assertion fault associated with ALTER TABLE and an
|
||||
# aggregate ORDER BY within an unknown aggregate function.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test alter-21.1 {
|
||||
CREATE TABLE t1(a,b,c,d);
|
||||
CREATE TABLE t2(a,b,c,d,x);
|
||||
CREATE TRIGGER r1 AFTER INSERT ON t2 BEGIN
|
||||
SELECT unknown_function(a ORDER BY (SELECT group_concat(DISTINCT a ORDER BY a) FROM t1)) FROM t1;
|
||||
END;
|
||||
ALTER TABLE t2 RENAME TO e;
|
||||
} {}
|
||||
do_execsql_test alter-21.2 {
|
||||
SELECT name, type FROM sqlite_schema ORDER BY name;
|
||||
} {e table r1 trigger t1 table}
|
||||
do_execsql_test alter-21.3 {
|
||||
DROP TRIGGER r1;
|
||||
CREATE TRIGGER r2 AFTER INSERT ON e BEGIN
|
||||
SELECT unknown_function(a ORDER BY (SELECT group_concat(a ORDER BY a) FROM (SELECT b FROM t1))) FROM t1;
|
||||
END;
|
||||
ALTER TABLE e RENAME TO t99;
|
||||
}
|
||||
do_execsql_test alter-21.4 {
|
||||
SELECT name, type FROM sqlite_schema ORDER BY name;
|
||||
} {r2 trigger t1 table t99 table}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -146,6 +146,8 @@ datetest 2.49 {datetime('2003-10-22 12:24','0000 second')} {2003-10-22 12:24:00}
|
||||
datetest 2.50 {datetime('2003-10-22 12:24','0001 second')} {2003-10-22 12:24:01}
|
||||
datetest 2.51 {datetime('2003-10-22 12:24','nonsense')} NULL
|
||||
|
||||
datetest 2.60 {datetime('2023-02-31')} {2023-03-03 00:00:00}
|
||||
|
||||
datetest 3.1 {strftime('%d','2003-10-31 12:34:56.432')} 31
|
||||
datetest 3.2.1 {strftime('pre%fpost','2003-10-31 12:34:56.432')} pre56.432post
|
||||
datetest 3.2.2 {strftime('%f','2003-10-31 12:34:59.9999999')} 59.999
|
||||
@@ -452,6 +454,9 @@ datetest 13.31 {date('2001-01-01','+1.5 years')} {2002-07-02}
|
||||
datetest 13.32 {date('2002-01-01','+1.5 years')} {2003-07-02}
|
||||
datetest 13.33 {date('2002-01-01','-1.5 years')} {2000-07-02}
|
||||
datetest 13.34 {date('2001-01-01','-1.5 years')} {1999-07-02}
|
||||
datetest 13.35 {date('2023-02-28')} {2023-02-28}
|
||||
datetest 13.36 {date('2023-02-29')} {2023-03-01}
|
||||
datetest 13.37 {date('2023-04-31')} {2023-05-01}
|
||||
|
||||
# Test for issues reported by BareFeet (list.sql at tandb.com.au)
|
||||
# on mailing list on 2008-06-12.
|
||||
|
||||
@@ -616,4 +616,18 @@ do_execsql_test indexexpr1-2200 {
|
||||
) v ON v.type = 0 AND v.tag = u.tag;
|
||||
} {7 100 8 101}
|
||||
|
||||
# 2023-11-08 Forum post https://sqlite.org/forum/forumpost/68d284c86b082c3e
|
||||
#
|
||||
# Functions that return subtypes and that are indexed cannot be used to
|
||||
# cover function calls from the main table, since the indexed value does
|
||||
# not know the subtype.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test indexexpr1-2300 {
|
||||
CREATE TABLE t1(x INT, y TEXT);
|
||||
INSERT INTO t1(x,y) VALUES(1,'{b:5}');
|
||||
CREATE INDEX t1j ON t1(json(y));
|
||||
SELECT json_insert('{}', '$.a', json(y)) FROM t1;
|
||||
} {{{"a":{"b":5}}}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -250,5 +250,63 @@ do_catchsql_test 9.11 {
|
||||
SELECT oid FROM wo2 JOIN (wo3 JOIN x3)
|
||||
} {0 99}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 10.0 {
|
||||
CREATE TABLE rt0 (c0 INTEGER, c1 INTEGER, c2 INTEGER, c3 INTEGER, c4 INTEGER);
|
||||
CREATE TABLE rt3 (c3 INTEGER);
|
||||
|
||||
INSERT INTO rt0(c3, c1) VALUES (x'', '1');
|
||||
INSERT INTO rt0(c3, c1) VALUES ('-1', -1e500);
|
||||
INSERT INTO rt0(c3, c1) VALUES (1, x'');
|
||||
|
||||
CREATE VIEW v6(c0, c1, c2) AS SELECT 0, 0, 0;
|
||||
}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
SELECT COUNT(*) FROM rt0 LEFT JOIN rt3 JOIN v6 ON ((CASE v6.c0 WHEN rt0.c4 THEN rt3.c3 END) NOT BETWEEN (rt0.c4) AND (NULL)) WHERE (rt0.c1); -- 2
|
||||
} {0}
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
SELECT COUNT(*) FROM rt0 LEFT JOIN rt3 RIGHT OUTER JOIN v6 ON ((CASE v6.c0 WHEN rt0.c4 THEN rt3.c3 END) NOT BETWEEN (rt0.c4) AND (NULL)) WHERE (rt0.c1); -- 2
|
||||
} {0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
do_execsql_test 11.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(c, d);
|
||||
CREATE TABLE t3(e, f);
|
||||
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
INSERT INTO t2 VALUES(2, 2);
|
||||
INSERT INTO t3 VALUES(3, 3);
|
||||
}
|
||||
|
||||
do_execsql_test 11.2 {
|
||||
SELECT * FROM t1 LEFT JOIN t2 RIGHT JOIN t3 ON (t2.c=10)
|
||||
} {{} {} {} {} 3 3}
|
||||
|
||||
do_execsql_test 11.3 {
|
||||
SELECT * FROM t1 LEFT JOIN t2 RIGHT JOIN t3 ON (t2.c=10) WHERE t1.a=1
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 12.1 {
|
||||
CREATE TABLE t1(a1 INT, b1 TEXT);
|
||||
INSERT INTO t1 VALUES(88,'');
|
||||
CREATE TABLE t2(c2 INT, d2 TEXT);
|
||||
INSERT INTO t2 VALUES(88,'');
|
||||
CREATE TABLE t3(e3 TEXT PRIMARY KEY);
|
||||
INSERT INTO t3 VALUES('');
|
||||
}
|
||||
|
||||
do_execsql_test 12.2 {
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1;
|
||||
}
|
||||
do_execsql_test 12.3 {
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
.mode qbox
|
||||
.timer on
|
||||
.param set $label '$.q87'
|
||||
SELECT rowid, x->>$label FROM data1 WHERE x->>$label IS NOT NULL;
|
||||
|
||||
CREATE TEMP TABLE t2(x JSON TEXT);
|
||||
WITH RECURSIVE
|
||||
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<25000),
|
||||
array1(y) AS (
|
||||
SELECT json_group_array(
|
||||
json_object('x',x,'y',random(),'z',hex(randomblob(50)))
|
||||
)
|
||||
FROM c
|
||||
),
|
||||
c2(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c2 WHERE n<5)
|
||||
INSERT INTO t2(x)
|
||||
SELECT jsonb(json_object('a',n,'b',n*2,'c',y,'d',3,'e',5,'f',6))
|
||||
FROM array1, c2;
|
||||
CREATE INDEX t2x1 ON t2(x->>'a');
|
||||
CREATE INDEX t2x2 ON t2(x->>'b');
|
||||
CREATE INDEX t2x3 ON t2(x->>'e');
|
||||
CREATE INDEX t2x4 ON t2(x->>'f');
|
||||
UPDATE t2 SET x=jsonb_replace(x,'$.f',(x->>'f')+1);
|
||||
UPDATE t2 SET x=jsonb_set(x,'$.e',(x->>'f')-1);
|
||||
UPDATE t2 SET x=jsonb_remove(x,'$.d');
|
||||
@@ -40,6 +40,7 @@ doCachegrind=1
|
||||
doVdbeProfile=0
|
||||
doWal=1
|
||||
doDiff=1
|
||||
doJsonB=0
|
||||
while test "$1" != ""; do
|
||||
case $1 in
|
||||
--nodiff)
|
||||
@@ -54,6 +55,9 @@ while test "$1" != ""; do
|
||||
--gcc7)
|
||||
CC=gcc-7
|
||||
;;
|
||||
--jsonb)
|
||||
doJsonB=1
|
||||
;;
|
||||
-*)
|
||||
CC_OPTS="$CC_OPTS $1"
|
||||
;;
|
||||
@@ -69,12 +73,18 @@ rm -f cachegrind.out.* jsonshell
|
||||
$CC -g -Os -Wall -I. $CC_OPTS ./shell.c ./sqlite3.c -o jsonshell -ldl -lpthread
|
||||
ls -l jsonshell | tee -a summary-$NAME.txt
|
||||
home=`echo $0 | sed -e 's,/[^/]*$,,'`
|
||||
echo ./jsonshell json100mb.db "<$home/json-q1.txt"
|
||||
valgrind --tool=cachegrind ./jsonshell json100mb.db <$home/json-q1.txt \
|
||||
2>&1 | tee -a summary-$NAME.txt
|
||||
if test $doJsonB -eq 1; then
|
||||
echo ./jsonshell json100mb_b.db "<$home/json-q1-b.txt"
|
||||
valgrind --tool=cachegrind ./jsonshell json100mb_b.db <$home/json-q1-b.txt \
|
||||
2>&1 | tee -a summary-$NAME.txt
|
||||
else
|
||||
echo ./jsonshell json100mb.db "<$home/json-q1.txt"
|
||||
valgrind --tool=cachegrind ./jsonshell json100mb.db <$home/json-q1.txt \
|
||||
2>&1 | tee -a summary-$NAME.txt
|
||||
fi
|
||||
cg_anno.tcl cachegrind.out.* >jout-$NAME.txt
|
||||
echo '*****************************************************' >>jout-$NAME.txt
|
||||
sed 's/^[0-9=-]\{9\}/==00000==/' summary-$NAME.txt >>jout-$NAME.txt
|
||||
if test "$NAME" != "$BASELINE"; then
|
||||
if test "$NAME" != "$BASELINE" -a $doDiff -ne 0; then
|
||||
fossil xdiff --tk -c 20 jout-$BASELINE.txt jout-$NAME.txt
|
||||
fi
|
||||
|
||||
+119
-11
@@ -36,6 +36,9 @@ do_execsql_test json101-1.2 {
|
||||
do_catchsql_test json101-1.3 {
|
||||
SELECT json_array(1,printf('%.1000c','x'),x'abcd',3);
|
||||
} {1 {JSON cannot hold BLOB values}}
|
||||
do_catchsql_test json101-1.3b {
|
||||
SELECT jsonb_array(1,printf('%.1000c','x'),x'abcd',3);
|
||||
} {1 {JSON cannot hold BLOB values}}
|
||||
do_execsql_test json101-1.4 {
|
||||
SELECT json_array(-9223372036854775808,9223372036854775807,0,1,-1,
|
||||
0.0, 1.0, -1.0, -1e99, +2e100,
|
||||
@@ -47,36 +50,83 @@ do_execsql_test json101-1.4 {
|
||||
'abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
99);
|
||||
} {[-9223372036854775808,9223372036854775807,0,1,-1,0.0,1.0,-1.0,-1.0e+99,2.0e+100,"one","two","three",4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,null,21,22,23,24,25,26,27,28,29,30,31,"abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ",99]}
|
||||
do_execsql_test json101-1.4b {
|
||||
SELECT json(jsonb_array(-9223372036854775808,9223372036854775807,0,1,-1,
|
||||
0.0, 1.0, -1.0, -1e99, +2e100,
|
||||
'one','two','three',
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
||||
19, NULL, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
'abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
99));
|
||||
} {[-9223372036854775808,9223372036854775807,0,1,-1,0.0,1.0,-1.0,-1.0e+99,2.0e+100,"one","two","three",4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,null,21,22,23,24,25,26,27,28,29,30,31,"abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ",99]}
|
||||
|
||||
do_execsql_test json101-2.1 {
|
||||
SELECT json_object('a',1,'b',2.5,'c',null,'d','String Test');
|
||||
} {{{"a":1,"b":2.5,"c":null,"d":"String Test"}}}
|
||||
do_execsql_test json101-2.1b {
|
||||
SELECT json(jsonb_object('a',1,'b',2.5,'c',null,'d','String Test'));
|
||||
} {{{"a":1,"b":2.5,"c":null,"d":"String Test"}}}
|
||||
do_catchsql_test json101-2.2 {
|
||||
SELECT json_object('a',printf('%.1000c','x'),2,2.5);
|
||||
} {1 {json_object() labels must be TEXT}}
|
||||
do_catchsql_test json101-2.2b {
|
||||
SELECT jsonb_object('a',printf('%.1000c','x'),2,2.5);
|
||||
} {1 {json_object() labels must be TEXT}}
|
||||
do_execsql_test json101-2.2.2 {
|
||||
SELECT json_object('a',json_array('xyx',77,4.5),'x',2.5);
|
||||
} {{{"a":["xyx",77,4.5],"x":2.5}}}
|
||||
do_execsql_test json101-2.2.2b {
|
||||
SELECT json(jsonb_object('a',json_array('xyx',77,4.5),'x',2.5));
|
||||
} {{{"a":["xyx",77,4.5],"x":2.5}}}
|
||||
do_execsql_test json101-2.2.3 {
|
||||
SELECT json_object('a',jsonb_array('xyx',77,4.5),'x',2.5);
|
||||
} {{{"a":["xyx",77,4.5],"x":2.5}}}
|
||||
do_execsql_test json101-2.2.3b {
|
||||
SELECT json(jsonb_object('a',jsonb_array('xyx',77,4.5),'x',2.5));
|
||||
} {{{"a":["xyx",77,4.5],"x":2.5}}}
|
||||
do_catchsql_test json101-2.3 {
|
||||
SELECT json_object('a',1,'b');
|
||||
} {1 {json_object() requires an even number of arguments}}
|
||||
do_catchsql_test json101-2.4 {
|
||||
SELECT json_object('a',printf('%.1000c','x'),'b',x'abcd');
|
||||
} {1 {JSON cannot hold BLOB values}}
|
||||
do_execsql_test json101-2.5 {
|
||||
SELECT json_object('a',printf('%.10c','x'),'b',jsonb_array(1,2,3));
|
||||
} {{{"a":"xxxxxxxxxx","b":[1,2,3]}}}
|
||||
|
||||
do_execsql_test json101-3.1 {
|
||||
SELECT json_replace('{"a":1,"b":2}','$.a','[3,4,5]');
|
||||
} {{{"a":"[3,4,5]","b":2}}}
|
||||
do_execsql_test json101-3.1b {
|
||||
SELECT json(jsonb_replace('{"a":1,"b":2}','$.a','[3,4,5]'));
|
||||
} {{{"a":"[3,4,5]","b":2}}}
|
||||
do_execsql_test json101-3.2 {
|
||||
SELECT json_replace('{"a":1,"b":2}','$.a',json('[3,4,5]'));
|
||||
} {{{"a":[3,4,5],"b":2}}}
|
||||
do_execsql_test json101-3.2b {
|
||||
SELECT json_replace('{"a":1,"b":2}','$.a',jsonb('[3,4,5]'));
|
||||
} {{{"a":[3,4,5],"b":2}}}
|
||||
do_execsql_test json101-3.3 {
|
||||
SELECT json_type(json_set('{"a":1,"b":2}','$.b','{"x":3,"y":4}'),'$.b');
|
||||
} {text}
|
||||
do_execsql_test json101-3.3b {
|
||||
SELECT json_type(jsonb_set('{"a":1,"b":2}','$.b','{"x":3,"y":4}'),'$.b');
|
||||
} {text}
|
||||
do_execsql_test json101-3.4 {
|
||||
SELECT json_type(json_set('{"a":1,"b":2}','$.b',json('{"x":3,"y":4}')),'$.b');
|
||||
} {object}
|
||||
do_execsql_test json101-3.4b {
|
||||
SELECT json_type(jsonb_set('{"a":1,"b":2}','$.b',jsonb('{"x":3,"y":4}')),'$.b');
|
||||
} {object}
|
||||
ifcapable vtab {
|
||||
do_execsql_test json101-3.5 {
|
||||
SELECT fullkey, atom, '|' FROM json_tree(json_set('{}','$.x',123,'$.x',456));
|
||||
} {{$} {} | {$.x} 456 |}
|
||||
do_execsql_test json101-3.5 {
|
||||
SELECT fullkey, atom, '|' FROM json_tree(json_set('{}','$.x',123,'$.x',456));
|
||||
} {{$} {} | {$.x} 456 |}
|
||||
do_execsql_test json101-3.5b {
|
||||
SELECT fullkey, atom, '|' FROM json_tree(jsonb_set('{}','$.x',123,'$.x',456));
|
||||
} {{$} {} | {$.x} 456 |}
|
||||
}
|
||||
|
||||
# Per rfc7159, any JSON value is allowed at the top level, and whitespace
|
||||
@@ -131,6 +181,13 @@ do_execsql_test json101-4.10 {
|
||||
WHERE json_extract(x,'$')<>x
|
||||
AND json_type(x) IN ('object','array');
|
||||
} {4}
|
||||
do_execsql_test json101-4.10b {
|
||||
CREATE TABLE j1b AS SELECT jsonb(x) AS "x" FROM j1;
|
||||
SELECT count(*) FROM j1b WHERE json_type(x) IN ('object','array');
|
||||
SELECT json(x) FROM j1b
|
||||
WHERE json_extract(x,'$')<>json(x)
|
||||
AND json_type(x) IN ('object','array');
|
||||
} {4}
|
||||
|
||||
do_execsql_test json101-5.1 {
|
||||
CREATE TABLE j2(id INTEGER PRIMARY KEY, json, src);
|
||||
@@ -258,11 +315,17 @@ do_execsql_test json101-5.1 {
|
||||
}
|
||||
]','https://adobe.github.io/Spry/samples/data_region/JSONDataSetSample.html');
|
||||
SELECT count(*) FROM j2;
|
||||
} {3}
|
||||
CREATE TABLE j2b(id INTEGER PRIMARY KEY, json, src);
|
||||
INSERT INTO J2b(id,json,src) SELECT id, jsonb(json), src FROM j2;
|
||||
SELECT count(*) FROM j2b;
|
||||
} {3 3}
|
||||
|
||||
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 |}
|
||||
do_execsql_test json101-5.2b {
|
||||
SELECT id, json_valid(json,5), json_type(json), '|' FROM j2b ORDER BY id;
|
||||
} {1 1 object | 2 1 object | 3 1 array |}
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
@@ -277,6 +340,12 @@ do_execsql_test json101-5.3 {
|
||||
WHERE fullkey!=(path || CASE WHEN typeof(key)=='integer' THEN '['||key||']'
|
||||
ELSE '.'||key END);
|
||||
} {}
|
||||
do_execsql_test json101-5.3b {
|
||||
SELECT j2b.rowid, jx.rowid, fullkey, path, key
|
||||
FROM j2b, json_tree(j2b.json) AS jx
|
||||
WHERE fullkey!=(path || CASE WHEN typeof(key)=='integer' THEN '['||key||']'
|
||||
ELSE '.'||key END);
|
||||
} {}
|
||||
do_execsql_test json101-5.4 {
|
||||
SELECT j2.rowid, jx.rowid, fullkey, path, key
|
||||
FROM j2, json_each(j2.json) AS jx
|
||||
@@ -371,6 +440,13 @@ do_execsql_test json101-8.1 {
|
||||
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 json101-8.1b {
|
||||
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=jsonb_array(a);
|
||||
SELECT json(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 json101-8.2 {
|
||||
SELECT a=json_extract(b,'$[0]') FROM t8;
|
||||
} {1}
|
||||
@@ -401,7 +477,7 @@ do_execsql_test json101-9.4 {
|
||||
SELECT json_quote(null);
|
||||
} {"null"}
|
||||
do_catchsql_test json101-9.5 {
|
||||
SELECT json_quote(x'30313233');
|
||||
SELECT json_quote(x'3031323334');
|
||||
} {1 {JSON cannot hold BLOB values}}
|
||||
do_catchsql_test json101-9.6 {
|
||||
SELECT json_quote(123,456)
|
||||
@@ -769,14 +845,23 @@ do_execsql_test json101-12.100 {
|
||||
}
|
||||
}');
|
||||
} {}
|
||||
|
||||
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 json101-12.110b {
|
||||
SELECT json_remove(jsonb(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 json101-12.120 {
|
||||
SELECT json_extract(x, '$.settings.layer2."tris.legomenon"."summary.report"')
|
||||
FROM t12;
|
||||
} {0}
|
||||
do_execsql_test json101-12.120b {
|
||||
SELECT json_extract(jsonb(x), '$.settings.layer2."tris.legomenon"."summary.report"')
|
||||
FROM t12;
|
||||
} {0}
|
||||
|
||||
# 2018-01-26
|
||||
# ticket https://www.sqlite.org/src/tktview/80177f0c226ff54f6ddd41
|
||||
@@ -840,16 +925,16 @@ do_execsql_test json101-14.170 {
|
||||
#
|
||||
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} {$}}
|
||||
} {a 1 integer 1 1 {} {$.a} {$} b 2 integer 2 5 {} {$.b} {$}}
|
||||
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} {$}}
|
||||
} {a 1 integer 1 1 {} {$.a} {$} b 2 integer 2 5 {} {$.b} {$}}
|
||||
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} {$}}
|
||||
} {a 1 integer 1 1 {} {$.a} {$} b 2 integer 2 5 {} {$.b} {$}}
|
||||
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} {$}}
|
||||
} {a 1 integer 1 1 {} {$.a} {$} b 2 integer 2 5 {} {$.b} {$}}
|
||||
|
||||
# 2019-11-10
|
||||
# Mailing list bug report on the handling of surrogate pairs
|
||||
@@ -889,7 +974,7 @@ do_execsql_test json101-18.4 {
|
||||
} {6}
|
||||
do_catchsql_test json101-18.5 {
|
||||
SELECT json_extract('{"":8}', '$.');
|
||||
} {1 {JSON path error near ''}}
|
||||
} {1 {bad JSON path: '$.'}}
|
||||
|
||||
# 2022-08-29 https://sqlite.org/forum/forumpost/9b9e4716c0d7bbd1
|
||||
# This is not a problem specifically with JSON functions. It is
|
||||
@@ -1054,6 +1139,29 @@ do_execsql_test json101-23.2 {
|
||||
FROM (SELECT json_set('[]','$[#]',0,'$[#]',1) AS j);
|
||||
} {{[0,1]} 0 1}
|
||||
|
||||
|
||||
# Insert/Set/Replace where the path specifies substructure that
|
||||
# does not yet exist
|
||||
#
|
||||
proc tx x {return [string map [list ( \173 ) \175 ' \042 < \133 > \135] $x]}
|
||||
foreach {id start path ins set repl} {
|
||||
1 {{}} {$.a.b.c} ('a':('b':('c':9))) ('a':('b':('c':9))) ()
|
||||
2 {{a:4}} {$.a.b.c} ('a':4) ('a':4) ('a':4)
|
||||
3 {{a:{}}} {$.a.b.c} ('a':('b':('c':9))) ('a':('b':('c':9))) ('a':())
|
||||
4 {[0,1,2]} {$[3].a[0].b} <0,1,2,('a':<('b':9)>)> <0,1,2,('a':<('b':9)>)> <0,1,2>
|
||||
5 {[0,1,2]} {$[1].a[0].b} <0,1,2> <0,1,2> <0,1,2>
|
||||
6 {[0,{},2]} {$[1].a[0].b} <0,('a':<('b':9)>),2> <0,('a':<('b':9)>),2> <0,(),2>
|
||||
7 {[0,1,2]} {$[3][0].b} <0,1,2,<('b':9)>> <0,1,2,<('b':9)>> <0,1,2>
|
||||
8 {[0,1,2]} {$[1][0].b} <0,1,2> <0,1,2> <0,1,2>
|
||||
} {
|
||||
do_execsql_test json101-24.$id.insert {
|
||||
SELECT json_insert($start,$path,9);
|
||||
} [list [tx $ins]]
|
||||
do_execsql_test json101-24.$id.set {
|
||||
SELECT json_set($start,$path,9);
|
||||
} [list [tx $set]]
|
||||
do_execsql_test json101-24.$id.replace {
|
||||
SELECT json_replace($start,$path,9);
|
||||
} [list [tx $repl]]
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+349
-3
@@ -21,159 +21,492 @@ source $testdir/tester.tcl
|
||||
do_execsql_test json102-100 {
|
||||
SELECT json_object('ex','[52,3.14159]');
|
||||
} {{{"ex":"[52,3.14159]"}}}
|
||||
do_execsql_test json102-100b {
|
||||
SELECT json(jsonb_object('ex','[52,3.14159]'));
|
||||
} {{{"ex":"[52,3.14159]"}}}
|
||||
do_execsql_test json102-110 {
|
||||
SELECT json_object('ex',json('[52,3.14159]'));
|
||||
} {{{"ex":[52,3.14159]}}}
|
||||
do_execsql_test json102-110-2 {
|
||||
SELECT json(jsonb_object('ex',json('[52,3.14159]')));
|
||||
} {{{"ex":[52,3.14159]}}}
|
||||
do_execsql_test json102-110-3 {
|
||||
SELECT json_object('ex',jsonb('[52,3.14159]'));
|
||||
} {{{"ex":[52,3.14159]}}}
|
||||
do_execsql_test json102-110-3 {
|
||||
SELECT json(jsonb_object('ex',jsonb('[52,3.14159]')));
|
||||
} {{{"ex":[52,3.14159]}}}
|
||||
do_execsql_test json102-120 {
|
||||
SELECT json_object('ex',json_array(52,3.14159));
|
||||
} {{{"ex":[52,3.14159]}}}
|
||||
do_execsql_test json102-120-2 {
|
||||
SELECT json(jsonb_object('ex',json_array(52,3.14159)));
|
||||
} {{{"ex":[52,3.14159]}}}
|
||||
do_execsql_test json102-120-3 {
|
||||
SELECT json_object('ex',jsonb_array(52,3.14159));
|
||||
} {{{"ex":[52,3.14159]}}}
|
||||
do_execsql_test json102-120-4 {
|
||||
SELECT json(jsonb_object('ex',jsonb_array(52,3.14159)));
|
||||
} {{{"ex":[52,3.14159]}}}
|
||||
do_execsql_test json102-130 {
|
||||
SELECT json(' { "this" : "is", "a": [ "test" ] } ');
|
||||
} {{{"this":"is","a":["test"]}}}
|
||||
do_execsql_test json102-130b {
|
||||
SELECT json(jsonb(' { "this" : "is", "a": [ "test" ] } '));
|
||||
} {{{"this":"is","a":["test"]}}}
|
||||
do_execsql_test json102-140 {
|
||||
SELECT json_array(1,2,'3',4);
|
||||
} {{[1,2,"3",4]}}
|
||||
do_execsql_test json102-140b {
|
||||
SELECT json(jsonb_array(1,2,'3',4));
|
||||
} {{[1,2,"3",4]}}
|
||||
do_execsql_test json102-150 {
|
||||
SELECT json_array('[1,2]');
|
||||
} {{["[1,2]"]}}
|
||||
do_execsql_test json102-150b {
|
||||
SELECT json(jsonb_array('[1,2]'));
|
||||
} {{["[1,2]"]}}
|
||||
do_execsql_test json102-160 {
|
||||
SELECT json_array(json_array(1,2));
|
||||
} {{[[1,2]]}}
|
||||
do_execsql_test json102-160-2 {
|
||||
SELECT json_array(jsonb_array(1,2));
|
||||
} {{[[1,2]]}}
|
||||
do_execsql_test json102-160-3 {
|
||||
SELECT json(jsonb_array(json_array(1,2)));
|
||||
} {{[[1,2]]}}
|
||||
do_execsql_test json102-160-4 {
|
||||
SELECT json(jsonb_array(jsonb_array(1,2)));
|
||||
} {{[[1,2]]}}
|
||||
do_execsql_test json102-170 {
|
||||
SELECT json_array(1,null,'3','[4,5]','{"six":7.7}');
|
||||
} {{[1,null,"3","[4,5]","{\"six\":7.7}"]}}
|
||||
do_execsql_test json102-170b {
|
||||
SELECT json(jsonb_array(1,null,'3','[4,5]','{"six":7.7}'));
|
||||
} {{[1,null,"3","[4,5]","{\"six\":7.7}"]}}
|
||||
do_execsql_test json102-180 {
|
||||
SELECT json_array(1,null,'3',json('[4,5]'),json('{"six":7.7}'));
|
||||
} {{[1,null,"3",[4,5],{"six":7.7}]}}
|
||||
do_execsql_test json102-180-2 {
|
||||
SELECT json_array(1,null,'3',jsonb('[4,5]'),json('{"six":7.7}'));
|
||||
} {{[1,null,"3",[4,5],{"six":7.7}]}}
|
||||
do_execsql_test json102-180-3 {
|
||||
SELECT json(jsonb_array(1,null,'3',json('[4,5]'),json('{"six":7.7}')));
|
||||
} {{[1,null,"3",[4,5],{"six":7.7}]}}
|
||||
do_execsql_test json102-180-4 {
|
||||
SELECT json(jsonb_array(1,null,'3',jsonb('[4,5]'),jsonb('{"six":7.7}')));
|
||||
} {{[1,null,"3",[4,5],{"six":7.7}]}}
|
||||
do_execsql_test json102-190 {
|
||||
SELECT json_array_length('[1,2,3,4]');
|
||||
} {{4}}
|
||||
do_execsql_test json102-190b {
|
||||
SELECT json_array_length(jsonb('[1,2,3,4]'));
|
||||
} {{4}}
|
||||
do_execsql_test json102-191 {
|
||||
SELECT json_array_length( json_remove('[1,2,3,4]','$[2]') );
|
||||
} {{3}}
|
||||
do_execsql_test json102-191b {
|
||||
SELECT json_array_length( jsonb_remove('[1,2,3,4]','$[2]') );
|
||||
} {{3}}
|
||||
do_execsql_test json102-200 {
|
||||
SELECT json_array_length('[1,2,3,4]', '$');
|
||||
} {{4}}
|
||||
do_execsql_test json102-200b {
|
||||
SELECT json_array_length(jsonb('[1,2,3,4]'), '$');
|
||||
} {{4}}
|
||||
do_execsql_test json102-210 {
|
||||
SELECT json_array_length('[1,2,3,4]', '$[2]');
|
||||
} {{0}}
|
||||
do_execsql_test json102-210b {
|
||||
SELECT json_array_length(jsonb('[1,2,3,4]'), '$[2]');
|
||||
} {{0}}
|
||||
do_execsql_test json102-220 {
|
||||
SELECT json_array_length('{"one":[1,2,3]}');
|
||||
} {{0}}
|
||||
do_execsql_test json102-230 {
|
||||
SELECT json_array_length('{"one":[1,2,3]}', '$.one');
|
||||
do_execsql_test json102-220 {
|
||||
SELECT json_array_length('{"one":[1,2,3]}');
|
||||
} {{0}}
|
||||
do_execsql_test json102-230b {
|
||||
SELECT json_array_length(jsonb('{"one":[1,2,3]}'), '$.one');
|
||||
} {{3}}
|
||||
do_execsql_test json102-240 {
|
||||
SELECT json_array_length('{"one":[1,2,3]}', '$.two');
|
||||
} {{}}
|
||||
do_execsql_test json102-240b {
|
||||
SELECT json_array_length(jsonb('{"one":[1,2,3]}'), '$.two');
|
||||
} {{}}
|
||||
do_execsql_test json102-250 {
|
||||
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$');
|
||||
} {{{"a":2,"c":[4,5,{"f":7}]}}}
|
||||
do_execsql_test json102-250-2 {
|
||||
SELECT json_extract(jsonb('{"a":2,"c":[4,5,{"f":7}]}'), '$');
|
||||
} {{{"a":2,"c":[4,5,{"f":7}]}}}
|
||||
do_execsql_test json102-250-3 {
|
||||
SELECT json(jsonb_extract('{"a":2,"c":[4,5,{"f":7}]}', '$'));
|
||||
} {{{"a":2,"c":[4,5,{"f":7}]}}}
|
||||
do_execsql_test json102-250-4 {
|
||||
SELECT json(jsonb_extract(jsonb('{"a":2,"c":[4,5,{"f":7}]}'), '$'));
|
||||
} {{{"a":2,"c":[4,5,{"f":7}]}}}
|
||||
do_execsql_test json102-260 {
|
||||
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c');
|
||||
} {{[4,5,{"f":7}]}}
|
||||
do_execsql_test json102-260-2 {
|
||||
SELECT json_extract(jsonb('{"a":2,"c":[4,5,{"f":7}]}'), '$.c');
|
||||
} {{[4,5,{"f":7}]}}
|
||||
do_execsql_test json102-260-3 {
|
||||
SELECT json(jsonb_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c'));
|
||||
} {{[4,5,{"f":7}]}}
|
||||
do_execsql_test json102-260-4 {
|
||||
SELECT json(jsonb_extract(jsonb('{"a":2,"c":[4,5,{"f":7}]}'), '$.c'));
|
||||
} {{[4,5,{"f":7}]}}
|
||||
do_execsql_test json102-270 {
|
||||
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]');
|
||||
} {{{"f":7}}}
|
||||
do_execsql_test json102-270-2 {
|
||||
SELECT json_extract(jsonb('{"a":2,"c":[4,5,{"f":7}]}'), '$.c[2]');
|
||||
} {{{"f":7}}}
|
||||
do_execsql_test json102-270-3 {
|
||||
SELECT json(jsonb_extract(jsonb('{"a":2,"c":[4,5,{"f":7}]}'), '$.c[2]'));
|
||||
} {{{"f":7}}}
|
||||
do_execsql_test json102-270-4 {
|
||||
SELECT json(jsonb_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]'));
|
||||
} {{{"f":7}}}
|
||||
do_execsql_test json102-280 {
|
||||
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2].f');
|
||||
} {{7}}
|
||||
do_execsql_test json102-280b {
|
||||
SELECT jsonb_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2].f');
|
||||
} {{7}}
|
||||
do_execsql_test json102-290 {
|
||||
SELECT json_extract('{"a":2,"c":[4,5],"f":7}','$.c','$.a');
|
||||
} {{[[4,5],2]}}
|
||||
do_execsql_test json102-290-2 {
|
||||
SELECT json_extract(jsonb('{"a":2,"c":[4,5],"f":7}'),'$.c','$.a');
|
||||
} {{[[4,5],2]}}
|
||||
do_execsql_test json102-290-3 {
|
||||
SELECT json(jsonb_extract('{"a":2,"c":[4,5],"f":7}','$.c','$.a'));
|
||||
} {{[[4,5],2]}}
|
||||
do_execsql_test json102-290-4 {
|
||||
SELECT json(jsonb_extract(jsonb('{"a":2,"c":[4,5],"f":7}'),'$.c','$.a'));
|
||||
} {{[[4,5],2]}}
|
||||
do_execsql_test json102-300 {
|
||||
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x');
|
||||
} {{}}
|
||||
do_execsql_test json102-300b {
|
||||
SELECT jsonb_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x');
|
||||
} {{}}
|
||||
do_execsql_test json102-310 {
|
||||
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x', '$.a');
|
||||
} {{[null,2]}}
|
||||
do_execsql_test json102-310-2 {
|
||||
SELECT json_extract(jsonb('{"a":2,"c":[4,5,{"f":7}]}'), '$.x', '$.a');
|
||||
} {{[null,2]}}
|
||||
do_execsql_test json102-310-3 {
|
||||
SELECT json(jsonb_extract(jsonb('{"a":2,"c":[4,5,{"f":7}]}'), '$.x', '$.a'));
|
||||
} {{[null,2]}}
|
||||
do_execsql_test json102-310-43 {
|
||||
SELECT json(jsonb_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x', '$.a'));
|
||||
} {{[null,2]}}
|
||||
do_execsql_test json102-320 {
|
||||
SELECT json_insert('{"a":2,"c":4}', '$.a', 99);
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-320-2 {
|
||||
SELECT json_insert(jsonb('{"a":2,"c":4}'), '$.a', 99);
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-320-3 {
|
||||
SELECT json(jsonb_insert('{"a":2,"c":4}', '$.a', 99));
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-320-4 {
|
||||
SELECT json(jsonb_insert(jsonb('{"a":2,"c":4}'), '$.a', 99));
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-330 {
|
||||
SELECT json_insert('{"a":2,"c":4}', '$.e', 99);
|
||||
} {{{"a":2,"c":4,"e":99}}}
|
||||
do_execsql_test json102-330-2 {
|
||||
SELECT json_insert(jsonb('{"a":2,"c":4}'), '$.e', 99);
|
||||
} {{{"a":2,"c":4,"e":99}}}
|
||||
do_execsql_test json102-330-3 {
|
||||
SELECT json(jsonb_insert('{"a":2,"c":4}', '$.e', 99));
|
||||
} {{{"a":2,"c":4,"e":99}}}
|
||||
do_execsql_test json102-330-4 {
|
||||
SELECT json(jsonb_insert(jsonb('{"a":2,"c":4}'), '$.e', 99));
|
||||
} {{{"a":2,"c":4,"e":99}}}
|
||||
do_execsql_test json102-340 {
|
||||
SELECT json_replace('{"a":2,"c":4}', '$.a', 99);
|
||||
} {{{"a":99,"c":4}}}
|
||||
do_execsql_test json102-340-2 {
|
||||
SELECT json_replace(jsonb('{"a":2,"c":4}'), '$.a', 99);
|
||||
} {{{"a":99,"c":4}}}
|
||||
do_execsql_test json102-340-3 {
|
||||
SELECT json(jsonb_replace('{"a":2,"c":4}', '$.a', 99));
|
||||
} {{{"a":99,"c":4}}}
|
||||
do_execsql_test json102-340-4 {
|
||||
SELECT json(jsonb_replace(jsonb('{"a":2,"c":4}'), '$.a', 99));
|
||||
} {{{"a":99,"c":4}}}
|
||||
do_execsql_test json102-350 {
|
||||
SELECT json_replace('{"a":2,"c":4}', '$.e', 99);
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-350-2 {
|
||||
SELECT json_replace(jsonb('{"a":2,"c":4}'), '$.e', 99);
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-350-3 {
|
||||
SELECT json(jsonb_replace('{"a":2,"c":4}', '$.e', 99));
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-350-4 {
|
||||
SELECT json(jsonb_replace(jsonb('{"a":2,"c":4}'), '$.e', 99));
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-360 {
|
||||
SELECT json_set('{"a":2,"c":4}', '$.a', 99);
|
||||
} {{{"a":99,"c":4}}}
|
||||
do_execsql_test json102-360-2 {
|
||||
SELECT json_set(jsonb('{"a":2,"c":4}'), '$.a', 99);
|
||||
} {{{"a":99,"c":4}}}
|
||||
do_execsql_test json102-360-3 {
|
||||
SELECT json(jsonb_set('{"a":2,"c":4}', '$.a', 99));
|
||||
} {{{"a":99,"c":4}}}
|
||||
do_execsql_test json102-360-4 {
|
||||
SELECT json(jsonb_set(jsonb('{"a":2,"c":4}'), '$.a', 99));
|
||||
} {{{"a":99,"c":4}}}
|
||||
do_execsql_test json102-370 {
|
||||
SELECT json_set('{"a":2,"c":4}', '$.e', 99);
|
||||
} {{{"a":2,"c":4,"e":99}}}
|
||||
do_execsql_test json102-370-2 {
|
||||
SELECT json_set(jsonb('{"a":2,"c":4}'), '$.e', 99);
|
||||
} {{{"a":2,"c":4,"e":99}}}
|
||||
do_execsql_test json102-370-3 {
|
||||
SELECT json(jsonb_set('{"a":2,"c":4}', '$.e', 99));
|
||||
} {{{"a":2,"c":4,"e":99}}}
|
||||
do_execsql_test json102-370-4 {
|
||||
SELECT json(jsonb_set(jsonb('{"a":2,"c":4}'), '$.e', 99));
|
||||
} {{{"a":2,"c":4,"e":99}}}
|
||||
do_execsql_test json102-380 {
|
||||
SELECT json_set('{"a":2,"c":4}', '$.c', '[97,96]');
|
||||
} {{{"a":2,"c":"[97,96]"}}}
|
||||
do_execsql_test json102-380-2 {
|
||||
SELECT json_set(jsonb('{"a":2,"c":4}'), '$.c', '[97,96]');
|
||||
} {{{"a":2,"c":"[97,96]"}}}
|
||||
do_execsql_test json102-380-3 {
|
||||
SELECT json(jsonb_set('{"a":2,"c":4}', '$.c', '[97,96]'));
|
||||
} {{{"a":2,"c":"[97,96]"}}}
|
||||
do_execsql_test json102-380-4 {
|
||||
SELECT json(jsonb_set(jsonb('{"a":2,"c":4}'), '$.c', '[97,96]'));
|
||||
} {{{"a":2,"c":"[97,96]"}}}
|
||||
do_execsql_test json102-390 {
|
||||
SELECT json_set('{"a":2,"c":4}', '$.c', json('[97,96]'));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-390-2 {
|
||||
SELECT json_set(jsonb('{"a":2,"c":4}'), '$.c', json('[97,96]'));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-390-3 {
|
||||
SELECT json(jsonb_set('{"a":2,"c":4}', '$.c', json('[97,96]')));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-390-4 {
|
||||
SELECT json(jsonb_set(jsonb('{"a":2,"c":4}'), '$.c', json('[97,96]')));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-390-5 {
|
||||
SELECT json_set('{"a":2,"c":4}', '$.c', jsonb('[97,96]'));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-390-6 {
|
||||
SELECT json_set(jsonb('{"a":2,"c":4}'), '$.c', jsonb('[97,96]'));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-390-7 {
|
||||
SELECT json(jsonb_set('{"a":2,"c":4}', '$.c', jsonb('[97,96]')));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-390-8 {
|
||||
SELECT json(jsonb_set(jsonb('{"a":2,"c":4}'), '$.c', jsonb('[97,96]')));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-400 {
|
||||
SELECT json_set('{"a":2,"c":4}', '$.c', json_array(97,96));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-400-2 {
|
||||
SELECT json_set(jsonb('{"a":2,"c":4}'), '$.c', json_array(97,96));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-400-3 {
|
||||
SELECT json(jsonb_set('{"a":2,"c":4}', '$.c', json_array(97,96)));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-400-4 {
|
||||
SELECT json(jsonb_set(jsonb('{"a":2,"c":4}'), '$.c', json_array(97,96)));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-400-5 {
|
||||
SELECT json_set('{"a":2,"c":4}', '$.c', jsonb_array(97,96));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-400-6 {
|
||||
SELECT json_set(jsonb('{"a":2,"c":4}'), '$.c', jsonb_array(97,96));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-400-7 {
|
||||
SELECT json(jsonb_set('{"a":2,"c":4}', '$.c', jsonb_array(97,96)));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-400-8 {
|
||||
SELECT json(jsonb_set(jsonb('{"a":2,"c":4}'), '$.c', jsonb_array(97,96)));
|
||||
} {{{"a":2,"c":[97,96]}}}
|
||||
do_execsql_test json102-410 {
|
||||
SELECT json_object('a',2,'c',4);
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-410b {
|
||||
SELECT json(jsonb_object('a',2,'c',4));
|
||||
} {{{"a":2,"c":4}}}
|
||||
do_execsql_test json102-420 {
|
||||
SELECT json_object('a',2,'c','{e:5}');
|
||||
} {{{"a":2,"c":"{e:5}"}}}
|
||||
do_execsql_test json102-420b {
|
||||
SELECT json(jsonb_object('a',2,'c','{e:5}'));
|
||||
} {{{"a":2,"c":"{e:5}"}}}
|
||||
do_execsql_test json102-430 {
|
||||
SELECT json_object('a',2,'c',json_object('e',5));
|
||||
} {{{"a":2,"c":{"e":5}}}}
|
||||
do_execsql_test json102-430-2 {
|
||||
SELECT json(jsonb_object('a',2,'c',json_object('e',5)));
|
||||
} {{{"a":2,"c":{"e":5}}}}
|
||||
do_execsql_test json102-430-3 {
|
||||
SELECT json_object('a',2,'c',jsonb_object('e',5));
|
||||
} {{{"a":2,"c":{"e":5}}}}
|
||||
do_execsql_test json102-430-4 {
|
||||
SELECT json(jsonb_object('a',2,'c',jsonb_object('e',5)));
|
||||
} {{{"a":2,"c":{"e":5}}}}
|
||||
do_execsql_test json102-440 {
|
||||
SELECT json_remove('[0,1,2,3,4]','$[2]');
|
||||
} {{[0,1,3,4]}}
|
||||
do_execsql_test json102-440-2 {
|
||||
SELECT json_remove(jsonb('[0,1,2,3,4]'),'$[2]');
|
||||
} {{[0,1,3,4]}}
|
||||
do_execsql_test json102-440-3 {
|
||||
SELECT json(jsonb_remove('[0,1,2,3,4]','$[2]'));
|
||||
} {{[0,1,3,4]}}
|
||||
do_execsql_test json102-440-4 {
|
||||
SELECT json(jsonb_remove(jsonb('[0,1,2,3,4]'),'$[2]'));
|
||||
} {{[0,1,3,4]}}
|
||||
do_execsql_test json102-450 {
|
||||
SELECT json_remove('[0,1,2,3,4]','$[2]','$[0]');
|
||||
} {{[1,3,4]}}
|
||||
do_execsql_test json102-450-2 {
|
||||
SELECT json_remove(jsonb('[0,1,2,3,4]'),'$[2]','$[0]');
|
||||
} {{[1,3,4]}}
|
||||
do_execsql_test json102-450-3 {
|
||||
SELECT json(jsonb_remove('[0,1,2,3,4]','$[2]','$[0]'));
|
||||
} {{[1,3,4]}}
|
||||
do_execsql_test json102-450-4 {
|
||||
SELECT json(jsonb_remove(jsonb('[0,1,2,3,4]'),'$[2]','$[0]'));
|
||||
} {{[1,3,4]}}
|
||||
do_execsql_test json102-460 {
|
||||
SELECT json_remove('[0,1,2,3,4]','$[0]','$[2]');
|
||||
} {{[1,2,4]}}
|
||||
do_execsql_test json102-460-2 {
|
||||
SELECT json_remove(jsonb('[0,1,2,3,4]'),'$[0]','$[2]');
|
||||
} {{[1,2,4]}}
|
||||
do_execsql_test json102-460-3 {
|
||||
SELECT json(jsonb_remove('[0,1,2,3,4]','$[0]','$[2]'));
|
||||
} {{[1,2,4]}}
|
||||
do_execsql_test json102-460-4 {
|
||||
SELECT json(jsonb_remove(jsonb('[0,1,2,3,4]'),'$[0]','$[2]'));
|
||||
} {{[1,2,4]}}
|
||||
do_execsql_test json102-470 {
|
||||
SELECT json_remove('{"x":25,"y":42}');
|
||||
} {{{"x":25,"y":42}}}
|
||||
do_execsql_test json102-470-2 {
|
||||
SELECT json_remove(jsonb('{"x":25,"y":42}'));
|
||||
} {{{"x":25,"y":42}}}
|
||||
do_execsql_test json102-470-3 {
|
||||
SELECT json(jsonb_remove('{"x":25,"y":42}'));
|
||||
} {{{"x":25,"y":42}}}
|
||||
do_execsql_test json102-470-4 {
|
||||
SELECT json(jsonb_remove(jsonb('{"x":25,"y":42}')));
|
||||
} {{{"x":25,"y":42}}}
|
||||
do_execsql_test json102-480 {
|
||||
SELECT json_remove('{"x":25,"y":42}','$.z');
|
||||
} {{{"x":25,"y":42}}}
|
||||
do_execsql_test json102-480-2 {
|
||||
SELECT json_remove(jsonb('{"x":25,"y":42}'),'$.z');
|
||||
} {{{"x":25,"y":42}}}
|
||||
do_execsql_test json102-480-3 {
|
||||
SELECT json(jsonb_remove('{"x":25,"y":42}','$.z'));
|
||||
} {{{"x":25,"y":42}}}
|
||||
do_execsql_test json102-480-4 {
|
||||
SELECT json(jsonb_remove(jsonb('{"x":25,"y":42}'),'$.z'));
|
||||
} {{{"x":25,"y":42}}}
|
||||
do_execsql_test json102-490 {
|
||||
SELECT json_remove('{"x":25,"y":42}','$.y');
|
||||
} {{{"x":25}}}
|
||||
do_execsql_test json102-490-2 {
|
||||
SELECT json_remove(jsonb('{"x":25,"y":42}'),'$.y');
|
||||
} {{{"x":25}}}
|
||||
do_execsql_test json102-490-3 {
|
||||
SELECT json(jsonb_remove('{"x":25,"y":42}','$.y'));
|
||||
} {{{"x":25}}}
|
||||
do_execsql_test json102-490-4 {
|
||||
SELECT json(jsonb_remove(jsonb('{"x":25,"y":42}'),'$.y'));
|
||||
} {{{"x":25}}}
|
||||
do_execsql_test json102-500 {
|
||||
SELECT json_remove('{"x":25,"y":42}','$');
|
||||
} {{}}
|
||||
do_execsql_test json102-500-2 {
|
||||
SELECT json_remove(jsonb('{"x":25,"y":42}'),'$');
|
||||
} {{}}
|
||||
do_execsql_test json102-500-3 {
|
||||
SELECT json(jsonb_remove('{"x":25,"y":42}','$'));
|
||||
} {{}}
|
||||
do_execsql_test json102-500-4 {
|
||||
SELECT json(jsonb_remove(jsonb('{"x":25,"y":42}'),'$'));
|
||||
} {{}}
|
||||
do_execsql_test json102-510 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}');
|
||||
} {{object}}
|
||||
do_execsql_test json102-510b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778');
|
||||
} {{object}}
|
||||
do_execsql_test json102-520 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$');
|
||||
} {{object}}
|
||||
do_execsql_test json102-520b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778','$');
|
||||
} {{object}}
|
||||
do_execsql_test json102-530 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a');
|
||||
} {{array}}
|
||||
do_execsql_test json102-530b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778','$.a');
|
||||
} {{array}}
|
||||
do_execsql_test json102-540 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[0]');
|
||||
} {{integer}}
|
||||
do_execsql_test json102-540b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778','$.a[0]');
|
||||
} {{integer}}
|
||||
do_execsql_test json102-550 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[1]');
|
||||
} {{real}}
|
||||
do_execsql_test json102-550b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778','$.a[1]');
|
||||
} {{real}}
|
||||
do_execsql_test json102-560 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[2]');
|
||||
} {{true}}
|
||||
do_execsql_test json102-560b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778','$.a[2]');
|
||||
} {{true}}
|
||||
do_execsql_test json102-570 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[3]');
|
||||
} {{false}}
|
||||
do_execsql_test json102-570b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778','$.a[3]');
|
||||
} {{false}}
|
||||
do_execsql_test json102-580 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[4]');
|
||||
} {{null}}
|
||||
do_execsql_test json102-580b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778','$.a[4]');
|
||||
} {{null}}
|
||||
do_execsql_test json102-590 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[5]');
|
||||
} {{text}}
|
||||
do_execsql_test json102-590b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778','$.a[5]');
|
||||
} {{text}}
|
||||
do_execsql_test json102-600 {
|
||||
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[6]');
|
||||
} {{}}
|
||||
do_execsql_test json102-600b {
|
||||
SELECT json_type(x'cc0f1761cb0b133235332e350102001778','$.a[6]');
|
||||
} {{}}
|
||||
do_execsql_test json102-610 {
|
||||
SELECT json_valid(char(123)||'"x":35'||char(125));
|
||||
} {{1}}
|
||||
@@ -183,17 +516,24 @@ do_execsql_test json102-620 {
|
||||
|
||||
ifcapable vtab {
|
||||
do_execsql_test json102-1000 {
|
||||
CREATE TABLE user(name,phone);
|
||||
CREATE TABLE user(name,phone,phoneb);
|
||||
INSERT INTO user(name,phone) VALUES
|
||||
('Alice','["919-555-2345","804-555-3621"]'),
|
||||
('Bob','["201-555-8872"]'),
|
||||
('Cindy','["704-555-9983"]'),
|
||||
('Dave','["336-555-8421","704-555-4321","803-911-4421"]');
|
||||
UPDATE user SET phoneb=jsonb(phone);
|
||||
SELECT DISTINCT user.name
|
||||
FROM user, json_each(user.phone)
|
||||
WHERE json_each.value LIKE '704-%'
|
||||
ORDER BY 1;
|
||||
} {Cindy Dave}
|
||||
do_execsql_test json102-1000b {
|
||||
SELECT DISTINCT user.name
|
||||
FROM user, json_each(user.phoneb)
|
||||
WHERE json_each.value LIKE '704-%'
|
||||
ORDER BY 1;
|
||||
} {Cindy Dave}
|
||||
|
||||
do_execsql_test json102-1010 {
|
||||
UPDATE user
|
||||
@@ -253,6 +593,12 @@ do_execsql_test json102-1110 {
|
||||
WHERE json_tree.type NOT IN ('object','array')
|
||||
ORDER BY +big.rowid, +json_tree.id
|
||||
} $correct_answer
|
||||
do_execsql_test json102-1110b {
|
||||
SELECT big.rowid, fullkey, value
|
||||
FROM big, json_tree(jsonb(big.json))
|
||||
WHERE json_tree.type NOT IN ('object','array')
|
||||
ORDER BY +big.rowid, +json_tree.id
|
||||
} $correct_answer
|
||||
do_execsql_test json102-1120 {
|
||||
SELECT big.rowid, fullkey, atom
|
||||
FROM big, json_tree(big.json)
|
||||
|
||||
+5
-5
@@ -96,18 +96,18 @@ json_replace_test 80 {'$.b[#-1]','AAA','$.b[#-1]','BBB'} \
|
||||
|
||||
do_catchsql_test json105-6.10 {
|
||||
SELECT json_extract(j, '$.b[#-]') FROM t1;
|
||||
} {1 {JSON path error near '[#-]'}}
|
||||
} {1 {bad JSON path: '$.b[#-]'}}
|
||||
do_catchsql_test json105-6.20 {
|
||||
SELECT json_extract(j, '$.b[#9]') FROM t1;
|
||||
} {1 {JSON path error near '[#9]'}}
|
||||
} {1 {bad JSON path: '$.b[#9]'}}
|
||||
do_catchsql_test json105-6.30 {
|
||||
SELECT json_extract(j, '$.b[#+2]') FROM t1;
|
||||
} {1 {JSON path error near '[#+2]'}}
|
||||
} {1 {bad JSON path: '$.b[#+2]'}}
|
||||
do_catchsql_test json105-6.40 {
|
||||
SELECT json_extract(j, '$.b[#-1') FROM t1;
|
||||
} {1 {JSON path error near '[#-1'}}
|
||||
} {1 {bad JSON path: '$.b[#-1'}}
|
||||
do_catchsql_test json105-6.50 {
|
||||
SELECT json_extract(j, '$.b[#-1x]') FROM t1;
|
||||
} {1 {JSON path error near '[#-1x]'}}
|
||||
} {1 {bad JSON path: '$.b[#-1x]'}}
|
||||
|
||||
finish_test
|
||||
|
||||
+8
-3
@@ -252,13 +252,13 @@ do_execsql_test 8.11 {
|
||||
|
||||
do_execsql_test 9.1 {
|
||||
WITH c(x) AS (VALUES('{x: +Infinity}')) SELECT x->>'x', json(x) FROM c;
|
||||
} {Inf {{"x":9.0e999}}}
|
||||
} {Inf {{"x":9e999}}}
|
||||
do_execsql_test 9.2 {
|
||||
WITH c(x) AS (VALUES('{x: -Infinity}')) SELECT x->>'x', json(x) FROM c;
|
||||
} {-Inf {{"x":-9.0e999}}}
|
||||
} {-Inf {{"x":-9e999}}}
|
||||
do_execsql_test 9.3 {
|
||||
WITH c(x) AS (VALUES('{x: Infinity}')) SELECT x->>'x', json(x) FROM c;
|
||||
} {Inf {{"x":9.0e999}}}
|
||||
} {Inf {{"x":9e999}}}
|
||||
do_execsql_test 9.4 {
|
||||
WITH c(x) AS (VALUES('{x: NaN}')) SELECT x->>'x', json(x) FROM c;
|
||||
} {{} {{"x":null}}}
|
||||
@@ -300,5 +300,10 @@ do_execsql_test 12.4 {
|
||||
|| ' "xyz"}')->>'a';
|
||||
} xyz
|
||||
|
||||
# 2023-11-08 forum/forumpost/ddcad3e884
|
||||
#
|
||||
do_execsql_test 13.1 {
|
||||
SELECT json('{x:''a "b" c''}');
|
||||
} {{{"x":"a \"b\" c"}}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# 2023-11-15
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# Test cases for JSONB
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test jsonb01-1.1 {
|
||||
CREATE TABLE t1(x JSON BLOB);
|
||||
INSERT INTO t1 VALUES(jsonb('{a:5,b:{x:10,y:11},c:[1,2,3,4]}'));
|
||||
}
|
||||
foreach {id path res} {
|
||||
1 {$.a} {{{"b":{"x":10,"y":11},"c":[1,2,3,4]}}}
|
||||
2 {$.b} {{{"a":5,"c":[1,2,3,4]}}}
|
||||
3 {$.c} {{{"a":5,"b":{"x":10,"y":11}}}}
|
||||
4 {$.d} {{{"a":5,"b":{"x":10,"y":11},"c":[1,2,3,4]}}}
|
||||
5 {$.b.x} {{{"a":5,"b":{"y":11},"c":[1,2,3,4]}}}
|
||||
6 {$.b.y} {{{"a":5,"b":{"x":10},"c":[1,2,3,4]}}}
|
||||
7 {$.c[0]} {{{"a":5,"b":{"x":10,"y":11},"c":[2,3,4]}}}
|
||||
8 {$.c[1]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,3,4]}}}
|
||||
9 {$.c[2]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,2,4]}}}
|
||||
10 {$.c[3]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,2,3]}}}
|
||||
11 {$.c[4]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,2,3,4]}}}
|
||||
12 {$.c[#]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,2,3,4]}}}
|
||||
13 {$.c[#-1]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,2,3]}}}
|
||||
14 {$.c[#-2]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,2,4]}}}
|
||||
15 {$.c[#-3]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,3,4]}}}
|
||||
16 {$.c[#-4]} {{{"a":5,"b":{"x":10,"y":11},"c":[2,3,4]}}}
|
||||
17 {$.c[#-5]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,2,3,4]}}}
|
||||
18 {$.c[#-6]} {{{"a":5,"b":{"x":10,"y":11},"c":[1,2,3,4]}}}
|
||||
} {
|
||||
do_execsql_test jsonb01-1.2.$id.1 {
|
||||
SELECT json(jsonb_remove(x,$path)) FROM t1;
|
||||
} $res
|
||||
do_execsql_test jsonb01-1.2.$id.2 {
|
||||
SELECT json_remove(x,$path) FROM t1;
|
||||
} $res
|
||||
}
|
||||
|
||||
finish_test
|
||||
@@ -1,845 +0,0 @@
|
||||
# 2019 August 01
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file implements a program that produces scripts (either shell scripts
|
||||
# or batch files) to implement a particular test that is part of the SQLite
|
||||
# release testing procedure. For example, to run veryquick.test with a
|
||||
# specified set of -D compiler switches.
|
||||
#
|
||||
# A "configuration" is a set of options passed to [./configure] and [make]
|
||||
# to build the SQLite library in a particular fashion. A "platform" is a
|
||||
# list of tests; most platforms are named after the hardware/OS platform
|
||||
# that the tests will be run on as part of the release procedure. Each
|
||||
# "test" is a combination of a configuration and a makefile target (e.g.
|
||||
# "fulltest"). The program may be invoked as follows:
|
||||
#
|
||||
set USAGE {
|
||||
$argv0 script ?-msvc? CONFIGURATION TARGET
|
||||
Given a configuration and make target, return a bash (or, if -msvc
|
||||
is specified, batch) script to execute the test. The first argument
|
||||
passed to the script must be a directory containing SQLite source code.
|
||||
|
||||
$argv0 configurations
|
||||
List available configurations.
|
||||
|
||||
$argv0 platforms
|
||||
List available platforms.
|
||||
|
||||
$argv0 tests ?-nodebug? PLATFORM
|
||||
List tests in a specified platform. If the -nodebug switch is
|
||||
specified, synthetic debug/ndebug configurations are omitted. Each
|
||||
test is a combination of a configuration and a makefile target.
|
||||
}
|
||||
|
||||
# Omit comments (text between # and \n) in a long multi-line string.
|
||||
#
|
||||
proc strip_comments {in} {
|
||||
regsub -all {#[^\n]*\n} $in {} out
|
||||
return $out
|
||||
}
|
||||
|
||||
array set ::Configs [strip_comments {
|
||||
"Default" {
|
||||
-O2
|
||||
--disable-amalgamation --disable-shared
|
||||
--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
|
||||
-DCONFIG_SLOWDOWN_FACTOR=5.0
|
||||
--enable-debug
|
||||
--enable-all
|
||||
}
|
||||
"Stdcall" {
|
||||
-DUSE_STDCALL=1
|
||||
-O2
|
||||
}
|
||||
"Have-Not" {
|
||||
# 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.
|
||||
-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
|
||||
}
|
||||
"Unlock-Notify" {
|
||||
-O2
|
||||
-DSQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
-DSQLITE_THREADSAFE
|
||||
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
|
||||
}
|
||||
"User-Auth" {
|
||||
-O2
|
||||
-DSQLITE_USER_AUTHENTICATION=1
|
||||
}
|
||||
"Secure-Delete" {
|
||||
-O2
|
||||
-DSQLITE_SECURE_DELETE=1
|
||||
-DSQLITE_SOUNDEX=1
|
||||
}
|
||||
"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
|
||||
}
|
||||
"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
|
||||
}
|
||||
"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
|
||||
}
|
||||
"Debug-Two" {
|
||||
-DSQLITE_DEFAULT_MEMSTATUS=0
|
||||
-DSQLITE_MAX_EXPR_DEPTH=0
|
||||
--enable-debug
|
||||
}
|
||||
"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
|
||||
}
|
||||
"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
|
||||
}
|
||||
"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
|
||||
}
|
||||
"Locking-Style" {
|
||||
-O2
|
||||
-DSQLITE_ENABLE_LOCKING_STYLE=1
|
||||
}
|
||||
"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_SQLLOG=1
|
||||
-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
|
||||
-DSQLITE_MAX_LENGTH=2147483645
|
||||
-DSQLITE_MAX_VARIABLE_NUMBER=500000
|
||||
# -DSQLITE_MEMDEBUG=1
|
||||
-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
|
||||
}
|
||||
"Extra-Robustness" {
|
||||
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
|
||||
-DSQLITE_MAX_ATTACHED=62
|
||||
}
|
||||
"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
|
||||
}
|
||||
"No-lookaside" {
|
||||
-DSQLITE_TEST_REALLOC_STRESS=1
|
||||
-DSQLITE_OMIT_LOOKASIDE=1
|
||||
}
|
||||
"Valgrind" {
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
-DSQLITE_ENABLE_FTS4
|
||||
-DSQLITE_ENABLE_RTREE
|
||||
-DSQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
-DLONGDOUBLE_TYPE=double
|
||||
-DCONFIG_SLOWDOWN_FACTOR=8.0
|
||||
}
|
||||
|
||||
"Windows-Memdebug" {
|
||||
MEMDEBUG=1
|
||||
DEBUG=3
|
||||
}
|
||||
"Windows-Win32Heap" {
|
||||
WIN32HEAP=1
|
||||
DEBUG=4
|
||||
}
|
||||
|
||||
# The next group of configurations are used only by the
|
||||
# Failure-Detection platform. They are all the same, but we need
|
||||
# different names for them all so that they results appear in separate
|
||||
# subdirectories.
|
||||
#
|
||||
Fail0 {-O0}
|
||||
Fail2 {-O0}
|
||||
Fail3 {-O0}
|
||||
Fail4 {-O0}
|
||||
FuzzFail1 {-O0}
|
||||
FuzzFail2 {-O0}
|
||||
}]
|
||||
if {$tcl_platform(os)=="Darwin"} {
|
||||
lappend Configs(Apple) -DSQLITE_ENABLE_LOCKING_STYLE=1
|
||||
}
|
||||
|
||||
array set ::Platforms [strip_comments {
|
||||
Linux-x86_64 {
|
||||
"Check-Symbols*" "" checksymbols
|
||||
"Fast-One" QUICKTEST_INCLUDE=rbu.test "fuzztest test"
|
||||
"Debug-One" "" "mptest test"
|
||||
"Debug-Two" "" test
|
||||
"Have-Not" "" test
|
||||
"Secure-Delete" "" test
|
||||
"Unlock-Notify" QUICKTEST_INCLUDE=notify2.test test
|
||||
"User-Auth" "" tcltest
|
||||
"Update-Delete-Limit" "" test
|
||||
"Extra-Robustness" "" test
|
||||
"Device-Two" "" "threadtest test"
|
||||
"No-lookaside" "" test
|
||||
"Devkit" "" test
|
||||
"Apple" "" test
|
||||
"Sanitize*" "" test
|
||||
"Device-One" "" alltest
|
||||
"Default" "" "threadtest fuzztest alltest"
|
||||
"Valgrind*" "" valgrindtest
|
||||
}
|
||||
Linux-i686 {
|
||||
"Devkit" "" test
|
||||
"Have-Not" "" test
|
||||
"Unlock-Notify" QUICKTEST_INCLUDE=notify2.test test
|
||||
"Device-One" "" test
|
||||
"Device-Two" "" test
|
||||
"Default" "" "threadtest fuzztest alltest"
|
||||
}
|
||||
Darwin-i386 {
|
||||
"Locking-Style" "" "mptest test"
|
||||
"Have-Not" "" test
|
||||
"Apple" "" "threadtest fuzztest alltest"
|
||||
}
|
||||
Darwin-x86_64 {
|
||||
"Locking-Style" "" "mptest test"
|
||||
"Have-Not" "" test
|
||||
"Apple" "" "threadtest fuzztest alltest"
|
||||
}
|
||||
Darwin-arm64 {
|
||||
"Locking-Style" "" "mptest test"
|
||||
"Have-Not" "" test
|
||||
"Apple" "" "threadtest fuzztest alltest"
|
||||
}
|
||||
"Windows NT-intel" {
|
||||
"Stdcall" "" test
|
||||
"Have-Not" "" test
|
||||
"Windows-Memdebug*" "" test
|
||||
"Windows-Win32Heap*" "" test
|
||||
"Default" "" "mptest fulltestonly"
|
||||
}
|
||||
"Windows NT-amd64" {
|
||||
"Stdcall" "" test
|
||||
"Have-Not" "" test
|
||||
"Windows-Memdebug*" "" test
|
||||
"Windows-Win32Heap*" "" test
|
||||
"Default" "" "mptest fulltestonly"
|
||||
}
|
||||
|
||||
# The Failure-Detection platform runs various tests that deliberately
|
||||
# fail. This is used as a test of this script to verify that this script
|
||||
# correctly identifies failures.
|
||||
#
|
||||
Failure-Detection {
|
||||
Fail0* "TEST_FAILURE=0" test
|
||||
Sanitize* "TEST_FAILURE=1" test
|
||||
Fail2* "TEST_FAILURE=2" valgrindtest
|
||||
Fail3* "TEST_FAILURE=3" valgrindtest
|
||||
Fail4* "TEST_FAILURE=4" test
|
||||
FuzzFail1* "TEST_FAILURE=5" test
|
||||
FuzzFail2* "TEST_FAILURE=5" valgrindtest
|
||||
}
|
||||
}]
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
#--------------------------------------------------------------------------
|
||||
#--------------------------------------------------------------------------
|
||||
# End of configuration section.
|
||||
#--------------------------------------------------------------------------
|
||||
#--------------------------------------------------------------------------
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
# Configuration verification: Check that each entry in the list of configs
|
||||
# specified for each platforms exists.
|
||||
#
|
||||
foreach {key value} [array get ::Platforms] {
|
||||
foreach {v vars t} $value {
|
||||
if {[string range $v end end]=="*"} {
|
||||
set v [string range $v 0 end-1]
|
||||
}
|
||||
if {0==[info exists ::Configs($v)]} {
|
||||
puts stderr "No such configuration: \"$v\""
|
||||
exit -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc usage {} {
|
||||
global argv0
|
||||
puts stderr [subst $::USAGE]
|
||||
exit 1
|
||||
}
|
||||
|
||||
proc is_prefix {p str min} {
|
||||
set n [string length $p]
|
||||
if {$n<$min} { return 0 }
|
||||
if {[string range $str 0 [expr $n-1]]!=$p} { return 0 }
|
||||
return 1
|
||||
}
|
||||
|
||||
proc main_configurations {} {
|
||||
foreach k [lsort [array names ::Configs]] {
|
||||
puts $k
|
||||
}
|
||||
}
|
||||
|
||||
proc main_platforms {} {
|
||||
foreach k [lsort [array names ::Platforms]] {
|
||||
puts "\"$k\""
|
||||
}
|
||||
}
|
||||
|
||||
proc main_script {args} {
|
||||
set bMsvc 0
|
||||
set nArg [llength $args]
|
||||
if {$nArg==3} {
|
||||
if {![is_prefix [lindex $args 0] -msvc 2]} usage
|
||||
set bMsvc 1
|
||||
} elseif {$nArg<2 || $nArg>3} {
|
||||
usage
|
||||
}
|
||||
set config [lindex $args end-1]
|
||||
set target [lindex $args end]
|
||||
|
||||
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]
|
||||
|
||||
if {$::tcl_platform(platform)=="windows" || $bMsvc} {
|
||||
lappend opts -DSQLITE_OS_WIN=1
|
||||
} else {
|
||||
lappend opts -DSQLITE_OS_UNIX=1
|
||||
}
|
||||
|
||||
# Figure out if this is a synthetic ndebug or debug configuration.
|
||||
#
|
||||
set bRemoveDebug 0
|
||||
if {[string match *-ndebug $config]} {
|
||||
set bRemoveDebug 1
|
||||
set config [string range $config 0 end-7]
|
||||
}
|
||||
if {[string match *-debug $config]} {
|
||||
lappend opts -DSQLITE_DEBUG
|
||||
lappend opts -DSQLITE_EXTRA_IFNULLROW
|
||||
set config [string range $config 0 end-6]
|
||||
}
|
||||
regexp {^(.*)-[0-9]+} $config -> config
|
||||
|
||||
# Ensure that the named configuration exists.
|
||||
#
|
||||
if {![info exists ::Configs($config)]} {
|
||||
puts stderr "No such config: $config"
|
||||
exit 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 a "*", discard it.
|
||||
#
|
||||
# 2. If $bRemoveDebug is set and the parameter is -DSQLITE_DEBUG or
|
||||
# -DSQLITE_DEBUG=1, discard it
|
||||
#
|
||||
# 3. If the parameter begins with "-D", add it to $opts.
|
||||
#
|
||||
# 4. 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.
|
||||
#
|
||||
# 5. 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.
|
||||
#
|
||||
# 6. If none of the above apply, add the parameter to $makeOpts
|
||||
#
|
||||
foreach param $::Configs($config) {
|
||||
if {[string range $param 0 0]=="*"} continue
|
||||
|
||||
if {$bRemoveDebug} {
|
||||
if {$param=="-DSQLITE_DEBUG" || $param=="-DSQLITE_DEBUG=1"
|
||||
|| $param=="-DSQLITE_MEMDEBUG" || $param=="-DSQLITE_MEMDEBUG=1"
|
||||
|| $param=="--enable-debug"
|
||||
} {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if {[string range $param 0 1]=="-D"} {
|
||||
lappend opts $param
|
||||
continue
|
||||
}
|
||||
|
||||
if {[string range $param 0 1]=="--"} {
|
||||
if {$bMsvc} {
|
||||
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
|
||||
}
|
||||
default {
|
||||
error "Cannot translate $param for MSVC"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lappend configOpts $param
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# Some configurations specify -DHAVE_USLEEP=0. For all others, add
|
||||
# -DHAVE_USLEEP=1.
|
||||
#
|
||||
if {[lsearch $opts "-DHAVE_USLEEP=0"]<0} {
|
||||
lappend opts -DHAVE_USLEEP=1
|
||||
}
|
||||
|
||||
if {$bMsvc==0} {
|
||||
puts {set -e}
|
||||
puts {}
|
||||
puts {if [ "$#" -ne 1 ] ; then}
|
||||
puts { echo "Usage: $0 <sqlite-src-dir>" }
|
||||
puts { exit -1 }
|
||||
puts {fi }
|
||||
puts {SRCDIR=$1}
|
||||
puts {}
|
||||
puts "TCL=\"[::tcl::pkgconfig get libdir,install]\""
|
||||
|
||||
puts "\$SRCDIR/configure --with-tcl=\$TCL $configOpts"
|
||||
puts {}
|
||||
puts {OPTS=" -DSQLITE_NO_SYNC=1"}
|
||||
foreach o $opts {
|
||||
puts "OPTS=\"\$OPTS $o\""
|
||||
}
|
||||
puts {}
|
||||
puts "CFLAGS=\"$cflags\""
|
||||
puts {}
|
||||
puts "make $target \"CFLAGS=\$CFLAGS\" \"OPTS=\$OPTS\" $makeOpts"
|
||||
} else {
|
||||
|
||||
puts {set SRCDIR=%1}
|
||||
set makecmd "nmake /f %SRCDIR%\\Makefile.msc TOP=%SRCDIR% $target "
|
||||
append makecmd "\"CFLAGS=$cflags\" \"OPTS=$opts\" $makeOpts"
|
||||
|
||||
puts "set TMP=%CD%"
|
||||
puts $makecmd
|
||||
}
|
||||
}
|
||||
|
||||
proc main_trscript {args} {
|
||||
set bMsvc 0
|
||||
set nArg [llength $args]
|
||||
if {$nArg==3} {
|
||||
if {![is_prefix [lindex $args 0] -msvc 2]} usage
|
||||
set bMsvc 1
|
||||
} elseif {$nArg<2 || $nArg>3} {
|
||||
usage
|
||||
}
|
||||
set config [lindex $args end-1]
|
||||
set srcdir [lindex $args end]
|
||||
|
||||
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]
|
||||
|
||||
if {$::tcl_platform(platform)=="windows" || $bMsvc} {
|
||||
lappend opts -DSQLITE_OS_WIN=1
|
||||
} else {
|
||||
lappend opts -DSQLITE_OS_UNIX=1
|
||||
}
|
||||
|
||||
# Figure out if this is a synthetic ndebug or debug configuration.
|
||||
#
|
||||
set bRemoveDebug 0
|
||||
if {[string match *-ndebug $config]} {
|
||||
set bRemoveDebug 1
|
||||
set config [string range $config 0 end-7]
|
||||
}
|
||||
if {[string match *-debug $config]} {
|
||||
lappend opts -DSQLITE_DEBUG
|
||||
lappend opts -DSQLITE_EXTRA_IFNULLROW
|
||||
set config [string range $config 0 end-6]
|
||||
}
|
||||
regexp {^(.*)-[0-9]+} $config -> config
|
||||
|
||||
# Ensure that the named configuration exists.
|
||||
#
|
||||
if {![info exists ::Configs($config)]} {
|
||||
puts stderr "No such config: $config"
|
||||
exit 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 a "*", discard it.
|
||||
#
|
||||
# 2. If $bRemoveDebug is set and the parameter is -DSQLITE_DEBUG or
|
||||
# -DSQLITE_DEBUG=1, discard it
|
||||
#
|
||||
# 3. If the parameter begins with "-D", add it to $opts.
|
||||
#
|
||||
# 4. 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.
|
||||
#
|
||||
# 5. 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.
|
||||
#
|
||||
# 6. If none of the above apply, add the parameter to $makeOpts
|
||||
#
|
||||
foreach param $::Configs($config) {
|
||||
if {[string range $param 0 0]=="*"} continue
|
||||
|
||||
if {$bRemoveDebug} {
|
||||
if {$param=="-DSQLITE_DEBUG" || $param=="-DSQLITE_DEBUG=1"
|
||||
|| $param=="-DSQLITE_MEMDEBUG" || $param=="-DSQLITE_MEMDEBUG=1"
|
||||
|| $param=="--enable-debug"
|
||||
} {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if {[string range $param 0 1]=="-D"} {
|
||||
lappend opts $param
|
||||
continue
|
||||
}
|
||||
|
||||
if {[string range $param 0 1]=="--"} {
|
||||
if {$bMsvc} {
|
||||
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"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lappend configOpts $param
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# Some configurations specify -DHAVE_USLEEP=0. For all others, add
|
||||
# -DHAVE_USLEEP=1.
|
||||
#
|
||||
if {[lsearch $opts "-DHAVE_USLEEP=0"]<0} {
|
||||
lappend opts -DHAVE_USLEEP=1
|
||||
}
|
||||
|
||||
if {$bMsvc==0} {
|
||||
puts {set -e}
|
||||
puts {}
|
||||
puts {if [ "$#" -ne 1 ] ; then}
|
||||
puts { echo "Usage: $0 <target>" }
|
||||
puts { exit -1 }
|
||||
puts {fi }
|
||||
puts "SRCDIR=\"$srcdir\""
|
||||
puts {}
|
||||
puts "TCL=\"[::tcl::pkgconfig get libdir,install]\""
|
||||
|
||||
puts {if [ ! -f Makefile ] ; then}
|
||||
puts " \$SRCDIR/configure --with-tcl=\$TCL $configOpts"
|
||||
puts {fi}
|
||||
puts {}
|
||||
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\""
|
||||
}
|
||||
puts {}
|
||||
puts "CFLAGS=\"$cflags\""
|
||||
puts {}
|
||||
puts "make \$1 \"CFLAGS=\$CFLAGS\" \"OPTS=\$OPTS\" $makeOpts"
|
||||
} else {
|
||||
|
||||
set srcdir [file nativename [file normalize $srcdir]]
|
||||
# set srcdir [string map [list "\\" "\\\\"] $srcdir]
|
||||
|
||||
puts {set TARGET=%1}
|
||||
set makecmd "nmake /f $srcdir\\Makefile.msc TOP=\"$srcdir\" %TARGET% "
|
||||
append makecmd "\"CFLAGS=$cflags\" \"OPTS=$opts\" $makeOpts"
|
||||
|
||||
puts "set TMP=%CD%"
|
||||
puts $makecmd
|
||||
}
|
||||
}
|
||||
|
||||
proc main_tests {args} {
|
||||
set bNodebug 0
|
||||
set nArg [llength $args]
|
||||
if {$nArg==2} {
|
||||
if {[is_prefix [lindex $args 0] -nodebug 2]} {
|
||||
set bNodebug 1
|
||||
} elseif {[is_prefix [lindex $args 0] -debug 2]} {
|
||||
set bNodebug 0
|
||||
} else usage
|
||||
} elseif {$nArg==0 || $nArg>2} {
|
||||
usage
|
||||
}
|
||||
set p [lindex $args end]
|
||||
if {![info exists ::Platforms($p)]} {
|
||||
puts stderr "No such platform: $p"
|
||||
exit 1
|
||||
}
|
||||
|
||||
set lTest [list]
|
||||
|
||||
foreach {config vars target} $::Platforms($p) {
|
||||
if {[string range $config end end]=="*"} {
|
||||
set config [string range $config 0 end-1]
|
||||
} elseif {$bNodebug==0} {
|
||||
set dtarget test
|
||||
if {[lsearch $target fuzztest]<0 && [lsearch $target test]<0} {
|
||||
set dtarget tcltest
|
||||
}
|
||||
if {$vars!=""} { set dtarget "$vars $dtarget" }
|
||||
|
||||
if {[string first SQLITE_DEBUG $::Configs($config)]>=0
|
||||
|| [string first --enable-debug $::Configs($config)]>=0
|
||||
} {
|
||||
lappend lTest "$config-ndebug \"$dtarget\""
|
||||
} else {
|
||||
lappend lTest "$config-debug \"$dtarget\""
|
||||
}
|
||||
}
|
||||
|
||||
if {[llength $target]==1 && ([string match "*TEST_FAILURE*" $vars] || (
|
||||
[lsearch $target "valgrindtest"]<0
|
||||
&& [lsearch $target "alltest"]<0
|
||||
&& [lsearch $target "fulltestonly"]<0
|
||||
&& ![string match Sanitize* $config]
|
||||
))} {
|
||||
if {$vars!=""} { set target "$vars $target" }
|
||||
lappend lTest "$config \"$target\""
|
||||
} else {
|
||||
set idir -1
|
||||
foreach t $target {
|
||||
if {$t=="valgrindtest" || $t=="alltest" || $t=="fulltestonly"
|
||||
|| [string match Sanitize* $config]
|
||||
} {
|
||||
if {$vars!=""} { set t "$vars $t" }
|
||||
for {set ii 1} {$ii<=4} {incr ii} {
|
||||
lappend lTest "$config-[incr idir] \"TCLTEST_PART=$ii/4 $t\""
|
||||
}
|
||||
} else {
|
||||
if {$vars!=""} { set t "$vars $t" }
|
||||
lappend lTest "$config-[incr idir] \"$t\""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach l $lTest {
|
||||
puts $l
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if {[llength $argv]==0} { usage }
|
||||
set cmd [lindex $argv 0]
|
||||
set n [expr [llength $argv]-1]
|
||||
if {[string match ${cmd}* configurations] && $n==0} {
|
||||
main_configurations
|
||||
} elseif {[string match ${cmd}* script]} {
|
||||
main_script {*}[lrange $argv 1 end]
|
||||
} elseif {[string match ${cmd}* trscript]} {
|
||||
main_trscript {*}[lrange $argv 1 end]
|
||||
} elseif {[string match ${cmd}* platforms] && $n==0} {
|
||||
main_platforms
|
||||
} elseif {[string match ${cmd}* tests]} {
|
||||
main_tests {*}[lrange $argv 1 end]
|
||||
} else {
|
||||
usage
|
||||
}
|
||||
+10
-5
@@ -496,11 +496,16 @@ do_test shell1-3.14.3 {
|
||||
|
||||
# .output FILENAME Send output to FILENAME
|
||||
do_test shell1-3.15.1 {
|
||||
catchcmd "test.db" ".output"
|
||||
} {0 {}}
|
||||
catchcmd "test.db" ".output
|
||||
.print x"
|
||||
} {0 x}
|
||||
do_test shell1-3.15.2 {
|
||||
catchcmd "test.db" ".output FOO"
|
||||
} {0 {}}
|
||||
catchcmd "test.db" ".output FOO
|
||||
.print x
|
||||
.output
|
||||
SELECT readfile('FOO');"
|
||||
} {0 {x
|
||||
}}
|
||||
do_test shell1-3.15.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".output FOO BAD"
|
||||
@@ -1067,7 +1072,7 @@ do_test shell1-5.0 {
|
||||
#
|
||||
set escapes [list \
|
||||
\a \\a \b \\b \t \\t \n \\n \v \\v \f \\f \r \\r \
|
||||
" " "\" \"" \" \\\" ' \"'\" \\ \\\\]
|
||||
" " "\" \"" \" \\\" \\ \\\\]
|
||||
} else {
|
||||
#
|
||||
# NOTE: On Unix, we need to escape most of the whitespace characters
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user