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

Merge the latest trunk enhancements into the reuse-schema branch.

FossilOrigin-Name: f9ce1ababbd62c579658c737059f6992bdb32909e7a06282fe6a359d10ad1272
This commit is contained in:
drh
2024-09-06 15:52:48 +00:00
35 changed files with 1538 additions and 711 deletions

View File

@@ -652,6 +652,7 @@ FUZZCHECK_SRC += $(TOP)/test/fuzzinvariants.c
FUZZCHECK_SRC += $(TOP)/ext/recover/dbdata.c FUZZCHECK_SRC += $(TOP)/ext/recover/dbdata.c
FUZZCHECK_SRC += $(TOP)/ext/recover/sqlite3recover.c FUZZCHECK_SRC += $(TOP)/ext/recover/sqlite3recover.c
FUZZCHECK_SRC += $(TOP)/test/vt02.c FUZZCHECK_SRC += $(TOP)/test/vt02.c
FUZZCHECK_SRC += $(TOP)/ext/misc/percentile.c
FUZZCHECK_SRC += $(TOP)/ext/misc/randomjson.c FUZZCHECK_SRC += $(TOP)/ext/misc/randomjson.c
DBFUZZ_OPT = DBFUZZ_OPT =
ST_OPT = -DSQLITE_OS_KV_OPTIONAL ST_OPT = -DSQLITE_OS_KV_OPTIONAL
@@ -662,11 +663,16 @@ SQLITE3_SHELL_TARGET_ = sqlite3$(TEXE)
SQLITE3_SHELL_TARGET_1 = SQLITE3_SHELL_TARGET_1 =
SQLITE3_SHELL_TARGET = $(SQLITE3_SHELL_TARGET_@HAVE_WASI_SDK@) SQLITE3_SHELL_TARGET = $(SQLITE3_SHELL_TARGET_@HAVE_WASI_SDK@)
# Use $(libtclsqlite3.la_$(HAVE_TCL)) to resolve to either
# libtclsqlite3.la or an empty value.
libtclsqlite3.la_0 =
libtclsqlite3.la_1 = libtclsqlite3.la
# This is the default Makefile target. The objects listed here # This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments. # are what get build when you type just "make" with no arguments.
# #
all: sqlite3.h libsqlite3.la $(SQLITE3_SHELL_TARGET) \ all: sqlite3.h libsqlite3.la $(SQLITE3_SHELL_TARGET) \
$(HAVE_TCL:1=libtclsqlite3.la) $(libtclsqlite3.la_$(HAVE_TCL))
Makefile: $(TOP)/Makefile.in Makefile: $(TOP)/Makefile.in
./config.status ./config.status
@@ -1184,6 +1190,7 @@ SHELL_DEP = \
$(TOP)/ext/misc/ieee754.c \ $(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/memtrace.c \ $(TOP)/ext/misc/memtrace.c \
$(TOP)/ext/misc/pcachetrace.c \ $(TOP)/ext/misc/pcachetrace.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/series.c \ $(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/shathree.c \ $(TOP)/ext/misc/shathree.c \
@@ -1392,7 +1399,7 @@ srctree-check: $(TOP)/tool/srctree-check.tcl
# Testing for a release # Testing for a release
# #
releasetest: srctree-check has_tclsh85 releasetest: srctree-check has_tclsh85 verify-source
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS) $(TCLSH_CMD) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
# Minimal testing that runs in less than 3 minutes # Minimal testing that runs in less than 3 minutes
@@ -1566,7 +1573,12 @@ lib_install: libsqlite3.la
$(INSTALL) -d $(DESTDIR)$(libdir) $(INSTALL) -d $(DESTDIR)$(libdir)
$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir) $(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install} # Use $(tcl_install_$(HAVE_TCL)) to resolve to either tcl_install or
# an empty value.
tcl_install_0 =
tcl_install_1 = tcl_install
install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc $(tcl_install_$(HAVE_TCL))
$(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) -d $(DESTDIR)$(bindir)
$(LTINSTALL) sqlite3$(TEXE) $(DESTDIR)$(bindir) $(LTINSTALL) sqlite3$(TEXE) $(DESTDIR)$(bindir)
$(INSTALL) -d $(DESTDIR)$(includedir) $(INSTALL) -d $(DESTDIR)$(includedir)
@@ -1608,43 +1620,40 @@ tclextension-uninstall:
tclextension-list: tclextension-list:
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info
clean:
rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la # Remove build products sufficient so that subsequent makes will recompile
rm -f sqlite3.h opcodes.* # everything from scratch. Do not remove:
rm -rf .libs .deps #
rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz # * test results and test logs
rm -f mkkeywordhash$(BEXE) keywordhash.h # * output from ./configure
rm -f mksourceid$(BEXE) #
rm -f *.da *.bb *.bbg gmon.out tidy:
rm -rf tsrc .target_source rm -f *.lo *.la *.o *.c *.da *.bb *.bbg gmon.* *.rws sqlite3$(TEXE)
rm -f tclsqlite3$(TEXE) rm -f fts5.h keywordhash.h opcodes.h sqlite3.h sqlite3ext.h sqlite3session.h
rm -f testfixture$(TEXE) test.db rm -rf .libs .deps tsrc .target_source
rm -f lemon$(BEXE) sqlite*.tar.gz
rm -f mkkeywordhash$(BEXE) mksourceid$(BEXE)
rm -f parse.* fts5parse.*
rm -f tclsqlite3$(TEXE) $(TESTPROGS)
rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE) rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE) rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
rm -f wordcount$(TEXE) changeset$(TEXE) rm -f wordcount$(TEXE) changeset$(TEXE) version-info$(TEXE)
rm -f version-info$(TEXT) rm -f *.dll *.lib *.exp *.def *.pc *.vsix *.so *.dylib pkgIndex.tcl
rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def rm -f sqlite3_analyzer$(TEXE)
rm -f sqlite3.c rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
rm -f sqlite3rc.h rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
rm -f shell.c sqlite3ext.h rm -f threadtest5$(TEXE)
rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c rm -f src-verify has_tclsh*
rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe
rm -f rbu rbu.exe
rm -f srcck1 srcck1.exe
rm -f fuzzershell fuzzershell.exe
rm -f fuzzcheck fuzzcheck.exe
rm -f sqldiff sqldiff.exe
rm -f dbhash dbhash.exe
rm -f fts5.* fts5parse.*
rm -f threadtest5
rm -f src-verify
rm -f custom.rws
rm -f has_tclsh84 has_tclsh85
# Removes build products and test logs. Retains ./configure outputs.
#
clean: tidy
rm -rf omittest* testrunner* testdir*
# Clean up everything. No exceptions.
#
distclean: clean distclean: clean
rm -f sqlite_cfg.h config.log config.status libtool Makefile sqlite3.pc \ rm -f sqlite_cfg.h config.log config.status Makefile $(LIBTOOL)
$(TESTPROGS)
# #
# Windows section # Windows section

View File

