Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 825026251f | |||
| fd486258a0 | |||
| 940cdc94f3 | |||
| 23a16c8387 | |||
| e6e49bfef2 | |||
| 06638117bb | |||
| 22cd1eec5a | |||
| 7c6f2880aa | |||
| 70989b6f59 | |||
| ef7c692baf | |||
| da52f11250 | |||
| 7a29505e57 | |||
| d281889ac8 | |||
| a955ec806a | |||
| b5df31d15f | |||
| b9a6e42a55 | |||
| 1c30df3598 | |||
| ca447020ae | |||
| 7aa01a0ffc | |||
| 5d5d6194c9 | |||
| c97ad9b4e1 | |||
| 41155d8885 | |||
| df2d14b86e | |||
| a239ece378 | |||
| c1042cd133 | |||
| 65b1244781 | |||
| 49af3dfbf4 | |||
| a5315a6ece | |||
| f138110dfd | |||
| ad8ec9db63 | |||
| 129767958a | |||
| 90fa4c7b2c | |||
| 3196c349d1 | |||
| 0337b9a628 | |||
| 6cb12337b9 | |||
| c589d5ab06 | |||
| 28db1a68ba | |||
| 11397ce104 | |||
| 494ba30c9b | |||
| 6a18c9e06a | |||
| ccd34894e1 | |||
| c1547d1f7a | |||
| 50ca8af6f2 | |||
| 8db3fc5488 | |||
| ba5994b181 | |||
| 3341f5ce85 | |||
| d6b56d65a8 | |||
| 4f2f91bf08 | |||
| 242e064978 | |||
| 4a90f81a6d | |||
| a88d61824d | |||
| af43eddc23 | |||
| b5b4ca2a11 | |||
| c3c645ef46 | |||
| f5a9b58c8b | |||
| ce018f5bb3 | |||
| 1a7cfbebb0 | |||
| db05c66a16 | |||
| 71475478a1 | |||
| c8edf07ca7 | |||
| d9bc2bb638 | |||
| 3c39f1f5d6 | |||
| dac0d0b310 | |||
| 4a972bc1b8 | |||
| 8aa9135f2c | |||
| fcd65efcf1 | |||
| c013fa50db | |||
| 1321ea5010 | |||
| 3a39c44c21 | |||
| 20728a599e |
+54
-43
@@ -83,9 +83,13 @@ TEMP_STORE = -DSQLITE_TEMP_STORE=@TEMP_STORE@
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
# LEMON parser generator and the mkkeywordhash tool as well.
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
|
||||
#
|
||||
# Add OPTIONS=... on the command line to append additional options
|
||||
# to the OPT_FEATURE_FLAGS.
|
||||
#
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@ $(OPTIONS)
|
||||
|
||||
TCC += $(OPT_FEATURE_FLAGS)
|
||||
TCC += $(OPT_FEATURE_FLAGS)
|
||||
|
||||
# Add in any optional parameters specified on the make commane line
|
||||
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
|
||||
@@ -646,6 +650,7 @@ FUZZCHECK_SRC += $(TOP)/test/fuzzinvariants.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/recover/dbdata.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/recover/sqlite3recover.c
|
||||
FUZZCHECK_SRC += $(TOP)/test/vt02.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/misc/percentile.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/misc/randomjson.c
|
||||
DBFUZZ_OPT =
|
||||
ST_OPT = -DSQLITE_OS_KV_OPTIONAL
|
||||
@@ -1178,6 +1183,7 @@ SHELL_DEP = \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/ext/misc/pcachetrace.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
@@ -1363,9 +1369,14 @@ tcltest: ./testfixture$(TEXE)
|
||||
testrunner: testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl
|
||||
|
||||
# Runs both fuzztest and testrunner, consecutively.
|
||||
# This is the testing target preferred by the core SQLite developers.
|
||||
# It runs tests under a standard configuration, regardless of how
|
||||
# ./configure was run. The devs run "make devtest" prior to each
|
||||
# check-in, at a minimum. Probably other tests too, but at least this
|
||||
# one.
|
||||
#
|
||||
devtest: srctree-check testfixture$(TEXE) fuzztest testrunner
|
||||
devtest: srctree-check sourcetest
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS)
|
||||
|
||||
mdevtest: srctree-check has_tclsh85
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS)
|
||||
@@ -1381,16 +1392,19 @@ srctree-check: $(TOP)/tool/srctree-check.tcl
|
||||
|
||||
# Testing for a release
|
||||
#
|
||||
releasetest: srctree-check testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
|
||||
releasetest: srctree-check has_tclsh85 verify-source
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
|
||||
|
||||
# Minimal testing that runs in less than 3 minutes
|
||||
#
|
||||
quicktest: ./testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)
|
||||
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
# Try to run tests on whatever options are specified by the
|
||||
# ./configure. The developers seldom use this target. Instead
|
||||
# they use "make devtest" which runs tests on a standard set of
|
||||
# options regardless of how SQLite is configured. This "test"
|
||||
# target is provided for legacy only.
|
||||
#
|
||||
test: srctree-check fuzztest sourcetest $(TESTPROGS) tcltest
|
||||
|
||||
@@ -1407,8 +1421,8 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
|
||||
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
|
||||
|
||||
shelltest: $(TESTPROGS)
|
||||
./testfixture$(TEXT) $(TOP)/test/permutations.test shell
|
||||
shelltest:
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release shell
|
||||
|
||||
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in has_tclsh85
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
|
||||
@@ -1594,43 +1608,40 @@ tclextension-uninstall:
|
||||
tclextension-list:
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info
|
||||
|
||||
clean:
|
||||
rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la
|
||||
rm -f sqlite3.h opcodes.*
|
||||
rm -rf .libs .deps
|
||||
rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz
|
||||
rm -f mkkeywordhash$(BEXE) keywordhash.h
|
||||
rm -f mksourceid$(BEXE)
|
||||
rm -f *.da *.bb *.bbg gmon.out
|
||||
rm -rf tsrc .target_source
|
||||
rm -f tclsqlite3$(TEXE)
|
||||
rm -f testfixture$(TEXE) test.db
|
||||
|
||||
# Remove build products sufficient so that subsequent makes will recompile
|
||||
# everything from scratch. Do not remove:
|
||||
#
|
||||
# * test results and test logs
|
||||
# * output from ./configure
|
||||
#
|
||||
tidy:
|
||||
rm -f *.lo *.la *.o *.c *.da *.bb *.bbg gmon.* *.rws sqlite3$(TEXE)
|
||||
rm -f fts5.h keywordhash.h opcodes.h sqlite3.h sqlite3ext.h sqlite3session.h
|
||||
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 showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
|
||||
rm -f wordcount$(TEXE) changeset$(TEXE)
|
||||
rm -f version-info$(TEXT)
|
||||
rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
|
||||
rm -f sqlite3.c
|
||||
rm -f sqlite3rc.h
|
||||
rm -f shell.c sqlite3ext.h
|
||||
rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
|
||||
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
|
||||
rm -f wordcount$(TEXE) changeset$(TEXE) version-info$(TEXE)
|
||||
rm -f *.dll *.lib *.exp *.def *.pc *.vsix
|
||||
rm -f sqlite3_analyzer$(TEXE)
|
||||
rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
|
||||
rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
|
||||
rm -f threadtest5$(TEXE)
|
||||
rm -f src-verify has_tclsh*
|
||||
|
||||
# Removes build products and test logs. Retains ./configure outputs.
|
||||
#
|
||||
clean: tidy
|
||||
rm -rf omittest* testrunner* testdir*
|
||||
|
||||
# Clean up everything. No exceptions.
|
||||
#
|
||||
distclean: clean
|
||||
rm -f sqlite_cfg.h config.log config.status libtool Makefile sqlite3.pc \
|
||||
$(TESTPROGS)
|
||||
rm -f sqlite_cfg.h config.log config.status Makefile $(LIBTOOL)
|
||||
|
||||
#
|
||||
# Windows section
|
||||
|
||||
+32
-5
@@ -379,6 +379,7 @@ SQLITE_TCL_DEP =
|
||||
# the Windows platform.
|
||||
#
|
||||
!IFNDEF OPT_FEATURE_FLAGS
|
||||
OPT_FEATURE_FLAGS = $(OPT_XTRA)
|
||||
!IF $(MINIMAL_AMALGAMATION)==0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=1
|
||||
@@ -392,6 +393,14 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
# Additional feature-options above and beyond what are normally used can be
|
||||
# be added using OPTIONS=.... on the command-line. These values are
|
||||
# appended to the OPT_FEATURE_FLAGS variable.
|
||||
#
|
||||
!IFDEF OPTIONS
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) $(OPTIONS)
|
||||
!ENDIF
|
||||
|
||||
# Should the session extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
#
|
||||
@@ -1758,6 +1767,7 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.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\sqlite3recover.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\percentile.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c
|
||||
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
@@ -2304,6 +2314,7 @@ SHELL_DEP = \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\memtrace.c \
|
||||
$(TOP)\ext\misc\pcachetrace.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\shathree.c \
|
||||
@@ -2535,6 +2546,13 @@ queryplantest: testfixture.exe shell
|
||||
fuzztest: fuzzcheck.exe
|
||||
.\fuzzcheck.exe $(FUZZDATA)
|
||||
|
||||
# Legacy testing target for third-party integrators. The SQLite
|
||||
# developers seldom use this target themselves. Instead
|
||||
# they use "nmake /f Makefile.msc devtest" which runs tests on
|
||||
# a standard set of options
|
||||
#
|
||||
test: $(TESTPROGS) sourcetest fuzztest tcltest
|
||||
|
||||
# Minimal testing that runs in less than 3 minutes (on a fast machine)
|
||||
#
|
||||
quicktest: testfixture.exe sourcetest
|
||||
@@ -2544,7 +2562,6 @@ quicktest: testfixture.exe sourcetest
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
#
|
||||
test: $(TESTPROGS) sourcetest fuzztest tcltest
|
||||
|
||||
# The veryquick.test TCL tests.
|
||||
#
|
||||
@@ -2558,17 +2575,27 @@ tcltest: testfixture.exe
|
||||
testrunner: testfixture.exe
|
||||
.\testfixture.exe $(TOP)\test\testrunner.tcl
|
||||
|
||||
# Runs both fuzztest and testrunner, consecutively.
|
||||
# This is the testing target preferred by the core SQLite developers.
|
||||
# It runs tests under a standard configuration. The devs run
|
||||
# "nmake /f Makefile.msc devtest" prior to each check-in, at a minimum.
|
||||
# Probably other tests too, but at least this one.
|
||||
#
|
||||
devtest: testfixture.exe fuzztest testrunner
|
||||
devtest: srctree-check sourcetest
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest
|
||||
|
||||
mdevtest:
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest
|
||||
|
||||
# Validate that various generated files in the source tree
|
||||
# are up-to-date.
|
||||
#
|
||||
srctree-check: $(TOP)\tool\srctree-check.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\srctree-check.tcl
|
||||
|
||||
# Testing for a release
|
||||
#
|
||||
releasetest: testfixture.exe
|
||||
testfixture.exe $(TOP)\test\testrunner.tcl release
|
||||
releasetest:
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release
|
||||
|
||||
|
||||
smoketest: $(TESTPROGS)
|
||||
|
||||
@@ -109,7 +109,7 @@ For example:
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make sqlite3 ;# Builds the "sqlite3" command-line tool
|
||||
make sqlite3.c ;# Build the "amalgamation" source file
|
||||
make mdevtest ;# Run development tests (requires tcl-dev)
|
||||
make devtest ;# Run development tests (requires tcl-dev)
|
||||
make releasetest ;# Run full release tests (requires tcl-dev)
|
||||
make sqldiff ;# Builds the "sqldiff" command-line tool
|
||||
make sqlite3_analyzer ;# Builds the "sqlite3_analyzer" tool (requires tcl-dev)
|
||||
@@ -128,6 +128,13 @@ Almost all makefile targets require a "tclsh" TCL interpreter
|
||||
version 8.6 or later. The targets marked with "(requires tcl-dev)" also require
|
||||
the TCL development libraries.
|
||||
|
||||
On "make" command-lines, one can add "OPTIONS=..." to specify additional
|
||||
compile-time options over and above those set by ./configure. For example,
|
||||
to compile with the SQLITE_OMIT_DEPRECATED compile-time option, one could say:
|
||||
|
||||
./configure --enable-all
|
||||
make OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3
|
||||
|
||||
The configure script uses autoconf 2.61 and libtool. If the configure
|
||||
script does not work out for you, there is a generic makefile named
|
||||
"Makefile.linux-gcc" in the top directory of the source tree that you
|
||||
@@ -156,13 +163,18 @@ Build using Makefile.msc. Example:
|
||||
|
||||
nmake /f Makefile.msc sqlite3.exe
|
||||
nmake /f Makefile.msc sqlite3.c
|
||||
nmake /f Makefile.msc mdevtest
|
||||
nmake /f Makefile.msc devtest
|
||||
nmake /f Makefile.msc releasetest
|
||||
nmake /f Makefile.msc tclextension-install
|
||||
|
||||
There are many other makefile targets. See comments in Makefile.msc for
|
||||
details.
|
||||
|
||||
As with the unix Makefile, the OPTIONS=... argument can be passed on the nmake
|
||||
command-line to enable new compile-time options. For example:
|
||||
|
||||
nmake /f Makefile.msc OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3.exe
|
||||
|
||||
## Source Tree Map
|
||||
|
||||
* **src/** - This directory contains the primary source code for the
|
||||
|
||||
@@ -301,6 +301,7 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
|
||||
# the Windows platform.
|
||||
#
|
||||
!IFNDEF OPT_FEATURE_FLAGS
|
||||
OPT_FEATURE_FLAGS = $(OPT_XTRA)
|
||||
!IF $(MINIMAL_AMALGAMATION)==0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=1
|
||||
@@ -314,6 +315,14 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
# Additional feature-options above and beyond what are normally used can be
|
||||
# be added using OPTIONS=.... on the command-line. These values are
|
||||
# appended to the OPT_FEATURE_FLAGS variable.
|
||||
#
|
||||
!IFDEF OPTIONS
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) $(OPTIONS)
|
||||
!ENDIF
|
||||
|
||||
# Should the session extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
#
|
||||
|
||||
+89
-2
@@ -595,6 +595,93 @@ oPutbUtf8(const char *cBuf, int nAccept){
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush the given output stream. Return non-zero for success, else 0.
|
||||
*/
|
||||
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fFlushBuffer(FILE *pfOut){
|
||||
# if CIO_WIN_WC_XLATE && !defined(SHELL_OMIT_FIO_DUPE)
|
||||
return FlushFileBuffers(handleOfFile(pfOut))? 1 : 0;
|
||||
# else
|
||||
return fflush(pfOut);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE \
|
||||
&& !defined(SHELL_OMIT_FIO_DUPE) \
|
||||
&& defined(SQLITE_USE_ONLY_WIN32)
|
||||
static struct FileAltIds {
|
||||
int fd;
|
||||
HANDLE fh;
|
||||
} altIdsOfFile(FILE *pf){
|
||||
struct FileAltIds rv = { _fileno(pf) };
|
||||
union { intptr_t osfh; HANDLE fh; } fid = {
|
||||
(rv.fd>=0)? _get_osfhandle(rv.fd) : (intptr_t)INVALID_HANDLE_VALUE
|
||||
};
|
||||
rv.fh = fid.fh;
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE size_t
|
||||
cfWrite(const void *buf, size_t osz, size_t ocnt, FILE *pf){
|
||||
size_t rv = 0;
|
||||
struct FileAltIds fai = altIdsOfFile(pf);
|
||||
int fmode = _setmode(fai.fd, _O_BINARY);
|
||||
_setmode(fai.fd, fmode);
|
||||
while( rv < ocnt ){
|
||||
size_t nbo = osz;
|
||||
while( nbo > 0 ){
|
||||
DWORD dwno = (nbo>(1L<<24))? 1L<<24 : (DWORD)nbo;
|
||||
BOOL wrc = TRUE;
|
||||
BOOL genCR = (fmode & _O_TEXT)!=0;
|
||||
if( genCR ){
|
||||
const char *pnl = (const char*)memchr(buf, '\n', nbo);
|
||||
if( pnl ) nbo = pnl - (const char*)buf;
|
||||
else genCR = 0;
|
||||
}
|
||||
if( dwno>0 ) wrc = WriteFile(fai.fh, buf, dwno, 0,0);
|
||||
if( genCR && wrc ){
|
||||
wrc = WriteFile(fai.fh, "\r\n", 2, 0,0);
|
||||
++dwno; /* Skip over the LF */
|
||||
}
|
||||
if( !wrc ) return rv;
|
||||
buf = (const char*)buf + dwno;
|
||||
nbo += dwno;
|
||||
}
|
||||
++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 *
|
||||
cfGets(char *cBuf, int n, FILE *pf){
|
||||
int nci = 0;
|
||||
struct FileAltIds fai = altIdsOfFile(pf);
|
||||
int fmode = _setmode(fai.fd, _O_BINARY);
|
||||
BOOL eatCR = (fmode & _O_TEXT)!=0;
|
||||
_setmode(fai.fd, fmode);
|
||||
while( nci < n-1 ){
|
||||
DWORD nr;
|
||||
if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break;
|
||||
if( nr>0 && (!eatCR || cBuf[nci]!='\r') ){
|
||||
nci += nr;
|
||||
if( cBuf[nci-nr]=='\n' ) break;
|
||||
}
|
||||
}
|
||||
if( nci < n ) cBuf[nci] = 0;
|
||||
return (nci>0)? cBuf : 0;
|
||||
}
|
||||
# else
|
||||
# define cfWrite(b,os,no,f) fwrite(b,os,no,f)
|
||||
# define cfGets(b,n,f) fgets(b,n,f)
|
||||
# endif
|
||||
|
||||
# ifdef CONSIO_EPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept){
|
||||
@@ -606,7 +693,7 @@ ePutbUtf8(const char *cBuf, int nAccept){
|
||||
return conZstrEmit(ppst, cBuf, nAccept);
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfErr);
|
||||
return (int)cfWrite(cBuf, 1, nAccept, pfErr);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
@@ -672,7 +759,7 @@ SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
|
||||
# endif
|
||||
}else{
|
||||
# endif
|
||||
return fgets(cBuf, ncMax, pfIn);
|
||||
return cfGets(cBuf, ncMax, pfIn);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
|
||||
+11
-4
@@ -176,12 +176,19 @@ SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Flush the given output stream. Return non-zero for success, else 0.
|
||||
*/
|
||||
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fFlushBuffer(FILE *pfOut);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Collect input like fgets(...) with special provisions for input
|
||||
** from the console on platforms that require same. Defers to the
|
||||
** C library fgets() when input is not from the console. Newline
|
||||
** translation may be done as set by set{Binary,Text}Mode(). As a
|
||||
** convenience, pfIn==NULL is treated as stdin.
|
||||
** from the console on such platforms as require same. Newline
|
||||
** translation may be done as set by set{Binary,Text}Mode().
|
||||
** As a convenience, pfIn==NULL is treated as stdin.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn);
|
||||
/* Like fGetsUtf8 except stream is always the designated input. */
|
||||
|
||||
+7
-6
@@ -493,18 +493,19 @@ struct Fts5ExtensionApi {
|
||||
**
|
||||
** FTS5_TOKENIZER
|
||||
**
|
||||
** There is also an fts5_tokenizer object. This is an older version of
|
||||
** fts5_tokenizer_v2. It is similar except that:
|
||||
** There is also an fts5_tokenizer object. This is an older, deprecated,
|
||||
** version of fts5_tokenizer_v2. It is similar except that:
|
||||
**
|
||||
** <ul>
|
||||
** <li> There is no "iVersion" field, and
|
||||
** <li> The xTokenize() method does not take a locale argument.
|
||||
** </ul>
|
||||
**
|
||||
** fts5_tokenizer tokenizers should be registered with the xCreateTokenizer()
|
||||
** function, instead of xCreateTokenizer_v2(). Tokenizers implementations
|
||||
** registered using either API may be retrieved using both xFindTokenizer()
|
||||
** and xFindTokenizer_v2().
|
||||
** Legacy fts5_tokenizer tokenizers must be registered using the
|
||||
** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
|
||||
**
|
||||
** Tokenizer implementations registered using either API may be retrieved
|
||||
** using both xFindTokenizer() and xFindTokenizer_v2().
|
||||
**
|
||||
** SYNONYM SUPPORT
|
||||
**
|
||||
|
||||
@@ -2185,7 +2185,7 @@ static void fts5SegIterNext_None(
|
||||
|
||||
if( iOff<pIter->iEndofDoclist ){
|
||||
/* Next entry is on the current page */
|
||||
i64 iDelta;
|
||||
u64 iDelta;
|
||||
iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
|
||||
pIter->iLeafOffset = iOff;
|
||||
pIter->iRowid += iDelta;
|
||||
|
||||
+19
-17
@@ -427,8 +427,7 @@ static int fts5InitVtab(
|
||||
|
||||
/* Load the initial configuration */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
|
||||
sqlite3Fts5IndexRollback(pTab->p.pIndex);
|
||||
rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie-1);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
@@ -2068,9 +2067,11 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
|
||||
** Implementation of xBegin() method.
|
||||
*/
|
||||
static int fts5BeginMethod(sqlite3_vtab *pVtab){
|
||||
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
|
||||
fts5NewTransaction((Fts5FullTable*)pVtab);
|
||||
return SQLITE_OK;
|
||||
int rc = fts5NewTransaction((Fts5FullTable*)pVtab);
|
||||
if( rc==SQLITE_OK ){
|
||||
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3267,7 +3268,9 @@ static int fts5NewTokenizerModule(
|
||||
*/
|
||||
typedef struct Fts5VtoVTokenizer Fts5VtoVTokenizer;
|
||||
struct Fts5VtoVTokenizer {
|
||||
Fts5TokenizerModule *pMod;
|
||||
int bV2Native; /* True if v2 native tokenizer */
|
||||
fts5_tokenizer x1; /* Tokenizer functions */
|
||||
fts5_tokenizer_v2 x2; /* V2 tokenizer functions */
|
||||
Fts5Tokenizer *pReal;
|
||||
};
|
||||
|
||||
@@ -3287,7 +3290,9 @@ static int fts5VtoVCreate(
|
||||
|
||||
pNew = (Fts5VtoVTokenizer*)sqlite3Fts5MallocZero(&rc, sizeof(*pNew));
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->pMod = pMod;
|
||||
pNew->x1 = pMod->x1;
|
||||
pNew->x2 = pMod->x2;
|
||||
pNew->bV2Native = pMod->bV2Native;
|
||||
if( pMod->bV2Native ){
|
||||
rc = pMod->x2.xCreate(pMod->pUserData, azArg, nArg, &pNew->pReal);
|
||||
}else{
|
||||
@@ -3309,11 +3314,10 @@ static int fts5VtoVCreate(
|
||||
static void fts5VtoVDelete(Fts5Tokenizer *pTok){
|
||||
Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
|
||||
if( p ){
|
||||
Fts5TokenizerModule *pMod = p->pMod;
|
||||
if( pMod->bV2Native ){
|
||||
pMod->x2.xDelete(p->pReal);
|
||||
if( p->bV2Native ){
|
||||
p->x2.xDelete(p->pReal);
|
||||
}else{
|
||||
pMod->x1.xDelete(p->pReal);
|
||||
p->x1.xDelete(p->pReal);
|
||||
}
|
||||
sqlite3_free(p);
|
||||
}
|
||||
@@ -3331,9 +3335,8 @@ static int fts5V1toV2Tokenize(
|
||||
int (*xToken)(void*, int, const char*, int, int, int)
|
||||
){
|
||||
Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
|
||||
Fts5TokenizerModule *pMod = p->pMod;
|
||||
assert( pMod->bV2Native );
|
||||
return pMod->x2.xTokenize(p->pReal, pCtx, flags, pText, nText, 0, 0, xToken);
|
||||
assert( p->bV2Native );
|
||||
return p->x2.xTokenize(p->pReal, pCtx, flags, pText, nText, 0, 0, xToken);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3348,10 +3351,9 @@ static int fts5V2toV1Tokenize(
|
||||
int (*xToken)(void*, int, const char*, int, int, int)
|
||||
){
|
||||
Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
|
||||
Fts5TokenizerModule *pMod = p->pMod;
|
||||
assert( pMod->bV2Native==0 );
|
||||
assert( p->bV2Native==0 );
|
||||
UNUSED_PARAM2(pLocale,nLocale);
|
||||
return pMod->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken);
|
||||
return p->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+96
-15
@@ -96,14 +96,14 @@ static int SQLITE_TCLAPI f5tDbAndApi(
|
||||
|
||||
rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
|
||||
sqlite3_step(pStmt);
|
||||
|
||||
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
CASE(12, "xSetAuxdata") {
|
||||
F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc(sizeof(F5tAuxData));
|
||||
if( pData==0 ){
|
||||
Tcl_AppendResult(interp, "out of memory", 0);
|
||||
Tcl_AppendResult(interp, "out of memory", (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pData->pObj = objv[2];
|
||||
@@ -452,7 +452,7 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
|
||||
rc = p->pApi->xPhraseFirst(p->pFts, iPhrase, &iter, &iCol, &iOff);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for( ;iCol>=0; p->pApi->xPhraseNext(p->pFts, &iter, &iCol, &iOff) ){
|
||||
@@ -683,7 +683,7 @@ static int SQLITE_TCLAPI f5tCreateFunction(
|
||||
pApi, zName, (void*)pCtx, xF5tFunction, xF5tDestroy
|
||||
);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -750,7 +750,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
if( objc==5 ){
|
||||
char *zOpt = Tcl_GetString(objv[1]);
|
||||
if( strcmp("-subst", zOpt) ){
|
||||
Tcl_AppendResult(interp, "unrecognized option: ", zOpt, 0);
|
||||
Tcl_AppendResult(interp, "unrecognized option: ", zOpt, (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -759,7 +759,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( nArg==0 ){
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", 0);
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", (char*)0);
|
||||
Tcl_Free((void*)azArg);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -767,13 +767,13 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
|
||||
rc = pApi->xFindTokenizer(pApi, azArg[0], &pUserdata, &tokenizer);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], 0);
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = tokenizer.xCreate(pUserdata, &azArg[1], (int)(nArg-1), &pTok);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xCreate()", 0);
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xCreate()", (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -787,7 +787,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
);
|
||||
tokenizer.xDelete(pTok);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", 0);
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", (char*)0);
|
||||
Tcl_DecrRefCount(pRet);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1049,7 +1049,7 @@ static int SQLITE_TCLAPI f5tTokenizerLocale(
|
||||
|
||||
if( p->xToken==0 ){
|
||||
Tcl_AppendResult(interp,
|
||||
"sqlite3_fts5_locale may only be used by tokenizer callback", 0
|
||||
"sqlite3_fts5_locale may only be used by tokenizer callback", (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1098,7 +1098,7 @@ static int SQLITE_TCLAPI f5tTokenizerReturn(
|
||||
|
||||
if( p->xToken==0 ){
|
||||
Tcl_AppendResult(interp,
|
||||
"sqlite3_fts5_token may only be used by tokenizer callback", 0
|
||||
"sqlite3_fts5_token may only be used by tokenizer callback", (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1250,7 +1250,7 @@ static int SQLITE_TCLAPI f5tCreateTokenizer(
|
||||
Tcl_AppendResult(interp, (
|
||||
bV2 ? "error in fts5_api.xCreateTokenizer_v2()"
|
||||
: "error in fts5_api.xCreateTokenizer()"
|
||||
), 0);
|
||||
), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -1540,12 +1540,92 @@ static int SQLITE_TCLAPI f5tRegisterOriginText(
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (void*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used to DROP an fts5 table. It works even if the data
|
||||
** structures fts5 stores within the database are corrupt, which sometimes
|
||||
** prevents a straight "DROP TABLE" command from succeeding.
|
||||
**
|
||||
** The first parameter is the database handle to use for the DROP TABLE
|
||||
** operation. The second is the name of the database to drop the fts5 table
|
||||
** from (i.e. "main", "temp" or the name of an attached database). The
|
||||
** third parameter is the name of the fts5 table to drop.
|
||||
**
|
||||
** SQLITE_OK is returned if the table is successfully dropped. Or, if an
|
||||
** error occurs, an SQLite error code.
|
||||
*/
|
||||
static int sqlite3_fts5_drop_corrupt_table(
|
||||
sqlite3 *db, /* Database handle */
|
||||
const char *zDb, /* Database name ("main", "temp" etc.) */
|
||||
const char *zTab /* Name of fts5 table to drop */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int bDef = 0;
|
||||
|
||||
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, -1, &bDef);
|
||||
if( rc==SQLITE_OK ){
|
||||
char *zScript = sqlite3_mprintf(
|
||||
"DELETE FROM %Q.'%q_data';"
|
||||
"DELETE FROM %Q.'%q_config';"
|
||||
"INSERT INTO %Q.'%q_data' VALUES(10, X'0000000000');"
|
||||
"INSERT INTO %Q.'%q_config' VALUES('version', 4);"
|
||||
"DROP TABLE %Q.'%q';",
|
||||
zDb, zTab, zDb, zTab, zDb, zTab, zDb, zTab, zDb, zTab
|
||||
);
|
||||
|
||||
if( zScript==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
if( bDef ) sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
|
||||
rc = sqlite3_exec(db, zScript, 0, 0, 0);
|
||||
if( bDef ) sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, 0);
|
||||
sqlite3_free(zScript);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_fts5_drop_corrupt_table DB DATABASE TABLE
|
||||
**
|
||||
** Description...
|
||||
*/
|
||||
static int SQLITE_TCLAPI f5tDropCorruptTable(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db = 0;
|
||||
const char *zDb = 0;
|
||||
const char *zTab = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB DATABASE TABLE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( f5tDbPointer(interp, objv[1], &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zDb = Tcl_GetString(objv[2]);
|
||||
zTab = Tcl_GetString(objv[3]);
|
||||
|
||||
rc = sqlite3_fts5_drop_corrupt_table(db, zDb, zTab);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (void*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Entry point.
|
||||
*/
|
||||
@@ -1564,7 +1644,8 @@ int Fts5tcl_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_fts5_token_hash", f5tTokenHash, 0 },
|
||||
{ "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 },
|
||||
{ "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 },
|
||||
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 }
|
||||
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 },
|
||||
{ "sqlite3_fts5_drop_corrupt_table", f5tDropCorruptTable, 0 }
|
||||
};
|
||||
int i;
|
||||
F5tTokenizerContext *pContext;
|
||||
|
||||
@@ -680,11 +680,11 @@ do_test 12.0 {
|
||||
|
||||
do_catchsql_test 11.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 11.2 {
|
||||
INSERT INTO t1(t1, rank) VALUES('merge', 500);
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -1040,7 +1040,7 @@ do_test 16.0 {
|
||||
|
||||
do_catchsql_test 16.1 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -1126,7 +1126,7 @@ do_test 17.0 {
|
||||
|
||||
do_catchsql_test 17.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -1630,7 +1630,7 @@ do_test 20.0 {
|
||||
|
||||
do_catchsql_test 20.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -2100,7 +2100,7 @@ do_test 22.0 {
|
||||
|
||||
do_catchsql_test 22.1 {
|
||||
INSERT INTO t1(t1) VALUES('optimize');
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -3700,7 +3700,7 @@ do_catchsql_test 32.1 {
|
||||
highlight(t1, 2, '[', ']')
|
||||
FROM t1('g + h')
|
||||
WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank;
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 32.2 {
|
||||
SELECT * FROM t3;
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# 2024 Aug 28
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt8
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
UPDATE t1_data SET block='hello world' WHERE id=10
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 1.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {database disk image is malformed}}
|
||||
do_catchsql_test 1.3 {
|
||||
DROP TABLE t1
|
||||
} {0 {}}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
do_execsql_test 2.1 {
|
||||
UPDATE t1_config SET v=555 WHERE k='version'
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 2.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {invalid fts5 file format (found 555, expected 4 or 5) - run 'rebuild'}}
|
||||
do_catchsql_test 2.3 {
|
||||
DROP TABLE t1
|
||||
} {1 {invalid fts5 file format (found 555, expected 4 or 5) - run 'rebuild'}}
|
||||
do_test 2.4 {
|
||||
sqlite3_fts5_drop_corrupt_table db main t1
|
||||
} {}
|
||||
do_execsql_test 2.5 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
DELETE FROM t1_config;
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 3.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {invalid fts5 file format (found 0, expected 4 or 5) - run 'rebuild'}}
|
||||
do_catchsql_test 3.3 {
|
||||
DROP TABLE t1
|
||||
} {1 {invalid fts5 file format (found 0, expected 4 or 5) - run 'rebuild'}}
|
||||
|
||||
|
||||
do_test 3.4 {
|
||||
sqlite3_db_config db DEFENSIVE 1
|
||||
} {1}
|
||||
do_test 3.5 {
|
||||
sqlite3_fts5_drop_corrupt_table db main t1
|
||||
} {}
|
||||
do_test 3.6 {
|
||||
sqlite3_db_config db DEFENSIVE -1
|
||||
} {1}
|
||||
do_execsql_test 3.7 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -90,7 +90,7 @@ set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}]
|
||||
do_faultsim_test 4 -faults oom-* -body {
|
||||
db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'}
|
||||
} -test {
|
||||
faultsim_test_result {0 {0 {} 3}}
|
||||
faultsim_test_result {0 {0 {} 2}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -256,6 +256,27 @@ do_faultsim_test 10 -faults oom* -prep {
|
||||
faultsim_test_result {0 hello}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 11.0 {
|
||||
CREATE VIRTUAL TABLE f1 USING fts5(content);
|
||||
CREATE TABLE g1(id, content);
|
||||
INSERT INTO g1 VALUES(30000, 'a b c');
|
||||
INSERT INTO g1 VALUES(40000, 'd e f');
|
||||
}
|
||||
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 11 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO f1(rowid, content) SELECT id, content FROM g1;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -44,12 +44,12 @@ do_catchsql_test 1.2.2 {
|
||||
|
||||
do_catchsql_test 1.3.1 {
|
||||
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads');
|
||||
} {1 {no such cursor: 1}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
do_catchsql_test 1.3.2 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
|
||||
} {1 {no such cursor: 1}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
@@ -57,12 +57,12 @@ sqlite3 db test.db
|
||||
do_catchsql_test 1.3.3 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
|
||||
} {1 {no such cursor: 1}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_catchsql_test 1.3.4 {
|
||||
SELECT fts5_columntext(t1) FROM t1('*reads');
|
||||
} {1 {no such cursor: 1}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
@@ -350,7 +350,7 @@ do_execsql_test 14.3 {
|
||||
|
||||
do_execsql_test 14.4 {
|
||||
SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'
|
||||
} {0 {} 3}
|
||||
} {0 {} 2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
+303
-89
@@ -11,7 +11,7 @@
|
||||
******************************************************************************
|
||||
**
|
||||
** 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
|
||||
** exactly two arguments.
|
||||
@@ -60,31 +60,105 @@
|
||||
**
|
||||
** (13) A separate median(Y) function is the equivalent percentile(Y,50).
|
||||
**
|
||||
** (14) A separate percentile_cond(Y,X) function is the equivalent of
|
||||
** percentile(Y,X*100.0).
|
||||
** (14) A separate percentile_cont(Y,P) function is equivalent to
|
||||
** 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"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#if defined(SQLITE3_H)
|
||||
/* no-op */
|
||||
#elif defined(SQLITE_STATIC_PERCENTILE)
|
||||
# include "sqlite3.h"
|
||||
#else
|
||||
# include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* The following object is the session context for a single percentile()
|
||||
** function. We have to remember all input Y values until the very end.
|
||||
/* The following object is the group context for a single percentile()
|
||||
** aggregate. Remember all input Y values until the very end.
|
||||
** Those values are accumulated in the Percentile.a[] array.
|
||||
*/
|
||||
typedef struct Percentile Percentile;
|
||||
struct Percentile {
|
||||
unsigned nAlloc; /* Number of slots allocated for 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 */
|
||||
};
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
static int isInfinity(double r){
|
||||
static int percentIsInfinity(double r){
|
||||
sqlite3_uint64 u;
|
||||
assert( sizeof(u)==sizeof(r) );
|
||||
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;
|
||||
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
|
||||
** input row.
|
||||
@@ -112,28 +237,20 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
|
||||
|
||||
if( argc==1 ){
|
||||
/* Requirement 13: median(Y) is the same as percentile(Y,50). */
|
||||
rPct = 50.0;
|
||||
}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;
|
||||
}
|
||||
rPct = 0.5;
|
||||
}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]);
|
||||
rPct = sqlite3_value_double(argv[1]);
|
||||
rPct = sqlite3_value_double(argv[1])/(double)pFunc->mxFrac;
|
||||
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
|
||||
|| 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);
|
||||
|| rPct<0.0 || rPct>1.0
|
||||
){
|
||||
percentError(pCtx, "the fraction argument to %%s()"
|
||||
" is not between 0.0 and %.1f",
|
||||
(double)pFunc->mxFrac);
|
||||
return;
|
||||
}
|
||||
rPct *= 100.0;
|
||||
}
|
||||
|
||||
/* 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
|
||||
** from any prior row, per Requirement (2). */
|
||||
if( p->rPct==0.0 ){
|
||||
p->rPct = rPct+1.0;
|
||||
}else if( !sameValue(p->rPct,rPct+1.0) ){
|
||||
sqlite3_result_error(pCtx, "2nd argument to percentile() is not the "
|
||||
"same for all input rows", -1);
|
||||
if( !p->bPctValid ){
|
||||
p->rPct = rPct;
|
||||
p->bPctValid = 1;
|
||||
}else if( !percentSameValue(p->rPct,rPct) ){
|
||||
percentError(pCtx, "the fraction argument to %%s()"
|
||||
" is not the same for all input rows");
|
||||
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.
|
||||
** Requirement 4 */
|
||||
if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
|
||||
sqlite3_result_error(pCtx, "1st argument to percentile() is not "
|
||||
"numeric", -1);
|
||||
percentError(pCtx, "input to %%s() is not numeric");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Throw an error if the Y value is infinity or NaN */
|
||||
y = sqlite3_value_double(argv[0]);
|
||||
if( isInfinity(y) ){
|
||||
sqlite3_result_error(pCtx, "Inf input to percentile()", -1);
|
||||
if( percentIsInfinity(y) ){
|
||||
percentError(pCtx, "Inf input to %%s()");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,50 +299,80 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
|
||||
p->nAlloc = n;
|
||||
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){
|
||||
int iLt; /* Entries with index less than iLt are less than rPivot */
|
||||
int iGt; /* Entries with index iGt or more are greater than rPivot */
|
||||
#define SWAP_DOUBLE(X,Y) {double ttt=(X);(X)=(Y);(Y)=ttt;}
|
||||
|
||||
/*
|
||||
** 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 */
|
||||
double rPivot; /* The pivot value */
|
||||
double rTmp; /* Temporary used to swap two values */
|
||||
|
||||
if( n<2 ) return;
|
||||
if( n>5 ){
|
||||
rPivot = (a[0] + a[n/2] + a[n-1])/3.0;
|
||||
}else{
|
||||
rPivot = a[n/2];
|
||||
|
||||
assert( n>=2 );
|
||||
if( a[0]>a[n-1] ){
|
||||
SWAP_DOUBLE(a[0],a[n-1])
|
||||
}
|
||||
iLt = i = 0;
|
||||
iGt = n;
|
||||
while( i<iGt ){
|
||||
if( n==2 ) return;
|
||||
iGt = n-1;
|
||||
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( i>iLt ){
|
||||
rTmp = a[i];
|
||||
a[i] = a[iLt];
|
||||
a[iLt] = rTmp;
|
||||
}
|
||||
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
|
||||
iLt++;
|
||||
i++;
|
||||
}else if( a[i]>rPivot ){
|
||||
do{
|
||||
iGt--;
|
||||
}while( iGt>i && a[iGt]>rPivot );
|
||||
rTmp = a[i];
|
||||
a[i] = a[iGt];
|
||||
a[iGt] = rTmp;
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if( iLt>=2 ) sortDoubles(a, iLt);
|
||||
if( n-iGt>=2 ) sortDoubles(a+iGt, n-iGt);
|
||||
|
||||
}while( i<iGt );
|
||||
if( iLt>=2 ) percentSort(a, iLt);
|
||||
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
|
||||
|
||||
/* Uncomment for testing */
|
||||
#if 0
|
||||
for(i=0; i<n-1; i++){
|
||||
@@ -234,12 +381,61 @@ static void sortDoubles(double *a, int n){
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Called to compute the final output of percentile() and to clean
|
||||
** up all allocated memory.
|
||||
** The "inverse" function for percentile(Y,P) is called to remove a
|
||||
** 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;
|
||||
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;
|
||||
double v1, v2;
|
||||
double ix, vx;
|
||||
@@ -247,21 +443,38 @@ static void percentFinal(sqlite3_context *pCtx){
|
||||
if( p==0 ) return;
|
||||
if( p->a==0 ) return;
|
||||
if( p->nUsed ){
|
||||
sortDoubles(p->a, p->nUsed);
|
||||
ix = (p->rPct-1.0)*(p->nUsed-1)*0.01;
|
||||
if( p->bSorted==0 ){
|
||||
assert( p->nUsed>1 );
|
||||
percentSort(p->a, p->nUsed);
|
||||
p->bSorted = 1;
|
||||
}
|
||||
ix = p->rPct*(p->nUsed-1);
|
||||
i1 = (unsigned)ix;
|
||||
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);
|
||||
if( pFunc->bDiscrete ){
|
||||
vx = p->a[i1];
|
||||
}else{
|
||||
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_free(p->a);
|
||||
memset(p, 0, sizeof(*p));
|
||||
if( bIsFinal ){
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(SQLITE3_H) && !defined(SQLITE_STATIC_PERCENTILE)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_percentile_init(
|
||||
@@ -270,20 +483,21 @@ int sqlite3_percentile_init(
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
unsigned int i;
|
||||
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
|
||||
(void)pApi; /* Unused parameter */
|
||||
#else
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#endif
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "percentile", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
|
||||
0, percentStep, percentFinal);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "median", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
|
||||
0, percentStep, percentFinal);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "percentile_cont", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS, &percentStep,
|
||||
0, percentStep, percentFinal);
|
||||
for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
|
||||
rc = sqlite3_create_window_function(db,
|
||||
aPercentFunc[i].zName,
|
||||
aPercentFunc[i].nArg,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_SELFORDER1,
|
||||
(void*)&aPercentFunc[i],
|
||||
percentStep, percentFinal, percentValue, percentInverse, 0);
|
||||
if( rc ) break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@
|
||||
# build the SQLite library and testing tools.
|
||||
################################################################################
|
||||
|
||||
# If OPTIONS... is specified on the command-line, append its value to OPTS
|
||||
#
|
||||
OPTS += $(OPTIONS)
|
||||
|
||||
# This is how we compile
|
||||
#
|
||||
TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
|
||||
@@ -537,6 +541,7 @@ FUZZSRC += $(TOP)/test/vt02.c
|
||||
FUZZSRC += $(TOP)/test/fuzzinvariants.c
|
||||
FUZZSRC += $(TOP)/ext/recover/dbdata.c
|
||||
FUZZSRC += $(TOP)/ext/recover/sqlite3recover.c
|
||||
FUZZSRC += $(TOP)/ext/misc/percentile.c
|
||||
FUZZSRC += $(TOP)/ext/misc/randomjson.c
|
||||
DBFUZZ_OPT =
|
||||
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
|
||||
@@ -760,6 +765,7 @@ SHELL_DEP = \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/ext/misc/pcachetrace.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
@@ -958,9 +964,14 @@ tcltest: ./testfixture$(EXE)
|
||||
testrunner: testfixture$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/testrunner.tcl
|
||||
|
||||
# Runs both fuzztest and testrunner, consecutively.
|
||||
# This is the testing target preferred by the core SQLite developers.
|
||||
# It runs tests under a standard configuration, regardless of how
|
||||
# ./configure was run. The devs run "make devtest" prior to each
|
||||
# check-in, at a minimum. Probably other tests too, but at least this
|
||||
# one.
|
||||
#
|
||||
devtest: testfixture$(EXE) fuzztest testrunner
|
||||
devtest: srctree-check sourcetest
|
||||
tclsh $(TOP)/test/testrunner.tcl mdevtest
|
||||
|
||||
mdevtest:
|
||||
tclsh $(TOP)/test/testrunner.tcl mdevtest
|
||||
@@ -971,10 +982,19 @@ mdevtest:
|
||||
quicktest: ./testfixture$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)
|
||||
|
||||
# The default test case. Runs most of the faster standard TCL tests,
|
||||
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
|
||||
test: fuzztest sourcetest $(TESTPROGS) tcltest
|
||||
# Validate that various generated files in the source tree
|
||||
# are up-to-date.
|
||||
#
|
||||
srctree-check: $(TOP)/tool/srctree-check.tcl
|
||||
tclsh $(TOP)/tool/srctree-check.tcl
|
||||
|
||||
# Try to run tests on whatever options are specified by the
|
||||
# environment variables. The SQLite developers seldom use this target.
|
||||
# Instead# they use "make devtest" which runs tests on a standard set of
|
||||
# options regardless of how SQLite is configured. This "test"
|
||||
# target is provided for legacy only.
|
||||
#
|
||||
test: fuzztest sourcetest $(TESTPROGS) tcltest
|
||||
|
||||
# Run a test using valgrind. This can take a really long time
|
||||
# because valgrind is so much slower than a native machine.
|
||||
@@ -1112,41 +1132,22 @@ install: sqlite3 libsqlite3.a sqlite3.h
|
||||
mv sqlite3.h /usr/include
|
||||
|
||||
clean:
|
||||
rm -f *.o sqlite3 sqlite3.exe libsqlite3.a sqlite3.h opcodes.*
|
||||
rm -f lemon lemon.exe lempar.c parse.* sqlite*.tar.gz
|
||||
rm -f mkkeywordhash mkkeywordhash.exe keywordhash.h
|
||||
rm -f $(PUBLISH)
|
||||
rm -f *.da *.bb *.bbg gmon.out
|
||||
rm -rf tsrc target_source
|
||||
rm -f testloadext.dll libtestloadext.so
|
||||
rm -f amalgamation-testfixture amalgamation-testfixture.exe
|
||||
rm -f fts3-testfixture fts3-testfixture.exe
|
||||
rm -f testfixture testfixture.exe
|
||||
rm -f threadtest3 threadtest3.exe
|
||||
rm -f LogEst LogEst.exe
|
||||
rm -f fts3view fts3view.exe
|
||||
rm -f rollback-test rollback-test.exe
|
||||
rm -f showdb showdb.exe
|
||||
rm -f showjournal showjournal.exe
|
||||
rm -f showstat4 showstat4.exe
|
||||
rm -f showwal showwal.exe
|
||||
rm -f changeset changeset.exe
|
||||
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
|
||||
rm -f *.lo *.la *.o *.c *.h *.da *.bb *.bbg gmon.* *.rws sqlite3$(TEXE)
|
||||
rm -rf .libs .deps tsrc libtool target_source testrunner_*
|
||||
rm -f lemon$(BEXE) sqlite*.tar.gz
|
||||
rm -f mkkeywordhash$(BEXE) mksourceid$(BEXE)
|
||||
rm -f parse.* fts5parse.*
|
||||
rm -rf tsrc .target_source testrunner_bld_* testdir*
|
||||
rm -f tclsqlite3$(TEXE)
|
||||
rm -f $(TESTPROGS) testrunner.*
|
||||
rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
|
||||
rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
|
||||
rm -f wordcount$(TEXE) changeset$(TEXE) version-info$(TEXE)
|
||||
rm -f *.dll *.lib *.exp *.def *.pc *.vsix
|
||||
rm -f sqlite3_analyzer$(TEXE)
|
||||
rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
|
||||
rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
|
||||
rm -f threadtest5$(TEXE)
|
||||
rm -f src-verify has_tclsh*
|
||||
|
||||
distclean: clean
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
C Remove\sredundant\s#ifdef\saccidentally\sinserted\sinto\smkkeywordhash.c
|
||||
D 2024-08-26T14:20:20.876
|
||||
C ADd\sSQLITE_USE_ONLY_WIN32\sto\sthe\sDefault\sconfiguration\sfor\stesting\son\nWindows.\s\sTake\sit\soff\sof\sStdcall.
|
||||
D 2024-09-03T17:01:07.501
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 101cb90f75c16ca3f8e7088364322441f9b01d6fdcef4a9c7f5fdcf78a3601a4
|
||||
F Makefile.in af5fbc3453b745daa68c7aa5dfdb945c09cb724971db3b783d6b5e1a62279e28
|
||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||
F Makefile.msc 6c3fe8b6ce60e73f34a148c957d78b4648745c8d30e792423aa1a8d8bf12d065
|
||||
F README.md 3d47ef5758e2de29d6f4e1aca714d51424baba86c8b561fef330f6ef2dc9282c
|
||||
F Makefile.msc 2c905f4c795a628d7fd892294e8fdec6d5f719fa5b252cb839fed147e64435a0
|
||||
F README.md 5b678e264236788390d11991f2c0052bd73f19790173883fc56d638bcb849154
|
||||
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
@@ -17,7 +17,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am adedc1324b6a87fdd1265ddd336d2fb7d4f36a0e77b86ea553ae7cc4ea239347
|
||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||
F autoconf/Makefile.msc 7ac6c331fc3b8aa57b6782db995b8c0e49230352decd4e2662fd07c06a9ed623
|
||||
F autoconf/Makefile.msc 2aced6442addab13ed115696eba28d9ed29caa3dd604a31392c2c7a5da301492
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
|
||||
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
|
||||
@@ -53,8 +53,8 @@ F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
|
||||
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
|
||||
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
|
||||
F ext/consio/console_io.c b4885dfea71ed583315de8f0792a29d5fc7c7460b4a26c0aebe5cda5da8b38f8 x
|
||||
F ext/consio/console_io.h 0548b83d7c4b7270ad544a67f2bb90cebc519637fa39b1838df4744cf0d87646
|
||||
F ext/consio/console_io.c d2b74afae8d301de2e8447b1045fcd33eb59df13bf581d906d99c74fe5d2b13f x
|
||||
F ext/consio/console_io.h b5ebe34aa15b357621ebbea3d3f2e2b24750d4280b5802516409e23947fd9ee5
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test 661f873fd451127edf822ef0d520088faa319135f6a15bd10be6801ac284ac9b
|
||||
@@ -92,17 +92,17 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl 63db9624ccf70d4887836c320eda93ab552f21008f3be7ede551eac3ead62baa
|
||||
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
||||
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
|
||||
F ext/fts5/fts5.h c72759fd15179934f10b71ae51ee999e8558f696335e4ec2d049243b764354ee
|
||||
F ext/fts5/fts5.h efaaac0df3d3bc740383044c144b582f47921aafa21d7b10eb98f42c24c740b0
|
||||
F ext/fts5/fts5Int.h 26a71a09cefa4ef6b4516b204ed48da3e1380970a19b3482eea7c5d805655360
|
||||
F ext/fts5/fts5_aux.c 65a0468dd177d6093aa9ae1622e6d86b0136b8d267c62c0ad6493ad1e9a3d759
|
||||
F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70673cb6f09
|
||||
F ext/fts5/fts5_config.c 353d2a0d12678cae6ab5b9ce54aed8dac0825667b69248b5a4ed81cbefc109ea
|
||||
F ext/fts5/fts5_expr.c 9a56f53700d1860f0ee2f373c2b9074eaf2a7aa0637d0e27a6476de26a3fee33
|
||||
F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
|
||||
F ext/fts5/fts5_index.c eb9a0dda3bc6ef969a6be8d2746af56856e67251810ddba08622b45be8477abe
|
||||
F ext/fts5/fts5_main.c 3d8b778f65fe5be218f6a8e4019048f092c0c09621b035ce3e8804093036b578
|
||||
F ext/fts5/fts5_index.c 571483823193f09439356741669aa8c81da838ae6f5e1bfa7517f7ee2fb3addd
|
||||
F ext/fts5/fts5_main.c 1fddb53f495425d9314c74b30c5848a9dd254be0e5f445bfe38292d5ab21c288
|
||||
F ext/fts5/fts5_storage.c 9a9b880be12901f1962ae2a5a7e1b74348b3099a1e728764e419f75d98e3e612
|
||||
F ext/fts5/fts5_tcl.c 1dcf08028141c40a32634bdcf2d5601622ce4edc48f82ac4ce0cbe0a92a6961d
|
||||
F ext/fts5/fts5_tcl.c 4db9258a7882c5eac0da4433042132aaf15b87dd1e1636c7a6ca203abd2c8bfe
|
||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
|
||||
F ext/fts5/fts5_tokenize.c ae9c4fa93174ef06ffc138bd4280a1c37f7e13624d3d2706aad4b80573f23c41
|
||||
@@ -148,11 +148,12 @@ F ext/fts5/test/fts5contentless4.test ec34dc69ef474ca9997dae6d91e072906e0e9a5a4b
|
||||
F ext/fts5/test/fts5contentless5.test 40cdcb4fe751672450829c5a96bd32c25fc2f6076279dd2ce5c58ac9a390132a
|
||||
F ext/fts5/test/fts5corrupt.test 6485f721b88ba355ca5d701e7ee87a4efa3ea578d8e6adb26f51ef956c8328bd
|
||||
F ext/fts5/test/fts5corrupt2.test 335911e3f68b9625d850325f9e29a128db3f4276a8c9d4e32134580da8f924c4
|
||||
F ext/fts5/test/fts5corrupt3.test 621e9bca3e7299f487e1b29ff4179d9fc9560f5847dfc5b50a16010c9d2a0e5f
|
||||
F ext/fts5/test/fts5corrupt3.test 4fc3bf129f1616bea00884a23fd9d7b0e46d01791d2b57fe8d68ac36e8d3ff7c
|
||||
F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93f68f7d7a0d7d7dd733
|
||||
F ext/fts5/test/fts5corrupt5.test 11b47126f5772cc37b67e3e8b2ed05895c4d07c05338bc07e4eea225bfe32c76
|
||||
F ext/fts5/test/fts5corrupt6.test 2d72db743db7b5d9c9a6d0cfef24d799ed1aa5e8192b66c40e871a37ed9eed06
|
||||
F ext/fts5/test/fts5corrupt7.test 4e830875c33b9ea3c4cf1ba71e692b63893cbb4faae8c69b1071889dc26e211c
|
||||
F ext/fts5/test/fts5corrupt8.test b81d802e41631e98100f49a1aadeeffef860e30a62d6ed7d743c2797c477239e
|
||||
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
|
||||
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
|
||||
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
|
||||
@@ -164,7 +165,7 @@ F ext/fts5/test/fts5expr.test c7e208813df7a90badc856fde3796da79569b39382e0fdb430
|
||||
F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd
|
||||
F ext/fts5/test/fts5fault2.test 69c8fdbef830cd0d450908d4504d5bb86609e255af99c421c20a0756251fe344
|
||||
F ext/fts5/test/fts5fault3.test da2f9e3e56ff5740d68ebdd6877c97089e7ed28ddff28a0da87a6afea27e5522
|
||||
F ext/fts5/test/fts5fault4.test 87a10d0caee57da587c7588b0c8d25d2930197399b4812ad1e4d574c75324cee
|
||||
F ext/fts5/test/fts5fault4.test a5c0e849127c24e1751bc453a817f09a1b8d460e75f9ae4764017e216a870db3
|
||||
F ext/fts5/test/fts5fault5.test a336e4e11847de24c9497f80cce18e00bb3fab7fb11f97d04eb9af898900a762
|
||||
F ext/fts5/test/fts5fault6.test 40f49976c6ca8927bf7d65d0b8df46009d7ea172e1d4050b294610e7ea0a2979
|
||||
F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd164090be139e9e97ed4c
|
||||
@@ -177,12 +178,13 @@ F ext/fts5/test/fts5faultE.test 844586ce71dab4be85bb86880e87b624d089f851654cd22e
|
||||
F ext/fts5/test/fts5faultF.test 4abef99f86e99d9f0c6460dd68c586a766b6b9f1f660ada55bf2e8266bd1bbc1
|
||||
F ext/fts5/test/fts5faultG.test 0544411ffcb3e19b42866f757a8a5e0fb8fef3a62c06f61d14deebc571bb7ea9
|
||||
F ext/fts5/test/fts5faultH.test 2b2b5b8cb1b3fd7679f488c06e22af44107fbc6137eaf45b3e771dc7b149312d
|
||||
F ext/fts5/test/fts5faultI.test e1e8a927122a8c3be8614a59717e838cad0505ba0a6f404983da8430e7aeb14d
|
||||
F ext/fts5/test/fts5faultI.test ae4b83ac953200bd7b66d53038f7d6a4fc29cd64831b8e1795538babcea7c638
|
||||
F ext/fts5/test/fts5first.test bfd685b96905bf541d99d8644e0a7219d1d833455a08ab64e344071a613b6ba9
|
||||
F ext/fts5/test/fts5full.test 97d263c1072f4a560929cca31e70f65d2ae232610e17e6affcf7e979df59547b
|
||||
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
|
||||
F ext/fts5/test/fts5hash.test fd3e0367fbf0b0944d6936fdb22696350f57b9871069c6766251578a103e8a14
|
||||
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/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400f8d2d27ea9373e0c4a1
|
||||
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
|
||||
@@ -191,7 +193,7 @@ F ext/fts5/test/fts5locale.test 797cf6f5e017462ab11313ce884b9f1df8ff063811e74ef4
|
||||
F ext/fts5/test/fts5matchinfo.test 877520582feb86bbfd95ab780099bcba4526f18ac75ee34979144cf86ba3a5a3
|
||||
F ext/fts5/test/fts5merge.test 2654df0bcdb2d117c2d38b6aeb0168061be01c643f9e9194b36c43a2970e8082
|
||||
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
||||
F ext/fts5/test/fts5misc.test 60bb2be4a2d83d7a45047c1812781e2e337a27efa539d86356ef7f4acaf08eab
|
||||
F ext/fts5/test/fts5misc.test 8c3cc771f773dc4bb4973620c51e7729e324ca2cc80eb8894f1c2c605e361f0b
|
||||
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
|
||||
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
|
||||
F ext/fts5/test/fts5near.test 33d60867581066e5db7016deb5d651628125d7ff4e0233a88175aa5b65874c74
|
||||
@@ -225,7 +227,7 @@ F ext/fts5/test/fts5secure6.test 74bf04733cc523bccca519bb03d3b4e2ed6f6e3db7c59bf
|
||||
F ext/fts5/test/fts5secure7.test fd03d0868d64340a1db8615b02e5508fea409de13910114e4f19eaefc120777a
|
||||
F ext/fts5/test/fts5secure8.test 808ade9d172ed07b24b85c57dd53b6d2b1aba018b4e634d267ce572221de80e0
|
||||
F ext/fts5/test/fts5securefault.test c34a28c7cd2f31a8b8907563889e1329a97da975c08df2d951422bcef8e2ebc5
|
||||
F ext/fts5/test/fts5simple.test ed7c3815c9fa1c16166258cb98edb2e014c63c7589958d76c5487df0df913d61
|
||||
F ext/fts5/test/fts5simple.test 302cdb4f8a3350b091f4f1bccd82d05610428657f6f9e81c17703ba48267ec40
|
||||
F ext/fts5/test/fts5simple2.test d10d963a357b8ec77b99032e4c816459b4dbdb1f6eee25eada7ef3ed245cb2dc
|
||||
F ext/fts5/test/fts5simple3.test 146ec3dc8f5763d6212641c9f0a2f1cba41679353d2add7b963beceb115dc7f4
|
||||
F ext/fts5/test/fts5synonym.test becc8cea6cfc958a50b30c572c68cbfdf7455971d0fe988202ce67638d2c6cf6
|
||||
@@ -409,7 +411,7 @@ F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58
|
||||
F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0
|
||||
F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
|
||||
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/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47cc06c
|
||||
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
|
||||
@@ -684,7 +686,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk 9541ffdce424ddddb463e2480c3f1cb4067bbd3a6d2c84b3f083cb128a2fa721
|
||||
F main.mk 5a2e7d4a852c058373efc78407816de41595d06975148c766092b3cf0fea4298
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@@ -703,13 +705,13 @@ F src/auth.c 4c1ea890e0069ad73bead5d17a5b12c34cfa4f1a24175c8147ea439b64be271c
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
|
||||
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
|
||||
F src/btree.c 8b42fc7d9efdb2df05c30e8f91ff6cfbd979724ae24bf90269028468b7a13333
|
||||
F src/btree.c 8c5592c618741c5fc9733e7efe3927bfafad3e999d15b0a0f3f1d3f3e17b919e
|
||||
F src/btree.h 55066f513eb095db935169dab1dc2f7c7a747ef223c533f5d4ad4dfed346cbd0
|
||||
F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
|
||||
F src/build.c 3a1840d9d171ce2d24f4c1f7acda7266ab796c664290c1acba65ff98ce2bd01e
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 64e4b1227b4ed123146f0aa2989131d1fbd9b927b11e80c9d58c6a68f9cd5ce3
|
||||
F src/ctime.c b224d3db0f28c4a5f1407c50107a0a8133bd244ff3c7f6f8cedeb896a8cf1b64
|
||||
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
|
||||
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
@@ -717,7 +719,7 @@ F src/delete.c 444c4d1eaac40103461e3b6f0881846dd3aafc1cec1dd169d3482fa331667da7
|
||||
F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
|
||||
F src/func.c 1f61e32e7a357e615b5d2e774bee563761fce4f2fd97ecb0f72c33e62a2ada5f
|
||||
F src/func.c df400a1d3f4625997d4dd8a81951c303e066277c29b861d37e03cd152d7858dd
|
||||
F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
|
||||
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
|
||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
@@ -727,7 +729,7 @@ F src/insert.c f8d1a0f8ee258411009c6b7f2d93170e351bd19f5ad89d57e1180644297cbe70
|
||||
F src/json.c 5b6a1d6015997b9ee848a32948720bdb26a0ef2de5a2127ebf7355ce66dbdc0d
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c a520c325c7400b249242945f2c602acb19662c40f5db1c04d88664cfaa8b85ac
|
||||
F src/main.c e7b53893f9fb3ad76baa8513f85c167b34d5c8e25ce64608db440f5637d0fe9e
|
||||
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -753,7 +755,7 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3
|
||||
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
|
||||
F src/parse.y f4c8ded81b05059c284bc9512aaa07f6ecd29add585e35d53d72a67894b6e4d7
|
||||
F src/parse.y a7a8d42eeff01d267444ddb476029b0b1726fb70ae3d77984140f17ad02e2d61
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
|
||||
@@ -765,11 +767,11 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 2c127880c0634962837f16f2f48a295e514357af959330cc038de73015d5b5e8
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c 4b14337a2742f0c0beeba490e9a05507e9b4b12184b9cd12773501d08d48e3fe
|
||||
F src/shell.c.in 5a05e1a1d187ab916afe9a628d7e9b20b5997273b595bd748db324814e0ccca9
|
||||
F src/sqlite.h.in f07bff4225a1244efd604a0ffef81ed69f29d3dbaed7e22f906f26229ba3ca9e
|
||||
F src/shell.c.in 40de636c1d90fb8a9ca7f49dc8f50d930f1b60736e73aca5eb37c4c7d0e47f9d
|
||||
F src/sqlite.h.in 77f55bd1978a04a14db211732f0a609077cf60ba4ccf9baf39988f508945419c
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 28c878bdf528879afefe1994ac007d094f8061f2fdacdc55d6055d7e9341151e
|
||||
F src/sqliteInt.h 889cd632f4386bbd8619b166abb7d25f1c8ce6514e90cb7f22f63bd530fc6107
|
||||
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
||||
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -789,7 +791,7 @@ F src/test_backup.c bd901e3c116c7f3b3bbbd4aae4ce87d99b400c9cbb0a9e7b4610af451d97
|
||||
F src/test_bestindex.c 3401bee51665cbf7f9ed2552b5795452a8b86365e4c9ece745b54155a55670c6
|
||||
F src/test_blob.c bcdf6a6c22d0bcc13c41479d63692ef413add2a4d30e1e26b9f74ab85b9fb4d5
|
||||
F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5
|
||||
F src/test_config.c 46eaf39842cace9d540aeefb50fe24dd3204a622893a97952cbb49c20b2f8b21
|
||||
F src/test_config.c 345b8e383f71cecc36d0fa05f2f06639c254b188f98101c3c97749df43037086
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
|
||||
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
|
||||
@@ -827,20 +829,20 @@ F src/test_windirent.h da2e5b73c32d09905fbdd00f27cd802212a32a58ead882736fe4f5eb7
|
||||
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 6fac7f14dd021fecfdd8be93c27937804c4b665d2da9e667a10e4b5f04c6e085
|
||||
F src/tokenize.c 3f703cacdab728d7741e5a6ac242006d74fe1c2754d4f03ed889d7253259bd68
|
||||
F src/treeview.c 88aa39b754f5ef7214385c1bbbdd2f3dc20efafeed0cf590e8d1199b9c6e44aa
|
||||
F src/trigger.c 0bb986a5b96047fd597c6aac28588853df56064e576e6b81ba777ef2ccaac461
|
||||
F src/update.c 0e01aa6a3edf9ec112b33eb714b9016a81241497b1fb7c3e74332f4f71756508
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
|
||||
F src/util.c 5d1a0134cf4240648d1c6bb5cc8efaca0ea2b5d5c840985aec7e947271f04375
|
||||
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
||||
F src/vacuum.c b763b6457bd058d2072ef9364832351fd8d11e8abf70cbb349657360f7d55c40
|
||||
F src/vdbe.c be5f58bc29f60252e041a618eae59e8d57d460ba136c5403cf0abf955560c457
|
||||
F src/vdbe.h c2549a215898a390de6669cfa32adba56f0d7e17ba5a7f7b14506d6fd5f0c36a
|
||||
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
||||
F src/vdbeapi.c 80235ac380e9467fec1cb0883354d841f2a771976e766995f7e0c77f845406df
|
||||
F src/vdbeaux.c 25d685cafe119ff890c94345e884ea558a6b5d823bfa52ba708eb8ff3c70aa71
|
||||
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
|
||||
F src/vdbeblob.c 255be187436da38b01f276c02e6a08103489bbe2a7c6c21537b7aecbe0e1f797
|
||||
F src/vdbemem.c 831a244831eaa45335f9ae276b50a7a82ee10d8c46c2c72492d4eb8c98d94d89
|
||||
F src/vdbesort.c d0a3c7056c081703c8b6d91ad60f17da5e062a5c64bf568ed0fa1b5f4cae311f
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
@@ -1265,7 +1267,7 @@ F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce3
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c 6e87c27df3d95c556870187987dff6efdc712b5cea60abedc8ab9215f471907a
|
||||
F test/fuzzcheck.c 20be6c96bd0da2e91d25f089a037c1b3f8142211c97104f20629bf15610019e6
|
||||
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -1516,7 +1518,7 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463
|
||||
F test/percentile.test 74e383216a075251512d6ba98beb9dccd6da465e3f73817fc438379e3a628de7
|
||||
F test/percentile.test 52ba89d6ee6b65f770972b67dace358bab7cdbd532803d3db157845268e789cd
|
||||
F test/permutations.test 405542f1d659942994a6b38a9e024cf5cfd23eaa68c806aeb24a72d7c9186e80
|
||||
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
|
||||
F test/pragma.test 11cb9310c42f921918f7f563e3c0b6e70f9f9c3a6a1cf12af8fccb6c574f3882
|
||||
@@ -1625,10 +1627,10 @@ F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8e
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test 490bf9d0c7c9564fea318c46d49369f4690b825b584c9a544dbdccf61bc0babc
|
||||
F test/shell2.test 56da24128304c9ab67da2964cc80beff7b35761c446ec6e6e98bff2775b15026
|
||||
F test/shell2.test 01a01f76ed98088ce598794fbf5b359e148271541a8ddbf79d21cc353cc67a24
|
||||
F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8
|
||||
F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
|
||||
F test/shell5.test bafa4c0b67b7a8027e729970a625c9225cb7ef854acc4e52624c45074faaaddf
|
||||
F test/shell5.test 0e5f8ce08206b9998a778cfe1989e20e47839153c05af2da29198150172e22fc
|
||||
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
|
||||
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
|
||||
F test/shell8.test aea51ecbcd4494c746b096aeff51d841d04d5f0dc4b62eb42427f16109b87acd
|
||||
@@ -1713,8 +1715,8 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl 2c203a2dd664298f239f0ec3ce22fbc65b5f021c1e09edbae8452af8a694e052
|
||||
F test/testrunner.tcl 5d02deeba7a53baeadae6aa7641d90aac58fdfa3a7bcac85cfcfd752b1aab87c
|
||||
F test/testrunner_data.tcl c5ae2b1f9a99210b0600d002fb3af1fee350997cee9416551e83b93501360ebf
|
||||
F test/testrunner.tcl d117492b6ec7293f7906dd4ff48135dd9801bdf42db0f48f88b3328867aa94ff
|
||||
F test/testrunner_data.tcl 9a85a86fd5f9a1a94102b246203aa7c3e047623b8bb5decde7789cfd959580b1
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -2069,7 +2071,7 @@ F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af
|
||||
F test/windowB.test aad7c31739999f68a98a813cfd78390918fc70f56d2d925317a1523cab548ecf
|
||||
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
|
||||
F test/windowD.test 65cf5a765fb8072450e8a0de2979ce7f09a38d87724fe1280c6444073e3da49b
|
||||
F test/windowE.test c98507e0b0d95980ad25845db758557757be2d7054198ccf522c7d277057a3df
|
||||
F test/windowE.test d045a5fbaaf50ecac9483e1249dd317ba4f9d189c405a730ba6effdefb87b94f
|
||||
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
|
||||
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
|
||||
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
|
||||
@@ -2130,8 +2132,8 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
|
||||
F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl 060e9785e9503bf51f8b1b11b542bdeef90fd0ceb0738154f6762acec0c61e5f x
|
||||
F tool/mkkeywordhash.c 8a0a0401a6e0f01ca6e02f58b294a813d067554474875f4fe0222c2b8b0d6ed3
|
||||
F tool/mkctimec.tcl e3af51acc2ef92062fe6d622de010a27a34b497258a248dada04388b916c61c6 x
|
||||
F tool/mkkeywordhash.c 6b0be901c47f9ad42215fc995eb2f4384ac49213b1fba395102ec3e999acf559
|
||||
F tool/mkmsvcmin.tcl d76c45efda1cce2d4005bcea7b8a22bb752e3256009f331120fb4fecb14ebb7a
|
||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||
F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
|
||||
@@ -2148,7 +2150,7 @@ F tool/mktoolzip.tcl c7a9b685f5131d755e7d941cec50cee7f34178b9e34c9a89811eeb08617
|
||||
F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e540a
|
||||
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
|
||||
F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
|
||||
F tool/omittest.tcl e99c9fecc3f7a8ca2fa75d8ec8bdbb5acce33dc69f0c280aae53064693387f65
|
||||
F tool/omittest.tcl 5ca5e4e01716d5f35b48b00fd351d929f01fbb98169a5a3cd00baf3d2e2019a9
|
||||
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
|
||||
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
|
||||
F tool/replace.tcl 511c61acfe563dfb58675efb4628bb158a13d48ff8322123ac447e9d25a82d9a
|
||||
@@ -2210,8 +2212,11 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 16d32676e2e98a7710787de16850c328e7519e893f81ed56f6155a8fa9cbc3a4
|
||||
R a100ff1c9bda3fc624920cd66e34ae7c
|
||||
P dcbebe30f594a99e23b5ccd8d199b92118204a3e52e75c78d98c394601252e81
|
||||
R dad5ee3b909b00a448aebb3a7771c6ec
|
||||
T *branch * new-win32-test-config
|
||||
T *sym-new-win32-test-config *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 58c98d8befdb125e16f0435abf5b1a98
|
||||
Z 5378530d857d88d300d11bbd793c3a45
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
b08f3b74495e125f92c8968472fc8028c73d8df5400195df3081e3d8df8bd985
|
||||
8ace3f15e4f7e8249bf4cf558ceecdf67792bb7801529ef86b4d36363bb8ff8c
|
||||
|
||||
+1
-1
@@ -5989,7 +5989,7 @@ int sqlite3BtreeIndexMoveto(
|
||||
&& indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
|
||||
&& pIdxKey->errCode==SQLITE_OK
|
||||
){
|
||||
pCur->curFlags &= ~BTCF_ValidOvfl;
|
||||
pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
|
||||
if( !pCur->pPage->isInit ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
|
||||
@@ -295,6 +295,9 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
"ENABLE_OFFSET_SQL_FUNC",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
"ENABLE_ORDERED_SET_AGGREGATES",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
"ENABLE_OVERSIZE_CELL_CHECK",
|
||||
#endif
|
||||
|
||||
+6
-2
@@ -2049,7 +2049,11 @@ static void minMaxFinalize(sqlite3_context *context){
|
||||
** group_concat(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
|
||||
** SEPARATOR were appended after EXPR. And the order is undocumented,
|
||||
** 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
|
||||
** run first to initialize it */
|
||||
if( ALWAYS(pGCC) ){
|
||||
int nVS;
|
||||
int nVS; /* Number of characters to remove */
|
||||
/* Must call sqlite3_value_text() to convert the argument into text prior
|
||||
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
|
||||
(void)sqlite3_value_text(argv[0]);
|
||||
|
||||
+2
-1
@@ -1926,7 +1926,8 @@ int sqlite3CreateFunc(
|
||||
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
|
||||
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
|
||||
extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
|
||||
SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE);
|
||||
SQLITE_SUBTYPE|SQLITE_INNOCUOUS|
|
||||
SQLITE_RESULT_SUBTYPE|SQLITE_SELFORDER1);
|
||||
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
|
||||
|
||||
/* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But
|
||||
|
||||
+111
-232
@@ -264,11 +264,14 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
|
||||
CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
|
||||
EXCLUDE GROUPS OTHERS TIES
|
||||
%endif SQLITE_OMIT_WINDOWFUNC
|
||||
%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
WITHIN
|
||||
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
%ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
GENERATED ALWAYS
|
||||
%endif
|
||||
MATERIALIZED
|
||||
REINDEX RENAME CTIME_KW IF AGGREGATE
|
||||
REINDEX RENAME CTIME_KW IF
|
||||
.
|
||||
%wildcard ANY.
|
||||
|
||||
@@ -295,8 +298,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
|
||||
%left CONCAT PTR.
|
||||
%left COLLATE.
|
||||
%right BITNOT.
|
||||
%nonassoc ON FROM.
|
||||
%nonassoc JOIN_KW JOIN.
|
||||
%nonassoc ON.
|
||||
|
||||
// An IDENTIFIER can be a generic identifier, or one of several
|
||||
// keywords. Any non-standard keyword can also be an identifier.
|
||||
@@ -625,233 +627,6 @@ oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
|
||||
}
|
||||
%endif
|
||||
|
||||
%ifndef SQLITE_OMIT_SUBQUERY
|
||||
%include {
|
||||
SQLITE_NOINLINE SrcList *sqlite3SrcListAppendSubFrom(
|
||||
Parse *pParse, /* Parsing context */
|
||||
SrcList *pFrom, /* LHS of the FROM clause */
|
||||
SrcList *pSubFrom, /* New parenthesized sub-FROM to append */
|
||||
Token *pAs, /* AS-Name of the sub-FROM */
|
||||
OnOrUsing *pOnUsing /* ON or USING clause associated with the join */
|
||||
){
|
||||
if( pFrom==0 && pAs->n==0 && pOnUsing->pOn==0 && pOnUsing->pUsing==0 ){
|
||||
pFrom = pSubFrom;
|
||||
}else if( ALWAYS(pSubFrom!=0) && pSubFrom->nSrc==1 ){
|
||||
pFrom = sqlite3SrcListAppendFromTerm(pParse,pFrom,0,0,pAs,0,pOnUsing);
|
||||
if( pFrom ){
|
||||
SrcItem *pNew = &pFrom->a[pFrom->nSrc-1];
|
||||
SrcItem *pOld = pSubFrom->a;
|
||||
assert( pOld->fg.fixedSchema==0 );
|
||||
pNew->zName = pOld->zName;
|
||||
assert( pOld->fg.fixedSchema==0 );
|
||||
if( pOld->fg.isSubquery ){
|
||||
pNew->fg.isSubquery = 1;
|
||||
pNew->u4.pSubq = pOld->u4.pSubq;
|
||||
pOld->u4.pSubq = 0;
|
||||
pOld->fg.isSubquery = 0;
|
||||
assert( pNew->u4.pSubq!=0 && pNew->u4.pSubq->pSelect!=0 );
|
||||
if( (pNew->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 ){
|
||||
pNew->fg.isNestedFrom = 1;
|
||||
}
|
||||
}else{
|
||||
pNew->u4.zDatabase = pOld->u4.zDatabase;
|
||||
pOld->u4.zDatabase = 0;
|
||||
}
|
||||
if( pOld->fg.isTabFunc ){
|
||||
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
|
||||
pOld->u1.pFuncArg = 0;
|
||||
pOld->fg.isTabFunc = 0;
|
||||
pNew->fg.isTabFunc = 1;
|
||||
}
|
||||
pOld->zName = 0;
|
||||
}
|
||||
sqlite3SrcListDelete(pParse->db, pSubFrom);
|
||||
}else{
|
||||
Select *pSubquery;
|
||||
sqlite3SrcListShiftJoinType(pParse,pSubFrom);
|
||||
pSubquery = sqlite3SelectNew(pParse,0,pSubFrom,0,0,0,0,SF_NestedFrom,0);
|
||||
pFrom = sqlite3SrcListAppendFromTerm(pParse,pFrom,0,0,pAs,pSubquery,pOnUsing);
|
||||
}
|
||||
return pFrom;
|
||||
}
|
||||
}
|
||||
%endif SQLITE_OMIT_SUBQUERY
|
||||
|
||||
%ifndef SQLITE_OMIT_FROM_FIRST
|
||||
%include {
|
||||
/* The Pipe object represents a pipe under construction. It is a transient
|
||||
** object found only on the LALR(1) parser stack. */
|
||||
typedef struct Pipe Pipe;
|
||||
struct Pipe {
|
||||
SrcList *pFrom; /* The FROM clause */
|
||||
ExprList *pProj; /* The projection - list of columns to return */
|
||||
ExprList *pOrderBy; /* The ORDER BY clause */
|
||||
ExprList *pGroupBy; /* The GROUP BY clause */
|
||||
Expr *pLimit; /* The LIMIT or LIMIT/OFFSET clause */
|
||||
Expr *pWhere; /* The WHERE clause */
|
||||
Expr *pHaving; /* The HAVING clause */
|
||||
int selFlags; /* SF_DISTINCT or SF_ALL or 0 */
|
||||
u8 bSeenAgg; /* True if AGGREGATE has been seen */
|
||||
u8 bNeedPush; /* PipePush needed before adding terms to pProj */
|
||||
Token sAs; /* Value of a pending AS clause */
|
||||
};
|
||||
|
||||
/* Delete a pipe object */
|
||||
void sqlite3PipeDelete(sqlite3 *db, Pipe *p){
|
||||
sqlite3SrcListDelete(db, p->pFrom);
|
||||
sqlite3ExprListDelete(db, p->pProj);
|
||||
sqlite3ExprListDelete(db, p->pOrderBy);
|
||||
sqlite3ExprListDelete(db, p->pGroupBy);
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
sqlite3ExprDelete(db, p->pWhere);
|
||||
sqlite3ExprDelete(db, p->pHaving);
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
|
||||
/* Generate a Select from the current content of a Pipe. Reset the Pipe
|
||||
** to be empty, except do not remove the AS token if there is one and do
|
||||
** not delete the Pipe.
|
||||
*/
|
||||
Select *sqlite3SelectFromPipe(Parse *pParse, Pipe *p){
|
||||
Token sAs = p->sAs;
|
||||
Select *pSel = sqlite3SelectNew(pParse, p->pProj, p->pFrom, p->pWhere,
|
||||
p->pGroupBy, p->pHaving, p->pOrderBy,
|
||||
p->selFlags, p->pLimit);
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->sAs = sAs;
|
||||
return pSel;
|
||||
}
|
||||
|
||||
/* Take the current content of the pipe and make it "FROM <subquery>" pipe.
|
||||
*/
|
||||
void sqlite3PipePush(Parse *pParse, Pipe *pPipe, int jointype){
|
||||
Select *pSel = sqlite3SelectFromPipe(pParse, pPipe);
|
||||
SrcList *pFrom = pPipe->pFrom;
|
||||
if( pFrom ) pFrom->a[pFrom->nSrc-1].fg.jointype = jointype;
|
||||
pPipe->pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&pPipe->sAs,pSel,0);
|
||||
pPipe->sAs.z = 0;
|
||||
}
|
||||
|
||||
}
|
||||
%type pipeline {Pipe*}
|
||||
%destructor pipeline {sqlite3PipeDelete(pParse->db,$$);}
|
||||
|
||||
oneselect(A) ::= pipeline(X). {
|
||||
Pipe *pPipe = X;
|
||||
Select *pSel = sqlite3SelectFromPipe(pParse,pPipe);
|
||||
sqlite3DbFree(pParse->db, pPipe);
|
||||
A = pSel; /*A-overwrites-X */
|
||||
}
|
||||
pipeline(A) ::= FROM seltablist(X). {
|
||||
Pipe *pPipe = sqlite3DbMallocZero(pParse->db, sizeof(*pPipe));
|
||||
A = pPipe;
|
||||
if( pPipe ){
|
||||
pPipe->pFrom = X;
|
||||
}else{
|
||||
sqlite3SrcListDelete(pParse->db, X);
|
||||
}
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe pipejoinop(J) nm(Y) dbnm(D) as(Z) on_using(N). {
|
||||
Pipe *p = A;
|
||||
if( p->bNeedPush ) sqlite3PipePush(pParse, p, J);
|
||||
p->pFrom = sqlite3SrcListAppendFromTerm(pParse, p->pFrom, &Y, &D, &Z, 0, &N);
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe
|
||||
pipejoinop(J) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) on_using(N). {
|
||||
Pipe *p = A;
|
||||
if( p->bNeedPush ) sqlite3PipePush(pParse, p, J);
|
||||
p->pFrom = sqlite3SrcListAppendFromTerm(pParse, p->pFrom, &Y, &D, &Z, 0, &N);
|
||||
sqlite3SrcListFuncArgs(pParse, p->pFrom, E);
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe pipejoinop(J) LP select(S) RP as(Z) on_using(N). {
|
||||
Pipe *p = A;
|
||||
if( p->bNeedPush ) sqlite3PipePush(pParse, p, J);
|
||||
p->pFrom = sqlite3SrcListAppendFromTerm(pParse,p->pFrom,0,0,&Z,S,&N);
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe pipejoinop(J) LP seltablist(F) RP as(Z) on_using(N).{
|
||||
Pipe *p = A;
|
||||
if( p->bNeedPush ) sqlite3PipePush(pParse, p, J);
|
||||
p->pFrom = sqlite3SrcListAppendSubFrom(pParse,p->pFrom,F,&Z,&N);
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe WHERE expr(W). {
|
||||
Pipe *p = A;
|
||||
if( p->bSeenAgg ){
|
||||
p->pHaving = sqlite3ExprAnd(pParse, A->pHaving, W);
|
||||
}else{
|
||||
p->pWhere = sqlite3ExprAnd(pParse, A->pWhere, W);
|
||||
}
|
||||
p->bNeedPush = 1;
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe HAVING expr(W). {
|
||||
Pipe *p = A;
|
||||
p->pHaving = sqlite3ExprAnd(pParse, A->pHaving, W);
|
||||
p->bNeedPush = 1;
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe AGGREGATE selcollist(W) groupby_opt(G). {
|
||||
Pipe *p = A;
|
||||
ExprList *pProj = W;
|
||||
ExprList *pGroupby = G;
|
||||
if( p->pProj ) sqlite3PipePush(pParse, p, 0);
|
||||
if( pGroupby ){
|
||||
int i;
|
||||
for(i=0; i<pGroupby->nExpr; i++){
|
||||
pProj = sqlite3ExprListAppend(pParse, pProj,
|
||||
sqlite3ExprDup(pParse->db, pGroupby->a[i].pExpr, 0));
|
||||
}
|
||||
p->pGroupBy = pGroupby;
|
||||
}
|
||||
p->pProj = pProj;
|
||||
p->bSeenAgg = 1;
|
||||
p->bNeedPush = 1;
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe SELECT distinct(D) selcollist(W). {
|
||||
Pipe *p = A;
|
||||
if( p->pProj ) sqlite3PipePush(pParse, p, 0);
|
||||
p->pProj = W;
|
||||
p->selFlags = D;
|
||||
p->bNeedPush = 1;
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe ORDER BY sortlist(X). {
|
||||
Pipe *p = A;
|
||||
if( p->pOrderBy || p->pLimit ) sqlite3PipePush(pParse, p, 0);
|
||||
p->pOrderBy = X;
|
||||
p->bNeedPush = 1;
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe LIMIT expr(X). {
|
||||
Pipe *p = A;
|
||||
Expr *pLimit = sqlite3PExpr(pParse,TK_LIMIT,X,0);
|
||||
if( pLimit ){
|
||||
sqlite3ExprDelete(pParse->db, p->pLimit);
|
||||
p->pLimit = pLimit;
|
||||
}
|
||||
p->bNeedPush = 1;
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) pipe LIMIT expr(X) OFFSET expr(Y). {
|
||||
Pipe *p = A;
|
||||
Expr *pLimit = sqlite3PExpr(pParse,TK_LIMIT,X,Y);
|
||||
if( pLimit ){
|
||||
sqlite3ExprDelete(pParse->db, p->pLimit);
|
||||
p->pLimit = pLimit;
|
||||
}
|
||||
p->bNeedPush = 1;
|
||||
}
|
||||
pipeline(A) ::= pipeline(A) PIPE AS nm(X). {A->sAs = X; A->bNeedPush = 1;}
|
||||
pipeline(A) ::= pipeline(A) pipe VIEW nm(X). {A->sAs = X; A->bNeedPush = 1;}
|
||||
//pipeline ::= pipeline pipe DISTINCT ON nexprlist.
|
||||
|
||||
pipe ::= .
|
||||
pipe ::= PIPE.
|
||||
|
||||
%type pipejoinop {int}
|
||||
pipejoinop(X) ::= JOIN. { X = JT_INNER; }
|
||||
pipejoinop(X) ::= JOIN_KW(A) JOIN.
|
||||
{X = sqlite3JoinType(pParse,&A,0,0); /*X-overwrites-A*/}
|
||||
pipejoinop(X) ::= JOIN_KW(A) nm(B) JOIN.
|
||||
{X = sqlite3JoinType(pParse,&A,&B,0); /*X-overwrites-A*/}
|
||||
pipejoinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN.
|
||||
{X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/}
|
||||
|
||||
%endif FROM_first
|
||||
|
||||
// Single row VALUES clause.
|
||||
//
|
||||
@@ -961,7 +736,44 @@ seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) on_using(N
|
||||
A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,&N);
|
||||
}
|
||||
seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP as(Z) on_using(N). {
|
||||
A = sqlite3SrcListAppendSubFrom(pParse,A,F,&Z,&N);
|
||||
if( A==0 && Z.n==0 && N.pOn==0 && N.pUsing==0 ){
|
||||
A = F;
|
||||
}else if( ALWAYS(F!=0) && F->nSrc==1 ){
|
||||
A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,&N);
|
||||
if( A ){
|
||||
SrcItem *pNew = &A->a[A->nSrc-1];
|
||||
SrcItem *pOld = F->a;
|
||||
assert( pOld->fg.fixedSchema==0 );
|
||||
pNew->zName = pOld->zName;
|
||||
assert( pOld->fg.fixedSchema==0 );
|
||||
if( pOld->fg.isSubquery ){
|
||||
pNew->fg.isSubquery = 1;
|
||||
pNew->u4.pSubq = pOld->u4.pSubq;
|
||||
pOld->u4.pSubq = 0;
|
||||
pOld->fg.isSubquery = 0;
|
||||
assert( pNew->u4.pSubq!=0 && pNew->u4.pSubq->pSelect!=0 );
|
||||
if( (pNew->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 ){
|
||||
pNew->fg.isNestedFrom = 1;
|
||||
}
|
||||
}else{
|
||||
pNew->u4.zDatabase = pOld->u4.zDatabase;
|
||||
pOld->u4.zDatabase = 0;
|
||||
}
|
||||
if( pOld->fg.isTabFunc ){
|
||||
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
|
||||
pOld->u1.pFuncArg = 0;
|
||||
pOld->fg.isTabFunc = 0;
|
||||
pNew->fg.isTabFunc = 1;
|
||||
}
|
||||
pOld->zName = 0;
|
||||
}
|
||||
sqlite3SrcListDelete(pParse->db, F);
|
||||
}else{
|
||||
Select *pSubquery;
|
||||
sqlite3SrcListShiftJoinType(pParse,F);
|
||||
pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0);
|
||||
A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,&N);
|
||||
}
|
||||
}
|
||||
%endif SQLITE_OMIT_SUBQUERY
|
||||
|
||||
@@ -1370,6 +1182,65 @@ expr(A) ::= idj(X) LP STAR RP. {
|
||||
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
|
||||
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP filter_over(Z). {
|
||||
A = sqlite3ExprFunction(pParse, Y, &X, D);
|
||||
@@ -1384,7 +1255,15 @@ expr(A) ::= idj(X) LP STAR RP filter_over(Z). {
|
||||
A = sqlite3ExprFunction(pParse, 0, &X, 0);
|
||||
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). {
|
||||
A = sqlite3ExprFunction(pParse, 0, &OP, 0);
|
||||
|
||||
@@ -246,6 +246,7 @@ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
|
||||
# define SQLITE_CIO_NO_CLASSIFY
|
||||
# define SQLITE_CIO_NO_TRANSLATE
|
||||
# define SQLITE_CIO_NO_SETMODE
|
||||
# define SQLITE_CIO_NO_FLUSH
|
||||
#endif
|
||||
INCLUDE ../ext/consio/console_io.h
|
||||
INCLUDE ../ext/consio/console_io.c
|
||||
@@ -279,6 +280,7 @@ INCLUDE ../ext/consio/console_io.c
|
||||
# define eputz(z) ePutsUtf8(z)
|
||||
# define eputf ePrintfUtf8
|
||||
# define oputb(buf,na) oPutbUtf8(buf,na)
|
||||
# define fflush(s) fFlushBuffer(s);
|
||||
|
||||
#else
|
||||
/* For Fiddle, all console handling and emit redirection is omitted. */
|
||||
@@ -295,6 +297,7 @@ INCLUDE ../ext/consio/console_io.c
|
||||
# define eputz(z) fputs(z,stderr)
|
||||
# define sputz(fp,z) fputs(z,fp)
|
||||
# define oputb(buf,na) fwrite(buf,1,na,stdout)
|
||||
# undef fflush
|
||||
#endif
|
||||
|
||||
/* True if the timer is enabled */
|
||||
|
||||
@@ -5615,6 +5615,15 @@ int sqlite3_create_window_function(
|
||||
** [sqlite3_result_subtype()] should avoid setting this property, as the
|
||||
** purpose of this property is to disable certain optimizations that are
|
||||
** 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>
|
||||
** </dl>
|
||||
*/
|
||||
@@ -5623,6 +5632,7 @@ int sqlite3_create_window_function(
|
||||
#define SQLITE_SUBTYPE 0x000100000
|
||||
#define SQLITE_INNOCUOUS 0x000200000
|
||||
#define SQLITE_RESULT_SUBTYPE 0x001000000
|
||||
#define SQLITE_SELFORDER1 0x002000000
|
||||
|
||||
/*
|
||||
** CAPI3REF: Deprecated Functions
|
||||
|
||||
@@ -658,6 +658,8 @@
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
# define double sqlite_int64
|
||||
# define float sqlite_int64
|
||||
# define fabs(X) ((X)<0?-(X):(X))
|
||||
# define sqlite3IsOverflow(X) 0
|
||||
# define LONGDOUBLE_TYPE sqlite_int64
|
||||
# ifndef SQLITE_BIG_DBL
|
||||
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
|
||||
|
||||
@@ -189,6 +189,14 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","0",TCL_GLOBAL_ONLY);
|
||||
#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
|
||||
Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
@@ -341,6 +349,14 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY);
|
||||
#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
|
||||
Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "1",
|
||||
TCL_GLOBAL_ONLY);
|
||||
|
||||
+4
-9
@@ -372,17 +372,12 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
||||
}
|
||||
}
|
||||
case CC_PIPE: {
|
||||
if( z[1]=='|' ){
|
||||
*tokenType = TK_CONCAT;
|
||||
return 2;
|
||||
#ifdef TK_PIPE
|
||||
}else if( z[1]=='>' ){
|
||||
*tokenType = TK_PIPE;
|
||||
return 2;
|
||||
#endif
|
||||
}else{
|
||||
if( z[1]!='|' ){
|
||||
*tokenType = TK_BITOR;
|
||||
return 1;
|
||||
}else{
|
||||
*tokenType = TK_CONCAT;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
case CC_COMMA: {
|
||||
|
||||
+14
-9
@@ -162,6 +162,9 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
const char *zDbMain; /* Schema name of database to vacuum */
|
||||
const char *zOut; /* Name of output file */
|
||||
u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */
|
||||
u64 iRandom; /* Random value used for zDbVacuum[] */
|
||||
char zDbVacuum[42]; /* Name of the ATTACH-ed database used for vacuum */
|
||||
|
||||
|
||||
if( !db->autoCommit ){
|
||||
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
|
||||
@@ -202,27 +205,29 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
pMain = db->aDb[iDb].pBt;
|
||||
isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
|
||||
|
||||
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
|
||||
/* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma
|
||||
** can be set to 'off' for this file, as it is not recovered if a crash
|
||||
** occurs anyway. The integrity of the database is maintained by a
|
||||
** (possibly synchronous) transaction opened on the main database before
|
||||
** sqlite3BtreeCopyFile() is called.
|
||||
**
|
||||
** An optimization would be to use a non-journaled pager.
|
||||
** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
|
||||
** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but
|
||||
** that actually made the VACUUM run slower. Very little journalling
|
||||
** actually occurs when doing a vacuum since the vacuum_db is initially
|
||||
** empty. Only the journal header is written. Apparently it takes more
|
||||
** time to parse and run the PRAGMA to turn journalling off than it does
|
||||
** to write the journal header file.
|
||||
*/
|
||||
sqlite3_randomness(sizeof(iRandom),&iRandom);
|
||||
sqlite3_snprintf(sizeof(zDbVacuum), zDbVacuum, "vacuum_%016llx", iRandom);
|
||||
nDb = db->nDb;
|
||||
rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
|
||||
rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS %s", zOut, zDbVacuum);
|
||||
db->openFlags = saved_openFlags;
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
assert( (db->nDb-1)==nDb );
|
||||
pDb = &db->aDb[nDb];
|
||||
assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
|
||||
assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
|
||||
pTemp = pDb->pBt;
|
||||
if( pOut ){
|
||||
sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
|
||||
@@ -299,11 +304,11 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
** the contents to the temporary database.
|
||||
*/
|
||||
rc = execSqlF(db, pzErrMsg,
|
||||
"SELECT'INSERT INTO vacuum_db.'||quote(name)"
|
||||
"SELECT'INSERT INTO %s.'||quote(name)"
|
||||
"||' SELECT*FROM\"%w\".'||quote(name)"
|
||||
"FROM vacuum_db.sqlite_schema "
|
||||
"FROM %s.sqlite_schema "
|
||||
"WHERE type='table'AND coalesce(rootpage,1)>0",
|
||||
zDbMain
|
||||
zDbVacuum, zDbMain, zDbVacuum
|
||||
);
|
||||
assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 );
|
||||
db->mDbFlags &= ~DBFLAG_Vacuum;
|
||||
@@ -315,11 +320,11 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
** from the schema table.
|
||||
*/
|
||||
rc = execSqlF(db, pzErrMsg,
|
||||
"INSERT INTO vacuum_db.sqlite_schema"
|
||||
"INSERT INTO %s.sqlite_schema"
|
||||
" SELECT*FROM \"%w\".sqlite_schema"
|
||||
" WHERE type IN('view','trigger')"
|
||||
" OR(type='table'AND rootpage=0)",
|
||||
zDbMain
|
||||
zDbVacuum, zDbMain
|
||||
);
|
||||
if( rc ) goto end_of_vacuum;
|
||||
|
||||
|
||||
@@ -167,6 +167,11 @@ int sqlite3_blob_open(
|
||||
pTab = 0;
|
||||
sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
|
||||
}
|
||||
if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){
|
||||
pTab = 0;
|
||||
sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s",
|
||||
zTable);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIEW
|
||||
if( pTab && IsView(pTab) ){
|
||||
pTab = 0;
|
||||
|
||||
+4
-2
@@ -159,10 +159,11 @@ static struct GlobalVars {
|
||||
} 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_randomjson_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
|
||||
|
||||
/*
|
||||
@@ -1329,7 +1330,8 @@ int runCombinedDbSqlInput(
|
||||
/* Add the vt02 virtual table */
|
||||
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);
|
||||
|
||||
/* Add support for sqlite_dbdata and sqlite_dbptr virtual tables used
|
||||
|
||||
+425
-61
@@ -9,7 +9,8 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
# 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]
|
||||
@@ -25,35 +26,65 @@ do_test percentile-1.0 {
|
||||
}
|
||||
execsql {SELECT percentile(x,0) FROM t1}
|
||||
} {1.0}
|
||||
foreach {in out} {
|
||||
100 11.0
|
||||
50 8.0
|
||||
12.5 4.0
|
||||
15 4.4
|
||||
20 5.2
|
||||
80 11.0
|
||||
89 11.0
|
||||
foreach {in out disc} {
|
||||
100 11.0 11.0
|
||||
50 8.0 8.0
|
||||
12.5 4.0 4.0
|
||||
15 4.4 4.0
|
||||
20 5.2 4.0
|
||||
80 11.0 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}
|
||||
} $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 {
|
||||
SELECT median(x) FROM t1;
|
||||
} 8.0
|
||||
|
||||
foreach {in out} {
|
||||
1.0 11.0
|
||||
0.5 8.0
|
||||
0.125 4.0
|
||||
0.15 4.4
|
||||
0.2 5.2
|
||||
0.8 11.0
|
||||
0.89 11.0
|
||||
} {
|
||||
do_test percentile-1.1b-$in {
|
||||
execsql {SELECT percentile_cont(x,$in) FROM t1}
|
||||
} $out
|
||||
ifcapable ordered_set_aggregates {
|
||||
do_execsql_test percentile-1.1.median {
|
||||
SELECT median() WITHIN GROUP (ORDER BY x) FROM t1;
|
||||
} 8.0
|
||||
do_execsql_test percentile-1.1.distinct.1 {
|
||||
SELECT median(DISTINCT x) FROM t1;
|
||||
} 7.0
|
||||
do_catchsql_test percentile-1.1.distinct.2 {
|
||||
SELECT percentile(DISTINCT 50) WITHIN GROUP (ORDER BY x) FROM t1;
|
||||
} {1 {DISTINCT not allowed on ordered-set aggregate percentile()}}
|
||||
} else {
|
||||
do_catchsql_test percentile-1.1.median {
|
||||
SELECT median() WITHIN GROUP (ORDER BY x) FROM t1;
|
||||
} {1 {near "(": syntax error}}
|
||||
}
|
||||
|
||||
# Add some NULL values.
|
||||
@@ -61,28 +92,69 @@ foreach {in out} {
|
||||
do_test percentile-1.2 {
|
||||
execsql {INSERT INTO t1 VALUES(NULL),(NULL);}
|
||||
} {}
|
||||
foreach {in out} {
|
||||
100 11.0
|
||||
50 8.0
|
||||
12.5 4.0
|
||||
15 4.4
|
||||
20 5.2
|
||||
80 11.0
|
||||
89 11.0
|
||||
foreach {in out disc} {
|
||||
100 11.0 11.0
|
||||
50 8.0 8.0
|
||||
12.5 4.0 4.0
|
||||
15 4.4 4.0
|
||||
20 5.2 4.0
|
||||
80 11.0 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}
|
||||
} $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.
|
||||
#
|
||||
do_test percentile-1.4 {
|
||||
do_test percentile-1.4.1 {
|
||||
catchsql {SELECT round(percentile(x, 15+0.000001*rowid),1) FROM t1}
|
||||
} {0 4.4}
|
||||
do_test percentile-1.5 {
|
||||
catchsql {SELECT round(percentile(x, 15+0.1*rowid),1) FROM t1}
|
||||
} {1 {2nd argument to percentile() is not the same for all input rows}}
|
||||
do_test percentile-1.4.2 {
|
||||
catchsql {SELECT round(percentile_cont(x,(15+0.000001*rowid)*0.01),1) FROM t1}
|
||||
} {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
|
||||
#
|
||||
@@ -92,65 +164,152 @@ do_test percentile-1.6 {
|
||||
INSERT INTO t2 SELECT x+0.0 FROM t1 ORDER BY random();
|
||||
}
|
||||
} {}
|
||||
foreach {in out} {
|
||||
100 11.0
|
||||
50 8.0
|
||||
12.5 4.0
|
||||
15 4.4
|
||||
20 5.2
|
||||
80 11.0
|
||||
89 11.0
|
||||
foreach {in out disc} {
|
||||
100 11.0 11.0
|
||||
50 8.0 8.0
|
||||
12.5 4.0 4.0
|
||||
15 4.4 4.0
|
||||
20 5.2 4.0
|
||||
80 11.0 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}
|
||||
} $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
|
||||
#
|
||||
do_test percentile-1.8 {
|
||||
do_test percentile-1.8.1 {
|
||||
catchsql {SELECT percentile(x,0,1) FROM t1}
|
||||
} {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}
|
||||
} {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
|
||||
#
|
||||
do_test percentile-1.10 {
|
||||
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 {
|
||||
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 {
|
||||
catchsql {SELECT percentile(x,x'3530') FROM t1}
|
||||
} {1 {2nd argument to percentile() is not a number 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}}
|
||||
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
|
||||
|
||||
# Second argument is out of range
|
||||
#
|
||||
do_test percentile-1.13 {
|
||||
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 {
|
||||
catchsql {SELECT percentile(x,100.0000001) FROM t1}
|
||||
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
|
||||
do_test percentile-1.14b {
|
||||
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
|
||||
do_test percentile-1.14.2 {
|
||||
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
|
||||
#
|
||||
do_test percentile-1.15 {
|
||||
do_test percentile-1.15.1 {
|
||||
catchsql {
|
||||
BEGIN;
|
||||
UPDATE t1 SET x='50' WHERE x IS NULL;
|
||||
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 {
|
||||
catchsql {
|
||||
ROLLBACK;
|
||||
@@ -158,7 +317,7 @@ do_test percentile-1.16 {
|
||||
UPDATE t1 SET x=x'3530' WHERE x IS NULL;
|
||||
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 {
|
||||
catchsql {
|
||||
ROLLBACK;
|
||||
@@ -186,7 +345,7 @@ do_test percentile-1.19 {
|
||||
|
||||
# Infinity as an input
|
||||
#
|
||||
do_test percentile-1.20 {
|
||||
do_test percentile-1.20.1 {
|
||||
catchsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 SELECT x+0.0 FROM t2;
|
||||
@@ -194,6 +353,43 @@ do_test percentile-1.20 {
|
||||
SELECT percentile(x,50) from t1;
|
||||
}
|
||||
} {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 {
|
||||
catchsql {
|
||||
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
|
||||
|
||||
@@ -217,6 +217,7 @@ do_test shell2-1.4.9 {
|
||||
done
|
||||
2}}
|
||||
|
||||
ifcapable vtab {
|
||||
# Verify that generate_series stays sane near 64-bit range boundaries.
|
||||
# See overflow report at https://sqlite.org/forum/forumpost/5d34ce5280
|
||||
do_test shell2-1.4.10 {
|
||||
@@ -247,7 +248,9 @@ do_test shell2-1.4.10 {
|
||||
0
|
||||
1
|
||||
2}}
|
||||
} ;# ifcapable vtab
|
||||
|
||||
ifcapable vtab {
|
||||
# Bug discovered while messing around, .import hangs with
|
||||
# bit 7 set in column separator.
|
||||
do_test shell2-1.4.11 {
|
||||
@@ -262,6 +265,7 @@ do_test shell2-1.4.11 {
|
||||
.import dummy.csv t
|
||||
SELECT count(*) FROM t;}]]
|
||||
} {0 1}
|
||||
} ;# ifcapable vtab
|
||||
|
||||
# Bug from forum post 7cbe081746dd3803
|
||||
# Keywords as column names were producing an error message.
|
||||
|
||||
@@ -84,6 +84,14 @@ do_test shell5-1.4.1 {
|
||||
.import FOO t1}]
|
||||
} {1 {Error: cannot open "FOO"}}
|
||||
|
||||
# the remainder of these test cases require virtual tables.
|
||||
#
|
||||
ifcapable !vtab {
|
||||
puts "Skipping subsequent tests due to SQLITE_OMIT_VIRTUALTABLE"
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# empty import file
|
||||
do_test shell5-1.4.2 {
|
||||
forcedelete shell5.csv
|
||||
|
||||
+160
-38
@@ -54,7 +54,7 @@ proc usage {} {
|
||||
Usage:
|
||||
$a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?
|
||||
$a0 PERMUTATION FILE
|
||||
$a0 errors ?-v|--verbose?
|
||||
$a0 errors ?-v|--verbose? ?-s|--summary? ?PATTERN?
|
||||
$a0 help
|
||||
$a0 njob ?NJOB?
|
||||
$a0 script ?-msvc? CONFIG
|
||||
@@ -89,7 +89,9 @@ Other PERMUTATION arguments must be run using testfixture, not tclsh:
|
||||
If no PATTERN arguments are present, all tests specified by the PERMUTATION
|
||||
are run. Otherwise, each pattern is interpreted as a glob pattern. Only
|
||||
those tcl tests for which the final component of the filename matches at
|
||||
least one specified pattern are run.
|
||||
least one specified pattern are run. The glob wildcard '*' is prepended
|
||||
to the pattern if it does not start with '^' and appended to every
|
||||
pattern that does not end with '$'.
|
||||
|
||||
If no PATTERN arguments are present, then various fuzztest, threadtest
|
||||
and other tests are run as part of the "release" permutation. These are
|
||||
@@ -110,10 +112,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
|
||||
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
|
||||
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
|
||||
}]]
|
||||
@@ -277,10 +281,12 @@ set TRG(schema) {
|
||||
priority INTEGER NOT NULL, -- higher priority jobs may run earlier
|
||||
|
||||
/* Fields updated as jobs run */
|
||||
starttime INTEGER,
|
||||
endtime INTEGER,
|
||||
starttime INTEGER, -- Start time (milliseconds since 1970)
|
||||
endtime INTEGER, -- End time
|
||||
state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ),
|
||||
output TEXT
|
||||
ntest INT, -- Number of test cases run
|
||||
nerr INT, -- Number of errors reported
|
||||
output TEXT -- test output
|
||||
);
|
||||
|
||||
CREATE TABLE config(
|
||||
@@ -352,8 +358,8 @@ if {([llength $argv]==2 || [llength $argv]==1)
|
||||
sqlite3 mydb $TRG(dbname)
|
||||
if {[llength $argv]==2} {
|
||||
set param [lindex $argv 1]
|
||||
if {[string is integer $param]==0 || $param<1 || $param>128} {
|
||||
puts stderr "parameter must be an integer between 1 and 128"
|
||||
if {[string is integer $param]==0 || $param<0 || $param>128} {
|
||||
puts stderr "parameter must be an integer between 0 and 128"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -389,14 +395,36 @@ if {[string compare -nocase script [lindex $argv 0]]==0} {
|
||||
exit
|
||||
}
|
||||
|
||||
# Compute an elapse time string MM:SS or HH:MM:SS based on the
|
||||
# number of milliseconds in the argument.
|
||||
#
|
||||
proc elapsetime {ms} {
|
||||
set s [expr {int(($ms+500.0)*0.001)}]
|
||||
set hr [expr {$s/3600}]
|
||||
set mn [expr {($s/60)%60}]
|
||||
set sc [expr {$s%60}]
|
||||
if {$hr>0} {
|
||||
return [format %02d:%02d:%02d $hr $mn $sc]
|
||||
} else {
|
||||
return [format %02d:%02d $mn $sc]
|
||||
}
|
||||
}
|
||||
|
||||
# Helper routine for show_status
|
||||
#
|
||||
proc display_job {jobdict {tm ""}} {
|
||||
array set job $jobdict
|
||||
set dfname [format %-60s $job(displayname)]
|
||||
if {[string length $job(displayname)]>65} {
|
||||
set dfname [format %.65s... $job(displayname)]
|
||||
} else {
|
||||
set dfname [format %-68s $job(displayname)]
|
||||
}
|
||||
set dtm ""
|
||||
if {$tm!=""} {
|
||||
set dtm [format %-10s "\[[expr {$tm-$job(starttime)}]ms\]"]
|
||||
set dtm [expr {$tm-$job(starttime)}]
|
||||
set dtm [format %8s [elapsetime $dtm]]
|
||||
} else {
|
||||
set dtm [format %8s ""]
|
||||
}
|
||||
puts " $dfname $dtm"
|
||||
}
|
||||
@@ -431,6 +459,11 @@ proc show_status {db cls} {
|
||||
incr S($state) $cnt
|
||||
incr total $cnt
|
||||
}
|
||||
set nt 0
|
||||
set ne 0
|
||||
$db eval {
|
||||
SELECT sum(ntest) AS nt, sum(nerr) AS ne FROM jobs HAVING nt>0
|
||||
} break
|
||||
set fin [expr $S(done)+$S(failed)]
|
||||
if {$cmdline!=""} {set cmdline " $cmdline"}
|
||||
|
||||
@@ -439,22 +472,25 @@ proc show_status {db cls} {
|
||||
# overwrite.
|
||||
puts -nonewline "\033\[H"
|
||||
flush stdout
|
||||
set clreol "\033\[K"
|
||||
} else {
|
||||
set clreol ""
|
||||
}
|
||||
set f ""
|
||||
if {$S(failed)>0} {
|
||||
set f "$S(failed) FAILED, "
|
||||
}
|
||||
puts "Command line: \[testrunner.tcl$cmdline\]$clreol"
|
||||
puts "Jobs: $nJob "
|
||||
puts "Summary: ${tm}ms, ($fin/$total) finished,\
|
||||
${f}$S(running) running "
|
||||
puts [format %-79.79s "Command: \[testrunner.tcl$cmdline\]"]
|
||||
puts [format %-79.79s "Summary: [elapsetime $tm], $fin/$total jobs,\
|
||||
$ne errors, $nt tests"]
|
||||
|
||||
set srcdir [file dirname [file dirname $TRG(info_script)]]
|
||||
set line "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} {
|
||||
puts "Running: "
|
||||
$db eval {
|
||||
SELECT * FROM jobs WHERE state='running' ORDER BY starttime
|
||||
} job {
|
||||
@@ -462,15 +498,30 @@ proc show_status {db cls} {
|
||||
}
|
||||
}
|
||||
if {$S(failed)>0} {
|
||||
puts "Failures: "
|
||||
# $toshow is the number of failures to report. In $cls mode,
|
||||
# status tries to limit the number of failure reported so that
|
||||
# the status display does not overflow a 24-line terminal. It will
|
||||
# always show at least the most recent 4 failures, even if an overflow
|
||||
# is needed. No limit is imposed for a status within $cls.
|
||||
#
|
||||
if {$cls && $S(failed)>18-$S(running)} {
|
||||
set toshow [expr {18-$S(running)}]
|
||||
if {$toshow<4} {set toshow 4}
|
||||
set shown " (must recent $toshow shown)"
|
||||
} else {
|
||||
set toshow $S(failed)
|
||||
set shown ""
|
||||
}
|
||||
puts [format %-79s "Failed: $S(failed) $shown"]
|
||||
$db eval {
|
||||
SELECT * FROM jobs WHERE state='failed' ORDER BY starttime
|
||||
SELECT * FROM jobs WHERE state='failed'
|
||||
ORDER BY endtime DESC LIMIT $toshow
|
||||
} job {
|
||||
display_job [array get job]
|
||||
}
|
||||
set nOmit [$db one {SELECT count(*) FROM jobs WHERE state='omit'}]
|
||||
if {$nOmit} {
|
||||
puts "$nOmit jobs omitted due to failures$clreol"
|
||||
puts [format %-79s " ... $nOmit jobs omitted due to failures"]
|
||||
}
|
||||
}
|
||||
if {$cls} {
|
||||
@@ -557,15 +608,21 @@ proc aggregate_test_counts {db} {
|
||||
#--------------------------------------------------------------------------
|
||||
# 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 match err* [lindex $argv 0]]==1)
|
||||
} {
|
||||
set verbose 0
|
||||
set pattern {}
|
||||
set summary 0
|
||||
for {set ii 1} {$ii<[llength $argv]} {incr ii} {
|
||||
set a0 [lindex $argv $ii]
|
||||
if {$a0=="-v" || $a0=="--verbose" || $a0=="-verbose"} {
|
||||
set verbose 1
|
||||
} elseif {$a0=="-s" || $a0=="--summary" || $a0=="-summary"} {
|
||||
set summary 1
|
||||
} elseif {$pattern==""} {
|
||||
set pattern *[string trim $a0 *]*
|
||||
} else {
|
||||
puts "unknown option: \"$a0\"". Use --help for more info."
|
||||
exit 1
|
||||
@@ -573,9 +630,22 @@ if {[llength $argv]>=1 && [llength $argv]<=2
|
||||
}
|
||||
set cnt 0
|
||||
sqlite3 mydb $TRG(dbname)
|
||||
mydb timeout 2000
|
||||
mydb eval {SELECT displaytype, displayname, output
|
||||
FROM jobs WHERE state='failed'} {
|
||||
mydb timeout 5000
|
||||
if {$summary} {
|
||||
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 ****"
|
||||
if {$verbose || $displaytype!="tcl"} {
|
||||
puts $output
|
||||
@@ -588,9 +658,13 @@ if {[llength $argv]>=1 && [llength $argv]<=2
|
||||
}
|
||||
incr cnt
|
||||
}
|
||||
set summary [aggregate_test_counts mydb]
|
||||
mydb close
|
||||
puts "Total [lindex $summary 0] errors out of [lindex $summary 1] tests"
|
||||
if {$pattern==""} {
|
||||
set summary [aggregate_test_counts mydb]
|
||||
mydb close
|
||||
puts "Total [lindex $summary 0] errors out of [lindex $summary 1] tests"
|
||||
} else {
|
||||
mydb close
|
||||
}
|
||||
exit
|
||||
}
|
||||
|
||||
@@ -842,7 +916,18 @@ proc add_tcl_jobs {build config patternlist {shelldepid ""}} {
|
||||
if {[llength $patternlist]>0} {
|
||||
set bMatch 0
|
||||
foreach p $patternlist {
|
||||
if {[string match $p [file tail $f]]} {
|
||||
set p [string trim $p *]
|
||||
if {[string index $p 0]=="^"} {
|
||||
set p [string range $p 1 end]
|
||||
} else {
|
||||
set p "*$p"
|
||||
}
|
||||
if {[string index $p end]=="\$"} {
|
||||
set p [string range $p 0 end-1]
|
||||
} else {
|
||||
set p "$p*"
|
||||
}
|
||||
if {[string match $p "$config [file tail $f]"]} {
|
||||
set bMatch 1
|
||||
break
|
||||
}
|
||||
@@ -1068,7 +1153,7 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
if {[regexp "\\y$b\\y" $TRG(omitconfig)]} continue
|
||||
set bld [add_build_job $b $TRG(testfixture)]
|
||||
foreach c [trd_configs $TRG(platform) $b] {
|
||||
add_tcl_jobs $bld $c $patternlist
|
||||
add_tcl_jobs $bld $c $patternlist SHELL
|
||||
}
|
||||
|
||||
if {$patternlist==""} {
|
||||
@@ -1080,6 +1165,15 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {[trdb one "SELECT EXISTS(SELECT 1
|
||||
FROM jobs WHERE depid='SHELL')"]} {
|
||||
set sbld [add_shell_build_job $b [lindex $bld 1] [lindex $bld 0]]
|
||||
set sbldid [lindex $sbld 0]
|
||||
trdb eval {
|
||||
UPDATE jobs SET depid=$sbldid WHERE depid='SHELL'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,15 +1214,25 @@ proc make_new_testset {} {
|
||||
}
|
||||
|
||||
proc mark_job_as_finished {jobid output state endtm} {
|
||||
set ntest 1
|
||||
set nerr 0
|
||||
if {$endtm>0} {
|
||||
if {[regexp {\y(\d+) errors out of (\d+) tests} $output all a b]} {
|
||||
set nerr $a
|
||||
set ntest $b
|
||||
}
|
||||
}
|
||||
r_write_db {
|
||||
if {$state=="failed"} {
|
||||
set childstate omit
|
||||
if {$nerr<=0} {set nerr 1}
|
||||
} else {
|
||||
set childstate ready
|
||||
}
|
||||
trdb eval {
|
||||
UPDATE jobs
|
||||
SET output=$output, state=$state, endtime=$endtm
|
||||
SET output=$output, state=$state, endtime=$endtm,
|
||||
ntest=$ntest, nerr=$nerr
|
||||
WHERE jobid=$jobid;
|
||||
UPDATE jobs SET state=$childstate WHERE depid=$jobid;
|
||||
}
|
||||
@@ -1371,6 +1475,17 @@ proc run_testset {} {
|
||||
|
||||
puts "\nTest database is $TRG(dbname)"
|
||||
puts "Test log is $TRG(logname)"
|
||||
trdb eval {
|
||||
SELECT sum(ntest) AS totaltest,
|
||||
sum(nerr) AS totalerr
|
||||
FROM jobs
|
||||
} break
|
||||
trdb eval {
|
||||
SELECT max(endtime)-min(starttime) AS totaltime
|
||||
FROM jobs WHERE endtime>0
|
||||
} break;
|
||||
set et [elapsetime $totaltime]
|
||||
puts "$totalerr errors out of $totaltest tests in about $et"
|
||||
}
|
||||
|
||||
# Handle the --buildonly option, if it was specified.
|
||||
@@ -1401,7 +1516,14 @@ proc explain_layer {indent depid} {
|
||||
puts "${indent}$displayname in $dirname"
|
||||
explain_layer "${indent} " $jobid
|
||||
} elseif {$showtests} {
|
||||
puts "${indent}[lindex $displayname end]"
|
||||
set tail [lindex $displayname end]
|
||||
set e1 [lindex $displayname 1]
|
||||
if {[string match config=* $e1]} {
|
||||
set cfg [string range $e1 7 end]
|
||||
puts "${indent}($cfg) $tail"
|
||||
} else {
|
||||
puts "${indent}$tail"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1416,7 +1538,7 @@ if {$TRG(explain)} {
|
||||
explain_tests
|
||||
} else {
|
||||
if {$TRG(nJob)>1} {
|
||||
puts "splitting work across $TRG(nJob) jobs"
|
||||
puts "splitting work across $TRG(nJob) cores"
|
||||
}
|
||||
puts "built testset in [expr $tm/1000]ms.."
|
||||
handle_buildonly
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace eval trd {
|
||||
set tcltest(linux.Have-Not) veryquick
|
||||
set tcltest(linux.Secure-Delete) veryquick
|
||||
set tcltest(linux.Unlock-Notify) veryquick
|
||||
set tcltest(linux.User-Auth) veryquick
|
||||
set tcltest(linux.Update-Delete-Limit) veryquick
|
||||
set tcltest(linux.Extra-Robustness) veryquick
|
||||
set tcltest(linux.Device-Two) veryquick
|
||||
@@ -89,6 +88,8 @@ namespace eval trd {
|
||||
--disable-amalgamation --disable-shared
|
||||
--enable-session
|
||||
-DSQLITE_ENABLE_RBU
|
||||
-DSQLITE_ENABLE_STMT_SCANSTATUS
|
||||
-DSQLITE_USE_ONLY_WIN32=1
|
||||
}
|
||||
|
||||
# These two are used by [testrunner.tcl mdevtest] (All-O0) and
|
||||
@@ -96,6 +97,7 @@ namespace eval trd {
|
||||
#
|
||||
set build(All-Debug) {
|
||||
--enable-debug --enable-all
|
||||
-DSQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
}
|
||||
set build(All-O0) {
|
||||
-O0 --enable-all
|
||||
@@ -139,10 +141,6 @@ namespace eval trd {
|
||||
-DSQLITE_THREADSAFE
|
||||
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
|
||||
}
|
||||
set build(User-Auth) {
|
||||
-O2
|
||||
-DSQLITE_USER_AUTHENTICATION=1
|
||||
}
|
||||
set build(Secure-Delete) {
|
||||
-O2
|
||||
-DSQLITE_SECURE_DELETE=1
|
||||
|
||||
@@ -73,6 +73,38 @@ do_catchsql_test 2.2 {
|
||||
WINDOW w1 AS (PARTITION BY x OVER w1);
|
||||
} {1 {near "OVER": syntax error}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE t2(c1 INT, c2 REAL);
|
||||
INSERT INTO t2 VALUES
|
||||
(447,0.0), (448,0.0), (449,0.0), (452,0.0), (453,0.0), (454,0.0), (455,0.0),
|
||||
(456,0.0), (459,0.0), (460,0.0), (462,0.0), (463,0.0), (466,0.0), (467,0.0),
|
||||
(468,0.0), (469,0.0), (470,0.0), (473,0.0), (474,0.0), (475,0.0), (476,0.0),
|
||||
(477,0.0), (480,0.0), (481,0.0), (482,0.0), (483,0.0), (484,0.0), (487,0.0),
|
||||
(488,0.0), (489,0.0), (490,0.0), (491,0.0), (494,0.0), (495,0.0), (496,0.0),
|
||||
(497,0.0), (498,0.0), (501,0.0), (502,0.0), (503,0.0), (504,0.0), (505,0.0),
|
||||
(508,0.0), (509,0.0), (510,0.0), (511,0.0), (512,0.0), (515,0.0), (516,0.0),
|
||||
(517,0.0), (518,0.0), (519,0.0), (522,0.0), (523,0.0), (524,0.0), (525,0.0),
|
||||
(526,0.0), (529,0.0), (530,0.0), (531,0.0), (532,0.0), (533,0.0), (536,0.0),
|
||||
(537,1.0), (538,0.0), (539,0.0), (540,0.0), (543,0.0), (544,0.0);
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
select c1, max(c2) over (order by c1 range 366.0 preceding) from t2;
|
||||
} {
|
||||
447 0.0 448 0.0 449 0.0 452 0.0 453 0.0 454 0.0 455 0.0 456 0.0 459 0.0
|
||||
460 0.0 462 0.0 463 0.0 466 0.0 467 0.0 468 0.0 469 0.0 470 0.0 473 0.0
|
||||
474 0.0 475 0.0 476 0.0 477 0.0 480 0.0 481 0.0 482 0.0 483 0.0 484 0.0
|
||||
487 0.0 488 0.0 489 0.0 490 0.0 491 0.0 494 0.0 495 0.0 496 0.0 497 0.0
|
||||
498 0.0 501 0.0 502 0.0 503 0.0 504 0.0 505 0.0 508 0.0 509 0.0 510 0.0
|
||||
511 0.0 512 0.0 515 0.0 516 0.0 517 0.0 518 0.0 519 0.0 522 0.0 523 0.0
|
||||
524 0.0 525 0.0 526 0.0 529 0.0 530 0.0 531 0.0 532 0.0 533 0.0 536 0.0
|
||||
537 1.0 538 1.0 539 1.0 540 1.0 543 1.0 544 1.0
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ set boolean_defnil_options {
|
||||
SQLITE_ENABLE_MULTIPLEX
|
||||
SQLITE_ENABLE_NORMALIZE
|
||||
SQLITE_ENABLE_NULL_TRIM
|
||||
SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
@@ -448,6 +449,7 @@ if {[catch {set cfd [open $destfile w]}]!=0} {
|
||||
puts stderr "File '$destfile' unwritable."
|
||||
exit 1;
|
||||
}
|
||||
fconfigure $cfd -translation binary
|
||||
|
||||
puts $cfd $::headWarning;
|
||||
puts $cfd $::headCode;
|
||||
|
||||
@@ -164,10 +164,10 @@ struct Keyword {
|
||||
#else
|
||||
# define RETURNING 0x00400000
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_FROM_FIRST
|
||||
# define PIPE 0
|
||||
#ifndef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
# define ORDERSET 0
|
||||
#else
|
||||
# define PIPE 0x00800000
|
||||
# define ORDERSET 0x00800000
|
||||
#endif
|
||||
|
||||
|
||||
@@ -179,7 +179,6 @@ static Keyword aKeywordTable[] = {
|
||||
{ "ACTION", "TK_ACTION", FKEY, 0 },
|
||||
{ "ADD", "TK_ADD", ALTER, 1 },
|
||||
{ "AFTER", "TK_AFTER", TRIGGER, 0 },
|
||||
{ "AGGREGATE", "TK_AGGREGATE", PIPE, 10 },
|
||||
{ "ALL", "TK_ALL", ALWAYS, 0 },
|
||||
{ "ALTER", "TK_ALTER", ALTER, 0 },
|
||||
{ "ALWAYS", "TK_ALWAYS", GENCOL, 0 },
|
||||
@@ -322,6 +321,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "WHERE", "TK_WHERE", ALWAYS, 10 },
|
||||
{ "WINDOW", "TK_WINDOW", WINDOWFUNC, 3 },
|
||||
{ "WITH", "TK_WITH", CTE, 4 },
|
||||
{ "WITHIN", "TK_WITHIN", ORDERSET, 1 },
|
||||
{ "WITHOUT", "TK_WITHOUT", ALWAYS, 1 },
|
||||
};
|
||||
|
||||
|
||||
+201
-351
@@ -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.
|
||||
#
|
||||
set ::USAGE_MESSAGE {
|
||||
This Tcl script is used to test the various compile time options
|
||||
available for omitting code (the SQLITE_OMIT_xxx options). It
|
||||
should be invoked as follows:
|
||||
available for building SQLite, especially options taht omit
|
||||
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.
|
||||
}
|
||||
|
||||
|
||||
# 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:
|
||||
# List of all options to be tested.
|
||||
#
|
||||
# run_quick_test /tmp/testdir {SQLITE_OMIT_TRIGGER SQLITE_OMIT_VIEW}
|
||||
#
|
||||
#
|
||||
proc run_quick_test {dir omit_symbol_list} {
|
||||
# Compile the value of the OPTS Makefile variable.
|
||||
set opts ""
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
append opts "OPTS += -DSQLITE_OS_WIN=1\n"
|
||||
set target "testfixture.exe"
|
||||
} else {
|
||||
append opts "OPTS += -DSQLITE_OS_UNIX=1\n"
|
||||
}
|
||||
foreach sym $omit_symbol_list {
|
||||
append opts "OPTS += -D${sym}=1\n"
|
||||
}
|
||||
set CompileOptionsToTest {
|
||||
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
|
||||
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
|
||||
# early without attempting to run the test suite.
|
||||
file mkdir $dir
|
||||
puts -nonewline "Building $dir..."
|
||||
flush stdout
|
||||
catch {
|
||||
file copy -force ./config.h $dir
|
||||
file copy -force ./libtool $dir
|
||||
}
|
||||
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
|
||||
# Parse command-line options.
|
||||
#
|
||||
for {set i 0} {$i<[llength $argv]} {incr i} {
|
||||
set arg [lindex $argv $i]
|
||||
switch -- $arg {
|
||||
-start -
|
||||
--start {
|
||||
incr i
|
||||
set startat [lindex $argv $i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {$::SKIP_RUN} {
|
||||
# puts "Skip testing $dir."
|
||||
} else {
|
||||
# Run the test suite.
|
||||
puts -nonewline "Testing $dir..."
|
||||
flush stdout
|
||||
set rc [catch {
|
||||
exec $::MAKEBIN -C $dir -f makefile test >& $dir/test.log
|
||||
}]
|
||||
if {$rc} {
|
||||
puts "No good. See $dir/test.log."
|
||||
# Additional options required for some settings.
|
||||
#
|
||||
set More(SQLITE_OMIT_DISKIO) {-DSQLITE_OMIT_WAL}
|
||||
|
||||
# Compile-time options for Mac only
|
||||
#
|
||||
set MacOnly(SQLITE_ENABLE_LOCKING_STYLE) 1
|
||||
|
||||
# Compile-time options that might fail, depending on what libraries
|
||||
# are installed. Failures on these tests issue a warning, but testing
|
||||
# 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 {
|
||||
puts "Ok"
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# This proc processes the command line options passed to this script.
|
||||
# Currently the only option supported is "-makefile", default
|
||||
# "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this
|
||||
# option.
|
||||
#
|
||||
proc process_options {argv} {
|
||||
set ::MAKEBIN make ;# Default value
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
set ::MAKEFILE ./Makefile ;# Default value on Windows
|
||||
if {[info exists MacOnly($sym)] && $tcl_platform(os)!="Darwin"} {
|
||||
continue
|
||||
}
|
||||
set logfile "omittest/$sym.log"
|
||||
if {[info exists More($sym)]} {
|
||||
append opts "OPT_FEATURE_FLAGS=-D$sym $More($sym)"
|
||||
} else {
|
||||
set ::MAKEFILE ./Makefile.linux-gcc ;# Default value
|
||||
set opts OPT_FEATURE_FLAGS=-D$sym
|
||||
}
|
||||
set ::SKIP_RUN 1 ;# Default to attempt test
|
||||
set ::TARGET testfixture ;# Default thing to build
|
||||
|
||||
for {set i 0} {$i < [llength $argv]} {incr i} {
|
||||
switch -regexp -- [lindex $argv $i] {
|
||||
-{1,2}makefile {
|
||||
incr i
|
||||
set ::MAKEFILE [lindex $argv $i]
|
||||
}
|
||||
|
||||
-{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
|
||||
puts "make tidy sqlite3.lo $opts"
|
||||
if {[catch {exec make tidy sqlite3.lo $opts >& $logfile}]} {
|
||||
puts "BUILD FAILED: see $logfile for details"
|
||||
if {[info exists FailIsOk($sym)]} {
|
||||
set Failure($sym) 1
|
||||
} else {
|
||||
puts "Note: After fixes, continue the test using:\n"
|
||||
puts " [info nameofexe] $argv0 --start $sym\n"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main $argv
|
||||
if {[llength [array names Failure]]>0} {
|
||||
puts "BUILD FAILED on the following:"
|
||||
foreach sym [array names Failure] {
|
||||
puts " * $sym"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user