@@ -938,7 +938,7 @@ TCLSUFFIX =
!ENDIF !ENDIF
!IFNDEF TCLDIR !IFNDEF TCLDIR
TCLDIR = $(TOP)\compat\tcl TCLDIR = C:\Tcl
!ENDIF !ENDIF
!IFNDEF TCLINCDIR !IFNDEF TCLINCDIR
@@ -1768,6 +1768,7 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\percentile.c
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
@@ -2314,6 +2315,7 @@ SHELL_DEP = \
$(TOP)\ext\misc\ieee754.c \ $(TOP)\ext\misc\ieee754.c \
$(TOP)\ext\misc\memtrace.c \ $(TOP)\ext\misc\memtrace.c \
$(TOP)\ext\misc\pcachetrace.c \ $(TOP)\ext\misc\pcachetrace.c \
$(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\regexp.c \ $(TOP)\ext\misc\regexp.c \
$(TOP)\ext\misc\series.c \ $(TOP)\ext\misc\series.c \
$(TOP)\ext\misc\shathree.c \ $(TOP)\ext\misc\shathree.c \

View File

@@ -73,23 +73,26 @@ archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
then click on the "Tarball" or "ZIP Archive" links on the information then click on the "Tarball" or "ZIP Archive" links on the information
page. page.
To access sources directly using Fossil, first install Fossil version 2.0 or later. To access sources directly using [Fossil](https://fossil-scm.org/home),
Source tarballs and precompiled binaries available first install Fossil version 2.0 or later.
[here](https://www.fossil-scm.org/home/uv/download.html). Fossil is Source tarballs and precompiled binaries available at
<https://fossil-scm.org/home/uv/download.html>. Fossil is
a stand-alone program. To install, simply download or build the single a stand-alone program. To install, simply download or build the single
executable file and put that file someplace on your $PATH. executable file and put that file someplace on your $PATH.
Then run commands like this: Then run commands like this:
mkdir -p ~/sqlite ~/Fossils mkdir -p ~/sqlite
cd ~/sqlite cd ~/sqlite
fossil clone https://www.sqlite.org/src ~/Fossils/sqlite.fossil fossil open https://sqlite.org/src
fossil open ~/Fossils/sqlite.fossil
After setting up a repository using the steps above, you can do The "fossil open" command will take two or three minutes. Afterwards,
bandwidth-efficient updates to the latest version using: you can do fast, bandwidth-efficient updates to the whatever versions
of SQLite you like. Some examples:
fossil update trunk ;# latest trunk check-in fossil update trunk ;# latest trunk check-in
fossil update release ;# latest official release fossil update release ;# latest official release
fossil update trunk:2024-01-01 ;# First trunk check-in after 2024-01-01
fossil update version-3.39.0 ;# Version 3.39.0
Or type "fossil ui" to get a web-based user interface. Or type "fossil ui" to get a web-based user interface.
@@ -103,17 +106,19 @@ script found at the root of the source tree. Then run "make".
For example: For example:
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite" apt install gcc make tcl-dev ;# Make sure you have all the necessary build tools
mkdir bld ;# Build will occur in a sibling directory tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
cd bld ;# Change to the build directory mkdir bld ;# Build will occur in a sibling directory
../sqlite/configure ;# Run the configure script cd bld ;# Change to the build directory
make sqlite3 ;# Builds the "sqlite3" command-line tool ../sqlite/configure ;# Run the configure script
make sqlite3.c ;# Build the "amalgamation" source file make sqlite3 ;# Builds the "sqlite3" command-line tool
make devtest ;# Run development tests (requires tcl-dev) make sqlite3.c ;# Build the "amalgamation" source file
make releasetest ;# Run full release tests (requires tcl-dev) make sqldiff ;# Builds the "sqldiff" command-line tool
make sqldiff ;# Builds the "sqldiff" command-line tool # Makefile targets below this point require tcl-dev
make sqlite3_analyzer ;# Builds the "sqlite3_analyzer" tool (requires tcl-dev) make tclextension-install ;# Build and install the SQLite TCL extension
make tclextension-install ;# Build and install the SQLite TCL extension make devtest ;# Run development tests
make releasetest ;# Run full release tests
make sqlite3_analyzer ;# Builds the "sqlite3_analyzer" tool
See the makefile for additional targets. For debugging builds, the See the makefile for additional targets. For debugging builds, the
core developers typically run "configure" with options like this: core developers typically run "configure" with options like this:
@@ -124,9 +129,12 @@ For release builds, the core developers usually do:
../sqlite/configure --enable-all ../sqlite/configure --enable-all
Almost all makefile targets require a "tclsh" TCL interpreter Almost all makefile targets require a "tclsh" TCL interpreter version 8.6 or
version 8.6 or later. The targets marked with "(requires tcl-dev)" also require later. The "tclextension-install" target and the test targets that follow
the TCL development libraries. all require TCL development libraries too. ("apt install tcl-dev"). It is
helpful, but is not required, to install the SQLite TCL extension (the
"tclextension-install" target) prior to running tests. The "releasetest"
target has additional requiremenst, such as "valgrind".
On "make" command-lines, one can add "OPTIONS=..." to specify additional On "make" command-lines, one can add "OPTIONS=..." to specify additional
compile-time options over and above those set by ./configure. For example, compile-time options over and above those set by ./configure. For example,
@@ -143,7 +151,7 @@ show what changes are needed.
## Compiling for Windows Using MSVC ## Compiling for Windows Using MSVC
On Windows, all applicable build products can be compiled with MSVC. On Windows, everything can be compiled with MSVC.
You will also need a working installation of TCL. You will also need a working installation of TCL.
See the [compile-for-windows.md](doc/compile-for-windows.md) document for See the [compile-for-windows.md](doc/compile-for-windows.md) document for
additional information about how to install MSVC and TCL and configure your additional information about how to install MSVC and TCL and configure your
@@ -157,15 +165,21 @@ TCL library, using a command like this:
SQLite uses "tclsh.exe" as part of the build process, and so that SQLite uses "tclsh.exe" as part of the build process, and so that
program will need to be somewhere on your %PATH%. SQLite itself program will need to be somewhere on your %PATH%. SQLite itself
does not contain any TCL code, but it does use TCL to help with the does not contain any TCL code, but it does use TCL to help with the
build process and to run tests. build process and to run tests. You may need to install TCL development
libraries in order to successfully complete some makefile targets.
It is helpful, but is not required, to install the SQLite TCL extension
(the "tclextension-install" target) prior to running tests.
Build using Makefile.msc. Example: Build using Makefile.msc. Example:
nmake /f Makefile.msc sqlite3.exe nmake /f Makefile.msc sqlite3.exe
nmake /f Makefile.msc sqlite3.c nmake /f Makefile.msc sqlite3.c
nmake /f Makefile.msc sqldiff.exe
# Makefile targets below this point require TCL development libraries
nmake /f Makefile.msc tclextension-install
nmake /f Makefile.msc devtest nmake /f Makefile.msc devtest
nmake /f Makefile.msc releasetest nmake /f Makefile.msc releasetest
nmake /f Makefile.msc tclextension-install nmake /f Makefile.msc sqlite3_analyzer.exe
There are many other makefile targets. See comments in Makefile.msc for There are many other makefile targets. See comments in Makefile.msc for
details. details.
@@ -372,7 +386,7 @@ implementation. It will not be the easiest library in the world to hack.
* **VERSION**, **manifest**, and **manifest.uuid** - These files define * **VERSION**, **manifest**, and **manifest.uuid** - These files define
the current SQLite version number. The "VERSION" file is human generated, the current SQLite version number. The "VERSION" file is human generated,
but the "manifest" and "manifest.uuid" files are automatically generated but the "manifest" and "manifest.uuid" files are automatically generated
by the [Fossil version control system](https://fossil-scm/). by the [Fossil version control system](https://fossil-scm.org/).
There are many other source files. Each has a succinct header comment that There are many other source files. Each has a succinct header comment that
describes its purpose and role within the larger system. describes its purpose and role within the larger system.

View File

@@ -57,11 +57,22 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
<ul> <ul>
<li> `nmake /f makefile.msc` <li> `nmake /f makefile.msc`
<li> `nmake /f makefile.msc sqlite3.c` <li> `nmake /f makefile.msc sqlite3.c`
<li> `nmake /f makefile.msc sqlite3.exe`
<li> `nmake /f makefile.msc sqldiff.exe`
<li> `nmake /f makefile.msc tclextension-install`
<li> `nmake /f makefile.msc devtest` <li> `nmake /f makefile.msc devtest`
<li> `nmake /f makefile.msc releasetest` <li> `nmake /f makefile.msc releasetest`
<li> `nmake /f makefile.msc sqlite3.exe` <li> `nmake /f makefile.msc sqlite3_analyzer.exe`
</ul> </ul>
It is not required that you run the "tclextension-install" target prior to
running tests. However, the tests will run more smoothly if you do.
The version of SQLite used for the TCL extension does *not* need to
correspond to the version of SQLite under test. So you can install the
SQLite TCL extension once, and then use it to test many different versions
of SQLite.
7. For a debugging build of the CLI, where the ".treetrace" and ".wheretrace" 7. For a debugging build of the CLI, where the ".treetrace" and ".wheretrace"
commands work, add the DEBUG=3 argument to nmake. Like this: commands work, add the DEBUG=3 argument to nmake. Like this:
<ul> <ul>

View File

@@ -655,6 +655,10 @@ cfWrite(const void *buf, size_t osz, size_t ocnt, FILE *pf){
return rv; return rv;
} }
/* An fgets() equivalent, using Win32 file API for actual input.
** Input ends when given buffer is filled or a newline is read.
** If the FILE object is in text mode, swallows 0x0D. (ASCII CR)
*/
SQLITE_INTERNAL_LINKAGE char * SQLITE_INTERNAL_LINKAGE char *
cfGets(char *cBuf, int n, FILE *pf){ cfGets(char *cBuf, int n, FILE *pf){
int nci = 0; int nci = 0;
@@ -665,7 +669,10 @@ cfGets(char *cBuf, int n, FILE *pf){
while( nci < n-1 ){ while( nci < n-1 ){
DWORD nr; DWORD nr;
if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break; if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break;
if( nr>0 && (!eatCR || cBuf[nci]!='\r') ) nci += nr; if( nr>0 && (!eatCR || cBuf[nci]!='\r') ){
nci += nr;
if( cBuf[nci-nr]=='\n' ) break;
}
} }
if( nci < n ) cBuf[nci] = 0; if( nci < n ) cBuf[nci] = 0;
return (nci>0)? cBuf : 0; return (nci>0)? cBuf : 0;

View File

@@ -2185,7 +2185,7 @@ static void fts5SegIterNext_None(
if( iOff<pIter->iEndofDoclist ){ if( iOff<pIter->iEndofDoclist ){
/* Next entry is on the current page */ /* Next entry is on the current page */
i64 iDelta; u64 iDelta;
iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta); iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
pIter->iLeafOffset = iOff; pIter->iLeafOffset = iOff;
pIter->iRowid += iDelta; pIter->iRowid += iDelta;

View File

@@ -0,0 +1,56 @@
# 2024 September 3
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests focused on the integrity-check procedure.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5integrity2
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t2 USING fts5(a, detail='none');
BEGIN;
INSERT INTO t2(rowid, a) VALUES(-1, 'hello world');
INSERT INTO t2(rowid, a) VALUES(9223372036854775807, 'hello world');
COMMIT;
}
do_execsql_test 2.1 {
SELECT rowid FROM t2('hello AND world');
} {-1 9223372036854775807}
#-------------------------------------------------------------------------
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, detail='none');
CREATE TABLE r1(r);
WITH c(x) AS (VALUES(1) UNION SELECT x<<1 FROM c)
INSERT INTO r1(r) SELECT -1-x FROM c;
INSERT INTO t1(rowid, a) SELECT r, 'abc' FROM r1;
}
do_execsql_test 2.1 {
PRAGMA integrity_check;
} {ok}
do_execsql_test 2.2 {
SELECT rowid FROM t1('abc') ORDER BY +rowid;
} [db eval {SELECT r FROM r1 ORDER BY r}]
finish_test

View File

@@ -11,7 +11,7 @@
****************************************************************************** ******************************************************************************
** **
** This file contains code to implement the percentile(Y,P) SQL function ** This file contains code to implement the percentile(Y,P) SQL function
** as described below: ** and similar as described below:
** **
** (1) The percentile(Y,P) function is an aggregate function taking ** (1) The percentile(Y,P) function is an aggregate function taking
** exactly two arguments. ** exactly two arguments.
@@ -60,31 +60,105 @@
** **
** (13) A separate median(Y) function is the equivalent percentile(Y,50). ** (13) A separate median(Y) function is the equivalent percentile(Y,50).
** **
** (14) A separate percentile_cond(Y,X) function is the equivalent of ** (14) A separate percentile_cont(Y,P) function is equivalent to
** percentile(Y,X*100.0). ** percentile(Y,P/100.0). In other words, the fraction value in
** the second argument is in the range of 0 to 1 instead of 0 to 100.
**
** (15) A separate percentile_disc(Y,P) function is like
** percentile_cont(Y,P) except that instead of returning the weighted
** average of the nearest two input values, it returns the next lower
** value. So the percentile_disc(Y,P) will always return a value
** that was one of the inputs.
**
** (16) All of median(), percentile(Y,P), percentile_cont(Y,P) and
** percentile_disc(Y,P) can be used as window functions.
**
** Differences from standard SQL:
**
** * The percentile_cont(X,P) function is equivalent to the following in
** standard SQL:
**
** (percentile_cont(P) WITHIN GROUP (ORDER BY X))
**
** The SQLite syntax is much more compact. The standard SQL syntax
** is also supported if SQLite is compiled with the
** -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES option.
**
** * No median(X) function exists in the SQL standard. App developers
** are expected to write "percentile_cont(0.5)WITHIN GROUP(ORDER BY X)".
**
** * No percentile(Y,P) function exists in the SQL standard. Instead of
** percential(Y,P), developers must write this:
** "percentile_cont(P/100.0) WITHIN GROUP (ORDER BY Y)". Note that
** the fraction parameter to percentile() goes from 0 to 100 whereas
** the fraction parameter in SQL standard percentile_cont() goes from
** 0 to 1.
**
** Implementation notes as of 2024-08-31:
**
** * The regular aggregate-function versions of these routines work
** by accumulating all values in an array of doubles, then sorting
** that array using quicksort before computing the answer. Thus
** the runtime is O(NlogN) where N is the number of rows of input.
**
** * For the window-function versions of these routines, the array of
** inputs is sorted as soon as the first value is computed. Thereafter,
** the array is kept in sorted order using an insert-sort. This
** results in O(N*K) performance where K is the size of the window.
** One can imagine alternative implementations that give O(N*logN*logK)
** performance, but they require more complex logic and data structures.
** The developers have elected to keep the asymptotically slower
** algorithm for now, for simplicity, under the theory that window
** functions are seldom used and when they are, the window size K is
** often small. The developers might revisit that decision later,
** should the need arise.
*/ */
#include "sqlite3ext.h" #if defined(SQLITE3_H)
SQLITE_EXTENSION_INIT1 /* no-op */
#elif defined(SQLITE_STATIC_PERCENTILE)
# include "sqlite3.h"
#else
# include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#endif
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
/* The following object is the session context for a single percentile() /* The following object is the group context for a single percentile()
** function. We have to remember all input Y values until the very end. ** aggregate. Remember all input Y values until the very end.
** Those values are accumulated in the Percentile.a[] array. ** Those values are accumulated in the Percentile.a[] array.
*/ */
typedef struct Percentile Percentile; typedef struct Percentile Percentile;
struct Percentile { struct Percentile {
unsigned nAlloc; /* Number of slots allocated for a[] */ unsigned nAlloc; /* Number of slots allocated for a[] */
unsigned nUsed; /* Number of slots actually used in a[] */ unsigned nUsed; /* Number of slots actually used in a[] */
double rPct; /* 1.0 more than the value for P */ char bSorted; /* True if a[] is already in sorted order */
char bKeepSorted; /* True if advantageous to keep a[] sorted */
char bPctValid; /* True if rPct is valid */
double rPct; /* Fraction. 0.0 to 1.0 */
double *a; /* Array of Y values */ double *a; /* Array of Y values */
}; };
/* Details of each function in the percentile family */
typedef struct PercentileFunc PercentileFunc;
struct PercentileFunc {
const char *zName; /* Function name */
char nArg; /* Number of arguments */
char mxFrac; /* Maximum value of the "fraction" input */
char bDiscrete; /* True for percentile_disc() */
};
static const PercentileFunc aPercentFunc[] = {
{ "median", 1, 1, 0 },
{ "percentile", 2, 100, 0 },
{ "percentile_cont", 2, 1, 0 },
{ "percentile_disc", 2, 1, 1 },
};
/* /*
** Return TRUE if the input floating-point number is an infinity. ** Return TRUE if the input floating-point number is an infinity.
*/ */
static int isInfinity(double r){ static int percentIsInfinity(double r){
sqlite3_uint64 u; sqlite3_uint64 u;
assert( sizeof(u)==sizeof(r) ); assert( sizeof(u)==sizeof(r) );
memcpy(&u, &r, sizeof(u)); memcpy(&u, &r, sizeof(u));
@@ -92,13 +166,64 @@ static int isInfinity(double r){
} }
/* /*
** Return TRUE if two doubles differ by 0.001 or less ** Return TRUE if two doubles differ by 0.001 or less.
*/ */
static int sameValue(double a, double b){ static int percentSameValue(double a, double b){
a -= b; a -= b;
return a>=-0.001 && a<=0.001; return a>=-0.001 && a<=0.001;
} }
/*
** Search p (which must have p->bSorted) looking for an entry with
** value y. Return the index of that entry.
**
** If bExact is true, return -1 if the entry is not found.
**
** If bExact is false, return the index at which a new entry with
** value y should be insert in order to keep the values in sorted
** order. The smallest return value in this case will be 0, and
** the largest return value will be p->nUsed.
*/
static int percentBinarySearch(Percentile *p, double y, int bExact){
int iFirst = 0; /* First element of search range */
int iLast = p->nUsed - 1; /* Last element of search range */
while( iLast>=iFirst ){
int iMid = (iFirst+iLast)/2;
double x = p->a[iMid];
if( x<y ){
iFirst = iMid + 1;
}else if( x>y ){
iLast = iMid - 1;
}else{
return iMid;
}
}
if( bExact ) return -1;
return iFirst;
}
/*
** Generate an error for a percentile function.
**
** The error format string must have exactly one occurrance of "%%s()"
** (with two '%' characters). That substring will be replaced by the name
** of the function.
*/
static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
char *zMsg1;
char *zMsg2;
va_list ap;
va_start(ap, zFormat);
zMsg1 = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, pFunc->zName) : 0;
sqlite3_result_error(pCtx, zMsg2, -1);
sqlite3_free(zMsg1);
sqlite3_free(zMsg2);
}
/* /*
** The "step" function for percentile(Y,P) is called once for each ** The "step" function for percentile(Y,P) is called once for each
** input row. ** input row.
@@ -112,28 +237,20 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
if( argc==1 ){ if( argc==1 ){
/* Requirement 13: median(Y) is the same as percentile(Y,50). */ /* Requirement 13: median(Y) is the same as percentile(Y,50). */
rPct = 50.0; rPct = 0.5;
}else if( sqlite3_user_data(pCtx)==0 ){
/* Requirement 3: P must be a number between 0 and 100 */
eType = sqlite3_value_numeric_type(argv[1]);
rPct = sqlite3_value_double(argv[1]);
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
|| rPct<0.0 || rPct>100.0 ){
sqlite3_result_error(pCtx, "2nd argument to percentile() is not "
"a number between 0.0 and 100.0", -1);
return;
}
}else{ }else{
/* Requirement 3: P must be a number between 0 and 1 */ /* Requirement 3: P must be a number between 0 and 100 */
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
eType = sqlite3_value_numeric_type(argv[1]); eType = sqlite3_value_numeric_type(argv[1]);
rPct = sqlite3_value_double(argv[1]); rPct = sqlite3_value_double(argv[1])/(double)pFunc->mxFrac;
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
|| rPct<0.0 || rPct>1.0 ){ || rPct<0.0 || rPct>1.0
sqlite3_result_error(pCtx, "2nd argument to percentile_cont() is not " ){
"a number between 0.0 and 1.0", -1); percentError(pCtx, "the fraction argument to %%s()"
" is not between 0.0 and %.1f",
(double)pFunc->mxFrac);
return; return;
} }
rPct *= 100.0;
} }
/* Allocate the session context. */ /* Allocate the session context. */
@@ -142,11 +259,12 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
/* Remember the P value. Throw an error if the P value is different /* Remember the P value. Throw an error if the P value is different
** from any prior row, per Requirement (2). */ ** from any prior row, per Requirement (2). */
if( p->rPct==0.0 ){ if( !p->bPctValid ){
p->rPct = rPct+1.0; p->rPct = rPct;
}else if( !sameValue(p->rPct,rPct+1.0) ){ p->bPctValid = 1;
sqlite3_result_error(pCtx, "2nd argument to percentile() is not the " }else if( !percentSameValue(p->rPct,rPct) ){
"same for all input rows", -1); percentError(pCtx, "the fraction argument to %%s()"
" is not the same for all input rows");
return; return;
} }
@@ -157,15 +275,14 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
/* If not NULL, then Y must be numeric. Otherwise throw an error. /* If not NULL, then Y must be numeric. Otherwise throw an error.
** Requirement 4 */ ** Requirement 4 */
if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){ if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
sqlite3_result_error(pCtx, "1st argument to percentile() is not " percentError(pCtx, "input to %%s() is not numeric");
"numeric", -1);
return; return;
} }
/* Throw an error if the Y value is infinity or NaN */ /* Throw an error if the Y value is infinity or NaN */
y = sqlite3_value_double(argv[0]); y = sqlite3_value_double(argv[0]);
if( isInfinity(y) ){ if( percentIsInfinity(y) ){
sqlite3_result_error(pCtx, "Inf input to percentile()", -1); percentError(pCtx, "Inf input to %%s()");
return; return;
} }
@@ -182,50 +299,80 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
p->nAlloc = n; p->nAlloc = n;
p->a = a; p->a = a;
} }
p->a[p->nUsed++] = y; if( p->nUsed==0 ){
p->a[p->nUsed++] = y;
p->bSorted = 1;
}else if( !p->bSorted || y>=p->a[p->nUsed-1] ){
p->a[p->nUsed++] = y;
}else if( p->bKeepSorted ){
int i;
i = percentBinarySearch(p, y, 0);
if( i<(int)p->nUsed ){
memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0]));
}
p->a[i] = y;
p->nUsed++;
}else{
p->a[p->nUsed++] = y;
p->bSorted = 0;
}
} }
/* /*
** Sort an array of doubles. ** Interchange two doubles.
*/ */
static void sortDoubles(double *a, int n){ #define SWAP_DOUBLE(X,Y) {double ttt=(X);(X)=(Y);(Y)=ttt;}
int iLt; /* Entries with index less than iLt are less than rPivot */
int iGt; /* Entries with index iGt or more are greater than rPivot */ /*
** Sort an array of doubles.
**
** Algorithm: quicksort
**
** This is implemented separately rather than using the qsort() routine
** from the standard library because:
**
** (1) To avoid a dependency on qsort()
** (2) To avoid the function call to the comparison routine for each
** comparison.
*/
static void percentSort(double *a, unsigned int n){
int iLt; /* Entries before a[iLt] are less than rPivot */
int iGt; /* Entries at or after a[iGt] are greater than rPivot */
int i; /* Loop counter */ int i; /* Loop counter */
double rPivot; /* The pivot value */ double rPivot; /* The pivot value */
double rTmp; /* Temporary used to swap two values */
assert( n>=2 );
if( n<2 ) return; if( a[0]>a[n-1] ){
if( n>5 ){ SWAP_DOUBLE(a[0],a[n-1])
rPivot = (a[0] + a[n/2] + a[n-1])/3.0;
}else{
rPivot = a[n/2];
} }
iLt = i = 0; if( n==2 ) return;
iGt = n; iGt = n-1;
while( i<iGt ){ i = n/2;
if( a[0]>a[i] ){
SWAP_DOUBLE(a[0],a[i])
}else if( a[i]>a[iGt] ){
SWAP_DOUBLE(a[i],a[iGt])
}
if( n==3 ) return;
rPivot = a[i];
iLt = i = 1;
do{
if( a[i]<rPivot ){ if( a[i]<rPivot ){
if( i>iLt ){ if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
rTmp = a[i];
a[i] = a[iLt];
a[iLt] = rTmp;
}
iLt++; iLt++;
i++; i++;
}else if( a[i]>rPivot ){ }else if( a[i]>rPivot ){
do{ do{
iGt--; iGt--;
}while( iGt>i && a[iGt]>rPivot ); }while( iGt>i && a[iGt]>rPivot );
rTmp = a[i]; SWAP_DOUBLE(a[i],a[iGt])
a[i] = a[iGt];
a[iGt] = rTmp;
}else{ }else{
i++; i++;
} }
} }while( i<iGt );
if( iLt>=2 ) sortDoubles(a, iLt); if( iLt>=2 ) percentSort(a, iLt);
if( n-iGt>=2 ) sortDoubles(a+iGt, n-iGt); if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
/* Uncomment for testing */ /* Uncomment for testing */
#if 0 #if 0
for(i=0; i<n-1; i++){ for(i=0; i<n-1; i++){
@@ -234,12 +381,61 @@ static void sortDoubles(double *a, int n){
#endif #endif
} }
/* /*
** Called to compute the final output of percentile() and to clean ** The "inverse" function for percentile(Y,P) is called to remove a
** up all allocated memory. ** row that was previously inserted by "step".
*/ */
static void percentFinal(sqlite3_context *pCtx){ static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
Percentile *p; Percentile *p;
int eType;
double y;
int i;
assert( argc==2 || argc==1 );
/* Allocate the session context. */
p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
assert( p!=0 );
/* Ignore rows for which Y is NULL */
eType = sqlite3_value_type(argv[0]);
if( eType==SQLITE_NULL ) return;
/* If not NULL, then Y must be numeric. Otherwise throw an error.
** Requirement 4 */
if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
return;
}
/* Ignore the Y value if it is infinity or NaN */
y = sqlite3_value_double(argv[0]);
if( percentIsInfinity(y) ){
return;
}
if( p->bSorted==0 ){
assert( p->nUsed>1 );
percentSort(p->a, p->nUsed);
p->bSorted = 1;
}
p->bKeepSorted = 1;
/* Find and remove the row */
i = percentBinarySearch(p, y, 1);
if( i>=0 ){
p->nUsed--;
if( i<(int)p->nUsed ){
memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0]));
}
}
}
/*
** Compute the final output of percentile(). Clean up all allocated
** memory if and only if bIsFinal is true.
*/
static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
Percentile *p;
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
unsigned i1, i2; unsigned i1, i2;
double v1, v2; double v1, v2;
double ix, vx; double ix, vx;
@@ -247,21 +443,38 @@ static void percentFinal(sqlite3_context *pCtx){
if( p==0 ) return; if( p==0 ) return;
if( p->a==0 ) return; if( p->a==0 ) return;
if( p->nUsed ){ if( p->nUsed ){
sortDoubles(p->a, p->nUsed); if( p->bSorted==0 ){
ix = (p->rPct-1.0)*(p->nUsed-1)*0.01; assert( p->nUsed>1 );
percentSort(p->a, p->nUsed);
p->bSorted = 1;
}
ix = p->rPct*(p->nUsed-1);
i1 = (unsigned)ix; i1 = (unsigned)ix;
i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1; if( pFunc->bDiscrete ){
v1 = p->a[i1]; vx = p->a[i1];
v2 = p->a[i2]; }else{
vx = v1 + (v2-v1)*(ix-i1); i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
v1 = p->a[i1];
v2 = p->a[i2];
vx = v1 + (v2-v1)*(ix-i1);
}
sqlite3_result_double(pCtx, vx); sqlite3_result_double(pCtx, vx);
} }
sqlite3_free(p->a); if( bIsFinal ){
memset(p, 0, sizeof(*p)); sqlite3_free(p->a);
memset(p, 0, sizeof(*p));
}else{
p->bKeepSorted = 1;
}
}
static void percentFinal(sqlite3_context *pCtx){
percentCompute(pCtx, 1);
}
static void percentValue(sqlite3_context *pCtx){
percentCompute(pCtx, 0);
} }
#if defined(_WIN32) && !defined(SQLITE3_H) && !defined(SQLITE_STATIC_PERCENTILE)
#ifdef _WIN32
__declspec(dllexport) __declspec(dllexport)
#endif #endif
int sqlite3_percentile_init( int sqlite3_percentile_init(
@@ -270,20 +483,21 @@ int sqlite3_percentile_init(
const sqlite3_api_routines *pApi const sqlite3_api_routines *pApi
){ ){
int rc = SQLITE_OK; int rc = SQLITE_OK;
unsigned int i;
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
(void)pApi; /* Unused parameter */
#else
SQLITE_EXTENSION_INIT2(pApi); SQLITE_EXTENSION_INIT2(pApi);
#endif
(void)pzErrMsg; /* Unused parameter */ (void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "percentile", 2, for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
SQLITE_UTF8|SQLITE_INNOCUOUS, 0, rc = sqlite3_create_window_function(db,
0, percentStep, percentFinal); aPercentFunc[i].zName,
if( rc==SQLITE_OK ){ aPercentFunc[i].nArg,
rc = sqlite3_create_function(db, "median", 1, SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_SELFORDER1,
SQLITE_UTF8|SQLITE_INNOCUOUS, 0, (void*)&aPercentFunc[i],
0, percentStep, percentFinal); percentStep, percentFinal, percentValue, percentInverse, 0);
} if( rc ) break;
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "percentile_cont", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS, &percentStep,
0, percentStep, percentFinal);
} }
return rc; return rc;
} }

View File

@@ -336,6 +336,27 @@ struct RbuFrame {
u32 iWalFrame; u32 iWalFrame;
}; };
#ifndef UNUSED_PARAMETER
/*
** The following macros are used to suppress compiler warnings and to
** make it clear to human readers when a function parameter is deliberately
** left unused within the body of a function. This usually happens when
** a function is called via a function pointer. For example the
** implementation of an SQL aggregate step callback may not use the
** parameter indicating the number of arguments passed to the aggregate,
** if it knows that this is enforced elsewhere.
**
** When a function parameter is not used at all within the body of a function,
** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
** However, these macros may also be used to suppress warnings related to
** parameters that may or may not be used depending on compilation options.
** For example those parameters only used in assert() statements. In these
** cases the parameters are named as per the usual conventions.
*/
#define UNUSED_PARAMETER(x) (void)(x)
#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
#endif
/* /*
** RBU handle. ** RBU handle.
** **
@@ -387,7 +408,7 @@ struct sqlite3rbu {
int rc; /* Value returned by last rbu_step() call */ int rc; /* Value returned by last rbu_step() call */
char *zErrmsg; /* Error message if rc!=SQLITE_OK */ char *zErrmsg; /* Error message if rc!=SQLITE_OK */
int nStep; /* Rows processed for current object */ int nStep; /* Rows processed for current object */
int nProgress; /* Rows processed for all objects */ sqlite3_int64 nProgress; /* Rows processed for all objects */
RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ RbuObjIter objiter; /* Iterator for skipping through tbl/idx */
const char *zVfsName; /* Name of automatically created rbu vfs */ const char *zVfsName; /* Name of automatically created rbu vfs */
rbu_file *pTargetFd; /* File handle open on target db */ rbu_file *pTargetFd; /* File handle open on target db */
@@ -504,7 +525,7 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
v = (v<<6) + c; v = (v<<6) + c;
} }
z--; z--;
*pLen -= z - zStart; *pLen -= (int)(z - zStart);
*pz = (char*)z; *pz = (char*)z;
return v; return v;
} }
@@ -689,6 +710,7 @@ static void rbuFossilDeltaFunc(
char *aOut; char *aOut;
assert( argc==2 ); assert( argc==2 );
UNUSED_PARAMETER(argc);
nOrig = sqlite3_value_bytes(argv[0]); nOrig = sqlite3_value_bytes(argv[0]);
aOrig = (const char*)sqlite3_value_blob(argv[0]); aOrig = (const char*)sqlite3_value_blob(argv[0]);
@@ -2268,13 +2290,13 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
else if( c==')' ){ else if( c==')' ){
nParen--; nParen--;
if( nParen==0 ){ if( nParen==0 ){
int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan; int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
pIter->aIdxCol[iIdxCol++].nSpan = nSpan; pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
i++; i++;
break; break;
} }
}else if( c==',' && nParen==1 ){ }else if( c==',' && nParen==1 ){
int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan; int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
pIter->aIdxCol[iIdxCol++].nSpan = nSpan; pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1]; pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1];
}else if( c=='"' || c=='\'' || c=='`' ){ }else if( c=='"' || c=='\'' || c=='`' ){
@@ -2964,6 +2986,8 @@ static void rbuFileSuffix3(const char *zBase, char *z){
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4); if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4);
} }
#else
UNUSED_PARAMETER2(zBase,z);
#endif #endif
} }
@@ -3548,7 +3572,7 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){
"(%d, %Q), " "(%d, %Q), "
"(%d, %Q), " "(%d, %Q), "
"(%d, %d), " "(%d, %d), "
"(%d, %d), " "(%d, %lld), "
"(%d, %lld), " "(%d, %lld), "
"(%d, %lld), " "(%d, %lld), "
"(%d, %lld), " "(%d, %lld), "
@@ -3906,6 +3930,7 @@ static void rbuIndexCntFunc(
sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain); sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);
assert( nVal==1 ); assert( nVal==1 );
UNUSED_PARAMETER(nVal);
rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg, rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg,
sqlite3_mprintf("SELECT count(*) FROM sqlite_schema " sqlite3_mprintf("SELECT count(*) FROM sqlite_schema "
@@ -4181,7 +4206,7 @@ sqlite3rbu *sqlite3rbu_vacuum(
){ ){
if( zTarget==0 ){ return rbuMisuseError(); } if( zTarget==0 ){ return rbuMisuseError(); }
if( zState ){ if( zState ){
int n = strlen(zState); size_t n = strlen(zState);
if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){ if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
return rbuMisuseError(); return rbuMisuseError();
} }
@@ -4398,6 +4423,7 @@ int sqlite3rbu_savestate(sqlite3rbu *p){
*/ */
static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){ static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){
int rc = SQLITE_OK; int rc = SQLITE_OK;
UNUSED_PARAMETER(pArg);
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
{ {
LPWSTR zWideOld; LPWSTR zWideOld;
@@ -5302,6 +5328,9 @@ static int rbuVfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
** No-op. ** No-op.
*/ */
static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){ static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){
UNUSED_PARAMETER(pVfs);
UNUSED_PARAMETER(a);
UNUSED_PARAMETER(b);
return 0; return 0;
} }

View File

@@ -383,10 +383,10 @@ static int SQLITE_TCLAPI test_session_cmd(
{ "rowid", SQLITE_SESSION_OBJCONFIG_ROWID }, { "rowid", SQLITE_SESSION_OBJCONFIG_ROWID },
{ 0, 0 } { 0, 0 }
}; };
size_t sz = sizeof(aOpt[0]); int sz = (int)sizeof(aOpt[0]);
int iArg; int iArg;
int iOpt; Tcl_Size iOpt;
if( Tcl_GetIndexFromObjStruct(interp,objv[2],aOpt,sz,"option",0,&iOpt) ){ if( Tcl_GetIndexFromObjStruct(interp,objv[2],aOpt,sz,"option",0,&iOpt) ){
return TCL_ERROR; return TCL_ERROR;
} }
@@ -803,7 +803,7 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
if( bV2 ){ if( bV2 ){
while( objc>1 ){ while( objc>1 ){
const char *z1 = Tcl_GetString(objv[1]); const char *z1 = Tcl_GetString(objv[1]);
int n = strlen(z1); int n = (int)strlen(z1);
if( n>3 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){ if( n>3 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){
flags |= SQLITE_CHANGESETAPPLY_NOSAVEPOINT; flags |= SQLITE_CHANGESETAPPLY_NOSAVEPOINT;
} }
@@ -1119,7 +1119,7 @@ static int SQLITE_TCLAPI test_sqlite3session_foreach(
while( objc>1 ){ while( objc>1 ){
char *zOpt = Tcl_GetString(objv[1]); char *zOpt = Tcl_GetString(objv[1]);
int nOpt = strlen(zOpt); int nOpt = (int)strlen(zOpt);
if( zOpt[0]!='-' ) break; if( zOpt[0]!='-' ) break;
if( nOpt<=7 && 0==sqlite3_strnicmp(zOpt, "-invert", nOpt) ){ if( nOpt<=7 && 0==sqlite3_strnicmp(zOpt, "-invert", nOpt) ){
isInvert = 1; isInvert = 1;

59
main.mk
View File

@@ -543,6 +543,7 @@ FUZZSRC += $(TOP)/test/vt02.c
FUZZSRC += $(TOP)/test/fuzzinvariants.c FUZZSRC += $(TOP)/test/fuzzinvariants.c
FUZZSRC += $(TOP)/ext/recover/dbdata.c FUZZSRC += $(TOP)/ext/recover/dbdata.c
FUZZSRC += $(TOP)/ext/recover/sqlite3recover.c FUZZSRC += $(TOP)/ext/recover/sqlite3recover.c
FUZZSRC += $(TOP)/ext/misc/percentile.c
FUZZSRC += $(TOP)/ext/misc/randomjson.c FUZZSRC += $(TOP)/ext/misc/randomjson.c
DBFUZZ_OPT = DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
@@ -766,6 +767,7 @@ SHELL_DEP = \
$(TOP)/ext/misc/ieee754.c \ $(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/memtrace.c \ $(TOP)/ext/misc/memtrace.c \
$(TOP)/ext/misc/pcachetrace.c \ $(TOP)/ext/misc/pcachetrace.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/series.c \ $(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/shathree.c \ $(TOP)/ext/misc/shathree.c \
@@ -1132,41 +1134,22 @@ install: sqlite3 libsqlite3.a sqlite3.h
mv sqlite3.h /usr/include mv sqlite3.h /usr/include
clean: clean:
rm -f *.o sqlite3 sqlite3.exe libsqlite3.a sqlite3.h opcodes.* rm -f *.lo *.la *.o *.c *.h *.da *.bb *.bbg gmon.* *.rws sqlite3$(TEXE)
rm -f lemon lemon.exe lempar.c parse.* sqlite*.tar.gz rm -rf .libs .deps tsrc libtool target_source testrunner_*
rm -f mkkeywordhash mkkeywordhash.exe keywordhash.h rm -f lemon$(BEXE) sqlite*.tar.gz
rm -f $(PUBLISH) rm -f mkkeywordhash$(BEXE) mksourceid$(BEXE)
rm -f *.da *.bb *.bbg gmon.out rm -f parse.* fts5parse.*
rm -rf tsrc target_source rm -rf tsrc .target_source testrunner_bld_* testdir*
rm -f testloadext.dll libtestloadext.so rm -f tclsqlite3$(TEXE)
rm -f amalgamation-testfixture amalgamation-testfixture.exe rm -f $(TESTPROGS) testrunner.*
rm -f fts3-testfixture fts3-testfixture.exe rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
rm -f testfixture testfixture.exe rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
rm -f threadtest3 threadtest3.exe rm -f wordcount$(TEXE) changeset$(TEXE) version-info$(TEXE)
rm -f LogEst LogEst.exe rm -f *.dll *.lib *.exp *.def *.pc *.vsix
rm -f fts3view fts3view.exe rm -f sqlite3_analyzer$(TEXE)
rm -f rollback-test rollback-test.exe rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
rm -f showdb showdb.exe rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
rm -f showjournal showjournal.exe rm -f threadtest5$(TEXE)
rm -f showstat4 showstat4.exe rm -f src-verify has_tclsh*
rm -f showwal showwal.exe
rm -f changeset changeset.exe distclean: clean
rm -f speedtest1 speedtest1.exe
rm -f wordcount wordcount.exe
rm -f rbu rbu.exe
rm -f srcck1 srcck1.exe
rm -f sqlite3.c sqlite3-*.c fts?amal.c tclsqlite3.c
rm -f sqlite3rc.h
rm -f shell.c sqlite3ext.h
rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
rm -f sqlite3_expert sqlite3_expert.exe
rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe
rm -f fuzzershell fuzzershell.exe
rm -f fuzzcheck fuzzcheck.exe
rm -f sessionfuzz
rm -f sqldiff sqldiff.exe
rm -f fts5.* fts5parse.*
rm -f lsm.h lsm1.c
rm -f threadtest5
rm -f src-verify

View File

@@ -1,12 +1,12 @@
C Fix\sa\sproblem\sin\swinOpen().\s\sMerge\sthe\smakefile\senhancements\sfrom\strunk. C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sreuse-schema\sbranch.
D 2024-08-29T22:05:38.293 D 2024-09-06T15:52:48.974
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in c322adca45438743dd48882921f73c75f37f0fd4ab67446928b98e3fe928f65f F Makefile.in 9a0a78b9b8ec286340d206de94871ef551734d2a683dffa13ffbb3b7c7531ce6
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6 F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc 0ed3a1a328c744dc9fbecb848997105ea5ebd9635dbf6481ca179383a216d88f F Makefile.msc ee5f555631cc843c086082bed01bca1eeeae75a56e709a0d1a39cc242078e57e
F README.md 5b678e264236788390d11991f2c0052bd73f19790173883fc56d638bcb849154 F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6 F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5 F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -39,7 +39,7 @@ F configure 49523f0a070b583cea040d26eff53a65fb0893eca4663b1343a4d5a9a964da53 x
F configure.ac a100ebf7a07f5dedd319ef547dd467d1676ed059b85a7877aa9c44ac309f7000 F configure.ac a100ebf7a07f5dedd319ef547dd467d1676ed059b85a7877aa9c44ac309f7000
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/compile-for-windows.md e8635eea9153dcd6a51fd2740666ebc4492b3813cb1ac31cd8e99150df91762d F doc/compile-for-windows.md 4d4bfafda42a7a33f166d23aed4db1bb4ea1e5751595a5cced2bad349fd14652
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b
F doc/lemon.html 8b266ff711d2ec7f867c3dca37634963f48a630329908cc282beebfa8c708706 F doc/lemon.html 8b266ff711d2ec7f867c3dca37634963f48a630329908cc282beebfa8c708706
@@ -54,7 +54,7 @@ F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91 F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94 F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
F ext/consio/console_io.c 6e02dea912a49f55785b0027fe77960aafee6c236307c23f82ec86a69f1a2001 x F ext/consio/console_io.c d2b74afae8d301de2e8447b1045fcd33eb59df13bf581d906d99c74fe5d2b13f x
F ext/consio/console_io.h b5ebe34aa15b357621ebbea3d3f2e2b24750d4280b5802516409e23947fd9ee5 F ext/consio/console_io.h b5ebe34aa15b357621ebbea3d3f2e2b24750d4280b5802516409e23947fd9ee5
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3 F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4 F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
@@ -100,7 +100,7 @@ F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70
F ext/fts5/fts5_config.c 353d2a0d12678cae6ab5b9ce54aed8dac0825667b69248b5a4ed81cbefc109ea F ext/fts5/fts5_config.c 353d2a0d12678cae6ab5b9ce54aed8dac0825667b69248b5a4ed81cbefc109ea
F ext/fts5/fts5_expr.c 9a56f53700d1860f0ee2f373c2b9074eaf2a7aa0637d0e27a6476de26a3fee33 F ext/fts5/fts5_expr.c 9a56f53700d1860f0ee2f373c2b9074eaf2a7aa0637d0e27a6476de26a3fee33
F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1 F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
F ext/fts5/fts5_index.c eb9a0dda3bc6ef969a6be8d2746af56856e67251810ddba08622b45be8477abe F ext/fts5/fts5_index.c 571483823193f09439356741669aa8c81da838ae6f5e1bfa7517f7ee2fb3addd
F ext/fts5/fts5_main.c 1fddb53f495425d9314c74b30c5848a9dd254be0e5f445bfe38292d5ab21c288 F ext/fts5/fts5_main.c 1fddb53f495425d9314c74b30c5848a9dd254be0e5f445bfe38292d5ab21c288
F ext/fts5/fts5_storage.c 9a9b880be12901f1962ae2a5a7e1b74348b3099a1e728764e419f75d98e3e612 F ext/fts5/fts5_storage.c 9a9b880be12901f1962ae2a5a7e1b74348b3099a1e728764e419f75d98e3e612
F ext/fts5/fts5_tcl.c 4db9258a7882c5eac0da4433042132aaf15b87dd1e1636c7a6ca203abd2c8bfe F ext/fts5/fts5_tcl.c 4db9258a7882c5eac0da4433042132aaf15b87dd1e1636c7a6ca203abd2c8bfe
@@ -185,6 +185,7 @@ F ext/fts5/test/fts5full.test 97d263c1072f4a560929cca31e70f65d2ae232610e17e6affc
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
F ext/fts5/test/fts5hash.test fd3e0367fbf0b0944d6936fdb22696350f57b9871069c6766251578a103e8a14 F ext/fts5/test/fts5hash.test fd3e0367fbf0b0944d6936fdb22696350f57b9871069c6766251578a103e8a14
F ext/fts5/test/fts5integrity.test 646796671205dae46af5bb12a49b5696483cfe8e12d71d21454940b13ace95ab F ext/fts5/test/fts5integrity.test 646796671205dae46af5bb12a49b5696483cfe8e12d71d21454940b13ace95ab
F ext/fts5/test/fts5integrity2.test 4c3636615c0201232c44a8105d5cb14fd5499fd0ee3014d7ffd7e83aac76ece8
F ext/fts5/test/fts5interrupt.test 20d04204d3e341b104c0c24a41596b6393a3a81eba1044c168db0e106f9ac92c F ext/fts5/test/fts5interrupt.test 20d04204d3e341b104c0c24a41596b6393a3a81eba1044c168db0e106f9ac92c
F ext/fts5/test/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400f8d2d27ea9373e0c4a1 F ext/fts5/test/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400f8d2d27ea9373e0c4a1
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
@@ -411,7 +412,7 @@ F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58
F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0 F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0
F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405 F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
F ext/misc/percentile.c af1941dc87d45dd0c2698a3087fbfe9ee0d157e5e72da521430c4b784abcbe81 F ext/misc/percentile.c 42eb041edab407e512aaa087f99ed9287fe0b3224f7a6d194456c00fc1454312
F ext/misc/prefixes.c 82645f79229877afab08c8b08ca1e7fa31921280906b90a61c294e4f540cd2a6 F ext/misc/prefixes.c 82645f79229877afab08c8b08ca1e7fa31921280906b90a61c294e4f540cd2a6
F ext/misc/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47cc06c F ext/misc/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47cc06c
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
@@ -484,7 +485,7 @@ F ext/rbu/rbuvacuum.test 542561741ff2b262e3694bc6012b44694ee62c545845319a06f3237
F ext/rbu/rbuvacuum2.test ae097d04feb041446a74fac94b24bffeb3fdd60e32b848c5611e507ab702b81b F ext/rbu/rbuvacuum2.test ae097d04feb041446a74fac94b24bffeb3fdd60e32b848c5611e507ab702b81b
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205 F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
F ext/rbu/sqlite3rbu.c 4a3376c0fb9a844a799ac529fb81260523f6b13c9f629bc270c632dbae5fc1f8 F ext/rbu/sqlite3rbu.c c07817e89477b8fc286ab6ed87da5bc82fc3490bbbe9e9b22eb2d900e81ee5dc
F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304 F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
F ext/rbu/test_rbu.c b9727c3394307d058e806c1da0f8bb7b24daf3c6bb94cb10cca88ea4d5c806c0 F ext/rbu/test_rbu.c b9727c3394307d058e806c1da0f8bb7b24daf3c6bb94cb10cca88ea4d5c806c0
F ext/recover/dbdata.c 5295f4f922b60d7035b6b9fd5846b13071b9d97ed7fad8496837bb7640d24771 F ext/recover/dbdata.c 5295f4f922b60d7035b6b9fd5846b13071b9d97ed7fad8496837bb7640d24771
@@ -595,7 +596,7 @@ F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3session.c c7473aafbd88f796391a8c25aa90975a8f3729ab7f4f8cf74ab9d3b014e10abe F ext/session/sqlite3session.c c7473aafbd88f796391a8c25aa90975a8f3729ab7f4f8cf74ab9d3b014e10abe
F ext/session/sqlite3session.h 683ccbf16e2c2521661fc4c1cf918ce57002039efbcabcd8097fa4bca569104b F ext/session/sqlite3session.h 683ccbf16e2c2521661fc4c1cf918ce57002039efbcabcd8097fa4bca569104b
F ext/session/test_session.c 6acbe67db80ab0806147eb62a12f9e3a44930f4a740b68b0a4340dddda2c10d7 F ext/session/test_session.c aa29abdcc9011ac02f4fa38e8ede226106eaeee7c3ea7d8b2b999a124e0c368c
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
@@ -686,7 +687,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0 F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk 6b4e3eb9f0e885f9f4b103c11862e3045018f089c335389b8301660f734b92a6 F main.mk cc0be8a9ab902e06c0b1c924fa30192e6a6cf3efa91e05ebc5dd1c652416e0a1
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421 F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -711,7 +712,7 @@ F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b
F src/build.c 648138031b04e573fd9ad6781f0adb0fcd6b6c7d849611918c280f696d7dfab5 F src/build.c 648138031b04e573fd9ad6781f0adb0fcd6b6c7d849611918c280f696d7dfab5
F src/callback.c fbd4e8247f1a7f37aec721bde0e312e79cc3bfa41f55a59930bc876ca6baf455 F src/callback.c fbd4e8247f1a7f37aec721bde0e312e79cc3bfa41f55a59930bc876ca6baf455
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 64e4b1227b4ed123146f0aa2989131d1fbd9b927b11e80c9d58c6a68f9cd5ce3 F src/ctime.c b224d3db0f28c4a5f1407c50107a0a8133bd244ff3c7f6f8cedeb896a8cf1b64
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
@@ -719,17 +720,17 @@ F src/delete.c 444c4d1eaac40103461e3b6f0881846dd3aafc1cec1dd169d3482fa331667da7
F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239 F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c 1f61e32e7a357e615b5d2e774bee563761fce4f2fd97ecb0f72c33e62a2ada5f F src/func.c df400a1d3f4625997d4dd8a81951c303e066277c29b861d37e03cd152d7858dd
F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90 F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c f8d1a0f8ee258411009c6b7f2d93170e351bd19f5ad89d57e1180644297cbe70 F src/insert.c f8d1a0f8ee258411009c6b7f2d93170e351bd19f5ad89d57e1180644297cbe70
F src/json.c 5b6a1d6015997b9ee848a32948720bdb26a0ef2de5a2127ebf7355ce66dbdc0d F src/json.c 68a98c020c22127f2d65f08855f7fc7460ff352a6ce0b543d8931dde83319c22
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
F src/main.c 7cfb761ce0d25ab41419659071326fc98277f2a210cd306ca5e4297d12359640 F src/main.c d1662b77a1ab3211430f4149a0c2e9023b890e7043a65293cadb5a62374c35dd
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2 F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -755,7 +756,7 @@ F src/os_win.c 3c5614e5ea39e2ea33659d2d652fabd82ec3b5a39e342ca587eb6e5806e6d047
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3 F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
F src/parse.y 5972b7d00af4c8d96fdad781af1ea1d5d51fc3b907ad61bda60e49503274e5ed F src/parse.y a7a8d42eeff01d267444ddb476029b0b1726fb70ae3d77984140f17ad02e2d61
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484 F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319 F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
@@ -768,16 +769,16 @@ F src/resolve.c 2c127880c0634962837f16f2f48a295e514357af959330cc038de73015d5b5e8
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4b14337a2742f0c0beeba490e9a05507e9b4b12184b9cd12773501d08d48e3fe F src/select.c 4b14337a2742f0c0beeba490e9a05507e9b4b12184b9cd12773501d08d48e3fe
F src/shell.c.in 592f97a0b1e42d7eb685c0b7d2f1b473abd61adef9e1be63ccde3928c3b3fe68 F src/shell.c.in 592f97a0b1e42d7eb685c0b7d2f1b473abd61adef9e1be63ccde3928c3b3fe68
F src/sqlite.h.in 21f83722ed7518e87dd23a023bdc879acabb837c51da12d90db6f78327b84066 F src/sqlite.h.in fa87b85bd482e1ee14afecec21a8624c2140e48b686d64af3b6eb011ad91ffd5
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
F src/sqliteInt.h e1234e14a5be5d4cc6de94667bc183453ad76fa6de6d6f053dbc64a9405592c4 F src/sqliteInt.h 9c620e7a97237847664f32abf45da3caf2923f14cb1e357154d4d079975f6837
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728 F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
F src/status.c 5028a0afee355aa492f26f0b6a3ec23145caa9261a93164d96cd0b9bf1b2318f F src/status.c 5028a0afee355aa492f26f0b6a3ec23145caa9261a93164d96cd0b9bf1b2318f
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c f3c74b7612c6f583c94af48531caa1a7fecc53202bf4e0b202d39e54dc9322bc F src/tclsqlite.c f3c74b7612c6f583c94af48531caa1a7fecc53202bf4e0b202d39e54dc9322bc
F src/tclsqlite.h c6af51f31a2b2172d674608763a4b98fdf5cd587e4025053e546fb8077757262 F src/tclsqlite.h c6af51f31a2b2172d674608763a4b98fdf5cd587e4025053e546fb8077757262
F src/test1.c 3f18399557d954bc85f4564aec8ea1777d2161a81d98a3ff6c9e9046bf3554c1 F src/test1.c 8d7cd219c004cd2ced60659ebf045025cc5c16ce19d12459589dacd4310f7f07
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3 F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
F src/test3.c e7573aa0f78ee4e070a4bc8c3493941c1aa64d5c66d4825c74c0f055451f432b F src/test3.c e7573aa0f78ee4e070a4bc8c3493941c1aa64d5c66d4825c74c0f055451f432b
F src/test4.c 13e57ae7ec7a959ee180970aef09deed141252fe9bb07c61054f0dfa4f1dfd5d F src/test4.c 13e57ae7ec7a959ee180970aef09deed141252fe9bb07c61054f0dfa4f1dfd5d
@@ -791,7 +792,7 @@ F src/test_backup.c bd901e3c116c7f3b3bbbd4aae4ce87d99b400c9cbb0a9e7b4610af451d97
F src/test_bestindex.c 3401bee51665cbf7f9ed2552b5795452a8b86365e4c9ece745b54155a55670c6 F src/test_bestindex.c 3401bee51665cbf7f9ed2552b5795452a8b86365e4c9ece745b54155a55670c6
F src/test_blob.c bcdf6a6c22d0bcc13c41479d63692ef413add2a4d30e1e26b9f74ab85b9fb4d5 F src/test_blob.c bcdf6a6c22d0bcc13c41479d63692ef413add2a4d30e1e26b9f74ab85b9fb4d5
F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5 F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5
F src/test_config.c 0e3579a520130bbbdb06c9166b11f181433fc23c22feb16f8c279fb9525a4b51 F src/test_config.c 54b4f17e0b4b49a04cd45394c172379d9471066ae56dd7441343146a650a751c
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383 F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86 F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
@@ -853,7 +854,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89 F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c d37f2b9e5bef275e605f2d2204de7f2f844708f9e1cc907e52e3e4f7e7ae07cf F src/where.c c924288b72eade267a3478c181f0aa8b627ed028734fc4ae6f1984d8bd5ad99e
F src/whereInt.h a5d079c346a658b7a6e9e47bb943d021e02fa1e6aed3b964ca112112a4892192 F src/whereInt.h a5d079c346a658b7a6e9e47bb943d021e02fa1e6aed3b964ca112112a4892192
F src/wherecode.c 5172d647798134e7c92536ddffe7e530c393d79b5dedd648b88faf2646c65baf F src/wherecode.c 5172d647798134e7c92536ddffe7e530c393d79b5dedd648b88faf2646c65baf
F src/whereexpr.c 44f41ae554c7572e1de1485b3169b233ee04d464b2ee5881687ede3bf07cacfa F src/whereexpr.c 44f41ae554c7572e1de1485b3169b233ee04d464b2ee5881687ede3bf07cacfa
@@ -1268,7 +1269,7 @@ F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce3
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634 F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830 F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2 F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c 6e87c27df3d95c556870187987dff6efdc712b5cea60abedc8ab9215f471907a F test/fuzzcheck.c 3b8b39e3c0c88422c51ef0a93481d3d528fb370668344bf0ae4c87629c18b021
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517 F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1280,7 +1281,7 @@ F test/fuzzdata8.db 4a53b6d077c6a5c23b609d8d3ac66996fa55ba3f8d02f9b6efdd0214a767
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
F test/fuzzinvariants.c 81167c9a7e82c0539a1d704aeb3384046d01f4108cda160a2447cb2a149d6362 F test/fuzzinvariants.c 3de49c7b33f5641b67edc2496328a49af029738e92c8499fafbf8618ad42f68d
F test/gcfault.test 4ea410ac161e685f17b19e1f606f58514a2850e806c65b846d05f60d436c5b0d F test/gcfault.test 4ea410ac161e685f17b19e1f606f58514a2850e806c65b846d05f60d436c5b0d
F test/gencol1.test e169bdfa11c7ed5e9f322a98a7db3afe9e66235750b68c923efee8e1876b46ec F test/gencol1.test e169bdfa11c7ed5e9f322a98a7db3afe9e66235750b68c923efee8e1876b46ec
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98 F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@@ -1347,7 +1348,7 @@ F test/ioerr5.test 5984da7bf74b6540aa356f2ab0c6ae68a6d12039a3d798a9ac6a100abc17d
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9 F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9
F test/join.test f7abfef3faeaf2800308872e33a57e5b6e4a2b44fb8c6b90c6068412e71a6cf4 F test/join.test f7abfef3faeaf2800308872e33a57e5b6e4a2b44fb8c6b90c6068412e71a6cf4
F test/join2.test 8561fe82ce434ac96de91544072e578dc2cadddf2d9bc9cd802f866a9b92502e F test/join2.test f59d63264fb24784ae9c3bc9d867eb569cd6d442da5660f8852effe5c1938c27
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test 380d12a9350f99f0cc681a4f1fea999886f18b3fe0d71a9b3065bcaead1e007f F test/join5.test 380d12a9350f99f0cc681a4f1fea999886f18b3fe0d71a9b3065bcaead1e007f
@@ -1382,7 +1383,7 @@ F test/json106.test 4aed3afd16549045d198a8d9cea00deea96e1f2ecf55864dce96cac558b8
F test/json107.test 59054e815c8f6b67d634d44ace421cf975828fb5651c4460aa66015c8e19d562 F test/json107.test 59054e815c8f6b67d634d44ace421cf975828fb5651c4460aa66015c8e19d562
F test/json108.test 0a5f1e2d4b35a1bc33052563d2a5ede03052e2099e58cb424547656c898e0f49 F test/json108.test 0a5f1e2d4b35a1bc33052563d2a5ede03052e2099e58cb424547656c898e0f49
F test/json501.test b95e2d14988b682a5cadf079dd6162f0f85fb74cd59c6b1f1624110104a974eb F test/json501.test b95e2d14988b682a5cadf079dd6162f0f85fb74cd59c6b1f1624110104a974eb
F test/json502.test 84634d3dbb521d2814e43624025b760c6198456c8197bbec6c977c0236648f5b F test/json502.test 4ef68e4f272dfb083d4cbceb4e9e51d67ec1186a185e0c13637c50a4dc2f9796
F test/jsonb01.test f4cdfb4cf5a0c940091b17675ed9583f45add0c938f07d65b0de0e19d3a9a101 F test/jsonb01.test f4cdfb4cf5a0c940091b17675ed9583f45add0c938f07d65b0de0e19d3a9a101
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
@@ -1519,7 +1520,7 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463 F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463
F test/percentile.test 74e383216a075251512d6ba98beb9dccd6da465e3f73817fc438379e3a628de7 F test/percentile.test 52ba89d6ee6b65f770972b67dace358bab7cdbd532803d3db157845268e789cd
F test/permutations.test 405542f1d659942994a6b38a9e024cf5cfd23eaa68c806aeb24a72d7c9186e80 F test/permutations.test 405542f1d659942994a6b38a9e024cf5cfd23eaa68c806aeb24a72d7c9186e80
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test 11cb9310c42f921918f7f563e3c0b6e70f9f9c3a6a1cf12af8fccb6c574f3882 F test/pragma.test 11cb9310c42f921918f7f563e3c0b6e70f9f9c3a6a1cf12af8fccb6c574f3882
@@ -1722,9 +1723,9 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16 F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637 F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 5fffa7c6d9e293fa109a3ccb925a92dba91c9ea1b824a2d64a0ae60b571231da F test/tester.tcl 14284e98554d0a27c3982dcf4b7c4b88cf025ae8e238dd7e2683071c51c371fd
F test/testrunner.tcl 2c28979f936bc07cfc769080f4268fb7e95b64d0e16a4eca7f9cc6b7eefcde7d F test/testrunner.tcl 0f371d50e606c43c09046fda1416ecdf69089bd125cb478800f040c70086bbe8 x
F test/testrunner_data.tcl 787af292f8c9e51ad2bb62dd8488ababd9e1bc303f920e4cbbe43a7650f3540e F test/testrunner_data.tcl 47a8b2430f0f6a31f56fe6c5fe5c736b3619df4081acaa816fd877f96a68d46a
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899 F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502 F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -2060,7 +2061,7 @@ F test/wherelimit3.test 22d73e046870cf8bbe15573eda6b432b07ebe64a88711f9f849c6b36
F test/widetab1.test c296a98e123762de79917350e45fa33fdf88577a2571eb3a64c8bf7e44ef74d1 F test/widetab1.test c296a98e123762de79917350e45fa33fdf88577a2571eb3a64c8bf7e44ef74d1
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74 F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
F test/win32lock.test e0924eb8daac02bf80e9da88930747bd44dd9b230b7759fed927b1655b467c9c F test/win32lock.test e0924eb8daac02bf80e9da88930747bd44dd9b230b7759fed927b1655b467c9c
F test/win32longpath.test 42210789bcfc5c0ac202643d6d0237db08df2c9218f2070d9a69e8af1eccf7d7 F test/win32longpath.test 304006024ca47104bf5a7415ef31ca83ecfc29351af202baf8588b880cffc116
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 79dc3b9a2226f622d7e104a1fc750d1c4c3c08d6147b59085bdbe05352947ffa F test/window1.test 79dc3b9a2226f622d7e104a1fc750d1c4c3c08d6147b59085bdbe05352947ffa
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476 F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
@@ -2141,8 +2142,8 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176 F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl 48ca8eefa9e615cb9057ce6485b9c9ae5801381f24690d7d60b3b2dc8e6b7457 x F tool/mkctimec.tcl e3af51acc2ef92062fe6d622de010a27a34b497258a248dada04388b916c61c6 x
F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd F tool/mkkeywordhash.c 6b0be901c47f9ad42215fc995eb2f4384ac49213b1fba395102ec3e999acf559
F tool/mkmsvcmin.tcl d76c45efda1cce2d4005bcea7b8a22bb752e3256009f331120fb4fecb14ebb7a F tool/mkmsvcmin.tcl d76c45efda1cce2d4005bcea7b8a22bb752e3256009f331120fb4fecb14ebb7a
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023 F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
@@ -2159,7 +2160,7 @@ F tool/mktoolzip.tcl c7a9b685f5131d755e7d941cec50cee7f34178b9e34c9a89811eeb08617
F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e540a F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e540a
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845 F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08 F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
F tool/omittest.tcl e99c9fecc3f7a8ca2fa75d8ec8bdbb5acce33dc69f0c280aae53064693387f65 F tool/omittest.tcl 5ca5e4e01716d5f35b48b00fd351d929f01fbb98169a5a3cd00baf3d2e2019a9
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
F tool/replace.tcl 511c61acfe563dfb58675efb4628bb158a13d48ff8322123ac447e9d25a82d9a F tool/replace.tcl 511c61acfe563dfb58675efb4628bb158a13d48ff8322123ac447e9d25a82d9a
@@ -2221,8 +2222,8 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 60795a30c64dbaa3be16dc35a39262b5487a5d4abcff20ae8973e12b73af5af2 854b3776ee1fcaa5931e3a0ed104978ca350d218e553586d1c40c2420e1be498 P bd247ae7f95d2e50436961e9aee60578e98ceccc0df9f71c201dd4b1884f2085 d94541ae76b5d8b69f5524f10dcccc0814283f438a03f553848ed631a1983633
R 25b272be2c06f88ae1e734e918af2e85 R 76a272439d4f25d75a300922d222edfc
U drh U drh
Z 3d8456fdef56a3a1151e6f41c182190c Z 51c246f5c4aa6e5e2a88e51d2bad5700
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
bd247ae7f95d2e50436961e9aee60578e98ceccc0df9f71c201dd4b1884f2085 f9ce1ababbd62c579658c737059f6992bdb32909e7a06282fe6a359d10ad1272

View File

@@ -295,6 +295,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
"ENABLE_OFFSET_SQL_FUNC", "ENABLE_OFFSET_SQL_FUNC",
#endif #endif
#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
"ENABLE_ORDERED_SET_AGGREGATES",
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK #ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK", "ENABLE_OVERSIZE_CELL_CHECK",
#endif #endif

View File

@@ -2049,7 +2049,11 @@ static void minMaxFinalize(sqlite3_context *context){
** group_concat(EXPR, ?SEPARATOR?) ** group_concat(EXPR, ?SEPARATOR?)
** string_agg(EXPR, SEPARATOR) ** string_agg(EXPR, SEPARATOR)
** **
** The SEPARATOR goes before the EXPR string. This is tragic. The ** Content is accumulated in GroupConcatCtx.str with the SEPARATOR
** coming before the EXPR value, except for the first entry which
** omits the SEPARATOR.
**
** It is tragic that the SEPARATOR goes before the EXPR string. The
** groupConcatInverse() implementation would have been easier if the ** groupConcatInverse() implementation would have been easier if the
** SEPARATOR were appended after EXPR. And the order is undocumented, ** SEPARATOR were appended after EXPR. And the order is undocumented,
** so we could change it, in theory. But the old behavior has been ** so we could change it, in theory. But the old behavior has been
@@ -2153,7 +2157,7 @@ static void groupConcatInverse(
/* pGCC is always non-NULL since groupConcatStep() will have always /* pGCC is always non-NULL since groupConcatStep() will have always
** run first to initialize it */ ** run first to initialize it */
if( ALWAYS(pGCC) ){ if( ALWAYS(pGCC) ){
int nVS; int nVS; /* Number of characters to remove */
/* Must call sqlite3_value_text() to convert the argument into text prior /* Must call sqlite3_value_text() to convert the argument into text prior
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */ ** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
(void)sqlite3_value_text(argv[0]); (void)sqlite3_value_text(argv[0]);

View File

@@ -2847,7 +2847,9 @@ static u32 jsonLookupStep(
zPath++; zPath++;
if( zPath[0]=='"' ){ if( zPath[0]=='"' ){
zKey = zPath + 1; zKey = zPath + 1;
for(i=1; zPath[i] && zPath[i]!='"'; i++){} for(i=1; zPath[i] && zPath[i]!='"'; i++){
if( zPath[i]=='\\' && zPath[i+1]!=0 ) i++;
}
nKey = i-1; nKey = i-1;
if( zPath[i] ){ if( zPath[i] ){
i++; i++;

View File

@@ -1938,7 +1938,8 @@ int sqlite3CreateFunc(
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY ); assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY| extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE); SQLITE_SUBTYPE|SQLITE_INNOCUOUS|
SQLITE_RESULT_SUBTYPE|SQLITE_SELFORDER1);
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
/* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But

View File

@@ -264,6 +264,9 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
EXCLUDE GROUPS OTHERS TIES EXCLUDE GROUPS OTHERS TIES
%endif SQLITE_OMIT_WINDOWFUNC %endif SQLITE_OMIT_WINDOWFUNC
%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
WITHIN
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
%ifndef SQLITE_OMIT_GENERATED_COLUMNS %ifndef SQLITE_OMIT_GENERATED_COLUMNS
GENERATED ALWAYS GENERATED ALWAYS
%endif %endif
@@ -1179,6 +1182,65 @@ expr(A) ::= idj(X) LP STAR RP. {
A = sqlite3ExprFunction(pParse, 0, &X, 0); A = sqlite3ExprFunction(pParse, 0, &X, 0);
} }
%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
%include {
/* Generate an expression node that represents an ordered-set aggregate function.
**
** SQLite does not do anything special to evaluate ordered-set aggregates. The
** aggregate function itself is expected to do any required ordering on its own.
** This is just syntactic sugar.
**
** This syntax: percentile(f) WITHIN GROUP ( ORDER BY y )
**
** Is equivalent to: percentile(y,f)
**
** The purpose of this function is to generate an Expr node from the first syntax
** into a TK_FUNCTION node that looks like it came from the second syntax.
**
** Only functions that have the SQLITE_SELFORDER1 perperty are allowed to do this
** transformation. Because DISTINCT is not allowed in the ordered-set aggregate
** syntax, an error is raised if DISTINCT is used.
*/
static Expr *sqlite3ExprAddOrderedsetFunction(
Parse *pParse, /* Parsing context */
Token *pFuncname, /* Name of the function */
int isDistinct, /* DISTINCT or ALL qualifier */
ExprList *pOrig, /* Arguments to the function */
Expr *pOrderby /* Expression in the ORDER BY clause */
){
ExprList *p; /* Modified argument list */
Expr *pExpr; /* Final result */
p = sqlite3ExprListAppend(pParse, 0, pOrderby);
if( pOrig ){
int i;
for(i=0; i<pOrig->nExpr; i++){
p = sqlite3ExprListAppend(pParse, p, pOrig->a[i].pExpr);
pOrig->a[i].pExpr = 0;
}
sqlite3ExprListDelete(pParse->db, pOrig);
}
pExpr = sqlite3ExprFunction(pParse, p, pFuncname, 0);
if( pParse->nErr==0 ){
FuncDef *pDef;
u8 enc = ENC(pParse->db);
assert( pExpr!=0 ); /* Because otherwise pParse->nErr would not be zero */
assert( p!=0 ); /* Because otherwise pParse->nErr would not be zero */
pDef = sqlite3FindFunction(pParse->db, pExpr->u.zToken, -2, enc, 0);
if( pDef==0 || (pDef->funcFlags & SQLITE_SELFORDER1)==0 ){
sqlite3ErrorMsg(pParse, "%#T() is not an ordered-set aggregate", pExpr);
}else if( isDistinct==SF_Distinct ){
sqlite3ErrorMsg(pParse, "DISTINCT not allowed on ordered-set aggregate %T()",
pFuncname);
}
}
return pExpr;
}
}
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP WITHIN GROUP LP ORDER BY expr(E) RP. {
A = sqlite3ExprAddOrderedsetFunction(pParse, &X, D, Y, E);
}
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
%ifndef SQLITE_OMIT_WINDOWFUNC %ifndef SQLITE_OMIT_WINDOWFUNC
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP filter_over(Z). { expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP filter_over(Z). {
A = sqlite3ExprFunction(pParse, Y, &X, D); A = sqlite3ExprFunction(pParse, Y, &X, D);
@@ -1193,7 +1255,15 @@ expr(A) ::= idj(X) LP STAR RP filter_over(Z). {
A = sqlite3ExprFunction(pParse, 0, &X, 0); A = sqlite3ExprFunction(pParse, 0, &X, 0);
sqlite3WindowAttach(pParse, A, Z); sqlite3WindowAttach(pParse, A, Z);
} }
%endif %ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP WITHIN GROUP LP ORDER BY expr(E) RP
filter_over(Z). {
A = sqlite3ExprAddOrderedsetFunction(pParse, &X, D, Y, E);
sqlite3WindowAttach(pParse, A, Z);
}
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
%endif SQLITE_OMIT_WINDOWFUNC
term(A) ::= CTIME_KW(OP). { term(A) ::= CTIME_KW(OP). {
A = sqlite3ExprFunction(pParse, 0, &OP, 0); A = sqlite3ExprFunction(pParse, 0, &OP, 0);

View File

@@ -5616,6 +5616,15 @@ int sqlite3_create_window_function(
** [sqlite3_result_subtype()] should avoid setting this property, as the ** [sqlite3_result_subtype()] should avoid setting this property, as the
** purpose of this property is to disable certain optimizations that are ** purpose of this property is to disable certain optimizations that are
** incompatible with subtypes. ** incompatible with subtypes.
**
** [[SQLITE_SELFORDER1]] <dt>SQLITE_SELFORDER1</dt><dd>
** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
** that internally orders the values provided to the first argument. The
** ordered-set aggregate SQL notation with a single ORDER BY term can be
** used to invoke this function. If the ordered-set aggregate notation is
** used on a function that lacks this flag, then an error is raised. Note
** that the ordered-set aggregate syntax is only available if SQLite is
** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
** </dd> ** </dd>
** </dl> ** </dl>
*/ */
@@ -5624,6 +5633,7 @@ int sqlite3_create_window_function(
#define SQLITE_SUBTYPE 0x000100000 #define SQLITE_SUBTYPE 0x000100000
#define SQLITE_INNOCUOUS 0x000200000 #define SQLITE_INNOCUOUS 0x000200000
#define SQLITE_RESULT_SUBTYPE 0x001000000 #define SQLITE_RESULT_SUBTYPE 0x001000000
#define SQLITE_SELFORDER1 0x002000000
/* /*
** CAPI3REF: Deprecated Functions ** CAPI3REF: Deprecated Functions

View File

@@ -658,6 +658,8 @@
#ifdef SQLITE_OMIT_FLOATING_POINT #ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite_int64 # define double sqlite_int64
# define float sqlite_int64 # define float sqlite_int64
# define fabs(X) ((X)<0?-(X):(X))
# define sqlite3IsOverflow(X) 0
# define LONGDOUBLE_TYPE sqlite_int64 # define LONGDOUBLE_TYPE sqlite_int64
# ifndef SQLITE_BIG_DBL # ifndef SQLITE_BIG_DBL
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) # define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)

View File

@@ -2343,7 +2343,7 @@ static int SQLITE_TCLAPI test_stmt_scanstatus(
} }
for(ii=0; ii<(int)nFlag; ii++){ for(ii=0; ii<(int)nFlag; ii++){
int iVal = 0; int iVal = 0;
int res = Tcl_GetIndexFromObjStruct( res = Tcl_GetIndexFromObjStruct(
interp, aFlag[ii], aTbl, sizeof(aTbl[0]), "flag", 0, &iVal interp, aFlag[ii], aTbl, sizeof(aTbl[0]), "flag", 0, &iVal
); );
if( res ) return TCL_ERROR; if( res ) return TCL_ERROR;

View File

@@ -189,6 +189,14 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","0",TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","0",TCL_GLOBAL_ONLY);
#endif #endif
#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
Tcl_SetVar2(interp, "sqlite_options",
"ordered_set_aggregates","1",TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options",
"ordered_set_aggregates","0",TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY);
#else #else
@@ -341,6 +349,14 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY);
#endif #endif
#ifdef SQLITE_ENABLE_ORDEREDSETFUNC
Tcl_SetVar2(interp, "sqlite_options", "ordered_set_funcs", "1",
TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "ordered_set_funcs", "0",
TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK #ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "1", Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "1",
TCL_GLOBAL_ONLY); TCL_GLOBAL_ONLY);

View File

@@ -6199,6 +6199,7 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
WhereTerm *pTerm, *pEnd; WhereTerm *pTerm, *pEnd;
SrcItem *pItem; SrcItem *pItem;
WhereLoop *pLoop; WhereLoop *pLoop;
Bitmask m1;
pLoop = pWInfo->a[i].pWLoop; pLoop = pWInfo->a[i].pWLoop;
pItem = &pWInfo->pTabList->a[pLoop->iTab]; pItem = &pWInfo->pTabList->a[pLoop->iTab];
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue; if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue;
@@ -6225,7 +6226,10 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
} }
} }
if( pTerm<pEnd ) continue; if( pTerm<pEnd ) continue;
WHERETRACE(0xffffffff, ("-> drop loop %c not used\n", pLoop->cId)); WHERETRACE(0xffffffff,("-> omit unused FROM-clause term %c\n",pLoop->cId));
m1 = MASKBIT(i)-1;
testcase( ((pWInfo->revMask>>1) & ~m1)!=0 );
pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1);
notReady &= ~pLoop->maskSelf; notReady &= ~pLoop->maskSelf;
for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){ for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){ if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){

View File

@@ -159,10 +159,11 @@ static struct GlobalVars {
} g; } g;
/* /*
** Include the external vt02.c and randomjson.c modules. ** Include various extensions.
*/ */
extern int sqlite3_vt02_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_vt02_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_randomjson_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_randomjson_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
/* /*
@@ -1044,10 +1045,11 @@ static void bindDebugParameters(sqlite3_stmt *pStmt){
sqlite3_bind_int(pStmt, i+1, atoi(&zVar[5])); sqlite3_bind_int(pStmt, i+1, atoi(&zVar[5]));
}else }else
if( strncmp(zVar, "$text_", 6)==0 ){ if( strncmp(zVar, "$text_", 6)==0 ){
char *zBuf = sqlite3_malloc64( strlen(zVar)-5 ); size_t szVar = strlen(zVar);
char *zBuf = sqlite3_malloc64( szVar-5 );
if( zBuf ){ if( zBuf ){
memcpy(zBuf, &zVar[6], strlen(zVar)-5); memcpy(zBuf, &zVar[6], szVar-5);
sqlite3_bind_text64(pStmt, i+1, zBuf, -1, sqlite3_free, SQLITE_UTF8); sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
} }
} }
} }
@@ -1329,7 +1331,8 @@ int runCombinedDbSqlInput(
/* Add the vt02 virtual table */ /* Add the vt02 virtual table */
sqlite3_vt02_init(cx.db, 0, 0); sqlite3_vt02_init(cx.db, 0, 0);
/* Add the random_json() and random_json5() functions */ /* Activate extensions */
sqlite3_percentile_init(cx.db, 0, 0);
sqlite3_randomjson_init(cx.db, 0, 0); sqlite3_randomjson_init(cx.db, 0, 0);
/* Add support for sqlite_dbdata and sqlite_dbptr virtual tables used /* Add support for sqlite_dbdata and sqlite_dbptr virtual tables used

View File

@@ -54,10 +54,11 @@ static void bindDebugParameters(sqlite3_stmt *pStmt){
sqlite3_bind_int(pStmt, i+1, atoi(&zVar[5])); sqlite3_bind_int(pStmt, i+1, atoi(&zVar[5]));
}else }else
if( strncmp(zVar, "$text_", 6)==0 ){ if( strncmp(zVar, "$text_", 6)==0 ){
char *zBuf = sqlite3_malloc64( strlen(zVar)-5 ); size_t szVar = strlen(zVar);
char *zBuf = sqlite3_malloc64( szVar-5 );
if( zBuf ){ if( zBuf ){
memcpy(zBuf, &zVar[6], strlen(zVar)-5); memcpy(zBuf, &zVar[6], szVar-5);
sqlite3_bind_text64(pStmt, i+1, zBuf, -1, sqlite3_free, SQLITE_UTF8); sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
} }
} }
} }

View File

@@ -428,4 +428,25 @@ do_eqp_test 12.3 {
`--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN `--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
} }
# 2024-09-05 https://sqlite.org/forum/forumpost/8a1e467e905b8d27
# When performing the Omit-Noop-Join optimization, if FROM clause terms
# to the right of the omitted join have the reverse-order bit set in the
# WhereInfo.revMask bitmask, those bits need to be shifted to account
# for the omitted join.
#
reset_db
do_execsql_test 13.0 {
CREATE TABLE t1(a1 INTEGER PRIMARY KEY, b1 INT);
CREATE TABLE t2(c2 INT, d2 INTEGER PRIMARY KEY);
CREATE TABLE t3(e3 INTEGER PRIMARY KEY);
INSERT INTO t1 VALUES(33,0);
INSERT INTO t2 VALUES(33,1),(33,2);
}
do_execsql_test 13.1 {
SELECT t1.a1, t2.d2
FROM (t1 LEFT JOIN t3 ON t3.e3=t1.b1) JOIN t2 ON t2.c2=t1.a1
WHERE t1.a1=33
ORDER BY t2.d2 DESC;
} {33 2 33 1}
finish_test finish_test

View File

@@ -64,4 +64,17 @@ ifcapable vtab {
} {{\x17} 1 integer 1 1 null {$."\x17"} {$}} } {{\x17} 1 integer 1 1 null {$."\x17"} {$}}
} }
# JSON PATH parsing bug involving backslash escapes, reported via
# private email from Florent De'Neve on 2024-09-04.
#
do_execsql_test 5.1 {
SELECT json_extract('{"A\"Key":1}', '$.A"Key');
} 1
do_execsql_test 5.2 {
SELECT json_extract('{"A\"Key":1}', '$."A\"Key"');
} 1
do_execsql_test 5.3 {
SELECT JSON_SET('{}', '$."\"Key"', 1);
} {{{"\"Key":1}}}
finish_test finish_test

View File

@@ -9,7 +9,8 @@
# #
#*********************************************************************** #***********************************************************************
# This file implements regression tests for SQLite library. The # This file implements regression tests for SQLite library. The
# focus of this file is percentile.c extension # focus of this file is percentile.c extension. This also tests
# the SQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
# #
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
@@ -25,35 +26,65 @@ do_test percentile-1.0 {
} }
execsql {SELECT percentile(x,0) FROM t1} execsql {SELECT percentile(x,0) FROM t1}
} {1.0} } {1.0}
foreach {in out} { foreach {in out disc} {
100 11.0 100 11.0 11.0
50 8.0 50 8.0 8.0
12.5 4.0 12.5 4.0 4.0
15 4.4 15 4.4 4.0
20 5.2 20 5.2 4.0
80 11.0 80 11.0 11.0
89 11.0 89 11.0 11.0
} { } {
do_test percentile-1.1.$in { do_test percentile-1.1.$in.1 {
execsql {SELECT percentile(x,$in) FROM t1} execsql {SELECT percentile(x,$in) FROM t1}
} $out } $out
do_test percentile-1.1.$in.2 {
execsql {SELECT percentile_cont(x,$in*0.01) FROM t1}
} $out
do_test percentile-1.1.$in.3 {
execsql {SELECT percentile_disc(x,$in*0.01) FROM t1}
} $disc
if {$in==50} {
do_test percentile-1.1.$in.4 {
execsql {SELECT median(x) FROM t1}
} $out
}
ifcapable ordered_set_aggregates {
do_test percentile-1.1.$in.5 {
execsql {SELECT percentile($in)WITHIN GROUP(ORDER BY x) FROM t1}
} $out
do_test percentile-1.1.$in.6 {
execsql {SELECT percentile_cont($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t1}
} $out
do_test percentile-1.1.$in.7 {
execsql {SELECT percentile_disc($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t1}
} $disc
if {$in==50} {
do_test percentile-1.1.$in.8 {
execsql {SELECT median() WITHIN GROUP (ORDER BY x) FROM t1}
} $out
}
}
} }
do_execsql_test percentile-1.1.median { do_execsql_test percentile-1.1.median {
SELECT median(x) FROM t1; SELECT median(x) FROM t1;
} 8.0 } 8.0
ifcapable ordered_set_aggregates {
foreach {in out} { do_execsql_test percentile-1.1.median {
1.0 11.0 SELECT median() WITHIN GROUP (ORDER BY x) FROM t1;
0.5 8.0 } 8.0
0.125 4.0 do_execsql_test percentile-1.1.distinct.1 {
0.15 4.4 SELECT median(DISTINCT x) FROM t1;
0.2 5.2 } 7.0
0.8 11.0 do_catchsql_test percentile-1.1.distinct.2 {
0.89 11.0 SELECT percentile(DISTINCT 50) WITHIN GROUP (ORDER BY x) FROM t1;
} { } {1 {DISTINCT not allowed on ordered-set aggregate percentile()}}
do_test percentile-1.1b-$in { } else {
execsql {SELECT percentile_cont(x,$in) FROM t1} do_catchsql_test percentile-1.1.median {
} $out SELECT median() WITHIN GROUP (ORDER BY x) FROM t1;
} {1 {near "(": syntax error}}
} }
# Add some NULL values. # Add some NULL values.
@@ -61,28 +92,69 @@ foreach {in out} {
do_test percentile-1.2 { do_test percentile-1.2 {
execsql {INSERT INTO t1 VALUES(NULL),(NULL);} execsql {INSERT INTO t1 VALUES(NULL),(NULL);}
} {} } {}
foreach {in out} { foreach {in out disc} {
100 11.0 100 11.0 11.0
50 8.0 50 8.0 8.0
12.5 4.0 12.5 4.0 4.0
15 4.4 15 4.4 4.0
20 5.2 20 5.2 4.0
80 11.0 80 11.0 11.0
89 11.0 89 11.0 11.0
} { } {
do_test percentile-1.3.$in { do_test percentile-1.3.$in.1 {
execsql {SELECT percentile(x,$in) FROM t1} execsql {SELECT percentile(x,$in) FROM t1}
} $out } $out
do_test percentile-1.3.$in.2 {
execsql {SELECT percentile_cont(x,$in*0.01) FROM t1}
} $out
do_test percentile-1.3.$in.3 {
execsql {SELECT percentile_disc(x,$in*0.01) FROM t1}
} $disc
if {$in==50} {
do_test percentile-1.3.$in.4 {
execsql {SELECT median(x) FROM t1}
} $out
}
ifcapable ordered_set_aggregates {
do_test percentile-1.3.$in.5 {
execsql {SELECT percentile($in)WITHIN GROUP(ORDER BY x) FROM t1}
} $out
do_test percentile-1.3.$in.6 {
execsql {SELECT percentile_cont($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t1}
} $out
do_test percentile-1.3.$in.7 {
execsql {SELECT percentile_disc($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t1}
} $disc
if {$in==50} {
do_test percentile-1.3.$in.8 {
execsql {SELECT median() WITHIN GROUP (ORDER BY x) FROM t1}
} $out
}
}
} }
# The second argument to percentile can change some, but not much. # The second argument to percentile can change some, but not much.
# #
do_test percentile-1.4 { do_test percentile-1.4.1 {
catchsql {SELECT round(percentile(x, 15+0.000001*rowid),1) FROM t1} catchsql {SELECT round(percentile(x, 15+0.000001*rowid),1) FROM t1}
} {0 4.4} } {0 4.4}
do_test percentile-1.5 { do_test percentile-1.4.2 {
catchsql {SELECT round(percentile(x, 15+0.1*rowid),1) FROM t1} catchsql {SELECT round(percentile_cont(x,(15+0.000001*rowid)*0.01),1) FROM t1}
} {1 {2nd argument to percentile() is not the same for all input rows}} } {0 4.4}
do_test percentile-1.4.3 {
catchsql {SELECT percentile_disc(x, (15+0.000001*rowid)*0.01) FROM t1}
} {0 4.0}
do_test percentile-1.5.1 {
catchsql {SELECT percentile(x, 15+0.1*rowid) FROM t1}
} {1 {the fraction argument to percentile() is not the same for all input rows}}
do_test percentile-1.5.2 {
catchsql {SELECT percentile_cont(x, (15+0.1*rowid)*0.01) FROM t1}
} {1 {the fraction argument to percentile_cont() is not the same for all input rows}}
do_test percentile-1.5.3 {
catchsql {SELECT percentile_disc(x, (15+0.1*rowid)*0.01) FROM t1}
} {1 {the fraction argument to percentile_disc() is not the same for all input rows}}
# Input values in a random order # Input values in a random order
# #
@@ -92,65 +164,152 @@ do_test percentile-1.6 {
INSERT INTO t2 SELECT x+0.0 FROM t1 ORDER BY random(); INSERT INTO t2 SELECT x+0.0 FROM t1 ORDER BY random();
} }
} {} } {}
foreach {in out} { foreach {in out disc} {
100 11.0 100 11.0 11.0
50 8.0 50 8.0 8.0
12.5 4.0 12.5 4.0 4.0
15 4.4 15 4.4 4.0
20 5.2 20 5.2 4.0
80 11.0 80 11.0 11.0
89 11.0 89 11.0 11.0
} { } {
do_test percentile-1.7.$in { do_test percentile-1.7.$in.1 {
execsql {SELECT percentile(x,$in) FROM t2} execsql {SELECT percentile(x,$in) FROM t2}
} $out } $out
do_test percentile-1.7.$in.2 {
execsql {SELECT percentile_cont(x,$in*0.01) FROM t2}
} $out
do_test percentile-1.7.$in.3 {
execsql {SELECT percentile_disc(x,$in*0.01) FROM t2}
} $disc
if {$in==50} {
do_test percentile-1.7.$in.4 {
execsql {SELECT median(x) FROM t2}
} $out
}
ifcapable ordered_set_aggregates {
do_test percentile-1.7.$in.5 {
execsql {SELECT percentile($in)WITHIN GROUP(ORDER BY x) FROM t2}
} $out
do_test percentile-1.7.$in.6 {
execsql {SELECT percentile_cont($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t2}
} $out
do_test percentile-1.7.$in.7 {
execsql {SELECT percentile_disc($in*0.01) WITHIN GROUP(ORDER BY x)
FROM t2}
} $disc
if {$in==50} {
do_test percentile-1.7.$in.8 {
execsql {SELECT median() WITHIN GROUP (ORDER BY x) FROM t2}
} $out
}
}
} }
# Wrong number of arguments # Wrong number of arguments
# #
do_test percentile-1.8 { do_test percentile-1.8.1 {
catchsql {SELECT percentile(x,0,1) FROM t1} catchsql {SELECT percentile(x,0,1) FROM t1}
} {1 {wrong number of arguments to function percentile()}} } {1 {wrong number of arguments to function percentile()}}
do_test percentile-1.9 { do_test percentile-1.8.2 {
catchsql {SELECT percentile_cont(x,0,1) FROM t1}
} {1 {wrong number of arguments to function percentile_cont()}}
do_test percentile-1.8.3 {
catchsql {SELECT percentile_disc(x,0,1) FROM t1}
} {1 {wrong number of arguments to function percentile_disc()}}
do_test percentile-1.8.4 {
catchsql {SELECT median(x,0) FROM t1}
} {1 {wrong number of arguments to function median()}}
ifcapable ordered_set_aggregates {
do_test percentile-1.8.5 {
catchsql {SELECT percentile(0,1) WITHIN GROUP(ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile()}}
do_test percentile-1.8.2 {
catchsql {SELECT percentile_cont(0,1)WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile_cont()}}
do_test percentile-1.8.3 {
catchsql {SELECT percentile_disc(0,1)WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile_disc()}}
do_test percentile-1.8.4 {
catchsql {SELECT median(x) WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function median()}}
}
do_test percentile-1.9.1 {
catchsql {SELECT percentile(x) FROM t1} catchsql {SELECT percentile(x) FROM t1}
} {1 {wrong number of arguments to function percentile()}} } {1 {wrong number of arguments to function percentile()}}
do_test percentile-1.9.2 {
catchsql {SELECT percentile_cont(x) FROM t1}
} {1 {wrong number of arguments to function percentile_cont()}}
do_test percentile-1.9.3 {
catchsql {SELECT percentile_disc(x) FROM t1}
} {1 {wrong number of arguments to function percentile_disc()}}
do_test percentile-1.9.4 {
catchsql {SELECT median() FROM t1}
} {1 {wrong number of arguments to function median()}}
ifcapable ordered_set_aggregates {
do_test percentile-1.9.5 {
catchsql {SELECT percentile() WITHIN GROUP(ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile()}}
do_test percentile-1.9.6 {
catchsql {SELECT percentile_cont()WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile_cont()}}
do_test percentile-1.9.7 {
catchsql {SELECT percentile_disc()WITHIN GROUP (ORDER BY x) FROM t1}
} {1 {wrong number of arguments to function percentile_disc()}}
}
# Second argument must be numeric # Second argument must be numeric
# #
do_test percentile-1.10 { do_test percentile-1.10 {
catchsql {SELECT percentile(x,null) FROM t1} catchsql {SELECT percentile(x,null) FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}} } {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
do_test percentile-1.11 { do_test percentile-1.11 {
catchsql {SELECT percentile(x,'fifty') FROM t1} catchsql {SELECT percentile(x,'fifty') FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}} } {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
do_test percentile-1.12 { do_test percentile-1.12 {
catchsql {SELECT percentile(x,x'3530') FROM t1} catchsql {SELECT percentile(x,x'3530') FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}} } {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
do_test percentile-1.12b {
catchsql {SELECT percentile_cont(x,x'3530') FROM t1}
} {1 {2nd argument to percentile_cont() is not a number between 0.0 and 1.0}}
# Second argument is out of range # Second argument is out of range
# #
do_test percentile-1.13 { do_test percentile-1.13 {
catchsql {SELECT percentile(x,-0.0000001) FROM t1} catchsql {SELECT percentile(x,-0.0000001) FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}} } {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
do_test percentile-1.14 { do_test percentile-1.14 {
catchsql {SELECT percentile(x,100.0000001) FROM t1} catchsql {SELECT percentile(x,100.0000001) FROM t1}
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}} } {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
do_test percentile-1.14b { do_test percentile-1.14.2 {
catchsql {SELECT percentile_cont(x,1.0000001) FROM t1} catchsql {SELECT percentile_cont(x,1.0000001) FROM t1}
} {1 {2nd argument to percentile_cont() is not a number between 0.0 and 1.0}} } {1 {the fraction argument to percentile_cont() is not between 0.0 and 1.0}}
do_test percentile-1.14.3 {
catchsql {SELECT percentile_disc(x,1.0000001) FROM t1}
} {1 {the fraction argument to percentile_disc() is not between 0.0 and 1.0}}
# First argument is not NULL and is not NUMERIC # First argument is not NULL and is not NUMERIC
# #
do_test percentile-1.15 { do_test percentile-1.15.1 {
catchsql { catchsql {
BEGIN; BEGIN;
UPDATE t1 SET x='50' WHERE x IS NULL; UPDATE t1 SET x='50' WHERE x IS NULL;
SELECT percentile(x, 50) FROM t1; SELECT percentile(x, 50) FROM t1;
} }
} {1 {1st argument to percentile() is not numeric}} } {1 {input to percentile() is not numeric}}
do_test percentile-1.15.2 {
catchsql {
SELECT percentile_cont(x, 0.50) FROM t1;
}
} {1 {input to percentile_cont() is not numeric}}
do_test percentile-1.15.3 {
catchsql {
SELECT percentile_disc(x, 0.50) FROM t1;
}
} {1 {input to percentile_disc() is not numeric}}
do_test percentile-1.15.4 {
catchsql {
SELECT median(x) FROM t1;
}
} {1 {input to median() is not numeric}}
do_test percentile-1.16 { do_test percentile-1.16 {
catchsql { catchsql {
ROLLBACK; ROLLBACK;
@@ -158,7 +317,7 @@ do_test percentile-1.16 {
UPDATE t1 SET x=x'3530' WHERE x IS NULL; UPDATE t1 SET x=x'3530' WHERE x IS NULL;
SELECT percentile(x, 50) FROM t1; SELECT percentile(x, 50) FROM t1;
} }
} {1 {1st argument to percentile() is not numeric}} } {1 {input to percentile() is not numeric}}
do_test percentile-1.17 { do_test percentile-1.17 {
catchsql { catchsql {
ROLLBACK; ROLLBACK;
@@ -186,7 +345,7 @@ do_test percentile-1.19 {
# Infinity as an input # Infinity as an input
# #
do_test percentile-1.20 { do_test percentile-1.20.1 {
catchsql { catchsql {
DELETE FROM t1; DELETE FROM t1;
INSERT INTO t1 SELECT x+0.0 FROM t2; INSERT INTO t1 SELECT x+0.0 FROM t2;
@@ -194,6 +353,43 @@ do_test percentile-1.20 {
SELECT percentile(x,50) from t1; SELECT percentile(x,50) from t1;
} }
} {1 {Inf input to percentile()}} } {1 {Inf input to percentile()}}
do_test percentile-1.20.2 {
catchsql {
SELECT percentile_cont(x,0.50) from t1;
}
} {1 {Inf input to percentile_cont()}}
do_test percentile-1.20.3 {
catchsql {
SELECT percentile_disc(x,0.50) from t1;
}
} {1 {Inf input to percentile_disc()}}
do_test percentile-1.20.4 {
catchsql {
SELECT median(x) from t1;
}
} {1 {Inf input to median()}}
ifcapable ordered_set_aggregates {
do_test percentile-1.20.5 {
catchsql {
SELECT percentile(50) WITHIN GROUP (ORDER BY x) from t1;
}
} {1 {Inf input to percentile()}}
do_test percentile-1.20.6 {
catchsql {
SELECT percentile_cont(0.50) WITHIN GROUP (ORDER BY x) from t1;
}
} {1 {Inf input to percentile_cont()}}
do_test percentile-1.20.7 {
catchsql {
SELECT percentile_disc(0.50) WITHIN GROUP(ORDER BY X) from t1;
}
} {1 {Inf input to percentile_disc()}}
do_test percentile-1.20.8 {
catchsql {
SELECT median() WITHIN GROUP (ORDER BY x) from t1;
}
} {1 {Inf input to median()}}
}
do_test percentile-1.21 { do_test percentile-1.21 {
catchsql { catchsql {
UPDATE t1 SET x=-1.0e300*1.0e300 WHERE rowid=5; UPDATE t1 SET x=-1.0e300*1.0e300 WHERE rowid=5;
@@ -229,4 +425,172 @@ ifcapable vtab {
} }
} }
# median() as a window function. (2024-08-31)
#
do_execsql_test percentile-3.0 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
INSERT INTO t1 VALUES (1, 'A', 'one', 8.4),
(2, 'B', 'two', 7.1),
(3, 'C', 'three', 5.9),
(4, 'D', 'one', 11.0),
(5, 'E', 'two', 12.5),
(6, 'F', 'three', 0.0),
(7, 'G', 'one', 2.7);
}
foreach {id oba expr} {
1 0 "median(d)"
2 0 "percentile(d,50)"
3 0 "percentile_cont(d,0.5)"
4 1 "median() WITHIN GROUP (ORDER BY d)"
5 1 "percentile(50) WITHIN GROUP (ORDER BY d)"
6 1 "percentile_cont(0.5) WITHIN GROUP (ORDER BY d)"
} {
if {$oba} {
ifcapable !ordered_set_aggregates break
}
set sql "SELECT a, b, c, d, \
group_concat(b,'.') OVER w1 AS 'elements', \
$expr OVER w1 AS 'median' \
FROM t1 \
WINDOW w1 AS (ORDER BY c, a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)"
do_execsql_test percentile-3.$id.1 $sql {
1 A one 8.4 A.D 9.7
4 D one 11.0 A.D.G 8.4
7 G one 2.7 D.G.C 5.9
3 C three 5.9 G.C.F 2.7
6 F three 0.0 C.F.B 5.9
2 B two 7.1 F.B.E 7.1
5 E two 12.5 B.E 9.8
}
set sql "SELECT a, b, c, d, \
group_concat(b,'.') OVER w1 AS 'elements', \
$expr OVER w1 AS 'median' \
FROM t1 \
WINDOW w1 AS (ORDER BY c, a \
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING)"
do_execsql_test percentile-3.$id.2 $sql {
1 A one 8.4 A.D 9.7
4 D one 11.0 A.D.G 8.4
7 G one 2.7 A.D.G.C 7.15
3 C three 5.9 A.D.G.C.F 5.9
6 F three 0.0 A.D.G.C.F.B 6.5
2 B two 7.1 A.D.G.C.F.B.E 7.1
5 E two 12.5 A.D.G.C.F.B.E 7.1
}
set sql "SELECT a, b, c, d, \
group_concat(b,'.') OVER w1 AS 'elements', \
$expr OVER w1 AS 'median' \
FROM t1 \
WINDOW w1 AS (ORDER BY c, a \
ROWS BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING)"
do_execsql_test percentile-3.$id.3 $sql {
1 A one 8.4 A.D.G.C.F.B.E 7.1
4 D one 11.0 A.D.G.C.F.B.E 7.1
7 G one 2.7 D.G.C.F.B.E 6.5
3 C three 5.9 G.C.F.B.E 5.9
6 F three 0.0 C.F.B.E 6.5
2 B two 7.1 F.B.E 7.1
5 E two 12.5 B.E 9.8
}
}
# Test case adapted from examples shown at
# https://database.guide/3-functions-to-calculate-the-median-in-sql/
#
do_execsql_test percential-4.0 {
CREATE TABLE products(
vendorId INT,
productId INTEGER PRIMARY KEY,
productName REAL,
price REAL
);
INSERT INTO products VALUES
(1001, 17, 'Left-handed screwdriver', 25.99),
(1001, 49, 'Right-handed screwdriver', 25.99),
(1001, 216, 'Long weight (blue)', 14.75),
(1001, 31, 'Long weight (green)', 11.99),
(1002, 37, 'Sledge hammer', 33.49),
(1003, 7, 'Chainsaw', 245.00),
(1003, 8, 'Straw dog box', 55.99),
(1003, 12, 'Hammock', 11.01),
(1004, 113, 'Teapot', 12.45),
(1004, 117, 'Bottomless coffee mug', 9.99);
}
do_execsql_test percentile-4.1 {
SELECT VendorId, ProductId, /* ProductName,*/ Price,
avg(price) OVER (PARTITION BY vendorId) AS "Average",
median(price) OVER (PARTITION BY vendorId) AS "Median"
FROM products
ORDER BY vendorId, productId;
} {
1001 17 25.99 19.68 20.37
1001 31 11.99 19.68 20.37
1001 49 25.99 19.68 20.37
1001 216 14.75 19.68 20.37
1002 37 33.49 33.49 33.49
1003 7 245.0 104.0 55.99
1003 8 55.99 104.0 55.99
1003 12 11.01 104.0 55.99
1004 113 12.45 11.22 11.22
1004 117 9.99 11.22 11.22
}
do_execsql_test percentile-4.2 {
SELECT vendorId, median(price) FROM products
GROUP BY 1 ORDER BY 1;
} {1001 20.37 1002 33.49 1003 55.99 1004 11.22}
do_execsql_test percentile-5.0 {
CREATE TABLE user(name TEXT, class TEXT, cost REAL);
INSERT INTO user VALUES
('Alice', 'Y', 3578.27),
('Bob', 'X', 3399.99),
('Cindy', 'Z', 699.10),
('Dave', 'Y', 3078.27),
('Emma', 'Z', 2319.99),
('Fred', 'Y', 539.99),
('Gina', 'X', 2320.49),
('Hank', 'W', 24.99),
('Irma', 'W', 24.99),
('Jake', 'X', 2234.99),
('Kim', 'Y', 4319.99),
('Liam', 'X', 4968.59),
('Mia', 'W', 59.53),
('Nate', 'W', 23.50);
}
do_execsql_test percentile-5.1 {
SELECT name, class, cost,
percentile(cost, 0) OVER w1 AS 'P0',
percentile(cost, 25) OVER w1 AS 'P1',
percentile(cost, 50) OVER w1 AS 'P2',
percentile(cost, 75) OVER w1 AS 'P3',
percentile(cost, 100) OVER w1 AS 'P4'
FROM user
WINDOW w1 AS (PARTITION BY class)
ORDER BY class, cost;
} {
Nate W 23.5 23.5 24.6175 24.99 33.625 59.53
Hank W 24.99 23.5 24.6175 24.99 33.625 59.53
Irma W 24.99 23.5 24.6175 24.99 33.625 59.53
Mia W 59.53 23.5 24.6175 24.99 33.625 59.53
Jake X 2234.99 2234.99 2299.115 2860.24 3792.14 4968.59
Gina X 2320.49 2234.99 2299.115 2860.24 3792.14 4968.59
Bob X 3399.99 2234.99 2299.115 2860.24 3792.14 4968.59
Liam X 4968.59 2234.99 2299.115 2860.24 3792.14 4968.59
Fred Y 539.99 539.99 2443.7 3328.27 3763.7 4319.99
Dave Y 3078.27 539.99 2443.7 3328.27 3763.7 4319.99
Alice Y 3578.27 539.99 2443.7 3328.27 3763.7 4319.99
Kim Y 4319.99 539.99 2443.7 3328.27 3763.7 4319.99
Cindy Z 699.1 699.1 1104.3225 1509.545 1914.7675 2319.99
Emma Z 2319.99 699.1 1104.3225 1509.545 1914.7675 2319.99
}
# Fuzzer find.
do_execsql_test percentile-6.0 {
WITH RECURSIVE c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<12)
SELECT median(iif(n%2,0.1,1.0)) FROM c;
} 0.55
finish_test finish_test

View File

@@ -1279,10 +1279,15 @@ proc finalize_testing {} {
out of $nTest tests" out of $nTest tests"
} else { } else {
set cpuinfo {} set cpuinfo {}
if {[catch {exec hostname} hname]==0} {set cpuinfo [string trim $hname]} if {[catch {exec hostname} hname]==0} {
regsub {\.local$} $hname {} hname
set cpuinfo [string trim $hname]
}
append cpuinfo " $::tcl_platform(os)" append cpuinfo " $::tcl_platform(os)"
append cpuinfo " [expr {$::tcl_platform(pointerSize)*8}]-bit" append cpuinfo " [expr {$::tcl_platform(pointerSize)*8}]-bit"
append cpuinfo " [string map {E -e} $::tcl_platform(byteOrder)]" if {[string match big* $::tcl_platform(byteOrder)]} {
append cpuinfo " [string map {E -e} $::tcl_platform(byteOrder)]"
}
output2 "SQLite [sqlite3 -sourceid]" output2 "SQLite [sqlite3 -sourceid]"
output2 "$nErr errors out of $nTest tests on $cpuinfo" output2 "$nErr errors out of $nTest tests on $cpuinfo"
} }

190
test/testrunner.tcl Normal file → Executable file
View File

@@ -1,3 +1,6 @@
#!/bin/sh
# Script to runs tests for SQLite. Run with option "help" for more info. \
exec tclsh "$0" "$@"
set dir [pwd] set dir [pwd]
set testdir [file normalize [file dirname $argv0]] set testdir [file normalize [file dirname $argv0]]
@@ -14,8 +17,14 @@ cd $dir
# recommend that the user build one. # recommend that the user build one.
# #
proc find_interpreter {} { proc find_interpreter {} {
global dir
set interpreter [file tail [info nameofexec]] set interpreter [file tail [info nameofexec]]
set rc [catch { package require sqlite3 }] set rc [catch { package require sqlite3 }]
if {$rc} {
if {[file readable pkgIndex.tcl] && [catch {source pkgIndex.tcl}]==0} {
set rc [catch { package require sqlite3 }]
}
}
if {$rc} { if {$rc} {
if { [string match -nocase testfixture* $interpreter]==0 if { [string match -nocase testfixture* $interpreter]==0
&& [file executable ./testfixture] && [file executable ./testfixture]
@@ -28,8 +37,30 @@ proc find_interpreter {} {
} }
} }
if {$rc} { if {$rc} {
puts stderr "Failed to find tcl package sqlite3" puts "Cannot find tcl package sqlite3: Trying to build it now..."
puts stderr "Run \"make testfixture\" and then try again..." if {$::tcl_platform(platform)=="windows"} {
set bat [open make-tcl-extension.bat w]
puts $bat "nmake /f Makefile.msc tclextension"
close $bat
catch {exec -ignorestderr -- make-tcl-extension.bat}
} else {
catch {exec make tclextension}
}
if {[file readable pkgIndex.tcl] && [catch {source pkgIndex.tcl}]==0} {
set rc [catch { package require sqlite3 }]
}
if {$rc==0} {
puts "The SQLite tcl extension was successfully built and loaded."
puts "Run \"make tclextension-install\" to avoid having to rebuild\
it in the future."
} else {
puts "Unable to build the SQLite tcl extension"
}
}
if {$rc} {
puts stderr "Cannot find a working instance of the SQLite tcl extension."
puts stderr "Run \"make tclextension\" or \"make testfixture\" and\
try again..."
exit 1 exit 1
} }
} }
@@ -54,8 +85,9 @@ proc usage {} {
Usage: Usage:
$a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS? $a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?
$a0 PERMUTATION FILE $a0 PERMUTATION FILE
$a0 errors ?-v|--verbose? $a0 errors ?-v|--verbose? ?-s|--summary? ?PATTERN?
$a0 help $a0 help
$a0 joblist ?PATTERN?
$a0 njob ?NJOB? $a0 njob ?NJOB?
$a0 script ?-msvc? CONFIG $a0 script ?-msvc? CONFIG
$a0 status ?-d SECS? ?--cls? $a0 status ?-d SECS? ?--cls?
@@ -112,10 +144,12 @@ The "script" command outputs the script used to build a configuration.
Add the "-msvc" option for a Windows-compatible script. For a list of Add the "-msvc" option for a Windows-compatible script. For a list of
available configurations enter "$a0 script help". available configurations enter "$a0 script help".
The "errors" commands shows the output of all tests that failed in the The "errors" commands shows the output of tests that failed in the
most recent run. Complete output is shown if the -v or --verbose options most recent run. Complete output is shown if the -v or --verbose options
are used. Otherwise, an attempt is made to minimize the output to show are used. Otherwise, an attempt is made to minimize the output to show
only the parts that contain the error messages. only the parts that contain the error messages. The --summary option just
shows the jobs that failed. If PATTERN are provided, the error information
is only provided for jobs that match PATTERN.
Full documentation here: https://sqlite.org/src/doc/trunk/doc/testrunner.md Full documentation here: https://sqlite.org/src/doc/trunk/doc/testrunner.md
}]] }]]
@@ -284,6 +318,8 @@ set TRG(schema) {
state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ), state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ),
ntest INT, -- Number of test cases run ntest INT, -- Number of test cases run
nerr INT, -- Number of errors reported nerr INT, -- Number of errors reported
svers TEXT, -- Reported SQLite version
pltfm TEXT, -- Host platform reported
output TEXT -- test output output TEXT -- test output
); );
@@ -356,8 +392,8 @@ if {([llength $argv]==2 || [llength $argv]==1)
sqlite3 mydb $TRG(dbname) sqlite3 mydb $TRG(dbname)
if {[llength $argv]==2} { if {[llength $argv]==2} {
set param [lindex $argv 1] set param [lindex $argv 1]
if {[string is integer $param]==0 || $param<1 || $param>128} { if {[string is integer $param]==0 || $param<0 || $param>128} {
puts stderr "parameter must be an integer between 1 and 128" puts stderr "parameter must be an integer between 0 and 128"
exit 1 exit 1
} }
@@ -476,13 +512,22 @@ proc show_status {db cls} {
$ne errors, $nt tests"] $ne errors, $nt tests"]
set srcdir [file dirname [file dirname $TRG(info_script)]] set srcdir [file dirname [file dirname $TRG(info_script)]]
set nrun 0 set line "Running: $S(running) (max: $nJob)"
puts [format %-79s "Running: $S(running) (max: $nJob)"] if {$S(running)>0 && $fin>100 && $fin>0.05*$total} {
# Only estimate the time remaining after completing at least 100
# jobs amounting to 10% of the total. Never estimate less than
# 2% of the total time used so far.
set tmleft [expr {($tm/$fin)*($total-$fin)}]
if {$tmleft<0.02*$tm} {
set tmleft [expr {$tm*0.02}]
}
append line " est time left [elapsetime $tmleft]"
}
puts [format %-79.79s $line]
if {$S(running)>0} { if {$S(running)>0} {
$db eval { $db eval {
SELECT * FROM jobs WHERE state='running' ORDER BY starttime SELECT * FROM jobs WHERE state='running' ORDER BY starttime
} job { } job {
incr nrun
display_job [array get job] $now display_job [array get job] $now
} }
} }
@@ -568,44 +613,80 @@ if {[llength $argv]>=1
exit exit
} }
#--------------------------------------------------------------------------
# Check if this is the "joblist" command:
#
if {[llength $argv]>=1
&& [string compare -nocase "joblist" [lindex $argv 0]]==0
} {
set pattern {}
for {set ii 1} {$ii<[llength $argv]} {incr ii} {
set a0 [lindex $argv $ii]
if {$pattern==""} {
set pattern [string trim $a0 *]
} else {
puts "unknown option: \"$a0\""
exit 1
}
}
set SQL {SELECT displaytype, displayname, state FROM jobs}
if {$pattern!=""} {
regsub -all {[^a-zA-Z0-9*.-/]} $pattern ? pattern
append SQL " WHERE displayname GLOB '*$pattern*'"
}
append SQL " ORDER BY starttime"
if {![file readable $TRG(dbname)]} {
puts "Database missing: $TRG(dbname)"
exit
}
sqlite3 mydb $TRG(dbname)
mydb timeout 2000
mydb eval $SQL {
set label UNKNOWN
switch -- $state {
ready {set label READY}
done {set label DONE}
failed {set label FAILED}
omit {set label OMIT}
running {set label RUNNING}
}
puts [format {%-7s %-5s %s} $label $displaytype $displayname]
}
mydb close
exit
}
# Scan the output of all jobs looking for the summary lines that # Scan the output of all jobs looking for the summary lines that
# report the number of test cases and the number of errors. # report the number of test cases and the number of errors.
# Aggregate these numbers and return them. # Aggregate these numbers and return them.
# #
proc aggregate_test_counts {db} { proc aggregate_test_counts {db} {
set ncase 0 set ne 0
set nerr 0 set nt 0
$db eval {SELECT output FROM jobs WHERE displaytype IN ('tcl','fuzz')} { $db eval {SELECT sum(nerr) AS ne, sum(ntest) as nt FROM jobs} break
set n 0 return [list $ne $nt]
set m 0
if {[regexp {(\d+) errors out of (\d+) tests} $output all n m]
&& [string is integer -strict $n]
&& [string is integer -strict $m]} {
incr ncase $m
incr nerr $n
} elseif {[regexp {sessionfuzz.*: *(\d+) cases, (\d+) crash} $output \
all m n]
&& [string is integer -strict $m]
&& [string is integer -strict $n]} {
incr ncase $m
incr nerr $n
}
}
return [list $nerr $ncase]
} }
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# Check if this is the "errors" command: # Check if this is the "errors" command:
# #
if {[llength $argv]>=1 && [llength $argv]<=2 if {[llength $argv]>=1
&& ([string compare -nocase errors [lindex $argv 0]]==0 || && ([string compare -nocase errors [lindex $argv 0]]==0 ||
[string match err* [lindex $argv 0]]==1) [string match err* [lindex $argv 0]]==1)
} { } {
set verbose 0 set verbose 0
set pattern {}
set summary 0
for {set ii 1} {$ii<[llength $argv]} {incr ii} { for {set ii 1} {$ii<[llength $argv]} {incr ii} {
set a0 [lindex $argv $ii] set a0 [lindex $argv $ii]
if {$a0=="-v" || $a0=="--verbose" || $a0=="-verbose"} { if {$a0=="-v" || $a0=="--verbose" || $a0=="-verbose"} {
set verbose 1 set verbose 1
} elseif {$a0=="-s" || $a0=="--summary" || $a0=="-summary"} {
set summary 1
} elseif {$pattern==""} {
set pattern *[string trim $a0 *]*
} else { } else {
puts "unknown option: \"$a0\"". Use --help for more info." puts "unknown option: \"$a0\"". Use --help for more info."
exit 1 exit 1
@@ -613,9 +694,22 @@ if {[llength $argv]>=1 && [llength $argv]<=2
} }
set cnt 0 set cnt 0
sqlite3 mydb $TRG(dbname) sqlite3 mydb $TRG(dbname)
mydb timeout 2000 mydb timeout 5000
mydb eval {SELECT displaytype, displayname, output if {$summary} {
FROM jobs WHERE state='failed'} { set sql "SELECT displayname FROM jobs WHERE state='failed'"
} else {
set sql "SELECT displaytype, displayname, output FROM jobs \
WHERE state='failed'"
}
if {$pattern!=""} {
regsub -all {[^a-zA-Z0-9*/ ?]} $pattern . pattern
append sql " AND displayname GLOB '$pattern'"
}
mydb eval $sql {
if {$summary} {
puts "FAILED: $displayname"
continue
}
puts "**** $displayname ****" puts "**** $displayname ****"
if {$verbose || $displaytype!="tcl"} { if {$verbose || $displaytype!="tcl"} {
puts $output puts $output
@@ -628,9 +722,13 @@ if {[llength $argv]>=1 && [llength $argv]<=2
} }
incr cnt incr cnt
} }
set summary [aggregate_test_counts mydb] if {$pattern==""} {
mydb close set summary [aggregate_test_counts mydb]
puts "Total [lindex $summary 0] errors out of [lindex $summary 1] tests" mydb close
puts "Total [lindex $summary 0] errors out of [lindex $summary 1] tests"
} else {
mydb close
}
exit exit
} }
@@ -1096,6 +1194,7 @@ proc add_jobs_from_cmdline {patternlist} {
} }
} }
devtest -
mdevtest { mdevtest {
set config_set { set config_set {
ReuseSchema-O0 ReuseSchema-O0
@@ -1184,10 +1283,13 @@ proc mark_job_as_finished {jobid output state endtm} {
set ntest 1 set ntest 1
set nerr 0 set nerr 0
if {$endtm>0} { if {$endtm>0} {
if {[regexp {\y(\d+) errors out of (\d+) tests} $output all a b]} { set re {\y(\d+) errors out of (\d+) tests( on [^\n]+\n)?}
if {[regexp $re $output all a b pltfm]} {
set nerr $a set nerr $a
set ntest $b set ntest $b
} }
regexp {\ySQLite \d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [0-9a-fA-F]+} \
$output svers
} }
r_write_db { r_write_db {
if {$state=="failed"} { if {$state=="failed"} {
@@ -1196,10 +1298,11 @@ proc mark_job_as_finished {jobid output state endtm} {
} else { } else {
set childstate ready set childstate ready
} }
if {[info exists pltfm]} {set pltfm [string trim $pltfm]}
trdb eval { trdb eval {
UPDATE jobs UPDATE jobs
SET output=$output, state=$state, endtime=$endtm, SET output=$output, state=$state, endtime=$endtm,
ntest=$ntest, nerr=$nerr ntest=$ntest, nerr=$nerr, svers=$svers, pltfm=$pltfm
WHERE jobid=$jobid; WHERE jobid=$jobid;
UPDATE jobs SET state=$childstate WHERE depid=$jobid; UPDATE jobs SET state=$childstate WHERE depid=$jobid;
} }
@@ -1452,7 +1555,16 @@ proc run_testset {} {
FROM jobs WHERE endtime>0 FROM jobs WHERE endtime>0
} break; } break;
set et [elapsetime $totaltime] set et [elapsetime $totaltime]
puts "$totalerr errors out of $totaltest tests in about $et" set pltfm {}
trdb eval {
SELECT pltfm, count(*) FROM jobs WHERE pltfm IS NOT NULL
ORDER BY 2 DESC LIMIT 1
} break
puts "$totalerr errors out of $totaltest tests in $et $pltfm"
trdb eval {
SELECT DISTINCT substr(svers,1,79) as v1 FROM jobs WHERE svers IS NOT NULL
} {puts $v1}
} }
# Handle the --buildonly option, if it was specified. # Handle the --buildonly option, if it was specified.

View File

@@ -88,6 +88,7 @@ namespace eval trd {
--disable-amalgamation --disable-shared --disable-amalgamation --disable-shared
--enable-session --enable-session
-DSQLITE_ENABLE_RBU -DSQLITE_ENABLE_RBU
-DSQLITE_ENABLE_STMT_SCANSTATUS
} }
# These two are used by [testrunner.tcl mdevtest] (All-O0) and # These two are used by [testrunner.tcl mdevtest] (All-O0) and
@@ -95,6 +96,7 @@ namespace eval trd {
# #
set build(All-Debug) { set build(All-Debug) {
--enable-debug --enable-all --enable-debug --enable-all
-DSQLITE_ENABLE_ORDERED_SET_AGGREGATES
} }
set build(All-O0) { set build(All-O0) {
-O0 --enable-all -O0 --enable-all

View File

@@ -127,6 +127,17 @@ foreach tn {1a 1b 1c 1d 1e 1f} {
db3 close db3 close
} }
# These over-length file and directory names are difficult to delete.
# The "file delete -force" might not work, depending on the TCL build
# being used. So first try to delete using the windows rmdir command.
#
set fd [open cleanup.bat w]
puts $fd "rmdir /q /s $longPath(1)"
close $fd
if {[catch {exec cleanup.bat} msg]} {
puts "Command \[cleanup.bat\] returns $msg"
}
file delete -force $fileName file delete -force $fileName
file delete -force $longPath(3) file delete -force $longPath(3)
file delete -force $longPath(2) file delete -force $longPath(2)

View File

@@ -159,6 +159,7 @@ set boolean_defnil_options {
SQLITE_ENABLE_MULTIPLEX SQLITE_ENABLE_MULTIPLEX
SQLITE_ENABLE_NORMALIZE SQLITE_ENABLE_NORMALIZE
SQLITE_ENABLE_NULL_TRIM SQLITE_ENABLE_NULL_TRIM
SQLITE_ENABLE_ORDERED_SET_AGGREGATES
SQLITE_ENABLE_OFFSET_SQL_FUNC SQLITE_ENABLE_OFFSET_SQL_FUNC
SQLITE_ENABLE_OVERSIZE_CELL_CHECK SQLITE_ENABLE_OVERSIZE_CELL_CHECK
SQLITE_ENABLE_PREUPDATE_HOOK SQLITE_ENABLE_PREUPDATE_HOOK

View File

@@ -164,6 +164,11 @@ struct Keyword {
#else #else
# define RETURNING 0x00400000 # define RETURNING 0x00400000
#endif #endif
#ifndef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
# define ORDERSET 0
#else
# define ORDERSET 0x00800000
#endif
/* /*
@@ -316,6 +321,7 @@ static Keyword aKeywordTable[] = {
{ "WHERE", "TK_WHERE", ALWAYS, 10 }, { "WHERE", "TK_WHERE", ALWAYS, 10 },
{ "WINDOW", "TK_WINDOW", WINDOWFUNC, 3 }, { "WINDOW", "TK_WINDOW", WINDOWFUNC, 3 },
{ "WITH", "TK_WITH", CTE, 4 }, { "WITH", "TK_WITH", CTE, 4 },
{ "WITHIN", "TK_WITHIN", ORDERSET, 1 },
{ "WITHOUT", "TK_WITHOUT", ALWAYS, 1 }, { "WITHOUT", "TK_WITHOUT", ALWAYS, 1 },
}; };

View File

@@ -1,370 +1,220 @@
# Documentation for this script. This may be output to stderr #!/usr/bin/tclsh
#
# Documentation for this script. This may be output to
# if the script is invoked incorrectly. # if the script is invoked incorrectly.
#
set ::USAGE_MESSAGE { set ::USAGE_MESSAGE {
This Tcl script is used to test the various compile time options This Tcl script is used to test the various compile time options
available for omitting code (the SQLITE_OMIT_xxx options). It available for building SQLite, especially options taht omit
should be invoked as follows: features (the SQLITE_OMIT_xxx options). It should be invoked as follows:
<script> ?test-symbol? ?-makefile PATH-TO-MAKEFILE? ?-skip_run? ./configure CFLAGS=-O0
tclsh test/omittest.tcl
The default value for ::MAKEFILE is "../Makefile.linux.gcc".
If -skip_run option is given then only the compile part is attempted.
This script builds the testfixture program and runs the SQLite test suite
once with each SQLITE_OMIT_ option defined and then once with all options
defined together. Each run is performed in a seperate directory created
as a sub-directory of the current directory by the script. The output
of the build is saved in <sub-directory>/build.log. The output of the
test-suite is saved in <sub-directory>/test.log.
Almost any SQLite makefile (except those generated by configure - see below)
should work. The following properties are required:
* The makefile should support the "testfixture" target.
* The makefile should support the "test" target.
* The makefile should support the variable "OPTS" as a way to pass
options from the make command line to lemon and the C compiler.
More precisely, the following two invocations must be supported:
$::MAKEBIN -f $::MAKEFILE testfixture OPTS="-DSQLITE_OMIT_ALTERTABLE=1"
$::MAKEBIN -f $::MAKEFILE test
Makefiles generated by the sqlite configure program cannot be used as
they do not respect the OPTS variable.
} }
# List of all options to be tested.
# Build a testfixture executable and run quick.test using it. The first
# parameter is the name of the directory to create and use to run the
# test in. The second parameter is a list of OMIT symbols to define
# when doing so. For example:
# #
# run_quick_test /tmp/testdir {SQLITE_OMIT_TRIGGER SQLITE_OMIT_VIEW} set CompileOptionsToTest {
# SQLITE_OMIT_ALTERTABLE
# SQLITE_OMIT_ANALYZE
proc run_quick_test {dir omit_symbol_list} { SQLITE_OMIT_ATTACH
# Compile the value of the OPTS Makefile variable. SQLITE_OMIT_AUTHORIZATION
set opts "" SQLITE_OMIT_AUTOINCREMENT
if {$::tcl_platform(platform)=="windows"} { SQLITE_OMIT_AUTOINIT
append opts "OPTS += -DSQLITE_OS_WIN=1\n" SQLITE_OMIT_AUTOMATIC_INDEX
set target "testfixture.exe" SQLITE_OMIT_AUTORESET
} else { SQLITE_OMIT_AUTOVACUUM
append opts "OPTS += -DSQLITE_OS_UNIX=1\n" SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS
} SQLITE_OMIT_BETWEEN_OPTIMIZATION
foreach sym $omit_symbol_list { SQLITE_OMIT_BLOB_LITERAL
append opts "OPTS += -D${sym}=1\n" SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA
} SQLITE_OMIT_CAST
SQLITE_OMIT_CHECK
SQLITE_OMIT_COMPILEOPTION_DIAGS
SQLITE_OMIT_COMPLETE
SQLITE_OMIT_COMPOUND_SELECT
SQLITE_OMIT_CONFLICT_CLAUSE
SQLITE_OMIT_CTE
SQLITE_OMIT_DATETIME_FUNCS
SQLITE_OMIT_DECLTYPE
SQLITE_OMIT_DEPRECATED
SQLITE_OMIT_DESERIALIZE
SQLITE_OMIT_DISKIO
SQLITE_OMIT_EXPLAIN
SQLITE_OMIT_FLAG_PRAGMAS
SQLITE_OMIT_FLOATING_POINT
SQLITE_OMIT_FOREIGN_KEY
SQLITE_OMIT_GENERATED_COLUMNS
SQLITE_OMIT_GET_TABLE
SQLITE_OMIT_HEX_INTEGER
SQLITE_OMIT_INCRBLOB
SQLITE_OMIT_INTEGRITY_CHECK
SQLITE_OMIT_INTROSPECTION_PRAGMAS
SQLITE_OMIT_JSON
SQLITE_OMIT_LIKE_OPTIMIZATION
SQLITE_OMIT_LOAD_EXTENSION
SQLITE_OMIT_LOCALTIME
SQLITE_OMIT_LOOKASIDE
SQLITE_OMIT_MEMORYDB
SQLITE_OMIT_OR_OPTIMIZATION
SQLITE_OMIT_PAGER_PRAGMAS
SQLITE_OMIT_PARSER_TRACE
SQLITE_OMIT_POPEN
SQLITE_OMIT_PRAGMA
SQLITE_OMIT_PROGRESS_CALLBACK
SQLITE_OMIT_QUICKBALANCE
SQLITE_OMIT_RANDOMNESS
SQLITE_OMIT_REINDEX
SQLITE_OMIT_SCHEMA_PRAGMAS
SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
SQLITE_OMIT_SHARED_CACHE
SQLITE_OMIT_SHUTDOWN_DIRECTORIES
SQLITE_OMIT_SUBQUERY
SQLITE_OMIT_TCL_VARIABLE
SQLITE_OMIT_TEMPDB
SQLITE_OMIT_TEST_CONTROL
SQLITE_OMIT_TRACE
SQLITE_OMIT_TRIGGER
SQLITE_OMIT_TRUNCATE_OPTIMIZATION
SQLITE_OMIT_TWOSIZE_LOOKASIDE
SQLITE_OMIT_UPSERT
SQLITE_OMIT_UTF
SQLITE_OMIT_VACUUM
SQLITE_OMIT_VIEW
SQLITE_OMIT_VIRTUALTABLE
SQLITE_OMIT_WAL
SQLITE_OMIT_WINDOWFUNC
SQLITE_OMIT_WSD
SQLITE_OMIT_XFER_OPT
SQLITE_ALLOW_ROWID_IN_VIEW
SQLITE_DISABLE_DIRSYNC
SQLITE_DISABLE_FTS
SQLITE_DISABLE_INTRINSIC
SQLITE_DISABLE_LFS
SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
SQLITE_DISABLE_SKIPAHEAD_DISTINCT
SQLITE_ENABLE_API_ARMOR
SQLITE_ENABLE_ATOMIC_WRITE
SQLITE_ENABLE_BATCH_ATOMIC_WRITE
SQLITE_ENABLE_BYTECODE_VTAB
SQLITE_ENABLE_CEROD
SQLITE_ENABLE_COLUMN_METADATA
SQLITE_ENABLE_COLUMN_USED_MASK
SQLITE_ENABLE_COMMENTS
SQLITE_ENABLE_CORRUPT_PGNO
SQLITE_ENABLE_COSTMULT
SQLITE_ENABLE_CURSOR_HINTS
SQLITE_ENABLE_DBPAGE_VTAB
SQLITE_ENABLE_DBSTAT_VTAB
SQLITE_ENABLE_EXPENSIVE_ASSERT
SQLITE_ENABLE_EXPLAIN_COMMENTS
SQLITE_ENABLE_FTS
SQLITE_ENABLE_GEOPOLY
SQLITE_ENABLE_HIDDEN_COLUMNS
SQLITE_ENABLE_ICU
SQLITE_ENABLE_ICU_COLLATIONS
SQLITE_ENABLE_INTERNAL_FUNCTIONS
SQLITE_ENABLE_IOTRACE
SQLITE_ENABLE_LOAD_EXTENSION
SQLITE_ENABLE_LOCKING_STYLE
SQLITE_ENABLE_MATH_FUNCTIONS
SQLITE_ENABLE_MEMORY_MANAGEMENT
SQLITE_ENABLE_MEMSYS
SQLITE_ENABLE_MODULE_COMMENTS
SQLITE_ENABLE_MULTIPLEX
SQLITE_ENABLE_MULTITHREADED_CHECKS
SQLITE_ENABLE_NORMALIZE
SQLITE_ENABLE_NULL_TRIM
SQLITE_ENABLE_OFFSET_SQL_FUNC
SQLITE_ENABLE_OVERSIZE_CELL_CHECK
SQLITE_ENABLE_PREUPDATE_HOOK
SQLITE_ENABLE_QPSG
SQLITE_ENABLE_RBU
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_SELECTTRACE
SQLITE_ENABLE_SESSION
SQLITE_ENABLE_SETLK_TIMEOUT
SQLITE_ENABLE_SNAPSHOT
SQLITE_ENABLE_SORTER_MMAP
SQLITE_ENABLE_SORTER_REFERENCE
SQLITE_ENABLE_SORTER_REFERENCES
SQLITE_ENABLE_SQLLOG
SQLITE_ENABLE_STAT
SQLITE_ENABLE_STMT_SCANSTATUS
SQLITE_ENABLE_STMTVTAB
SQLITE_ENABLE_TREETRACE
SQLITE_ENABLE_UNKNOWN_FUNCTION
SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SQLITE_ENABLE_UNLOCK_NOTIFY
SQLITE_ENABLE_UPDATE_DELETE_LIMIT
SQLITE_ENABLE_URI_00_ERROR
SQLITE_ENABLE_VFSTRACE
SQLITE_ENABLE_WHERETRACE
SQLITE_ENABLE_ZIPVFS
}
# Create the directory and do the build. If an error occurs return # Parse command-line options.
# early without attempting to run the test suite. #
file mkdir $dir for {set i 0} {$i<[llength $argv]} {incr i} {
puts -nonewline "Building $dir..." set arg [lindex $argv $i]
flush stdout switch -- $arg {
catch { -start -
file copy -force ./config.h $dir --start {
file copy -force ./libtool $dir incr i
} set startat [lindex $argv $i]
set fd [open $::MAKEFILE] }
set mkfile [read $fd]
close $fd
regsub {\ninclude} $mkfile "\n$opts\ninclude" mkfile
set fd [open $dir/makefile w]
puts $fd $mkfile
close $fd
set rc [catch {
exec $::MAKEBIN -C $dir -f makefile clean $::TARGET >& $dir/build.log
}]
if {$rc} {
puts "No good. See $dir/build.log."
return
} else {
puts "Ok"
}
# Create an empty file "$dir/sqlite3". This is to trick the makefile out
# of trying to build the sqlite shell. The sqlite shell won't build
# with some of the OMIT options (i.e OMIT_COMPLETE).
set sqlite3_dummy $dir/sqlite3
if {$::tcl_platform(platform)=="windows"} {
append sqlite3_dummy ".exe"
}
if {![file exists $sqlite3_dummy]} {
set wr [open $sqlite3_dummy w]
puts $wr "dummy"
close $wr
} }
}
if {$::SKIP_RUN} { # Additional options required for some settings.
# puts "Skip testing $dir." #
} else { set More(SQLITE_OMIT_DISKIO) {-DSQLITE_OMIT_WAL}
# Run the test suite.
puts -nonewline "Testing $dir..." # Compile-time options for Mac only
flush stdout #
set rc [catch { set MacOnly(SQLITE_ENABLE_LOCKING_STYLE) 1
exec $::MAKEBIN -C $dir -f makefile test >& $dir/test.log
}] # Compile-time options that might fail, depending on what libraries
if {$rc} { # are installed. Failures on these tests issue a warning, but testing
puts "No good. See $dir/test.log." # continues.
#
set FailIsOk(SQLITE_ENABLE_ICU) 1
set FailIsOk(SQLITE_ENABLE_ICU_COLLATIONS) 1
file mkdir omittest
foreach sym $CompileOptionsToTest {
if {[info exists startat]} {
if {$startat==$sym} {
unset startat
} else { } else {
puts "Ok" continue
} }
} }
} if {[info exists MacOnly($sym)] && $tcl_platform(os)!="Darwin"} {
continue
}
# This proc processes the command line options passed to this script. set logfile "omittest/$sym.log"
# Currently the only option supported is "-makefile", default if {[info exists More($sym)]} {
# "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this append opts "OPT_FEATURE_FLAGS=-D$sym $More($sym)"
# option.
#
proc process_options {argv} {
set ::MAKEBIN make ;# Default value
if {$::tcl_platform(platform)=="windows"} {
set ::MAKEFILE ./Makefile ;# Default value on Windows
} else { } else {
set ::MAKEFILE ./Makefile.linux-gcc ;# Default value set opts OPT_FEATURE_FLAGS=-D$sym
} }
set ::SKIP_RUN 1 ;# Default to attempt test puts "make tidy sqlite3.lo $opts"
set ::TARGET testfixture ;# Default thing to build if {[catch {exec make tidy sqlite3.lo $opts >& $logfile}]} {
puts "BUILD FAILED: see $logfile for details"
for {set i 0} {$i < [llength $argv]} {incr i} { if {[info exists FailIsOk($sym)]} {
switch -regexp -- [lindex $argv $i] { set Failure($sym) 1
-{1,2}makefile { } else {
incr i puts "Note: After fixes, continue the test using:\n"
set ::MAKEFILE [lindex $argv $i] puts " [info nameofexe] $argv0 --start $sym\n"
} exit 1
-{1,2}nmake {
set ::MAKEBIN nmake
set ::MAKEFILE ./Makefile.msc
}
-{1,2}target {
incr i
set ::TARGET [lindex $argv $i]
}
-{1,2}skip_run {
set ::SKIP_RUN 1
}
-{1,2}run {
set ::SKIP_RUN 0
}
-{1,2}help {
puts $::USAGE_MESSAGE
exit
}
-.* {
puts stderr "Unknown option: [lindex $argv i]"
puts stderr $::USAGE_MESSAGE
exit 1
}
default {
if {[info exists ::SYMBOL]} {
puts stderr [string trim $::USAGE_MESSAGE]
exit -1
}
set ::SYMBOL [lindex $argv $i]
}
}
set ::MAKEFILE [file normalize $::MAKEFILE]
}
}
# Main routine.
#
proc main {argv} {
# List of SQLITE_OMIT_XXX symbols supported by SQLite.
set ::OMIT_SYMBOLS [list \
SQLITE_OMIT_ALTERTABLE \
SQLITE_OMIT_ANALYZE \
SQLITE_OMIT_ATTACH \
SQLITE_OMIT_AUTHORIZATION \
SQLITE_OMIT_AUTOINCREMENT \
SQLITE_OMIT_AUTOINIT \
SQLITE_OMIT_AUTOMATIC_INDEX \
SQLITE_OMIT_AUTORESET \
SQLITE_OMIT_AUTOVACUUM \
SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS \
SQLITE_OMIT_BETWEEN_OPTIMIZATION \
SQLITE_OMIT_BLOB_LITERAL \
SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA \
SQLITE_OMIT_CAST \
SQLITE_OMIT_CHECK \
SQLITE_OMIT_COMPILEOPTION_DIAGS \
SQLITE_OMIT_COMPLETE \
SQLITE_OMIT_COMPOUND_SELECT \
SQLITE_OMIT_CONFLICT_CLAUSE \
SQLITE_OMIT_CTE \
SQLITE_OMIT_DATETIME_FUNCS \
SQLITE_OMIT_DECLTYPE \
SQLITE_OMIT_DEPRECATED \
SQLITE_OMIT_DESERIALIZE \
SQLITE_OMIT_DISKIO \
SQLITE_OMIT_EXPLAIN \
SQLITE_OMIT_FLAG_PRAGMAS \
SQLITE_OMIT_FLOATING_POINT \
SQLITE_OMIT_FOREIGN_KEY \
SQLITE_OMIT_GENERATED_COLUMNS \
SQLITE_OMIT_GET_TABLE \
SQLITE_OMIT_HEX_INTEGER \
SQLITE_OMIT_INCRBLOB \
SQLITE_OMIT_INTEGRITY_CHECK \
SQLITE_OMIT_INTROSPECTION_PRAGMAS \
SQLITE_OMIT_JSON \
SQLITE_OMIT_LIKE_OPTIMIZATION \
SQLITE_OMIT_LOAD_EXTENSION \
SQLITE_OMIT_LOCALTIME \
SQLITE_OMIT_LOOKASIDE \
SQLITE_OMIT_MEMORYDB \
SQLITE_OMIT_OR_OPTIMIZATION \
SQLITE_OMIT_PAGER_PRAGMAS \
SQLITE_OMIT_PARSER_TRACE \
SQLITE_OMIT_POPEN \
SQLITE_OMIT_PRAGMA \
SQLITE_OMIT_PROGRESS_CALLBACK \
SQLITE_OMIT_QUICKBALANCE \
SQLITE_OMIT_RANDOMNESS \
SQLITE_OMIT_REINDEX \
SQLITE_OMIT_SCHEMA_PRAGMAS \
SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS \
SQLITE_OMIT_SHARED_CACHE \
SQLITE_OMIT_SHUTDOWN_DIRECTORIES \
SQLITE_OMIT_SUBQUERY \
SQLITE_OMIT_TCL_VARIABLE \
SQLITE_OMIT_TEMPDB \
SQLITE_OMIT_TEST_CONTROL \
SQLITE_OMIT_TRACE \
SQLITE_OMIT_TRIGGER \
SQLITE_OMIT_TRUNCATE_OPTIMIZATION \
SQLITE_OMIT_TWOSIZE_LOOKASIDE \
SQLITE_OMIT_UPSERT \
SQLITE_OMIT_UTF \
SQLITE_OMIT_VACUUM \
SQLITE_OMIT_VIEW \
SQLITE_OMIT_VIRTUALTABLE \
SQLITE_OMIT_WAL \
SQLITE_OMIT_WINDOWFUNC \
SQLITE_OMIT_WSD \
SQLITE_OMIT_XFER_OPT \
]
set ::ENABLE_SYMBOLS [list \
SQLITE_ALLOW_ROWID_IN_VIEW \
SQLITE_DISABLE_DIRSYNC \
SQLITE_DISABLE_FTS \
SQLITE_DISABLE_INTRINSIC \
SQLITE_DISABLE_LFS \
SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS \
SQLITE_DISABLE_SKIPAHEAD_DISTINCT \
SQLITE_ENABLE_API_ARMOR \
SQLITE_ENABLE_ATOMIC_WRITE \
SQLITE_ENABLE_BATCH_ATOMIC_WRITE \
SQLITE_ENABLE_BYTECODE_VTAB \
SQLITE_ENABLE_CEROD \
SQLITE_ENABLE_COLUMN_METADATA \
SQLITE_ENABLE_COLUMN_USED_MASK \
SQLITE_ENABLE_COMMENTS \
SQLITE_ENABLE_CORRUPT_PGNO \
SQLITE_ENABLE_COSTMULT \
SQLITE_ENABLE_CURSOR_HINTS \
SQLITE_ENABLE_DBPAGE_VTAB \
SQLITE_ENABLE_DBSTAT_VTAB \
SQLITE_ENABLE_EXPENSIVE_ASSERT \
SQLITE_ENABLE_EXPLAIN_COMMENTS \
SQLITE_ENABLE_FTS \
SQLITE_ENABLE_GEOPOLY \
SQLITE_ENABLE_HIDDEN_COLUMNS \
SQLITE_ENABLE_ICU \
SQLITE_ENABLE_ICU_COLLATIONS \
SQLITE_ENABLE_INTERNAL_FUNCTIONS \
SQLITE_ENABLE_IOTRACE \
SQLITE_ENABLE_LOAD_EXTENSION \
SQLITE_ENABLE_LOCKING_STYLE \
SQLITE_ENABLE_MATH_FUNCTIONS \
SQLITE_ENABLE_MEMORY_MANAGEMENT \
SQLITE_ENABLE_MEMSYS \
SQLITE_ENABLE_MODULE_COMMENTS \
SQLITE_ENABLE_MULTIPLEX \
SQLITE_ENABLE_MULTITHREADED_CHECKS \
SQLITE_ENABLE_NORMALIZE \
SQLITE_ENABLE_NULL_TRIM \
SQLITE_ENABLE_OFFSET_SQL_FUNC \
SQLITE_ENABLE_OVERSIZE_CELL_CHECK \
SQLITE_ENABLE_PREUPDATE_HOOK \
SQLITE_ENABLE_QPSG \
SQLITE_ENABLE_RBU \
SQLITE_ENABLE_RTREE \
SQLITE_ENABLE_SELECTTRACE \
SQLITE_ENABLE_SESSION \
SQLITE_ENABLE_SETLK_TIMEOUT \
SQLITE_ENABLE_SNAPSHOT \
SQLITE_ENABLE_SORTER_MMAP\
SQLITE_ENABLE_SORTER_REFERENCE \
SQLITE_ENABLE_SORTER_REFERENCES \
SQLITE_ENABLE_SQLLOG\
SQLITE_ENABLE_STAT \
SQLITE_ENABLE_STMT_SCANSTATUS \
SQLITE_ENABLE_STMTVTAB \
SQLITE_ENABLE_TREETRACE \
SQLITE_ENABLE_UNKNOWN_FUNCTION \
SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
SQLITE_ENABLE_UNLOCK_NOTIFY \
SQLITE_ENABLE_UPDATE_DELETE_LIMIT \
SQLITE_ENABLE_URI_00_ERROR \
SQLITE_ENABLE_VFSTRACE \
SQLITE_ENABLE_WHERETRACE \
SQLITE_ENABLE_ZIPVFS \
]
# Process any command line options.
process_options $argv
if {[info exists ::SYMBOL] } {
set sym $::SYMBOL
if {[lsearch $::OMIT_SYMBOLS $sym]<0 && [lsearch $::ENABLE_SYMBOLS $sym]<0} {
puts stderr "No such symbol: $sym"
exit -1
}
set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
run_quick_test $dirname $sym
} else {
# First try a test with all OMIT symbols except SQLITE_OMIT_FLOATING_POINT
# and SQLITE_OMIT_PRAGMA defined. The former doesn't work (causes segfaults)
# and the latter is currently incompatible with the test suite (this should
# be fixed, but it will be a lot of work).
set allsyms [list]
foreach s $::OMIT_SYMBOLS {
if {$s!="SQLITE_OMIT_FLOATING_POINT" && $s!="SQLITE_OMIT_PRAGMA"} {
lappend allsyms $s
}
}
run_quick_test test_OMIT_EVERYTHING $allsyms
# Now try one quick.test with each of the OMIT symbols defined. Included
# are the OMIT_FLOATING_POINT and OMIT_PRAGMA symbols, even though we
# know they will fail. It's good to be reminded of this from time to time.
foreach sym $::OMIT_SYMBOLS {
set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
run_quick_test $dirname $sym
}
# Try the ENABLE/DISABLE symbols one at a time.
# We don't do them all at once since some are conflicting.
foreach sym $::ENABLE_SYMBOLS {
set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
run_quick_test $dirname $sym
} }
} }
} }
if {[llength [array names Failure]]>0} {
main $argv puts "BUILD FAILED on the following:"
foreach sym [array names Failure] {
puts " * $sym"
}
}