mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Merge recent trunk enhancements and fixes.
FossilOrigin-Name: c39cb0e2571f58c87053de009e2c135d71b2c3af
This commit is contained in:
50
Makefile.in
50
Makefile.in
@ -184,10 +184,11 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
|||||||
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||||
random.lo resolve.lo rowset.lo rtree.lo \
|
random.lo resolve.lo rowset.lo rtree.lo \
|
||||||
sqlite3session.lo select.lo status.lo \
|
sqlite3session.lo select.lo status.lo \
|
||||||
table.lo threads.lo tokenize.lo trigger.lo \
|
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
|
||||||
update.lo util.lo vacuum.lo \
|
update.lo util.lo vacuum.lo \
|
||||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||||
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
|
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
|
||||||
|
utf.lo vtab.lo
|
||||||
|
|
||||||
# Object files for the amalgamation.
|
# Object files for the amalgamation.
|
||||||
#
|
#
|
||||||
@ -276,6 +277,7 @@ SRC = \
|
|||||||
$(TOP)/src/threads.c \
|
$(TOP)/src/threads.c \
|
||||||
$(TOP)/src/tclsqlite.c \
|
$(TOP)/src/tclsqlite.c \
|
||||||
$(TOP)/src/tokenize.c \
|
$(TOP)/src/tokenize.c \
|
||||||
|
$(TOP)/src/treeview.c \
|
||||||
$(TOP)/src/trigger.c \
|
$(TOP)/src/trigger.c \
|
||||||
$(TOP)/src/utf.c \
|
$(TOP)/src/utf.c \
|
||||||
$(TOP)/src/update.c \
|
$(TOP)/src/update.c \
|
||||||
@ -296,6 +298,8 @@ SRC = \
|
|||||||
$(TOP)/src/wal.h \
|
$(TOP)/src/wal.h \
|
||||||
$(TOP)/src/walker.c \
|
$(TOP)/src/walker.c \
|
||||||
$(TOP)/src/where.c \
|
$(TOP)/src/where.c \
|
||||||
|
$(TOP)/src/wherecode.c \
|
||||||
|
$(TOP)/src/whereexpr.c \
|
||||||
$(TOP)/src/whereInt.h
|
$(TOP)/src/whereInt.h
|
||||||
|
|
||||||
# Source code for extensions
|
# Source code for extensions
|
||||||
@ -460,6 +464,8 @@ TESTSRC2 = \
|
|||||||
$(TOP)/src/vdbemem.c \
|
$(TOP)/src/vdbemem.c \
|
||||||
$(TOP)/src/vdbetrace.c \
|
$(TOP)/src/vdbetrace.c \
|
||||||
$(TOP)/src/where.c \
|
$(TOP)/src/where.c \
|
||||||
|
$(TOP)/src/wherecode.c \
|
||||||
|
$(TOP)/src/whereexpr.c \
|
||||||
parse.c \
|
parse.c \
|
||||||
$(TOP)/ext/fts3/fts3.c \
|
$(TOP)/ext/fts3/fts3.c \
|
||||||
$(TOP)/ext/fts3/fts3_aux.c \
|
$(TOP)/ext/fts3/fts3_aux.c \
|
||||||
@ -536,6 +542,10 @@ FUZZDATA = \
|
|||||||
$(TOP)/test/fuzzdata2.db \
|
$(TOP)/test/fuzzdata2.db \
|
||||||
$(TOP)/test/fuzzdata3.db
|
$(TOP)/test/fuzzdata3.db
|
||||||
|
|
||||||
|
# Standard options to testfixture
|
||||||
|
#
|
||||||
|
TESTOPTS = --verbose=file --output=test-out.txt
|
||||||
|
|
||||||
# This is the default Makefile target. The objects listed here
|
# This is the default Makefile target. The objects listed here
|
||||||
# are what get build when you type just "make" with no arguments.
|
# are what get build when you type just "make" with no arguments.
|
||||||
#
|
#
|
||||||
@ -809,6 +819,9 @@ threads.lo: $(TOP)/src/threads.c $(HDR)
|
|||||||
tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR)
|
tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR)
|
||||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/tokenize.c
|
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/tokenize.c
|
||||||
|
|
||||||
|
treeview.lo: $(TOP)/src/treeview.c $(HDR)
|
||||||
|
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/treeview.c
|
||||||
|
|
||||||
trigger.lo: $(TOP)/src/trigger.c $(HDR)
|
trigger.lo: $(TOP)/src/trigger.c $(HDR)
|
||||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/trigger.c
|
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/trigger.c
|
||||||
|
|
||||||
@ -857,6 +870,12 @@ walker.lo: $(TOP)/src/walker.c $(HDR)
|
|||||||
where.lo: $(TOP)/src/where.c $(HDR)
|
where.lo: $(TOP)/src/where.c $(HDR)
|
||||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/where.c
|
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/where.c
|
||||||
|
|
||||||
|
wherecode.lo: $(TOP)/src/wherecode.c $(HDR)
|
||||||
|
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/wherecode.c
|
||||||
|
|
||||||
|
whereexpr.lo: $(TOP)/src/whereexpr.c $(HDR)
|
||||||
|
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/whereexpr.c
|
||||||
|
|
||||||
tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR)
|
tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR)
|
||||||
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c
|
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c
|
||||||
|
|
||||||
@ -989,39 +1008,46 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC)
|
|||||||
|
|
||||||
# A very detailed test running most or all test cases
|
# A very detailed test running most or all test cases
|
||||||
fulltest: $(TESTPROGS) fuzztest
|
fulltest: $(TESTPROGS) fuzztest
|
||||||
./testfixture$(TEXE) $(TOP)/test/all.test
|
./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS)
|
||||||
|
|
||||||
# Really really long testing
|
# Really really long testing
|
||||||
soaktest: $(TESTPROGS)
|
soaktest: $(TESTPROGS)
|
||||||
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1
|
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)
|
||||||
|
|
||||||
# Do extra testing but not everything.
|
# Do extra testing but not everything.
|
||||||
fulltestonly: $(TESTPROGS)
|
fulltestonly: $(TESTPROGS)
|
||||||
./testfixture$(TEXE) $(TOP)/test/full.test
|
./testfixture$(TEXE) $(TOP)/test/full.test
|
||||||
|
|
||||||
# Fuzz testing
|
# Fuzz testing
|
||||||
fuzztest: fuzzcheck$(TEXE)
|
fuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
|
||||||
./fuzzcheck$(TEXE) $(FUZZDATA)
|
./fuzzcheck$(TEXE) $(FUZZDATA)
|
||||||
|
|
||||||
# This is the common case. Run many tests but not those that take
|
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA)
|
||||||
# a really long time.
|
valgrind ./fuzzcheck$(TEXE) --cell-size-check --quiet $(FUZZDATA)
|
||||||
|
|
||||||
|
# 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.
|
||||||
#
|
#
|
||||||
test: $(TESTPROGS) fuzztest
|
test: $(TESTPROGS) fuzztest
|
||||||
./testfixture$(TEXE) $(TOP)/test/veryquick.test
|
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
|
||||||
|
|
||||||
# Run a test using valgrind. This can take a really long time
|
# Run a test using valgrind. This can take a really long time
|
||||||
# because valgrind is so much slower than a native machine.
|
# because valgrind is so much slower than a native machine.
|
||||||
#
|
#
|
||||||
valgrindtest: $(TESTPROGS) fuzzcheck$(TEXE)
|
valgrindtest: $(TESTPROGS) valgrindfuzz
|
||||||
valgrind -v ./fuzzcheck$(TEXE) --cell-size-check --quiet $(FUZZDATA)
|
OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)
|
||||||
OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind
|
|
||||||
|
|
||||||
# A very fast test that checks basic sanity. The name comes from
|
# A very fast test that checks basic sanity. The name comes from
|
||||||
# the 60s-era electronics testing: "Turn it on and see if smoke
|
# the 60s-era electronics testing: "Turn it on and see if smoke
|
||||||
# comes out."
|
# comes out."
|
||||||
#
|
#
|
||||||
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
|
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
|
||||||
./testfixture$(TEXE) $(TOP)/test/main.test
|
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
|
||||||
|
|
||||||
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
|
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
|
||||||
echo "#define TCLSH 2" > $@
|
echo "#define TCLSH 2" > $@
|
||||||
|
42
Makefile.msc
42
Makefile.msc
@ -846,10 +846,11 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
|
|||||||
pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
|
||||||
random.lo resolve.lo rowset.lo rtree.lo \
|
random.lo resolve.lo rowset.lo rtree.lo \
|
||||||
sqlite3session.lo select.lo status.lo \
|
sqlite3session.lo select.lo status.lo \
|
||||||
table.lo threads.lo tokenize.lo trigger.lo \
|
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
|
||||||
update.lo util.lo vacuum.lo \
|
update.lo util.lo vacuum.lo \
|
||||||
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||||
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
|
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
|
||||||
|
utf.lo vtab.lo
|
||||||
|
|
||||||
# Object files for the amalgamation.
|
# Object files for the amalgamation.
|
||||||
#
|
#
|
||||||
@ -950,6 +951,7 @@ SRC2 = \
|
|||||||
$(TOP)\src\threads.c \
|
$(TOP)\src\threads.c \
|
||||||
$(TOP)\src\tclsqlite.c \
|
$(TOP)\src\tclsqlite.c \
|
||||||
$(TOP)\src\tokenize.c \
|
$(TOP)\src\tokenize.c \
|
||||||
|
$(TOP)\src\treeview.c \
|
||||||
$(TOP)\src\trigger.c \
|
$(TOP)\src\trigger.c \
|
||||||
$(TOP)\src\utf.c \
|
$(TOP)\src\utf.c \
|
||||||
$(TOP)\src\update.c \
|
$(TOP)\src\update.c \
|
||||||
@ -970,6 +972,8 @@ SRC2 = \
|
|||||||
$(TOP)\src\wal.h \
|
$(TOP)\src\wal.h \
|
||||||
$(TOP)\src\walker.c \
|
$(TOP)\src\walker.c \
|
||||||
$(TOP)\src\where.c \
|
$(TOP)\src\where.c \
|
||||||
|
$(TOP)\src\wherecode.c \
|
||||||
|
$(TOP)\src\whereexpr.c \
|
||||||
$(TOP)\src\whereInt.h
|
$(TOP)\src\whereInt.h
|
||||||
|
|
||||||
# Source code for extensions
|
# Source code for extensions
|
||||||
@ -1136,6 +1140,8 @@ TESTSRC2 = \
|
|||||||
$(TOP)\src\vdbesort.c \
|
$(TOP)\src\vdbesort.c \
|
||||||
$(TOP)\src\vdbetrace.c \
|
$(TOP)\src\vdbetrace.c \
|
||||||
$(TOP)\src\where.c \
|
$(TOP)\src\where.c \
|
||||||
|
$(TOP)\src\wherecode.c \
|
||||||
|
$(TOP)\src\whereexpr.c \
|
||||||
parse.c \
|
parse.c \
|
||||||
$(TOP)\ext\fts3\fts3.c \
|
$(TOP)\ext\fts3\fts3.c \
|
||||||
$(TOP)\ext\fts3\fts3_aux.c \
|
$(TOP)\ext\fts3\fts3_aux.c \
|
||||||
@ -1221,6 +1227,9 @@ FUZZDATA = \
|
|||||||
$(TOP)\test\fuzzdata2.db \
|
$(TOP)\test\fuzzdata2.db \
|
||||||
$(TOP)\test\fuzzdata3.db
|
$(TOP)\test\fuzzdata3.db
|
||||||
|
|
||||||
|
# Standard options to testfixture
|
||||||
|
#
|
||||||
|
TESTOPTS = --verbose=file --output=test-out.txt
|
||||||
|
|
||||||
# This is the default Makefile target. The objects listed here
|
# This is the default Makefile target. The objects listed here
|
||||||
# are what get build when you type just "make" with no arguments.
|
# are what get build when you type just "make" with no arguments.
|
||||||
@ -1507,6 +1516,9 @@ threads.lo: $(TOP)\src\threads.c $(HDR)
|
|||||||
tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR)
|
tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR)
|
||||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\tokenize.c
|
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\tokenize.c
|
||||||
|
|
||||||
|
treeview.lo: $(TOP)\src\treeview.c $(HDR)
|
||||||
|
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\treeview.c
|
||||||
|
|
||||||
trigger.lo: $(TOP)\src\trigger.c $(HDR)
|
trigger.lo: $(TOP)\src\trigger.c $(HDR)
|
||||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c
|
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c
|
||||||
|
|
||||||
@ -1555,6 +1567,12 @@ walker.lo: $(TOP)\src\walker.c $(HDR)
|
|||||||
where.lo: $(TOP)\src\where.c $(HDR)
|
where.lo: $(TOP)\src\where.c $(HDR)
|
||||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\where.c
|
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\where.c
|
||||||
|
|
||||||
|
wherecode.lo: $(TOP)\src\wherecode.c $(HDR)
|
||||||
|
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wherecode.c
|
||||||
|
|
||||||
|
whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR)
|
||||||
|
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c
|
||||||
|
|
||||||
tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
|
tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
|
||||||
$(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
|
$(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
|
||||||
|
|
||||||
@ -1690,28 +1708,36 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR)
|
|||||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||||
|
|
||||||
extensiontest: testfixture.exe testloadext.dll
|
extensiontest: testfixture.exe testloadext.dll
|
||||||
.\testfixture.exe $(TOP)\test\loadext.test
|
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
|
||||||
|
|
||||||
fulltest: $(TESTPROGS) fuzztest
|
fulltest: $(TESTPROGS) fuzztest
|
||||||
.\testfixture.exe $(TOP)\test\all.test
|
.\testfixture.exe $(TOP)\test\all.test $(TESTOPTS)
|
||||||
|
|
||||||
soaktest: $(TESTPROGS)
|
soaktest: $(TESTPROGS)
|
||||||
.\testfixture.exe $(TOP)\test\all.test -soak=1
|
.\testfixture.exe $(TOP)\test\all.test -soak=1 $(TESTOPTS)
|
||||||
|
|
||||||
fulltestonly: $(TESTPROGS) fuzztest
|
fulltestonly: $(TESTPROGS) fuzztest
|
||||||
.\testfixture.exe $(TOP)\test\full.test
|
.\testfixture.exe $(TOP)\test\full.test
|
||||||
|
|
||||||
queryplantest: testfixture.exe sqlite3.exe
|
queryplantest: testfixture.exe sqlite3.exe
|
||||||
.\testfixture.exe $(TOP)\test\permutations.test queryplanner
|
.\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS)
|
||||||
|
|
||||||
fuzztest: fuzzcheck.exe
|
fuzztest: fuzzcheck.exe
|
||||||
.\fuzzcheck.exe $(FUZZDATA)
|
.\fuzzcheck.exe $(FUZZDATA)
|
||||||
|
|
||||||
|
# Minimal testing that runs in less than 3 minutes (on a fast machine)
|
||||||
|
#
|
||||||
|
quicktest: testfixture.exe
|
||||||
|
.\testfixture.exe $(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.
|
||||||
|
#
|
||||||
test: $(TESTPROGS) fuzztest
|
test: $(TESTPROGS) fuzztest
|
||||||
.\testfixture.exe $(TOP)\test\veryquick.test
|
.\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)
|
||||||
|
|
||||||
smoketest: $(TESTPROGS)
|
smoketest: $(TESTPROGS)
|
||||||
.\testfixture.exe $(TOP)\test\main.test
|
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
|
||||||
|
|
||||||
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
|
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
|
||||||
echo #define TCLSH 2 > $@
|
echo #define TCLSH 2 > $@
|
||||||
|
15
README.md
15
README.md
@ -178,7 +178,7 @@ complex code. So there is a lot of complexity in the SQLite implementation.
|
|||||||
|
|
||||||
Key files:
|
Key files:
|
||||||
|
|
||||||
* **sqlite3.h** - This file defines the public interface to the SQLite
|
* **sqlite.h.in** - This file defines the public interface to the SQLite
|
||||||
library. Readers will need to be familiar with this interface before
|
library. Readers will need to be familiar with this interface before
|
||||||
trying to understand how the library works internally.
|
trying to understand how the library works internally.
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ Key files:
|
|||||||
used internally by SQLite.
|
used internally by SQLite.
|
||||||
|
|
||||||
* **parse.y** - This file describes the LALR(1) grammer that SQLite uses
|
* **parse.y** - This file describes the LALR(1) grammer that SQLite uses
|
||||||
to parse SQL statements, and the actions that are taken at each stop
|
to parse SQL statements, and the actions that are taken at each step
|
||||||
in the parsing process.
|
in the parsing process.
|
||||||
|
|
||||||
* **vdbe.c** - This file implements the virtual machine that runs
|
* **vdbe.c** - This file implements the virtual machine that runs
|
||||||
@ -210,6 +210,17 @@ Key files:
|
|||||||
between SQLite and the underlying operating system using the run-time
|
between SQLite and the underlying operating system using the run-time
|
||||||
pluggable VFS interface.
|
pluggable VFS interface.
|
||||||
|
|
||||||
|
* **shell.c** - This file is not part of the core SQLite library. This
|
||||||
|
is the file that, when linked against sqlite3.a, generates the
|
||||||
|
"sqlite3.exe" command-line shell.
|
||||||
|
|
||||||
|
* **tclsqlite.c** - This file implements the Tcl bindings for SQLite. It
|
||||||
|
is not part of the core SQLite library. But as most of the tests in this
|
||||||
|
repository are written in Tcl, the Tcl language bindings are important.
|
||||||
|
|
||||||
|
There are many other source files. Each has a suscinct header comment that
|
||||||
|
describes its purpose and role within the larger system.
|
||||||
|
|
||||||
|
|
||||||
## Contacts
|
## Contacts
|
||||||
|
|
||||||
|
14
configure
vendored
14
configure
vendored
@ -10715,6 +10715,20 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# On ubuntu 14.10, $auto_path on tclsh is not quite correct.
|
||||||
|
# So try again after applying corrections.
|
||||||
|
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||||
|
if test x"$cross_compiling" = xno; then
|
||||||
|
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD} | sed 's,/tcltk/tcl,/tcl,g'`
|
||||||
|
do
|
||||||
|
if test -f "$i/tclConfig.sh" ; then
|
||||||
|
ac_cv_c_tclconfig="$i"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# then check for a private Tcl installation
|
# then check for a private Tcl installation
|
||||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||||
for i in \
|
for i in \
|
||||||
|
14
configure.ac
14
configure.ac
@ -320,6 +320,20 @@ if test "${use_tcl}" = "yes" ; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# On ubuntu 14.10, $auto_path on tclsh is not quite correct.
|
||||||
|
# So try again after applying corrections.
|
||||||
|
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||||
|
if test x"$cross_compiling" = xno; then
|
||||||
|
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD} | sed 's,/tcltk/tcl,/tcl,g'`
|
||||||
|
do
|
||||||
|
if test -f "$i/tclConfig.sh" ; then
|
||||||
|
ac_cv_c_tclconfig="$i"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# then check for a private Tcl installation
|
# then check for a private Tcl installation
|
||||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||||
for i in \
|
for i in \
|
||||||
|
@ -269,5 +269,88 @@ ifcapable rtree {
|
|||||||
db close
|
db close
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Test that queries featuring LEFT or CROSS JOINS are handled correctly.
|
||||||
|
# Handled correctly in this case means:
|
||||||
|
#
|
||||||
|
# * Terms with prereqs that appear to the left of a LEFT JOIN against
|
||||||
|
# the virtual table are always available to xBestIndex.
|
||||||
|
#
|
||||||
|
# * Terms with prereqs that appear to the right of a LEFT JOIN against
|
||||||
|
# the virtual table are never available to xBestIndex.
|
||||||
|
#
|
||||||
|
# And the same behaviour for CROSS joins.
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 7.0 {
|
||||||
|
CREATE TABLE xdir(x1);
|
||||||
|
CREATE TABLE ydir(y1);
|
||||||
|
CREATE VIRTUAL TABLE rt USING rtree_i32(id, xmin, xmax, ymin, ymax);
|
||||||
|
|
||||||
|
INSERT INTO xdir VALUES(5);
|
||||||
|
INSERT INTO ydir VALUES(10);
|
||||||
|
|
||||||
|
INSERT INTO rt VALUES(1, 2, 7, 12, 14); -- Not a hit
|
||||||
|
INSERT INTO rt VALUES(2, 2, 7, 8, 12); -- A hit!
|
||||||
|
INSERT INTO rt VALUES(3, 7, 11, 8, 12); -- Not a hit!
|
||||||
|
INSERT INTO rt VALUES(4, 5, 5, 10, 10); -- A hit!
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
proc do_eqp_execsql_test {tn sql res} {
|
||||||
|
set query "EXPLAIN QUERY PLAN $sql ; $sql "
|
||||||
|
uplevel [list do_execsql_test $tn $query $res]
|
||||||
|
}
|
||||||
|
|
||||||
|
do_eqp_execsql_test 7.1 {
|
||||||
|
SELECT id FROM xdir, rt, ydir
|
||||||
|
ON (y1 BETWEEN ymin AND ymax)
|
||||||
|
WHERE (x1 BETWEEN xmin AND xmax);
|
||||||
|
} {
|
||||||
|
0 0 0 {SCAN TABLE xdir}
|
||||||
|
0 1 2 {SCAN TABLE ydir}
|
||||||
|
0 2 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1}
|
||||||
|
2 4
|
||||||
|
}
|
||||||
|
|
||||||
|
do_eqp_execsql_test 7.2 {
|
||||||
|
SELECT * FROM xdir, rt LEFT JOIN ydir
|
||||||
|
ON (y1 BETWEEN ymin AND ymax)
|
||||||
|
WHERE (x1 BETWEEN xmin AND xmax);
|
||||||
|
} {
|
||||||
|
0 0 0 {SCAN TABLE xdir}
|
||||||
|
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
|
||||||
|
0 2 2 {SCAN TABLE ydir}
|
||||||
|
|
||||||
|
5 1 2 7 12 14 {}
|
||||||
|
5 2 2 7 8 12 10
|
||||||
|
5 4 5 5 10 10 10
|
||||||
|
}
|
||||||
|
|
||||||
|
do_eqp_execsql_test 7.3 {
|
||||||
|
SELECT id FROM xdir, rt CROSS JOIN ydir
|
||||||
|
ON (y1 BETWEEN ymin AND ymax)
|
||||||
|
WHERE (x1 BETWEEN xmin AND xmax);
|
||||||
|
} {
|
||||||
|
0 0 0 {SCAN TABLE xdir}
|
||||||
|
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
|
||||||
|
0 2 2 {SCAN TABLE ydir}
|
||||||
|
2 4
|
||||||
|
}
|
||||||
|
|
||||||
|
do_eqp_execsql_test 7.4 {
|
||||||
|
SELECT id FROM rt, xdir CROSS JOIN ydir
|
||||||
|
ON (y1 BETWEEN ymin AND ymax)
|
||||||
|
WHERE (x1 BETWEEN xmin AND xmax);
|
||||||
|
} {
|
||||||
|
0 0 1 {SCAN TABLE xdir}
|
||||||
|
0 1 0 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
|
||||||
|
0 2 2 {SCAN TABLE ydir}
|
||||||
|
2 4
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
44
main.mk
44
main.mk
@ -67,10 +67,11 @@ LIBOBJ+= vdbe.o parse.o \
|
|||||||
notify.o opcodes.o os.o os_unix.o os_win.o \
|
notify.o opcodes.o os.o os_unix.o os_win.o \
|
||||||
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
|
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
|
||||||
random.o resolve.o rowset.o rtree.o select.o sqlite3ota.o status.o \
|
random.o resolve.o rowset.o rtree.o select.o sqlite3ota.o status.o \
|
||||||
table.o threads.o tokenize.o trigger.o \
|
table.o threads.o tokenize.o treeview.o trigger.o \
|
||||||
update.o userauth.o util.o vacuum.o \
|
update.o userauth.o util.o vacuum.o \
|
||||||
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
|
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
|
||||||
vdbetrace.o wal.o walker.o where.o utf.o vtab.o
|
vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \
|
||||||
|
utf.o vtab.o
|
||||||
|
|
||||||
LIBOBJ += sqlite3session.o
|
LIBOBJ += sqlite3session.o
|
||||||
|
|
||||||
@ -154,6 +155,7 @@ SRC = \
|
|||||||
$(TOP)/src/tclsqlite.c \
|
$(TOP)/src/tclsqlite.c \
|
||||||
$(TOP)/src/threads.c \
|
$(TOP)/src/threads.c \
|
||||||
$(TOP)/src/tokenize.c \
|
$(TOP)/src/tokenize.c \
|
||||||
|
$(TOP)/src/treeview.c \
|
||||||
$(TOP)/src/trigger.c \
|
$(TOP)/src/trigger.c \
|
||||||
$(TOP)/src/utf.c \
|
$(TOP)/src/utf.c \
|
||||||
$(TOP)/src/update.c \
|
$(TOP)/src/update.c \
|
||||||
@ -174,6 +176,8 @@ SRC = \
|
|||||||
$(TOP)/src/wal.h \
|
$(TOP)/src/wal.h \
|
||||||
$(TOP)/src/walker.c \
|
$(TOP)/src/walker.c \
|
||||||
$(TOP)/src/where.c \
|
$(TOP)/src/where.c \
|
||||||
|
$(TOP)/src/wherecode.c \
|
||||||
|
$(TOP)/src/whereexpr.c \
|
||||||
$(TOP)/src/whereInt.h
|
$(TOP)/src/whereInt.h
|
||||||
|
|
||||||
# Source code for extensions
|
# Source code for extensions
|
||||||
@ -343,6 +347,8 @@ TESTSRC2 = \
|
|||||||
$(TOP)/src/vdbe.c \
|
$(TOP)/src/vdbe.c \
|
||||||
$(TOP)/src/vdbemem.c \
|
$(TOP)/src/vdbemem.c \
|
||||||
$(TOP)/src/where.c \
|
$(TOP)/src/where.c \
|
||||||
|
$(TOP)/src/wherecode.c \
|
||||||
|
$(TOP)/src/whereexpr.c \
|
||||||
parse.c \
|
parse.c \
|
||||||
$(TOP)/ext/fts3/fts3.c \
|
$(TOP)/ext/fts3/fts3.c \
|
||||||
$(TOP)/ext/fts3/fts3_aux.c \
|
$(TOP)/ext/fts3/fts3_aux.c \
|
||||||
@ -418,6 +424,10 @@ FUZZDATA = \
|
|||||||
$(TOP)/test/fuzzdata2.db \
|
$(TOP)/test/fuzzdata2.db \
|
||||||
$(TOP)/test/fuzzdata3.db
|
$(TOP)/test/fuzzdata3.db
|
||||||
|
|
||||||
|
# Standard options to testfixture
|
||||||
|
#
|
||||||
|
TESTOPTS = --verbose=file --output=test-out.txt
|
||||||
|
|
||||||
# This is the default Makefile target. The objects listed here
|
# This is the default Makefile target. The objects listed here
|
||||||
# are what get build when you type just "make" with no arguments.
|
# are what get build when you type just "make" with no arguments.
|
||||||
#
|
#
|
||||||
@ -675,36 +685,48 @@ fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
|
|||||||
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
|
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
|
||||||
|
|
||||||
fulltest: $(TESTPROGS) fuzztest
|
fulltest: $(TESTPROGS) fuzztest
|
||||||
./testfixture$(EXE) $(TOP)/test/all.test
|
./testfixture$(EXE) $(TOP)/test/all.test $(TESTOPTS)
|
||||||
|
|
||||||
soaktest: $(TESTPROGS)
|
soaktest: $(TESTPROGS)
|
||||||
./testfixture$(EXE) $(TOP)/test/all.test -soak=1
|
./testfixture$(EXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)
|
||||||
|
|
||||||
fulltestonly: $(TESTPROGS) fuzztest
|
fulltestonly: $(TESTPROGS) fuzztest
|
||||||
./testfixture$(EXE) $(TOP)/test/full.test
|
./testfixture$(EXE) $(TOP)/test/full.test $(TESTOPTS)
|
||||||
|
|
||||||
queryplantest: testfixture$(EXE) sqlite3$(EXE)
|
queryplantest: testfixture$(EXE) sqlite3$(EXE)
|
||||||
./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner
|
./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner $(TESTOPTS)
|
||||||
|
|
||||||
fuzztest: fuzzcheck$(EXE) $(FUZZDATA)
|
fuzztest: fuzzcheck$(EXE) $(FUZZDATA)
|
||||||
./fuzzcheck$(EXE) $(FUZZDATA)
|
./fuzzcheck$(EXE) $(FUZZDATA)
|
||||||
|
|
||||||
|
valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA)
|
||||||
|
valgrind ./fuzzcheck$(EXE) --cell-size-check --quiet $(FUZZDATA)
|
||||||
|
|
||||||
|
# A very quick test using only testfixture and omitting all the slower
|
||||||
|
# tests. Designed to run in under 3 minutes on a workstation.
|
||||||
|
#
|
||||||
|
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: $(TESTPROGS) fuzztest
|
test: $(TESTPROGS) fuzztest
|
||||||
./testfixture$(EXE) $(TOP)/test/veryquick.test
|
./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS)
|
||||||
|
|
||||||
# Run a test using valgrind. This can take a really long time
|
# Run a test using valgrind. This can take a really long time
|
||||||
# because valgrind is so much slower than a native machine.
|
# because valgrind is so much slower than a native machine.
|
||||||
#
|
#
|
||||||
valgrindtest: $(TESTPROGS) fuzzcheck$(EXE) $(FUZZDATA)
|
valgrindtest: $(TESTPROGS) valgrindfuzz
|
||||||
valgrind -v ./fuzzcheck$(EXE) --cell-size-check --quiet $(FUZZDATA)
|
OMIT_MISUSE=1 valgrind -v \
|
||||||
OMIT_MISUSE=1 valgrind -v ./testfixture$(EXE) $(TOP)/test/permutations.test valgrind
|
./testfixture$(EXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)
|
||||||
|
|
||||||
# A very fast test that checks basic sanity. The name comes from
|
# A very fast test that checks basic sanity. The name comes from
|
||||||
# the 60s-era electronics testing: "Turn it on and see if smoke
|
# the 60s-era electronics testing: "Turn it on and see if smoke
|
||||||
# comes out."
|
# comes out."
|
||||||
#
|
#
|
||||||
smoketest: $(TESTPROGS) fuzzcheck$(EXE)
|
smoketest: $(TESTPROGS) fuzzcheck$(EXE)
|
||||||
./testfixture$(EXE) $(TOP)/test/main.test
|
./testfixture$(EXE) $(TOP)/test/main.test $(TESTOPTS)
|
||||||
|
|
||||||
# The next two rules are used to support the "threadtest" target. Building
|
# The next two rules are used to support the "threadtest" target. Building
|
||||||
# threadtest runs a few thread-safety tests that are implemented in C. This
|
# threadtest runs a few thread-safety tests that are implemented in C. This
|
||||||
|
95
manifest
95
manifest
@ -1,11 +1,11 @@
|
|||||||
C Add\sthe\ssqlite3changegroup_xxx()\sAPIs\sto\sthe\ssessions\smodule.\sFor\scombining\smultiple\schangesets\sor\spatchsets.
|
C Merge\srecent\strunk\senhancements\sand\sfixes.
|
||||||
D 2015-06-11T17:26:10.939
|
D 2015-06-11T18:01:29.396
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 58c16cc8cd876ed112902e70cf33d33f3270b5aa
|
F Makefile.in 5f56f6186fdbd0fb33226e9d2279acde3b3fa88b
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
F Makefile.msc f4c7677780d417c7574b61904ad9195124675b26
|
F Makefile.msc 3165ac5ae2fee79cf7d5e025b879f7a52ae66776
|
||||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||||
F README.md 0bfccb18927349653c09137a458b961fa8ab4cb9
|
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||||
F VERSION ce0ae95abd7121c534f6917c1c8f2b70d9acd4db
|
F VERSION ce0ae95abd7121c534f6917c1c8f2b70d9acd4db
|
||||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||||
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
|
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
|
||||||
@ -38,8 +38,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
|||||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||||
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
|
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
|
||||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||||
F configure 35cbd52af707ae22401641fe7b3672f05aea0eb1 x
|
F configure 17bd8dc3e35c718df68d04f53bf7dacf2b639732 x
|
||||||
F configure.ac 0b775d383c536bbaafc1e46dd3cbb81a7ea11aeb
|
F configure.ac 713de38000413e469188db2cb85bed759b56f322
|
||||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||||
@ -156,7 +156,7 @@ F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
|
|||||||
F ext/rtree/rtree9.test b5eb13849545dfd271a54ff16784cb00d8792aea
|
F ext/rtree/rtree9.test b5eb13849545dfd271a54ff16784cb00d8792aea
|
||||||
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
|
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
|
||||||
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
|
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
|
||||||
F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06
|
F ext/rtree/rtreeC.test 90aaaffe2fd4f0dcd12289cad5515f6d41f45ffd
|
||||||
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
|
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
|
||||||
F ext/rtree/rtreeE.test 45a147a64a76306172819562309681d8e90f94bb
|
F ext/rtree/rtreeE.test 45a147a64a76306172819562309681d8e90f94bb
|
||||||
F ext/rtree/rtreeF.test 66deb9fd1611c7ca2e374adba63debdc2dbb12b4
|
F ext/rtree/rtreeF.test 66deb9fd1611c7ca2e374adba63debdc2dbb12b4
|
||||||
@ -190,7 +190,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
|||||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||||
F main.mk 3ba6bc8133b4b2f020a9c6043aa1fe7e35d16cb2
|
F main.mk 2395b88d31e71bbd6f9dd26bd6db26948ead9eb3
|
||||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||||
F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
|
F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
|
||||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||||
@ -204,24 +204,24 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
|||||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||||
F src/alter.c 8f6dc4a6ddc1ebc0ed5cc470c4e57ff0d1605e90
|
F src/alter.c 48e14b8aea28dc58baafe3cfcb8889c086b7744a
|
||||||
F src/analyze.c d23790787f80ebed58df7774744b4cf96401498b
|
F src/analyze.c d23790787f80ebed58df7774744b4cf96401498b
|
||||||
F src/attach.c c38ac5a520a231d5d0308fd7f2ad95191c867bae
|
F src/attach.c c38ac5a520a231d5d0308fd7f2ad95191c867bae
|
||||||
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||||
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
|
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
|
||||||
F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d
|
F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d
|
||||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||||
F src/btree.c 9e837a0e7e35c54bedddf55db906b7902d175078
|
F src/btree.c 5166c27883c24768c2f7f53479714f03ef34c612
|
||||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||||
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
|
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
|
||||||
F src/build.c 85a169a0a22f8b80caf513eaf2944d39b979f571
|
F src/build.c 6770b74ccb51cb485e81057c625f77455d5ddc06
|
||||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||||
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
|
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
|
||||||
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
|
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
|
||||||
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
|
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
|
||||||
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
|
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
|
||||||
F src/delete.c 5075d88557eb4e2a7fdb2b61a96142830d8589b8
|
F src/delete.c b998fbc3c55e8331a5f40aa7ff80972254de8de1
|
||||||
F src/expr.c 3fb2ab3ab69d15b4b75ae53fceb4e317f64cb306
|
F src/expr.c 710c764c1974b15a0e56b004ff9f5e6ceab3a854
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
|
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
|
||||||
F src/func.c 5b8b8e77a0fb644eaf8947d413804622e32692b6
|
F src/func.c 5b8b8e77a0fb644eaf8947d413804622e32692b6
|
||||||
@ -229,7 +229,7 @@ F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
|
|||||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||||
F src/insert.c 6d9cde1aafe23b157fcc4a6567bf1fb1a1cb8ce3
|
F src/insert.c a81d4454051c92d058d79cd77099e700e36a74f6
|
||||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||||
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
||||||
@ -265,16 +265,16 @@ F src/pcache1.c 69d137620a305f814398bd29a0c998038c0695e9
|
|||||||
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
|
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
|
||||||
F src/pragma.h b8632d7cdda7b25323fa580e3e558a4f0d4502cc
|
F src/pragma.h b8632d7cdda7b25323fa580e3e558a4f0d4502cc
|
||||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||||
F src/printf.c 13ce37e5574f9b0682fa86dbcf9faf76b9d82a15
|
F src/printf.c db11b5960105ee661dcac690f2ae6276e49bf251
|
||||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||||
F src/resolve.c 84c571794e3ee5806274d95158a4c0177c6c4708
|
F src/resolve.c 84c571794e3ee5806274d95158a4c0177c6c4708
|
||||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||||
F src/select.c 5978cc521cb8fc1aa6a0089e35edaf531accb52a
|
F src/select.c 45a814a755f90c1a6345164d2da4a8ef293da53d
|
||||||
F src/shell.c f26cca96f7dadab5efb5e655edf548f4b91695c5
|
F src/shell.c f26cca96f7dadab5efb5e655edf548f4b91695c5
|
||||||
F src/sqlite.h.in 9d68f87febe52dbba2f3fb30d68aeba38ab957e2
|
F src/sqlite.h.in f61a45445596dc9fe4cdc84a2c042fb310653bef
|
||||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||||
F src/sqlite3ext.h 2ebeb634e751a61a6f0eebfa0f4669f46a42f6cd
|
F src/sqlite3ext.h 2ebeb634e751a61a6f0eebfa0f4669f46a42f6cd
|
||||||
F src/sqliteInt.h 7f3d18ce72c0a3c81961941f9f288975bd134378
|
F src/sqliteInt.h eb4d0375eb9fdfcc95c58f7b4c3f6f738ba42850
|
||||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||||
@ -326,18 +326,19 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
|||||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||||
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
|
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
|
||||||
F src/tokenize.c baa0e550dfa76a8d781732a7bfb1f0aa094942f2
|
F src/tokenize.c baa0e550dfa76a8d781732a7bfb1f0aa094942f2
|
||||||
|
F src/treeview.c 84aa2d2ed26627ccc8dd3a2becfa18dc86ee4607
|
||||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||||
F src/update.c 24dd6a45b8b3470e62702128ebf11be1f2693145
|
F src/update.c 24dd6a45b8b3470e62702128ebf11be1f2693145
|
||||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||||
F src/util.c a6431c92803b975b7322724a7b433e538d243539
|
F src/util.c a6431c92803b975b7322724a7b433e538d243539
|
||||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||||
F src/vdbe.c e4b07daec26aaeb3700308f82770485f0a28a988
|
F src/vdbe.c c4fc60e18ec234d88f47f59f89f294f2af2436ea
|
||||||
F src/vdbe.h 01d8c35cb877faca74331bb690f0327493c2cb50
|
F src/vdbe.h 01d8c35cb877faca74331bb690f0327493c2cb50
|
||||||
F src/vdbeInt.h 50e298245b66b320c8930219c8aeab492c9a4cce
|
F src/vdbeInt.h 50e298245b66b320c8930219c8aeab492c9a4cce
|
||||||
F src/vdbeapi.c a5d2e8afd53b4f81934f5ca59c04465cd1a6d50d
|
F src/vdbeapi.c a5d2e8afd53b4f81934f5ca59c04465cd1a6d50d
|
||||||
F src/vdbeaux.c 9b50d9248b54a9961fdd4d5a9ec5c05f93045a7b
|
F src/vdbeaux.c 9b50d9248b54a9961fdd4d5a9ec5c05f93045a7b
|
||||||
F src/vdbeblob.c ab33f9b57cfce7dddb23853090186da614be4846
|
F src/vdbeblob.c ab33f9b57cfce7dddb23853090186da614be4846
|
||||||
F src/vdbemem.c c704f0f2515a658d8d1566a5f2f3dc9870622427
|
F src/vdbemem.c 794bba184f95cc64c7e089f01ca9789624c14a61
|
||||||
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
|
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
|
||||||
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
|
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
|
||||||
F src/vtab.c c535e80259ebe616467181a83a4263555b97c694
|
F src/vtab.c c535e80259ebe616467181a83a4263555b97c694
|
||||||
@ -345,9 +346,12 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
|||||||
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
|
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||||
F src/where.c f6f41c2f8b9903854992170ea5178898f9cb6c9c
|
F src/where.c 95c0fbfff7aef890b5da7293f6d85cd9a5f99af8
|
||||||
F src/whereInt.h a6f5a762bc1b4b1c76e1cea79976b437ac35a435
|
F src/whereInt.h 5f87e3c4b0551747d119730dfebddd3c54f04047
|
||||||
|
F src/wherecode.c 0669481cabaf5caf934b6bb825df15bc57f60d40
|
||||||
|
F src/whereexpr.c 9ce1c9cfedbf80c93c7d899497025ec8256ce652
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
|
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
|
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
|
||||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||||
@ -372,7 +376,7 @@ F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
|
|||||||
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
|
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
|
||||||
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
|
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
|
||||||
F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2
|
F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2
|
||||||
F test/analyzer1.test e3bccac3be49382050464952998a631bf51e3ce1
|
F test/analyzer1.test 498e2ff4b62740c2751c3a2f8b744fe26689fae9
|
||||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||||
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||||
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||||
@ -525,7 +529,7 @@ F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
|
|||||||
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
|
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
|
||||||
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
|
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
|
||||||
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
|
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
|
||||||
F test/e_walauto.test 6544af03423abc61b53cfb976839385ddc2a0a70
|
F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567
|
||||||
F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608
|
F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608
|
||||||
F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664
|
F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664
|
||||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||||
@ -541,8 +545,9 @@ F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
|||||||
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
|
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
|
||||||
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
|
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
|
||||||
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
||||||
|
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
|
||||||
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
||||||
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
|
F test/filectrl.test 7c13f96457435238da99aff7343ad6a3a4885787
|
||||||
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
|
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
|
||||||
F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2
|
F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2
|
||||||
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
|
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
|
||||||
@ -617,7 +622,7 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
|
|||||||
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
||||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||||
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
||||||
F test/fts3d.test 95c17d1b67b33a5eac0bf5a0d11116a0c0ac7a3a
|
F test/fts3d.test d3e9c8fb75135ada06bf3bab4f9666224965d708
|
||||||
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
|
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
|
||||||
F test/fts3defer2.test c540f5f5c2840f70c68fd9b597df817ec7170468
|
F test/fts3defer2.test c540f5f5c2840f70c68fd9b597df817ec7170468
|
||||||
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
|
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
|
||||||
@ -651,7 +656,7 @@ F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d
|
|||||||
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
||||||
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
|
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
|
||||||
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
|
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
|
||||||
F test/fts4incr.test 361960ed3550e781f3f313e17e2182ef9cefc0e9
|
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
|
||||||
F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
|
F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
|
||||||
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
|
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
|
||||||
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||||
@ -674,7 +679,7 @@ F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
|||||||
F test/fuzzcheck.c a60f926e3fa86c8d33908406d75eec868c22b9ca
|
F test/fuzzcheck.c a60f926e3fa86c8d33908406d75eec868c22b9ca
|
||||||
F test/fuzzdata1.db b60254eeb6bc11474071b883059662a73c48da7f
|
F test/fuzzdata1.db b60254eeb6bc11474071b883059662a73c48da7f
|
||||||
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
|
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
|
||||||
F test/fuzzdata3.db 2701a08185d24d8570eb6e765201131fe75eff84
|
F test/fuzzdata3.db a6e9bf75b8bfad0b7e60e57038908f4237b9c5d2
|
||||||
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
|
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
|
||||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||||
@ -702,8 +707,8 @@ F test/index.test 4d990005a67a36984e4f1a5f1bdccea8d08da4ee
|
|||||||
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||||
F test/index3.test b6ec456cf3b81d9a32123fe7e449bde434db338b
|
F test/index3.test b6ec456cf3b81d9a32123fe7e449bde434db338b
|
||||||
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
||||||
F test/index5.test 25b0b451aceed4ac5f7d49f856f6de7257470b3e
|
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
|
||||||
F test/index6.test 3ae54e53c53f2adcacda269237d8e52bdb05a481
|
F test/index6.test fbf45ceb39eb8a01b837d22623b93b208e6509ef
|
||||||
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
|
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
|
||||||
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
|
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
|
||||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||||
@ -724,7 +729,7 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
|
|||||||
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
|
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
|
||||||
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
||||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||||
F test/join.test 52d4d49f86d0cf46926672878c4eaf0da399104a
|
F test/join.test f9d4a28dec81c6e9dc21b73518e024d73b5ebf57
|
||||||
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
|
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
|
||||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||||
@ -839,13 +844,13 @@ F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
|
|||||||
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
||||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||||
F test/permutations.test 47e3d26e7412ae56b990c93e25ee2c49caa7f28e
|
F test/permutations.test 242d5aa14f84cb03ae830342b176d2b15ec55ffb
|
||||||
F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2
|
F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2
|
||||||
F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028
|
F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028
|
||||||
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
||||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||||
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
|
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
|
||||||
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
|
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||||
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
||||||
@ -858,7 +863,7 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
|||||||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||||
F test/releasetest.tcl 3e906a8bbd047b8e1f035984fbdc96df4caaea47
|
F test/releasetest.tcl 2aaffa548a8f8d10053b20bcf68a1b5a01081e51
|
||||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||||
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
|
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
|
||||||
@ -890,7 +895,7 @@ F test/select4.test 6d5bc6d178a367e8b48fa1c1d3ea12cae9c2d650
|
|||||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||||
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
||||||
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
|
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
|
||||||
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
|
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
|
||||||
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
|
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
|
||||||
F test/selectA.test e452bdb975f488ea46d091382a9185b5853ed2c7
|
F test/selectA.test e452bdb975f488ea46d091382a9185b5853ed2c7
|
||||||
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
|
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
|
||||||
@ -904,7 +909,7 @@ F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
|
|||||||
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
|
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
|
||||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||||
F test/shared3.test fcd65cb11d189eff5f5c85cc4fad246fb0933108
|
F test/shared3.test fcd65cb11d189eff5f5c85cc4fad246fb0933108
|
||||||
F test/shared4.test 72d90821e8d2fc918a08f16d32880868d8ee8e9d
|
F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558
|
||||||
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
|
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
|
||||||
F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
|
F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
|
||||||
F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538
|
F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538
|
||||||
@ -945,7 +950,7 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
|||||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||||
F test/speedtest1.c 9f1b745c24886cced3f70ffc666300152a39013c
|
F test/speedtest1.c 9f1b745c24886cced3f70ffc666300152a39013c
|
||||||
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
|
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
|
||||||
F test/sqldiff1.test e5ecfe95b3a2ff6380f0db6ea8bec246b675e122
|
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
|
||||||
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
|
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
|
||||||
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
|
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
|
||||||
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
|
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
|
||||||
@ -965,7 +970,7 @@ F test/tclsqlite.test 7179b4e0bf236ddf0bfa6bfaefa76fbe0a23c28a
|
|||||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||||
F test/tester.tcl 60a09b25c1c1b96ccd3a697bbf80e7c2402c94db
|
F test/tester.tcl d3f3d3e46f0bc852a395fa1d6469b75582708ff7
|
||||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||||
@ -1163,7 +1168,7 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
|||||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||||
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
|
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
|
||||||
F test/vtab1.test dbe0e9e121102d0ba365f20d126a72676aa2343f
|
F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd
|
||||||
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
|
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
|
||||||
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
||||||
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
||||||
@ -1266,7 +1271,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
|||||||
F tool/mkpragmatab.tcl 40c287d3f929ece67da6e9e7c49885789960accf
|
F tool/mkpragmatab.tcl 40c287d3f929ece67da6e9e7c49885789960accf
|
||||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||||
F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e
|
F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e
|
||||||
F tool/mksqlite3c.tcl 508aac36881e12c4f6e5eb72d9920d1fbc1a1216
|
F tool/mksqlite3c.tcl 12444ca6af8600db9fa08cbd134705f2f758387e
|
||||||
F tool/mksqlite3h.tcl 96d92fcac21c6037d9db20c7cb2e06b534b550ac
|
F tool/mksqlite3h.tcl 96d92fcac21c6037d9db20c7cb2e06b534b550ac
|
||||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||||
F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1
|
F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1
|
||||||
@ -1301,7 +1306,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P fb3914070791c84b5f323b7359ac845246d8a844
|
P 0c1a901cd60e557fc676b97625243163dfe9be9d afc6db9b105f32110112b877f06091757888a5f2
|
||||||
R 8257ada0208a724be61180fd75fdecb0
|
R badb2019580fc793add1b23514b50992
|
||||||
U dan
|
U drh
|
||||||
Z fef5e9795fb303b4eab93bd557fcafaf
|
Z f08b8b4c812a9cba111c95cd9b9fc9e3
|
||||||
|
@ -1 +1 @@
|
|||||||
0c1a901cd60e557fc676b97625243163dfe9be9d
|
c39cb0e2571f58c87053de009e2c135d71b2c3af
|
@ -692,7 +692,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
|||||||
if( pDflt ){
|
if( pDflt ){
|
||||||
sqlite3_value *pVal = 0;
|
sqlite3_value *pVal = 0;
|
||||||
int rc;
|
int rc;
|
||||||
rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal);
|
rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
|
||||||
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
|
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
db->mallocFailed = 1;
|
db->mallocFailed = 1;
|
||||||
|
14
src/btree.c
14
src/btree.c
@ -1272,7 +1272,10 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc, int *pbDefrag){
|
|||||||
int x = size - nByte;
|
int x = size - nByte;
|
||||||
testcase( x==4 );
|
testcase( x==4 );
|
||||||
testcase( x==3 );
|
testcase( x==3 );
|
||||||
if( x<4 ){
|
if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
|
||||||
|
*pRc = SQLITE_CORRUPT_BKPT;
|
||||||
|
return 0;
|
||||||
|
}else if( x<4 ){
|
||||||
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
|
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
|
||||||
** number of bytes in fragments may not exceed 60. */
|
** number of bytes in fragments may not exceed 60. */
|
||||||
if( aData[hdr+7]>=60 ){
|
if( aData[hdr+7]>=60 ){
|
||||||
@ -1283,9 +1286,6 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc, int *pbDefrag){
|
|||||||
** fragmented bytes within the page. */
|
** fragmented bytes within the page. */
|
||||||
memcpy(&aData[iAddr], &aData[pc], 2);
|
memcpy(&aData[iAddr], &aData[pc], 2);
|
||||||
aData[hdr+7] += (u8)x;
|
aData[hdr+7] += (u8)x;
|
||||||
}else if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
|
|
||||||
*pRc = SQLITE_CORRUPT_BKPT;
|
|
||||||
return 0;
|
|
||||||
}else{
|
}else{
|
||||||
/* The slot remains on the free-list. Reduce its size to account
|
/* The slot remains on the free-list. Reduce its size to account
|
||||||
** for the portion used by the new allocation. */
|
** for the portion used by the new allocation. */
|
||||||
@ -6141,9 +6141,9 @@ static void insertCell(
|
|||||||
ins = cellOffset + 2*i;
|
ins = cellOffset + 2*i;
|
||||||
rc = allocateSpace(pPage, sz, &idx);
|
rc = allocateSpace(pPage, sz, &idx);
|
||||||
if( rc ){ *pRC = rc; return; }
|
if( rc ){ *pRC = rc; return; }
|
||||||
/* The allocateSpace() routine guarantees the following two properties
|
/* The allocateSpace() routine guarantees the following properties
|
||||||
** if it returns success */
|
** if it returns successfully */
|
||||||
assert( idx >= end+2 );
|
assert( idx >= 0 && (idx >= end+2 || CORRUPT_DB) );
|
||||||
assert( idx+sz <= (int)pPage->pBt->usableSize );
|
assert( idx+sz <= (int)pPage->pBt->usableSize );
|
||||||
pPage->nCell++;
|
pPage->nCell++;
|
||||||
pPage->nFree -= (u16)(2 + sz);
|
pPage->nFree -= (u16)(2 + sz);
|
||||||
|
26
src/build.c
26
src/build.c
@ -1092,10 +1092,10 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
|
|||||||
pCol->zName = z;
|
pCol->zName = z;
|
||||||
|
|
||||||
/* If there is no type specified, columns have the default affinity
|
/* If there is no type specified, columns have the default affinity
|
||||||
** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
|
** 'BLOB'. If there is a type specified, then sqlite3AddColumnType() will
|
||||||
** be called next to set pCol->affinity correctly.
|
** be called next to set pCol->affinity correctly.
|
||||||
*/
|
*/
|
||||||
pCol->affinity = SQLITE_AFF_NONE;
|
pCol->affinity = SQLITE_AFF_BLOB;
|
||||||
pCol->szEst = 1;
|
pCol->szEst = 1;
|
||||||
p->nCol++;
|
p->nCol++;
|
||||||
}
|
}
|
||||||
@ -1130,7 +1130,7 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
|
|||||||
** 'CHAR' | SQLITE_AFF_TEXT
|
** 'CHAR' | SQLITE_AFF_TEXT
|
||||||
** 'CLOB' | SQLITE_AFF_TEXT
|
** 'CLOB' | SQLITE_AFF_TEXT
|
||||||
** 'TEXT' | SQLITE_AFF_TEXT
|
** 'TEXT' | SQLITE_AFF_TEXT
|
||||||
** 'BLOB' | SQLITE_AFF_NONE
|
** 'BLOB' | SQLITE_AFF_BLOB
|
||||||
** 'REAL' | SQLITE_AFF_REAL
|
** 'REAL' | SQLITE_AFF_REAL
|
||||||
** 'FLOA' | SQLITE_AFF_REAL
|
** 'FLOA' | SQLITE_AFF_REAL
|
||||||
** 'DOUB' | SQLITE_AFF_REAL
|
** 'DOUB' | SQLITE_AFF_REAL
|
||||||
@ -1156,7 +1156,7 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){
|
|||||||
aff = SQLITE_AFF_TEXT;
|
aff = SQLITE_AFF_TEXT;
|
||||||
}else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
|
}else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
|
||||||
&& (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
|
&& (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
|
||||||
aff = SQLITE_AFF_NONE;
|
aff = SQLITE_AFF_BLOB;
|
||||||
if( zIn[0]=='(' ) zChar = zIn;
|
if( zIn[0]=='(' ) zChar = zIn;
|
||||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||||
}else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
|
}else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
|
||||||
@ -1548,7 +1548,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
|
|||||||
zStmt[k++] = '(';
|
zStmt[k++] = '(';
|
||||||
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
|
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
|
||||||
static const char * const azType[] = {
|
static const char * const azType[] = {
|
||||||
/* SQLITE_AFF_NONE */ "",
|
/* SQLITE_AFF_BLOB */ "",
|
||||||
/* SQLITE_AFF_TEXT */ " TEXT",
|
/* SQLITE_AFF_TEXT */ " TEXT",
|
||||||
/* SQLITE_AFF_NUMERIC */ " NUM",
|
/* SQLITE_AFF_NUMERIC */ " NUM",
|
||||||
/* SQLITE_AFF_INTEGER */ " INT",
|
/* SQLITE_AFF_INTEGER */ " INT",
|
||||||
@ -1561,17 +1561,17 @@ static char *createTableStmt(sqlite3 *db, Table *p){
|
|||||||
k += sqlite3Strlen30(&zStmt[k]);
|
k += sqlite3Strlen30(&zStmt[k]);
|
||||||
zSep = zSep2;
|
zSep = zSep2;
|
||||||
identPut(zStmt, &k, pCol->zName);
|
identPut(zStmt, &k, pCol->zName);
|
||||||
assert( pCol->affinity-SQLITE_AFF_NONE >= 0 );
|
assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
|
||||||
assert( pCol->affinity-SQLITE_AFF_NONE < ArraySize(azType) );
|
assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
|
||||||
testcase( pCol->affinity==SQLITE_AFF_NONE );
|
testcase( pCol->affinity==SQLITE_AFF_BLOB );
|
||||||
testcase( pCol->affinity==SQLITE_AFF_TEXT );
|
testcase( pCol->affinity==SQLITE_AFF_TEXT );
|
||||||
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
|
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
|
||||||
testcase( pCol->affinity==SQLITE_AFF_INTEGER );
|
testcase( pCol->affinity==SQLITE_AFF_INTEGER );
|
||||||
testcase( pCol->affinity==SQLITE_AFF_REAL );
|
testcase( pCol->affinity==SQLITE_AFF_REAL );
|
||||||
|
|
||||||
zType = azType[pCol->affinity - SQLITE_AFF_NONE];
|
zType = azType[pCol->affinity - SQLITE_AFF_BLOB];
|
||||||
len = sqlite3Strlen30(zType);
|
len = sqlite3Strlen30(zType);
|
||||||
assert( pCol->affinity==SQLITE_AFF_NONE
|
assert( pCol->affinity==SQLITE_AFF_BLOB
|
||||||
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
|
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
|
||||||
memcpy(&zStmt[k], zType, len);
|
memcpy(&zStmt[k], zType, len);
|
||||||
k += len;
|
k += len;
|
||||||
@ -3701,7 +3701,7 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
|
|||||||
sqlite3DbFree(db, pItem->zDatabase);
|
sqlite3DbFree(db, pItem->zDatabase);
|
||||||
sqlite3DbFree(db, pItem->zName);
|
sqlite3DbFree(db, pItem->zName);
|
||||||
sqlite3DbFree(db, pItem->zAlias);
|
sqlite3DbFree(db, pItem->zAlias);
|
||||||
sqlite3DbFree(db, pItem->zIndex);
|
sqlite3DbFree(db, pItem->zIndexedBy);
|
||||||
sqlite3DeleteTable(db, pItem->pTab);
|
sqlite3DeleteTable(db, pItem->pTab);
|
||||||
sqlite3SelectDelete(db, pItem->pSelect);
|
sqlite3SelectDelete(db, pItem->pSelect);
|
||||||
sqlite3ExprDelete(db, pItem->pOn);
|
sqlite3ExprDelete(db, pItem->pOn);
|
||||||
@ -3774,13 +3774,13 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
|
|||||||
assert( pIndexedBy!=0 );
|
assert( pIndexedBy!=0 );
|
||||||
if( p && ALWAYS(p->nSrc>0) ){
|
if( p && ALWAYS(p->nSrc>0) ){
|
||||||
struct SrcList_item *pItem = &p->a[p->nSrc-1];
|
struct SrcList_item *pItem = &p->a[p->nSrc-1];
|
||||||
assert( pItem->notIndexed==0 && pItem->zIndex==0 );
|
assert( pItem->notIndexed==0 && pItem->zIndexedBy==0 );
|
||||||
if( pIndexedBy->n==1 && !pIndexedBy->z ){
|
if( pIndexedBy->n==1 && !pIndexedBy->z ){
|
||||||
/* A "NOT INDEXED" clause was supplied. See parse.y
|
/* A "NOT INDEXED" clause was supplied. See parse.y
|
||||||
** construct "indexed_opt" for details. */
|
** construct "indexed_opt" for details. */
|
||||||
pItem->notIndexed = 1;
|
pItem->notIndexed = 1;
|
||||||
}else{
|
}else{
|
||||||
pItem->zIndex = sqlite3NameFromToken(pParse->db, pIndexedBy);
|
pItem->zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -810,8 +810,8 @@ int sqlite3GenerateIndexKey(
|
|||||||
*piPartIdxLabel = sqlite3VdbeMakeLabel(v);
|
*piPartIdxLabel = sqlite3VdbeMakeLabel(v);
|
||||||
pParse->iPartIdxTab = iDataCur;
|
pParse->iPartIdxTab = iDataCur;
|
||||||
sqlite3ExprCachePush(pParse);
|
sqlite3ExprCachePush(pParse);
|
||||||
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
|
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
|
||||||
SQLITE_JUMPIFNULL);
|
SQLITE_JUMPIFNULL);
|
||||||
}else{
|
}else{
|
||||||
*piPartIdxLabel = 0;
|
*piPartIdxLabel = 0;
|
||||||
}
|
}
|
||||||
|
295
src/expr.c
295
src/expr.c
@ -191,13 +191,13 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){
|
|||||||
if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){
|
if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){
|
||||||
return SQLITE_AFF_NUMERIC;
|
return SQLITE_AFF_NUMERIC;
|
||||||
}else{
|
}else{
|
||||||
return SQLITE_AFF_NONE;
|
return SQLITE_AFF_BLOB;
|
||||||
}
|
}
|
||||||
}else if( !aff1 && !aff2 ){
|
}else if( !aff1 && !aff2 ){
|
||||||
/* Neither side of the comparison is a column. Compare the
|
/* Neither side of the comparison is a column. Compare the
|
||||||
** results directly.
|
** results directly.
|
||||||
*/
|
*/
|
||||||
return SQLITE_AFF_NONE;
|
return SQLITE_AFF_BLOB;
|
||||||
}else{
|
}else{
|
||||||
/* One side is a column, the other is not. Use the columns affinity. */
|
/* One side is a column, the other is not. Use the columns affinity. */
|
||||||
assert( aff1==0 || aff2==0 );
|
assert( aff1==0 || aff2==0 );
|
||||||
@ -221,7 +221,7 @@ static char comparisonAffinity(Expr *pExpr){
|
|||||||
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||||
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
|
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
|
||||||
}else if( !aff ){
|
}else if( !aff ){
|
||||||
aff = SQLITE_AFF_NONE;
|
aff = SQLITE_AFF_BLOB;
|
||||||
}
|
}
|
||||||
return aff;
|
return aff;
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ static char comparisonAffinity(Expr *pExpr){
|
|||||||
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
|
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
|
||||||
char aff = comparisonAffinity(pExpr);
|
char aff = comparisonAffinity(pExpr);
|
||||||
switch( aff ){
|
switch( aff ){
|
||||||
case SQLITE_AFF_NONE:
|
case SQLITE_AFF_BLOB:
|
||||||
return 1;
|
return 1;
|
||||||
case SQLITE_AFF_TEXT:
|
case SQLITE_AFF_TEXT:
|
||||||
return idx_affinity==SQLITE_AFF_TEXT;
|
return idx_affinity==SQLITE_AFF_TEXT;
|
||||||
@ -1041,7 +1041,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
|
|||||||
pNewItem->isCorrelated = pOldItem->isCorrelated;
|
pNewItem->isCorrelated = pOldItem->isCorrelated;
|
||||||
pNewItem->viaCoroutine = pOldItem->viaCoroutine;
|
pNewItem->viaCoroutine = pOldItem->viaCoroutine;
|
||||||
pNewItem->isRecursive = pOldItem->isRecursive;
|
pNewItem->isRecursive = pOldItem->isRecursive;
|
||||||
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
|
pNewItem->zIndexedBy = sqlite3DbStrDup(db, pOldItem->zIndexedBy);
|
||||||
pNewItem->notIndexed = pOldItem->notIndexed;
|
pNewItem->notIndexed = pOldItem->notIndexed;
|
||||||
pNewItem->pIndex = pOldItem->pIndex;
|
pNewItem->pIndex = pOldItem->pIndex;
|
||||||
pTab = pNewItem->pTab = pOldItem->pTab;
|
pTab = pNewItem->pTab = pOldItem->pTab;
|
||||||
@ -1268,7 +1268,7 @@ u32 sqlite3ExprListFlags(const ExprList *pList){
|
|||||||
**
|
**
|
||||||
** sqlite3ExprIsConstant() pWalker->eCode==1
|
** sqlite3ExprIsConstant() pWalker->eCode==1
|
||||||
** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2
|
** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2
|
||||||
** sqlite3ExprRefOneTableOnly() pWalker->eCode==3
|
** sqlite3ExprIsTableConstant() pWalker->eCode==3
|
||||||
** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5
|
** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5
|
||||||
**
|
**
|
||||||
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
|
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
|
||||||
@ -1376,7 +1376,7 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Walk an expression tree. Return non-zero if the expression constant
|
** Walk an expression tree. Return non-zero if the expression is constant
|
||||||
** for any single row of the table with cursor iCur. In other words, the
|
** for any single row of the table with cursor iCur. In other words, the
|
||||||
** expression must not refer to any non-deterministic function nor any
|
** expression must not refer to any non-deterministic function nor any
|
||||||
** table other than iCur.
|
** table other than iCur.
|
||||||
@ -1482,7 +1482,7 @@ int sqlite3ExprCanBeNull(const Expr *p){
|
|||||||
*/
|
*/
|
||||||
int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
|
int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
|
||||||
u8 op;
|
u8 op;
|
||||||
if( aff==SQLITE_AFF_NONE ) return 1;
|
if( aff==SQLITE_AFF_BLOB ) return 1;
|
||||||
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
|
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
|
||||||
op = p->op;
|
op = p->op;
|
||||||
if( op==TK_REGISTER ) op = p->op2;
|
if( op==TK_REGISTER ) op = p->op2;
|
||||||
@ -1933,7 +1933,7 @@ int sqlite3CodeSubselect(
|
|||||||
int r1, r2, r3;
|
int r1, r2, r3;
|
||||||
|
|
||||||
if( !affinity ){
|
if( !affinity ){
|
||||||
affinity = SQLITE_AFF_NONE;
|
affinity = SQLITE_AFF_BLOB;
|
||||||
}
|
}
|
||||||
if( pKeyInfo ){
|
if( pKeyInfo ){
|
||||||
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
|
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
|
||||||
@ -3311,268 +3311,6 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
|
|||||||
exprToRegister(pExpr, iMem);
|
exprToRegister(pExpr, iMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SQLITE_DEBUG
|
|
||||||
/*
|
|
||||||
** Generate a human-readable explanation of an expression tree.
|
|
||||||
*/
|
|
||||||
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
|
||||||
const char *zBinOp = 0; /* Binary operator */
|
|
||||||
const char *zUniOp = 0; /* Unary operator */
|
|
||||||
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
|
||||||
if( pExpr==0 ){
|
|
||||||
sqlite3TreeViewLine(pView, "nil");
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch( pExpr->op ){
|
|
||||||
case TK_AGG_COLUMN: {
|
|
||||||
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
|
|
||||||
pExpr->iTable, pExpr->iColumn);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_COLUMN: {
|
|
||||||
if( pExpr->iTable<0 ){
|
|
||||||
/* This only happens when coding check constraints */
|
|
||||||
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
|
|
||||||
}else{
|
|
||||||
sqlite3TreeViewLine(pView, "{%d:%d}",
|
|
||||||
pExpr->iTable, pExpr->iColumn);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_INTEGER: {
|
|
||||||
if( pExpr->flags & EP_IntValue ){
|
|
||||||
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
|
|
||||||
}else{
|
|
||||||
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
||||||
case TK_FLOAT: {
|
|
||||||
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
case TK_STRING: {
|
|
||||||
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_NULL: {
|
|
||||||
sqlite3TreeViewLine(pView,"NULL");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
|
||||||
case TK_BLOB: {
|
|
||||||
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
case TK_VARIABLE: {
|
|
||||||
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
|
|
||||||
pExpr->u.zToken, pExpr->iColumn);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_REGISTER: {
|
|
||||||
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_AS: {
|
|
||||||
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
|
|
||||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_ID: {
|
|
||||||
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifndef SQLITE_OMIT_CAST
|
|
||||||
case TK_CAST: {
|
|
||||||
/* Expressions of the form: CAST(pLeft AS token) */
|
|
||||||
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
|
|
||||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* SQLITE_OMIT_CAST */
|
|
||||||
case TK_LT: zBinOp = "LT"; break;
|
|
||||||
case TK_LE: zBinOp = "LE"; break;
|
|
||||||
case TK_GT: zBinOp = "GT"; break;
|
|
||||||
case TK_GE: zBinOp = "GE"; break;
|
|
||||||
case TK_NE: zBinOp = "NE"; break;
|
|
||||||
case TK_EQ: zBinOp = "EQ"; break;
|
|
||||||
case TK_IS: zBinOp = "IS"; break;
|
|
||||||
case TK_ISNOT: zBinOp = "ISNOT"; break;
|
|
||||||
case TK_AND: zBinOp = "AND"; break;
|
|
||||||
case TK_OR: zBinOp = "OR"; break;
|
|
||||||
case TK_PLUS: zBinOp = "ADD"; break;
|
|
||||||
case TK_STAR: zBinOp = "MUL"; break;
|
|
||||||
case TK_MINUS: zBinOp = "SUB"; break;
|
|
||||||
case TK_REM: zBinOp = "REM"; break;
|
|
||||||
case TK_BITAND: zBinOp = "BITAND"; break;
|
|
||||||
case TK_BITOR: zBinOp = "BITOR"; break;
|
|
||||||
case TK_SLASH: zBinOp = "DIV"; break;
|
|
||||||
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
|
|
||||||
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
|
|
||||||
case TK_CONCAT: zBinOp = "CONCAT"; break;
|
|
||||||
case TK_DOT: zBinOp = "DOT"; break;
|
|
||||||
|
|
||||||
case TK_UMINUS: zUniOp = "UMINUS"; break;
|
|
||||||
case TK_UPLUS: zUniOp = "UPLUS"; break;
|
|
||||||
case TK_BITNOT: zUniOp = "BITNOT"; break;
|
|
||||||
case TK_NOT: zUniOp = "NOT"; break;
|
|
||||||
case TK_ISNULL: zUniOp = "ISNULL"; break;
|
|
||||||
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
|
|
||||||
|
|
||||||
case TK_COLLATE: {
|
|
||||||
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
|
|
||||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TK_AGG_FUNCTION:
|
|
||||||
case TK_FUNCTION: {
|
|
||||||
ExprList *pFarg; /* List of function arguments */
|
|
||||||
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
|
|
||||||
pFarg = 0;
|
|
||||||
}else{
|
|
||||||
pFarg = pExpr->x.pList;
|
|
||||||
}
|
|
||||||
if( pExpr->op==TK_AGG_FUNCTION ){
|
|
||||||
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
|
|
||||||
pExpr->op2, pExpr->u.zToken);
|
|
||||||
}else{
|
|
||||||
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
|
|
||||||
}
|
|
||||||
if( pFarg ){
|
|
||||||
sqlite3TreeViewExprList(pView, pFarg, 0, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifndef SQLITE_OMIT_SUBQUERY
|
|
||||||
case TK_EXISTS: {
|
|
||||||
sqlite3TreeViewLine(pView, "EXISTS-expr");
|
|
||||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_SELECT: {
|
|
||||||
sqlite3TreeViewLine(pView, "SELECT-expr");
|
|
||||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_IN: {
|
|
||||||
sqlite3TreeViewLine(pView, "IN");
|
|
||||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
|
||||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
|
||||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
|
||||||
}else{
|
|
||||||
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* SQLITE_OMIT_SUBQUERY */
|
|
||||||
|
|
||||||
/*
|
|
||||||
** x BETWEEN y AND z
|
|
||||||
**
|
|
||||||
** This is equivalent to
|
|
||||||
**
|
|
||||||
** x>=y AND x<=z
|
|
||||||
**
|
|
||||||
** X is stored in pExpr->pLeft.
|
|
||||||
** Y is stored in pExpr->pList->a[0].pExpr.
|
|
||||||
** Z is stored in pExpr->pList->a[1].pExpr.
|
|
||||||
*/
|
|
||||||
case TK_BETWEEN: {
|
|
||||||
Expr *pX = pExpr->pLeft;
|
|
||||||
Expr *pY = pExpr->x.pList->a[0].pExpr;
|
|
||||||
Expr *pZ = pExpr->x.pList->a[1].pExpr;
|
|
||||||
sqlite3TreeViewLine(pView, "BETWEEN");
|
|
||||||
sqlite3TreeViewExpr(pView, pX, 1);
|
|
||||||
sqlite3TreeViewExpr(pView, pY, 1);
|
|
||||||
sqlite3TreeViewExpr(pView, pZ, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_TRIGGER: {
|
|
||||||
/* If the opcode is TK_TRIGGER, then the expression is a reference
|
|
||||||
** to a column in the new.* or old.* pseudo-tables available to
|
|
||||||
** trigger programs. In this case Expr.iTable is set to 1 for the
|
|
||||||
** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
|
|
||||||
** is set to the column of the pseudo-table to read, or to -1 to
|
|
||||||
** read the rowid field.
|
|
||||||
*/
|
|
||||||
sqlite3TreeViewLine(pView, "%s(%d)",
|
|
||||||
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_CASE: {
|
|
||||||
sqlite3TreeViewLine(pView, "CASE");
|
|
||||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
|
||||||
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
|
||||||
case TK_RAISE: {
|
|
||||||
const char *zType = "unk";
|
|
||||||
switch( pExpr->affinity ){
|
|
||||||
case OE_Rollback: zType = "rollback"; break;
|
|
||||||
case OE_Abort: zType = "abort"; break;
|
|
||||||
case OE_Fail: zType = "fail"; break;
|
|
||||||
case OE_Ignore: zType = "ignore"; break;
|
|
||||||
}
|
|
||||||
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
default: {
|
|
||||||
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( zBinOp ){
|
|
||||||
sqlite3TreeViewLine(pView, "%s", zBinOp);
|
|
||||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
|
||||||
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
|
|
||||||
}else if( zUniOp ){
|
|
||||||
sqlite3TreeViewLine(pView, "%s", zUniOp);
|
|
||||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
||||||
}
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
#endif /* SQLITE_DEBUG */
|
|
||||||
|
|
||||||
#ifdef SQLITE_DEBUG
|
|
||||||
/*
|
|
||||||
** Generate a human-readable explanation of an expression list.
|
|
||||||
*/
|
|
||||||
void sqlite3TreeViewExprList(
|
|
||||||
TreeView *pView,
|
|
||||||
const ExprList *pList,
|
|
||||||
u8 moreToFollow,
|
|
||||||
const char *zLabel
|
|
||||||
){
|
|
||||||
int i;
|
|
||||||
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
|
||||||
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
|
|
||||||
if( pList==0 ){
|
|
||||||
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
|
|
||||||
}else{
|
|
||||||
sqlite3TreeViewLine(pView, "%s", zLabel);
|
|
||||||
for(i=0; i<pList->nExpr; i++){
|
|
||||||
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
|
|
||||||
#if 0
|
|
||||||
if( pList->a[i].zName ){
|
|
||||||
sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
|
|
||||||
}
|
|
||||||
if( pList->a[i].bSpanIsTab ){
|
|
||||||
sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
#endif /* SQLITE_DEBUG */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code that pushes the value of every element of the given
|
** Generate code that pushes the value of every element of the given
|
||||||
** expression list into a sequence of registers beginning at target.
|
** expression list into a sequence of registers beginning at target.
|
||||||
@ -3964,6 +3702,21 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
sqlite3ReleaseTempReg(pParse, regFree2);
|
sqlite3ReleaseTempReg(pParse, regFree2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Like sqlite3ExprIfFalse() except that a copy is made of pExpr before
|
||||||
|
** code generation, and that copy is deleted after code generation. This
|
||||||
|
** ensures that the original pExpr is unchanged.
|
||||||
|
*/
|
||||||
|
void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){
|
||||||
|
sqlite3 *db = pParse->db;
|
||||||
|
Expr *pCopy = sqlite3ExprDup(db, pExpr, 0);
|
||||||
|
if( db->mallocFailed==0 ){
|
||||||
|
sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull);
|
||||||
|
}
|
||||||
|
sqlite3ExprDelete(db, pCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Do a deep comparison of two expression trees. Return 0 if the two
|
** Do a deep comparison of two expression trees. Return 0 if the two
|
||||||
** expressions are completely identical. Return 1 if they differ only
|
** expressions are completely identical. Return 1 if they differ only
|
||||||
|
14
src/insert.c
14
src/insert.c
@ -56,7 +56,7 @@ void sqlite3OpenTable(
|
|||||||
**
|
**
|
||||||
** Character Column affinity
|
** Character Column affinity
|
||||||
** ------------------------------
|
** ------------------------------
|
||||||
** 'A' NONE
|
** 'A' BLOB
|
||||||
** 'B' TEXT
|
** 'B' TEXT
|
||||||
** 'C' NUMERIC
|
** 'C' NUMERIC
|
||||||
** 'D' INTEGER
|
** 'D' INTEGER
|
||||||
@ -99,9 +99,9 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Compute the affinity string for table pTab, if it has not already been
|
** Compute the affinity string for table pTab, if it has not already been
|
||||||
** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities.
|
** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
|
||||||
**
|
**
|
||||||
** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and
|
** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and
|
||||||
** if iReg>0 then code an OP_Affinity opcode that will set the affinities
|
** if iReg>0 then code an OP_Affinity opcode that will set the affinities
|
||||||
** for register iReg and following. Or if affinities exists and iReg==0,
|
** for register iReg and following. Or if affinities exists and iReg==0,
|
||||||
** then just set the P4 operand of the previous opcode (which should be
|
** then just set the P4 operand of the previous opcode (which should be
|
||||||
@ -111,7 +111,7 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
|||||||
**
|
**
|
||||||
** Character Column affinity
|
** Character Column affinity
|
||||||
** ------------------------------
|
** ------------------------------
|
||||||
** 'A' NONE
|
** 'A' BLOB
|
||||||
** 'B' TEXT
|
** 'B' TEXT
|
||||||
** 'C' NUMERIC
|
** 'C' NUMERIC
|
||||||
** 'D' INTEGER
|
** 'D' INTEGER
|
||||||
@ -133,7 +133,7 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
|
|||||||
}
|
}
|
||||||
do{
|
do{
|
||||||
zColAff[i--] = 0;
|
zColAff[i--] = 0;
|
||||||
}while( i>=0 && zColAff[i]==SQLITE_AFF_NONE );
|
}while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB );
|
||||||
pTab->zColAff = zColAff;
|
pTab->zColAff = zColAff;
|
||||||
}
|
}
|
||||||
i = sqlite3Strlen30(zColAff);
|
i = sqlite3Strlen30(zColAff);
|
||||||
@ -1393,8 +1393,8 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
if( pIdx->pPartIdxWhere ){
|
if( pIdx->pPartIdxWhere ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
|
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
|
||||||
pParse->ckBase = regNewData+1;
|
pParse->ckBase = regNewData+1;
|
||||||
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
|
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
|
||||||
SQLITE_JUMPIFNULL);
|
SQLITE_JUMPIFNULL);
|
||||||
pParse->ckBase = 0;
|
pParse->ckBase = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
68
src/printf.c
68
src/printf.c
@ -1,16 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
** The "printf" code that follows dates from the 1980's. It is in
|
** The "printf" code that follows dates from the 1980's. It is in
|
||||||
** the public domain. The original comments are included here for
|
** the public domain.
|
||||||
** completeness. They are very out-of-date but might be useful as
|
|
||||||
** an historical reference. Most of the "enhancements" have been backed
|
|
||||||
** out so that the functionality is now the same as standard printf().
|
|
||||||
**
|
**
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**
|
**
|
||||||
** This file contains code for a set of "printf"-like routines. These
|
** This file contains code for a set of "printf"-like routines. These
|
||||||
** routines format strings much like the printf() from the standard C
|
** routines format strings much like the printf() from the standard C
|
||||||
** library, though the implementation here has enhancements to support
|
** library, though the implementation here has enhancements to support
|
||||||
** SQLlite.
|
** SQLite.
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -1058,67 +1055,6 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SQLITE_DEBUG
|
|
||||||
/*************************************************************************
|
|
||||||
** Routines for implementing the "TreeView" display of hierarchical
|
|
||||||
** data structures for debugging.
|
|
||||||
**
|
|
||||||
** The main entry points (coded elsewhere) are:
|
|
||||||
** sqlite3TreeViewExpr(0, pExpr, 0);
|
|
||||||
** sqlite3TreeViewExprList(0, pList, 0, 0);
|
|
||||||
** sqlite3TreeViewSelect(0, pSelect, 0);
|
|
||||||
** Insert calls to those routines while debugging in order to display
|
|
||||||
** a diagram of Expr, ExprList, and Select objects.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
/* Add a new subitem to the tree. The moreToFollow flag indicates that this
|
|
||||||
** is not the last item in the tree. */
|
|
||||||
TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
|
|
||||||
if( p==0 ){
|
|
||||||
p = sqlite3_malloc64( sizeof(*p) );
|
|
||||||
if( p==0 ) return 0;
|
|
||||||
memset(p, 0, sizeof(*p));
|
|
||||||
}else{
|
|
||||||
p->iLevel++;
|
|
||||||
}
|
|
||||||
assert( moreToFollow==0 || moreToFollow==1 );
|
|
||||||
if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
/* Finished with one layer of the tree */
|
|
||||||
void sqlite3TreeViewPop(TreeView *p){
|
|
||||||
if( p==0 ) return;
|
|
||||||
p->iLevel--;
|
|
||||||
if( p->iLevel<0 ) sqlite3_free(p);
|
|
||||||
}
|
|
||||||
/* Generate a single line of output for the tree, with a prefix that contains
|
|
||||||
** all the appropriate tree lines */
|
|
||||||
void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
|
|
||||||
va_list ap;
|
|
||||||
int i;
|
|
||||||
StrAccum acc;
|
|
||||||
char zBuf[500];
|
|
||||||
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
|
||||||
if( p ){
|
|
||||||
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
|
|
||||||
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
|
|
||||||
}
|
|
||||||
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
|
|
||||||
}
|
|
||||||
va_start(ap, zFormat);
|
|
||||||
sqlite3VXPrintf(&acc, 0, zFormat, ap);
|
|
||||||
va_end(ap);
|
|
||||||
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
|
|
||||||
sqlite3StrAccumFinish(&acc);
|
|
||||||
fprintf(stdout,"%s", zBuf);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
/* Shorthand for starting a new tree item that consists of a single label */
|
|
||||||
void sqlite3TreeViewItem(TreeView *p, const char *zLabel, u8 moreToFollow){
|
|
||||||
p = sqlite3TreeViewPush(p, moreToFollow);
|
|
||||||
sqlite3TreeViewLine(p, "%s", zLabel);
|
|
||||||
}
|
|
||||||
#endif /* SQLITE_DEBUG */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** variable-argument wrapper around sqlite3VXPrintf().
|
** variable-argument wrapper around sqlite3VXPrintf().
|
||||||
|
361
src/select.c
361
src/select.c
@ -21,7 +21,8 @@
|
|||||||
/***/ int sqlite3SelectTrace = 0;
|
/***/ int sqlite3SelectTrace = 0;
|
||||||
# define SELECTTRACE(K,P,S,X) \
|
# define SELECTTRACE(K,P,S,X) \
|
||||||
if(sqlite3SelectTrace&(K)) \
|
if(sqlite3SelectTrace&(K)) \
|
||||||
sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",(S)->zSelName,(S)),\
|
sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\
|
||||||
|
(S)->zSelName,(S)),\
|
||||||
sqlite3DebugPrintf X
|
sqlite3DebugPrintf X
|
||||||
#else
|
#else
|
||||||
# define SELECTTRACE(K,P,S,X)
|
# define SELECTTRACE(K,P,S,X)
|
||||||
@ -774,7 +775,8 @@ static void selectInnerLoop(
|
|||||||
|
|
||||||
default: {
|
default: {
|
||||||
assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
|
assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
|
||||||
codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, regResult);
|
codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol,
|
||||||
|
regResult);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -827,7 +829,8 @@ static void selectInnerLoop(
|
|||||||
** current row to the index and proceed with writing it to the
|
** current row to the index and proceed with writing it to the
|
||||||
** output table as well. */
|
** output table as well. */
|
||||||
int addr = sqlite3VdbeCurrentAddr(v) + 4;
|
int addr = sqlite3VdbeCurrentAddr(v) + 4;
|
||||||
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v);
|
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0);
|
||||||
|
VdbeCoverage(v);
|
||||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
|
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
|
||||||
assert( pSort==0 );
|
assert( pSort==0 );
|
||||||
}
|
}
|
||||||
@ -1310,28 +1313,27 @@ static void generateSortTail(
|
|||||||
*/
|
*/
|
||||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||||
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
|
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
|
||||||
|
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
|
||||||
|
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
|
||||||
|
#endif
|
||||||
static const char *columnTypeImpl(
|
static const char *columnTypeImpl(
|
||||||
NameContext *pNC,
|
NameContext *pNC,
|
||||||
Expr *pExpr,
|
Expr *pExpr,
|
||||||
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||||
const char **pzOrigDb,
|
const char **pzOrigDb,
|
||||||
const char **pzOrigTab,
|
const char **pzOrigTab,
|
||||||
const char **pzOrigCol,
|
const char **pzOrigCol,
|
||||||
|
#endif
|
||||||
u8 *pEstWidth
|
u8 *pEstWidth
|
||||||
){
|
){
|
||||||
char const *zOrigDb = 0;
|
|
||||||
char const *zOrigTab = 0;
|
|
||||||
char const *zOrigCol = 0;
|
|
||||||
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
|
|
||||||
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
|
|
||||||
static const char *columnTypeImpl(
|
|
||||||
NameContext *pNC,
|
|
||||||
Expr *pExpr,
|
|
||||||
u8 *pEstWidth
|
|
||||||
){
|
|
||||||
#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
|
|
||||||
char const *zType = 0;
|
char const *zType = 0;
|
||||||
int j;
|
int j;
|
||||||
u8 estWidth = 1;
|
u8 estWidth = 1;
|
||||||
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||||
|
char const *zOrigDb = 0;
|
||||||
|
char const *zOrigTab = 0;
|
||||||
|
char const *zOrigCol = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
|
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
|
||||||
switch( pExpr->op ){
|
switch( pExpr->op ){
|
||||||
@ -1705,11 +1707,12 @@ static void selectAddColumnTypeAndCollation(
|
|||||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||||
p = a[i].pExpr;
|
p = a[i].pExpr;
|
||||||
if( pCol->zType==0 ){
|
if( pCol->zType==0 ){
|
||||||
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
|
pCol->zType = sqlite3DbStrDup(db,
|
||||||
|
columnType(&sNC, p,0,0,0, &pCol->szEst));
|
||||||
}
|
}
|
||||||
szAll += pCol->szEst;
|
szAll += pCol->szEst;
|
||||||
pCol->affinity = sqlite3ExprAffinity(p);
|
pCol->affinity = sqlite3ExprAffinity(p);
|
||||||
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
|
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
|
||||||
pColl = sqlite3ExprCollSeq(pParse, p);
|
pColl = sqlite3ExprCollSeq(pParse, p);
|
||||||
if( pColl && pCol->zColl==0 ){
|
if( pColl && pCol->zColl==0 ){
|
||||||
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
|
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
|
||||||
@ -3215,8 +3218,8 @@ static void substSelect(
|
|||||||
**
|
**
|
||||||
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
|
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
|
||||||
** accidently carried the comment forward until 2014-09-15. Original
|
** accidently carried the comment forward until 2014-09-15. Original
|
||||||
** text: "The subquery does not use aggregates or the outer query does not
|
** text: "The subquery does not use aggregates or the outer query
|
||||||
** use LIMIT."
|
** does not use LIMIT."
|
||||||
**
|
**
|
||||||
** (11) The subquery and the outer query do not both have ORDER BY clauses.
|
** (11) The subquery and the outer query do not both have ORDER BY clauses.
|
||||||
**
|
**
|
||||||
@ -3709,7 +3712,7 @@ static int flattenSubquery(
|
|||||||
|
|
||||||
#if SELECTTRACE_ENABLED
|
#if SELECTTRACE_ENABLED
|
||||||
if( sqlite3SelectTrace & 0x100 ){
|
if( sqlite3SelectTrace & 0x100 ){
|
||||||
sqlite3DebugPrintf("After flattening:\n");
|
SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
|
||||||
sqlite3TreeViewSelect(0, p, 0);
|
sqlite3TreeViewSelect(0, p, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -3718,6 +3721,73 @@ static int flattenSubquery(
|
|||||||
}
|
}
|
||||||
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
||||||
|
/*
|
||||||
|
** Make copies of relevant WHERE clause terms of the outer query into
|
||||||
|
** the WHERE clause of subquery. Example:
|
||||||
|
**
|
||||||
|
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10;
|
||||||
|
**
|
||||||
|
** Transformed into:
|
||||||
|
**
|
||||||
|
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10)
|
||||||
|
** WHERE x=5 AND y=10;
|
||||||
|
**
|
||||||
|
** The hope is that the terms added to the inner query will make it more
|
||||||
|
** efficient.
|
||||||
|
**
|
||||||
|
** Do not attempt this optimization if:
|
||||||
|
**
|
||||||
|
** (1) The inner query is an aggregate. (In that case, we'd really want
|
||||||
|
** to copy the outer WHERE-clause terms onto the HAVING clause of the
|
||||||
|
** inner query. But they probably won't help there so do not bother.)
|
||||||
|
**
|
||||||
|
** (2) The inner query is the recursive part of a common table expression.
|
||||||
|
**
|
||||||
|
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
|
||||||
|
** close would change the meaning of the LIMIT).
|
||||||
|
**
|
||||||
|
** (4) The inner query is the right operand of a LEFT JOIN. (The caller
|
||||||
|
** enforces this restriction since this routine does not have enough
|
||||||
|
** information to know.)
|
||||||
|
**
|
||||||
|
** Return 0 if no changes are made and non-zero if one or more WHERE clause
|
||||||
|
** terms are duplicated into the subquery.
|
||||||
|
*/
|
||||||
|
static int pushDownWhereTerms(
|
||||||
|
sqlite3 *db, /* The database connection (for malloc()) */
|
||||||
|
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
|
||||||
|
Expr *pWhere, /* The WHERE clause of the outer query */
|
||||||
|
int iCursor /* Cursor number of the subquery */
|
||||||
|
){
|
||||||
|
Expr *pNew;
|
||||||
|
int nChng = 0;
|
||||||
|
if( pWhere==0 ) return 0;
|
||||||
|
if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
|
||||||
|
return 0; /* restrictions (1) and (2) */
|
||||||
|
}
|
||||||
|
if( pSubq->pLimit!=0 ){
|
||||||
|
return 0; /* restriction (3) */
|
||||||
|
}
|
||||||
|
while( pWhere->op==TK_AND ){
|
||||||
|
nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
|
||||||
|
pWhere = pWhere->pLeft;
|
||||||
|
}
|
||||||
|
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
|
||||||
|
nChng++;
|
||||||
|
while( pSubq ){
|
||||||
|
pNew = sqlite3ExprDup(db, pWhere, 0);
|
||||||
|
pNew = substExpr(db, pNew, iCursor, pSubq->pEList);
|
||||||
|
pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew);
|
||||||
|
pSubq = pSubq->pPrior;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nChng;
|
||||||
|
}
|
||||||
|
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Based on the contents of the AggInfo structure indicated by the first
|
** Based on the contents of the AggInfo structure indicated by the first
|
||||||
** argument, this function checks if the following are true:
|
** argument, this function checks if the following are true:
|
||||||
@ -3801,16 +3871,16 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
|
|||||||
** pFrom->pIndex and return SQLITE_OK.
|
** pFrom->pIndex and return SQLITE_OK.
|
||||||
*/
|
*/
|
||||||
int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
|
int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
|
||||||
if( pFrom->pTab && pFrom->zIndex ){
|
if( pFrom->pTab && pFrom->zIndexedBy ){
|
||||||
Table *pTab = pFrom->pTab;
|
Table *pTab = pFrom->pTab;
|
||||||
char *zIndex = pFrom->zIndex;
|
char *zIndexedBy = pFrom->zIndexedBy;
|
||||||
Index *pIdx;
|
Index *pIdx;
|
||||||
for(pIdx=pTab->pIndex;
|
for(pIdx=pTab->pIndex;
|
||||||
pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
|
pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
|
||||||
pIdx=pIdx->pNext
|
pIdx=pIdx->pNext
|
||||||
);
|
);
|
||||||
if( !pIdx ){
|
if( !pIdx ){
|
||||||
sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0);
|
sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
|
||||||
pParse->checkSchema = 1;
|
pParse->checkSchema = 1;
|
||||||
return SQLITE_ERROR;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
@ -4747,12 +4817,11 @@ int sqlite3Select(
|
|||||||
memset(&sSort, 0, sizeof(sSort));
|
memset(&sSort, 0, sizeof(sSort));
|
||||||
sSort.pOrderBy = p->pOrderBy;
|
sSort.pOrderBy = p->pOrderBy;
|
||||||
pTabList = p->pSrc;
|
pTabList = p->pSrc;
|
||||||
pEList = p->pEList;
|
|
||||||
if( pParse->nErr || db->mallocFailed ){
|
if( pParse->nErr || db->mallocFailed ){
|
||||||
goto select_end;
|
goto select_end;
|
||||||
}
|
}
|
||||||
|
assert( p->pEList!=0 );
|
||||||
isAgg = (p->selFlags & SF_Aggregate)!=0;
|
isAgg = (p->selFlags & SF_Aggregate)!=0;
|
||||||
assert( pEList!=0 );
|
|
||||||
#if SELECTTRACE_ENABLED
|
#if SELECTTRACE_ENABLED
|
||||||
if( sqlite3SelectTrace & 0x100 ){
|
if( sqlite3SelectTrace & 0x100 ){
|
||||||
SELECTTRACE(0x100,pParse,p, ("after name resolution:\n"));
|
SELECTTRACE(0x100,pParse,p, ("after name resolution:\n"));
|
||||||
@ -4761,29 +4830,67 @@ int sqlite3Select(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Begin generating code.
|
|
||||||
*/
|
|
||||||
v = sqlite3GetVdbe(pParse);
|
|
||||||
if( v==0 ) goto select_end;
|
|
||||||
|
|
||||||
/* If writing to memory or generating a set
|
/* If writing to memory or generating a set
|
||||||
** only a single column may be output.
|
** only a single column may be output.
|
||||||
*/
|
*/
|
||||||
#ifndef SQLITE_OMIT_SUBQUERY
|
#ifndef SQLITE_OMIT_SUBQUERY
|
||||||
if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){
|
if( checkForMultiColumnSelectError(pParse, pDest, p->pEList->nExpr) ){
|
||||||
goto select_end;
|
goto select_end;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Try to flatten subqueries in the FROM clause up into the main query
|
||||||
|
*/
|
||||||
|
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
||||||
|
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
|
||||||
|
struct SrcList_item *pItem = &pTabList->a[i];
|
||||||
|
Select *pSub = pItem->pSelect;
|
||||||
|
int isAggSub;
|
||||||
|
if( pSub==0 ) continue;
|
||||||
|
isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
|
||||||
|
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
|
||||||
|
/* This subquery can be absorbed into its parent. */
|
||||||
|
if( isAggSub ){
|
||||||
|
isAgg = 1;
|
||||||
|
p->selFlags |= SF_Aggregate;
|
||||||
|
}
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
pTabList = p->pSrc;
|
||||||
|
if( db->mallocFailed ) goto select_end;
|
||||||
|
if( !IgnorableOrderby(pDest) ){
|
||||||
|
sSort.pOrderBy = p->pOrderBy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Get a pointer the VDBE under construction, allocating a new VDBE if one
|
||||||
|
** does not already exist */
|
||||||
|
v = sqlite3GetVdbe(pParse);
|
||||||
|
if( v==0 ) goto select_end;
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_COMPOUND_SELECT
|
||||||
|
/* Handle compound SELECT statements using the separate multiSelect()
|
||||||
|
** procedure.
|
||||||
|
*/
|
||||||
|
if( p->pPrior ){
|
||||||
|
rc = multiSelect(pParse, p, pDest);
|
||||||
|
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
|
||||||
|
#if SELECTTRACE_ENABLED
|
||||||
|
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
|
||||||
|
pParse->nSelectIndent--;
|
||||||
|
#endif
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Generate code for all sub-queries in the FROM clause
|
/* Generate code for all sub-queries in the FROM clause
|
||||||
*/
|
*/
|
||||||
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
||||||
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
|
for(i=0; i<pTabList->nSrc; i++){
|
||||||
struct SrcList_item *pItem = &pTabList->a[i];
|
struct SrcList_item *pItem = &pTabList->a[i];
|
||||||
SelectDest dest;
|
SelectDest dest;
|
||||||
Select *pSub = pItem->pSelect;
|
Select *pSub = pItem->pSelect;
|
||||||
int isAggSub;
|
|
||||||
|
|
||||||
if( pSub==0 ) continue;
|
if( pSub==0 ) continue;
|
||||||
|
|
||||||
/* Sometimes the code for a subquery will be generated more than
|
/* Sometimes the code for a subquery will be generated more than
|
||||||
@ -4808,17 +4915,25 @@ int sqlite3Select(
|
|||||||
*/
|
*/
|
||||||
pParse->nHeight += sqlite3SelectExprHeight(p);
|
pParse->nHeight += sqlite3SelectExprHeight(p);
|
||||||
|
|
||||||
isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
|
/* Make copies of constant WHERE-clause terms in the outer query down
|
||||||
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
|
** inside the subquery. This can help the subquery to run more efficiently.
|
||||||
/* This subquery can be absorbed into its parent. */
|
*/
|
||||||
if( isAggSub ){
|
if( (pItem->jointype & JT_OUTER)==0
|
||||||
isAgg = 1;
|
&& pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
|
||||||
p->selFlags |= SF_Aggregate;
|
){
|
||||||
|
#if SELECTTRACE_ENABLED
|
||||||
|
if( sqlite3SelectTrace & 0x100 ){
|
||||||
|
SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
|
||||||
|
sqlite3TreeViewSelect(0, p, 0);
|
||||||
}
|
}
|
||||||
i = -1;
|
#endif
|
||||||
}else if( pTabList->nSrc==1
|
}
|
||||||
&& (p->selFlags & SF_All)==0
|
|
||||||
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
|
/* Generate code to implement the subquery
|
||||||
|
*/
|
||||||
|
if( pTabList->nSrc==1
|
||||||
|
&& (p->selFlags & SF_All)==0
|
||||||
|
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
|
||||||
){
|
){
|
||||||
/* Implement a co-routine that will return a single row of the result
|
/* Implement a co-routine that will return a single row of the result
|
||||||
** set on each invocation.
|
** set on each invocation.
|
||||||
@ -4869,33 +4984,23 @@ int sqlite3Select(
|
|||||||
sqlite3VdbeChangeP1(v, topAddr, retAddr);
|
sqlite3VdbeChangeP1(v, topAddr, retAddr);
|
||||||
sqlite3ClearTempRegCache(pParse);
|
sqlite3ClearTempRegCache(pParse);
|
||||||
}
|
}
|
||||||
if( /*pParse->nErr ||*/ db->mallocFailed ){
|
if( db->mallocFailed ) goto select_end;
|
||||||
goto select_end;
|
|
||||||
}
|
|
||||||
pParse->nHeight -= sqlite3SelectExprHeight(p);
|
pParse->nHeight -= sqlite3SelectExprHeight(p);
|
||||||
pTabList = p->pSrc;
|
|
||||||
if( !IgnorableOrderby(pDest) ){
|
|
||||||
sSort.pOrderBy = p->pOrderBy;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pEList = p->pEList;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Various elements of the SELECT copied into local variables for
|
||||||
|
** convenience */
|
||||||
|
pEList = p->pEList;
|
||||||
pWhere = p->pWhere;
|
pWhere = p->pWhere;
|
||||||
pGroupBy = p->pGroupBy;
|
pGroupBy = p->pGroupBy;
|
||||||
pHaving = p->pHaving;
|
pHaving = p->pHaving;
|
||||||
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
|
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_COMPOUND_SELECT
|
|
||||||
/* If there is are a sequence of queries, do the earlier ones first.
|
|
||||||
*/
|
|
||||||
if( p->pPrior ){
|
|
||||||
rc = multiSelect(pParse, p, pDest);
|
|
||||||
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
|
|
||||||
#if SELECTTRACE_ENABLED
|
#if SELECTTRACE_ENABLED
|
||||||
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
|
if( sqlite3SelectTrace & 0x400 ){
|
||||||
pParse->nSelectIndent--;
|
SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
|
||||||
#endif
|
sqlite3TreeViewSelect(0, p, 0);
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -4915,23 +5020,23 @@ int sqlite3Select(
|
|||||||
** BY and DISTINCT, and an index or separate temp-table for the other.
|
** BY and DISTINCT, and an index or separate temp-table for the other.
|
||||||
*/
|
*/
|
||||||
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
||||||
&& sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0
|
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
||||||
){
|
){
|
||||||
p->selFlags &= ~SF_Distinct;
|
p->selFlags &= ~SF_Distinct;
|
||||||
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
|
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||||
pGroupBy = p->pGroupBy;
|
|
||||||
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
|
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
|
||||||
** the sDistinct.isTnct is still set. Hence, isTnct represents the
|
** the sDistinct.isTnct is still set. Hence, isTnct represents the
|
||||||
** original setting of the SF_Distinct flag, not the current setting */
|
** original setting of the SF_Distinct flag, not the current setting */
|
||||||
assert( sDistinct.isTnct );
|
assert( sDistinct.isTnct );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there is an ORDER BY clause, then this sorting
|
/* If there is an ORDER BY clause, then create an ephemeral index to
|
||||||
** index might end up being unused if the data can be
|
** do the sorting. But this sorting ephemeral index might end up
|
||||||
** extracted in pre-sorted order. If that is the case, then the
|
** being unused if the data can be extracted in pre-sorted order.
|
||||||
** OP_OpenEphemeral instruction will be changed to an OP_Noop once
|
** If that is the case, then the OP_OpenEphemeral instruction will be
|
||||||
** we figure out that the sorting index is not needed. The addrSortIndex
|
** changed to an OP_Noop once we figure out that the sorting index is
|
||||||
** variable is used to facilitate that change.
|
** not needed. The sSort.addrSortIndex variable is used to facilitate
|
||||||
|
** that change.
|
||||||
*/
|
*/
|
||||||
if( sSort.pOrderBy ){
|
if( sSort.pOrderBy ){
|
||||||
KeyInfo *pKeyInfo;
|
KeyInfo *pKeyInfo;
|
||||||
@ -4962,14 +5067,14 @@ int sqlite3Select(
|
|||||||
sSort.sortFlags |= SORTFLAG_UseSorter;
|
sSort.sortFlags |= SORTFLAG_UseSorter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a virtual index to use for the distinct set.
|
/* Open an ephemeral index to use for the distinct set.
|
||||||
*/
|
*/
|
||||||
if( p->selFlags & SF_Distinct ){
|
if( p->selFlags & SF_Distinct ){
|
||||||
sDistinct.tabTnct = pParse->nTab++;
|
sDistinct.tabTnct = pParse->nTab++;
|
||||||
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
|
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
|
||||||
sDistinct.tabTnct, 0, 0,
|
sDistinct.tabTnct, 0, 0,
|
||||||
(char*)keyInfoFromExprList(pParse, p->pEList,0,0),
|
(char*)keyInfoFromExprList(pParse, p->pEList,0,0),
|
||||||
P4_KEYINFO);
|
P4_KEYINFO);
|
||||||
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
|
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
|
||||||
sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
|
sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
|
||||||
}else{
|
}else{
|
||||||
@ -5047,11 +5152,10 @@ int sqlite3Select(
|
|||||||
p->nSelectRow = 1;
|
p->nSelectRow = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If there is both a GROUP BY and an ORDER BY clause and they are
|
/* If there is both a GROUP BY and an ORDER BY clause and they are
|
||||||
** identical, then it may be possible to disable the ORDER BY clause
|
** identical, then it may be possible to disable the ORDER BY clause
|
||||||
** on the grounds that the GROUP BY will cause elements to come out
|
** on the grounds that the GROUP BY will cause elements to come out
|
||||||
** in the correct order. It also may not - the GROUP BY may use a
|
** in the correct order. It also may not - the GROUP BY might use a
|
||||||
** database index that causes rows to be grouped together as required
|
** database index that causes rows to be grouped together as required
|
||||||
** but not actually sorted. Either way, record the fact that the
|
** but not actually sorted. Either way, record the fact that the
|
||||||
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
|
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
|
||||||
@ -5229,7 +5333,8 @@ int sqlite3Select(
|
|||||||
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
|
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
|
||||||
sqlite3ExprCacheClear(pParse);
|
sqlite3ExprCacheClear(pParse);
|
||||||
if( groupBySort ){
|
if( groupBySort ){
|
||||||
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sortOut,sortPTab);
|
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
|
||||||
|
sortOut, sortPTab);
|
||||||
}
|
}
|
||||||
for(j=0; j<pGroupBy->nExpr; j++){
|
for(j=0; j<pGroupBy->nExpr; j++){
|
||||||
if( groupBySort ){
|
if( groupBySort ){
|
||||||
@ -5301,7 +5406,8 @@ int sqlite3Select(
|
|||||||
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
|
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
|
||||||
sqlite3VdbeResolveLabel(v, addrOutputRow);
|
sqlite3VdbeResolveLabel(v, addrOutputRow);
|
||||||
addrOutputRow = sqlite3VdbeCurrentAddr(v);
|
addrOutputRow = sqlite3VdbeCurrentAddr(v);
|
||||||
sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v);
|
sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
|
||||||
|
VdbeCoverage(v);
|
||||||
VdbeComment((v, "Groupby result generator entry point"));
|
VdbeComment((v, "Groupby result generator entry point"));
|
||||||
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
|
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
|
||||||
finalizeAggFunctions(pParse, &sAggInfo);
|
finalizeAggFunctions(pParse, &sAggInfo);
|
||||||
@ -5465,7 +5571,8 @@ int sqlite3Select(
|
|||||||
** and send them to the callback one by one.
|
** and send them to the callback one by one.
|
||||||
*/
|
*/
|
||||||
if( sSort.pOrderBy ){
|
if( sSort.pOrderBy ){
|
||||||
explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
|
explainTempTable(pParse,
|
||||||
|
sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
|
||||||
generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest);
|
generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5497,97 +5604,3 @@ select_end:
|
|||||||
#endif
|
#endif
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SQLITE_DEBUG
|
|
||||||
/*
|
|
||||||
** Generate a human-readable description of a the Select object.
|
|
||||||
*/
|
|
||||||
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
|
||||||
int n = 0;
|
|
||||||
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
|
||||||
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x",
|
|
||||||
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
|
|
||||||
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags
|
|
||||||
);
|
|
||||||
if( p->pSrc && p->pSrc->nSrc ) n++;
|
|
||||||
if( p->pWhere ) n++;
|
|
||||||
if( p->pGroupBy ) n++;
|
|
||||||
if( p->pHaving ) n++;
|
|
||||||
if( p->pOrderBy ) n++;
|
|
||||||
if( p->pLimit ) n++;
|
|
||||||
if( p->pOffset ) n++;
|
|
||||||
if( p->pPrior ) n++;
|
|
||||||
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
|
|
||||||
if( p->pSrc && p->pSrc->nSrc ){
|
|
||||||
int i;
|
|
||||||
pView = sqlite3TreeViewPush(pView, (n--)>0);
|
|
||||||
sqlite3TreeViewLine(pView, "FROM");
|
|
||||||
for(i=0; i<p->pSrc->nSrc; i++){
|
|
||||||
struct SrcList_item *pItem = &p->pSrc->a[i];
|
|
||||||
StrAccum x;
|
|
||||||
char zLine[100];
|
|
||||||
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
|
|
||||||
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
|
|
||||||
if( pItem->zDatabase ){
|
|
||||||
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
|
|
||||||
}else if( pItem->zName ){
|
|
||||||
sqlite3XPrintf(&x, 0, " %s", pItem->zName);
|
|
||||||
}
|
|
||||||
if( pItem->pTab ){
|
|
||||||
sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName);
|
|
||||||
}
|
|
||||||
if( pItem->zAlias ){
|
|
||||||
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
|
|
||||||
}
|
|
||||||
if( pItem->jointype & JT_LEFT ){
|
|
||||||
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
|
|
||||||
}
|
|
||||||
sqlite3StrAccumFinish(&x);
|
|
||||||
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
|
|
||||||
if( pItem->pSelect ){
|
|
||||||
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
|
|
||||||
}
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
if( p->pWhere ){
|
|
||||||
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
|
|
||||||
sqlite3TreeViewExpr(pView, p->pWhere, 0);
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
if( p->pGroupBy ){
|
|
||||||
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
|
|
||||||
}
|
|
||||||
if( p->pHaving ){
|
|
||||||
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
|
|
||||||
sqlite3TreeViewExpr(pView, p->pHaving, 0);
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
if( p->pOrderBy ){
|
|
||||||
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
|
|
||||||
}
|
|
||||||
if( p->pLimit ){
|
|
||||||
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
|
|
||||||
sqlite3TreeViewExpr(pView, p->pLimit, 0);
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
if( p->pOffset ){
|
|
||||||
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
|
|
||||||
sqlite3TreeViewExpr(pView, p->pOffset, 0);
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
if( p->pPrior ){
|
|
||||||
const char *zOp = "UNION";
|
|
||||||
switch( p->op ){
|
|
||||||
case TK_ALL: zOp = "UNION ALL"; break;
|
|
||||||
case TK_INTERSECT: zOp = "INTERSECT"; break;
|
|
||||||
case TK_EXCEPT: zOp = "EXCEPT"; break;
|
|
||||||
}
|
|
||||||
sqlite3TreeViewItem(pView, zOp, (n--)>0);
|
|
||||||
sqlite3TreeViewSelect(pView, p->pPrior, 0);
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
sqlite3TreeViewPop(pView);
|
|
||||||
}
|
|
||||||
#endif /* SQLITE_DEBUG */
|
|
||||||
|
@ -956,7 +956,7 @@ struct sqlite3_io_methods {
|
|||||||
** pointed to by the pArg argument. This capability is used during testing
|
** pointed to by the pArg argument. This capability is used during testing
|
||||||
** and only needs to be supported when SQLITE_TEST is defined.
|
** and only needs to be supported when SQLITE_TEST is defined.
|
||||||
**
|
**
|
||||||
* <li>[[SQLITE_FCNTL_WAL_BLOCK]]
|
** <li>[[SQLITE_FCNTL_WAL_BLOCK]]
|
||||||
** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
|
** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
|
||||||
** be advantageous to block on the next WAL lock if the lock is not immediately
|
** be advantageous to block on the next WAL lock if the lock is not immediately
|
||||||
** available. The WAL subsystem issues this signal during rare
|
** available. The WAL subsystem issues this signal during rare
|
||||||
|
@ -1509,9 +1509,9 @@ struct CollSeq {
|
|||||||
** used as the P4 operand, they will be more readable.
|
** used as the P4 operand, they will be more readable.
|
||||||
**
|
**
|
||||||
** Note also that the numeric types are grouped together so that testing
|
** Note also that the numeric types are grouped together so that testing
|
||||||
** for a numeric type is a single comparison. And the NONE type is first.
|
** for a numeric type is a single comparison. And the BLOB type is first.
|
||||||
*/
|
*/
|
||||||
#define SQLITE_AFF_NONE 'A'
|
#define SQLITE_AFF_BLOB 'A'
|
||||||
#define SQLITE_AFF_TEXT 'B'
|
#define SQLITE_AFF_TEXT 'B'
|
||||||
#define SQLITE_AFF_NUMERIC 'C'
|
#define SQLITE_AFF_NUMERIC 'C'
|
||||||
#define SQLITE_AFF_INTEGER 'D'
|
#define SQLITE_AFF_INTEGER 'D'
|
||||||
@ -2268,7 +2268,7 @@ struct SrcList {
|
|||||||
Expr *pOn; /* The ON clause of a join */
|
Expr *pOn; /* The ON clause of a join */
|
||||||
IdList *pUsing; /* The USING clause of a join */
|
IdList *pUsing; /* The USING clause of a join */
|
||||||
Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
|
Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
|
||||||
char *zIndex; /* Identifier from "INDEXED BY <zIndex>" clause */
|
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
|
||||||
Index *pIndex; /* Index structure corresponding to zIndex, if any */
|
Index *pIndex; /* Index structure corresponding to zIndex, if any */
|
||||||
} a[1]; /* One entry for each identifier on the list */
|
} a[1]; /* One entry for each identifier on the list */
|
||||||
};
|
};
|
||||||
@ -3182,10 +3182,6 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SQLITE_DEBUG)
|
#if defined(SQLITE_DEBUG)
|
||||||
TreeView *sqlite3TreeViewPush(TreeView*,u8);
|
|
||||||
void sqlite3TreeViewPop(TreeView*);
|
|
||||||
void sqlite3TreeViewLine(TreeView*, const char*, ...);
|
|
||||||
void sqlite3TreeViewItem(TreeView*, const char*, u8);
|
|
||||||
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
|
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
|
||||||
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
|
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
|
||||||
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
|
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
|
||||||
@ -3342,6 +3338,7 @@ int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8);
|
|||||||
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
|
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
|
||||||
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
|
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
|
||||||
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
|
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
|
||||||
|
void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
|
||||||
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
|
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
|
||||||
Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
|
Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
|
||||||
Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
|
Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
|
||||||
|
425
src/treeview.c
Normal file
425
src/treeview.c
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
/*
|
||||||
|
** 2015-06-08
|
||||||
|
**
|
||||||
|
** 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 C code to implement the TreeView debugging routines.
|
||||||
|
** These routines print a parse tree to standard output for debugging and
|
||||||
|
** analysis.
|
||||||
|
**
|
||||||
|
** The interfaces in this file is only available when compiling
|
||||||
|
** with SQLITE_DEBUG.
|
||||||
|
*/
|
||||||
|
#include "sqliteInt.h"
|
||||||
|
#ifdef SQLITE_DEBUG
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Add a new subitem to the tree. The moreToFollow flag indicates that this
|
||||||
|
** is not the last item in the tree.
|
||||||
|
*/
|
||||||
|
static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
|
||||||
|
if( p==0 ){
|
||||||
|
p = sqlite3_malloc64( sizeof(*p) );
|
||||||
|
if( p==0 ) return 0;
|
||||||
|
memset(p, 0, sizeof(*p));
|
||||||
|
}else{
|
||||||
|
p->iLevel++;
|
||||||
|
}
|
||||||
|
assert( moreToFollow==0 || moreToFollow==1 );
|
||||||
|
if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Finished with one layer of the tree
|
||||||
|
*/
|
||||||
|
static void sqlite3TreeViewPop(TreeView *p){
|
||||||
|
if( p==0 ) return;
|
||||||
|
p->iLevel--;
|
||||||
|
if( p->iLevel<0 ) sqlite3_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Generate a single line of output for the tree, with a prefix that contains
|
||||||
|
** all the appropriate tree lines
|
||||||
|
*/
|
||||||
|
static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
|
||||||
|
va_list ap;
|
||||||
|
int i;
|
||||||
|
StrAccum acc;
|
||||||
|
char zBuf[500];
|
||||||
|
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
||||||
|
if( p ){
|
||||||
|
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
|
||||||
|
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
|
||||||
|
}
|
||||||
|
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
|
||||||
|
}
|
||||||
|
va_start(ap, zFormat);
|
||||||
|
sqlite3VXPrintf(&acc, 0, zFormat, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
|
||||||
|
sqlite3StrAccumFinish(&acc);
|
||||||
|
fprintf(stdout,"%s", zBuf);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Shorthand for starting a new tree item that consists of a single label
|
||||||
|
*/
|
||||||
|
static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
|
||||||
|
p = sqlite3TreeViewPush(p, moreFollows);
|
||||||
|
sqlite3TreeViewLine(p, "%s", zLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Generate a human-readable description of a the Select object.
|
||||||
|
*/
|
||||||
|
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||||
|
int n = 0;
|
||||||
|
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
||||||
|
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x",
|
||||||
|
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
|
||||||
|
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags
|
||||||
|
);
|
||||||
|
if( p->pSrc && p->pSrc->nSrc ) n++;
|
||||||
|
if( p->pWhere ) n++;
|
||||||
|
if( p->pGroupBy ) n++;
|
||||||
|
if( p->pHaving ) n++;
|
||||||
|
if( p->pOrderBy ) n++;
|
||||||
|
if( p->pLimit ) n++;
|
||||||
|
if( p->pOffset ) n++;
|
||||||
|
if( p->pPrior ) n++;
|
||||||
|
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
|
||||||
|
if( p->pSrc && p->pSrc->nSrc ){
|
||||||
|
int i;
|
||||||
|
pView = sqlite3TreeViewPush(pView, (n--)>0);
|
||||||
|
sqlite3TreeViewLine(pView, "FROM");
|
||||||
|
for(i=0; i<p->pSrc->nSrc; i++){
|
||||||
|
struct SrcList_item *pItem = &p->pSrc->a[i];
|
||||||
|
StrAccum x;
|
||||||
|
char zLine[100];
|
||||||
|
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
|
||||||
|
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
|
||||||
|
if( pItem->zDatabase ){
|
||||||
|
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
|
||||||
|
}else if( pItem->zName ){
|
||||||
|
sqlite3XPrintf(&x, 0, " %s", pItem->zName);
|
||||||
|
}
|
||||||
|
if( pItem->pTab ){
|
||||||
|
sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName);
|
||||||
|
}
|
||||||
|
if( pItem->zAlias ){
|
||||||
|
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
|
||||||
|
}
|
||||||
|
if( pItem->jointype & JT_LEFT ){
|
||||||
|
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
|
||||||
|
}
|
||||||
|
sqlite3StrAccumFinish(&x);
|
||||||
|
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
|
||||||
|
if( pItem->pSelect ){
|
||||||
|
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
|
||||||
|
}
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
if( p->pWhere ){
|
||||||
|
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
|
||||||
|
sqlite3TreeViewExpr(pView, p->pWhere, 0);
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
if( p->pGroupBy ){
|
||||||
|
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
|
||||||
|
}
|
||||||
|
if( p->pHaving ){
|
||||||
|
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
|
||||||
|
sqlite3TreeViewExpr(pView, p->pHaving, 0);
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
if( p->pOrderBy ){
|
||||||
|
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
|
||||||
|
}
|
||||||
|
if( p->pLimit ){
|
||||||
|
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
|
||||||
|
sqlite3TreeViewExpr(pView, p->pLimit, 0);
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
if( p->pOffset ){
|
||||||
|
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
|
||||||
|
sqlite3TreeViewExpr(pView, p->pOffset, 0);
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
if( p->pPrior ){
|
||||||
|
const char *zOp = "UNION";
|
||||||
|
switch( p->op ){
|
||||||
|
case TK_ALL: zOp = "UNION ALL"; break;
|
||||||
|
case TK_INTERSECT: zOp = "INTERSECT"; break;
|
||||||
|
case TK_EXCEPT: zOp = "EXCEPT"; break;
|
||||||
|
}
|
||||||
|
sqlite3TreeViewItem(pView, zOp, (n--)>0);
|
||||||
|
sqlite3TreeViewSelect(pView, p->pPrior, 0);
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Generate a human-readable explanation of an expression tree.
|
||||||
|
*/
|
||||||
|
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||||
|
const char *zBinOp = 0; /* Binary operator */
|
||||||
|
const char *zUniOp = 0; /* Unary operator */
|
||||||
|
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
||||||
|
if( pExpr==0 ){
|
||||||
|
sqlite3TreeViewLine(pView, "nil");
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch( pExpr->op ){
|
||||||
|
case TK_AGG_COLUMN: {
|
||||||
|
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
|
||||||
|
pExpr->iTable, pExpr->iColumn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_COLUMN: {
|
||||||
|
if( pExpr->iTable<0 ){
|
||||||
|
/* This only happens when coding check constraints */
|
||||||
|
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
|
||||||
|
}else{
|
||||||
|
sqlite3TreeViewLine(pView, "{%d:%d}",
|
||||||
|
pExpr->iTable, pExpr->iColumn);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_INTEGER: {
|
||||||
|
if( pExpr->flags & EP_IntValue ){
|
||||||
|
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
|
||||||
|
}else{
|
||||||
|
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||||
|
case TK_FLOAT: {
|
||||||
|
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case TK_STRING: {
|
||||||
|
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_NULL: {
|
||||||
|
sqlite3TreeViewLine(pView,"NULL");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
||||||
|
case TK_BLOB: {
|
||||||
|
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case TK_VARIABLE: {
|
||||||
|
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
|
||||||
|
pExpr->u.zToken, pExpr->iColumn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_REGISTER: {
|
||||||
|
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_AS: {
|
||||||
|
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
|
||||||
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_ID: {
|
||||||
|
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_CAST
|
||||||
|
case TK_CAST: {
|
||||||
|
/* Expressions of the form: CAST(pLeft AS token) */
|
||||||
|
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
|
||||||
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_CAST */
|
||||||
|
case TK_LT: zBinOp = "LT"; break;
|
||||||
|
case TK_LE: zBinOp = "LE"; break;
|
||||||
|
case TK_GT: zBinOp = "GT"; break;
|
||||||
|
case TK_GE: zBinOp = "GE"; break;
|
||||||
|
case TK_NE: zBinOp = "NE"; break;
|
||||||
|
case TK_EQ: zBinOp = "EQ"; break;
|
||||||
|
case TK_IS: zBinOp = "IS"; break;
|
||||||
|
case TK_ISNOT: zBinOp = "ISNOT"; break;
|
||||||
|
case TK_AND: zBinOp = "AND"; break;
|
||||||
|
case TK_OR: zBinOp = "OR"; break;
|
||||||
|
case TK_PLUS: zBinOp = "ADD"; break;
|
||||||
|
case TK_STAR: zBinOp = "MUL"; break;
|
||||||
|
case TK_MINUS: zBinOp = "SUB"; break;
|
||||||
|
case TK_REM: zBinOp = "REM"; break;
|
||||||
|
case TK_BITAND: zBinOp = "BITAND"; break;
|
||||||
|
case TK_BITOR: zBinOp = "BITOR"; break;
|
||||||
|
case TK_SLASH: zBinOp = "DIV"; break;
|
||||||
|
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
|
||||||
|
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
|
||||||
|
case TK_CONCAT: zBinOp = "CONCAT"; break;
|
||||||
|
case TK_DOT: zBinOp = "DOT"; break;
|
||||||
|
|
||||||
|
case TK_UMINUS: zUniOp = "UMINUS"; break;
|
||||||
|
case TK_UPLUS: zUniOp = "UPLUS"; break;
|
||||||
|
case TK_BITNOT: zUniOp = "BITNOT"; break;
|
||||||
|
case TK_NOT: zUniOp = "NOT"; break;
|
||||||
|
case TK_ISNULL: zUniOp = "ISNULL"; break;
|
||||||
|
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
|
||||||
|
|
||||||
|
case TK_COLLATE: {
|
||||||
|
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
|
||||||
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TK_AGG_FUNCTION:
|
||||||
|
case TK_FUNCTION: {
|
||||||
|
ExprList *pFarg; /* List of function arguments */
|
||||||
|
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
|
||||||
|
pFarg = 0;
|
||||||
|
}else{
|
||||||
|
pFarg = pExpr->x.pList;
|
||||||
|
}
|
||||||
|
if( pExpr->op==TK_AGG_FUNCTION ){
|
||||||
|
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
|
||||||
|
pExpr->op2, pExpr->u.zToken);
|
||||||
|
}else{
|
||||||
|
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
|
||||||
|
}
|
||||||
|
if( pFarg ){
|
||||||
|
sqlite3TreeViewExprList(pView, pFarg, 0, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_SUBQUERY
|
||||||
|
case TK_EXISTS: {
|
||||||
|
sqlite3TreeViewLine(pView, "EXISTS-expr");
|
||||||
|
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_SELECT: {
|
||||||
|
sqlite3TreeViewLine(pView, "SELECT-expr");
|
||||||
|
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_IN: {
|
||||||
|
sqlite3TreeViewLine(pView, "IN");
|
||||||
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||||
|
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||||
|
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||||
|
}else{
|
||||||
|
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_SUBQUERY */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** x BETWEEN y AND z
|
||||||
|
**
|
||||||
|
** This is equivalent to
|
||||||
|
**
|
||||||
|
** x>=y AND x<=z
|
||||||
|
**
|
||||||
|
** X is stored in pExpr->pLeft.
|
||||||
|
** Y is stored in pExpr->pList->a[0].pExpr.
|
||||||
|
** Z is stored in pExpr->pList->a[1].pExpr.
|
||||||
|
*/
|
||||||
|
case TK_BETWEEN: {
|
||||||
|
Expr *pX = pExpr->pLeft;
|
||||||
|
Expr *pY = pExpr->x.pList->a[0].pExpr;
|
||||||
|
Expr *pZ = pExpr->x.pList->a[1].pExpr;
|
||||||
|
sqlite3TreeViewLine(pView, "BETWEEN");
|
||||||
|
sqlite3TreeViewExpr(pView, pX, 1);
|
||||||
|
sqlite3TreeViewExpr(pView, pY, 1);
|
||||||
|
sqlite3TreeViewExpr(pView, pZ, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_TRIGGER: {
|
||||||
|
/* If the opcode is TK_TRIGGER, then the expression is a reference
|
||||||
|
** to a column in the new.* or old.* pseudo-tables available to
|
||||||
|
** trigger programs. In this case Expr.iTable is set to 1 for the
|
||||||
|
** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
|
||||||
|
** is set to the column of the pseudo-table to read, or to -1 to
|
||||||
|
** read the rowid field.
|
||||||
|
*/
|
||||||
|
sqlite3TreeViewLine(pView, "%s(%d)",
|
||||||
|
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_CASE: {
|
||||||
|
sqlite3TreeViewLine(pView, "CASE");
|
||||||
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||||
|
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
|
case TK_RAISE: {
|
||||||
|
const char *zType = "unk";
|
||||||
|
switch( pExpr->affinity ){
|
||||||
|
case OE_Rollback: zType = "rollback"; break;
|
||||||
|
case OE_Abort: zType = "abort"; break;
|
||||||
|
case OE_Fail: zType = "fail"; break;
|
||||||
|
case OE_Ignore: zType = "ignore"; break;
|
||||||
|
}
|
||||||
|
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default: {
|
||||||
|
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( zBinOp ){
|
||||||
|
sqlite3TreeViewLine(pView, "%s", zBinOp);
|
||||||
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||||
|
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
|
||||||
|
}else if( zUniOp ){
|
||||||
|
sqlite3TreeViewLine(pView, "%s", zUniOp);
|
||||||
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||||
|
}
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Generate a human-readable explanation of an expression list.
|
||||||
|
*/
|
||||||
|
void sqlite3TreeViewExprList(
|
||||||
|
TreeView *pView,
|
||||||
|
const ExprList *pList,
|
||||||
|
u8 moreToFollow,
|
||||||
|
const char *zLabel
|
||||||
|
){
|
||||||
|
int i;
|
||||||
|
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
||||||
|
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
|
||||||
|
if( pList==0 ){
|
||||||
|
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
|
||||||
|
}else{
|
||||||
|
sqlite3TreeViewLine(pView, "%s", zLabel);
|
||||||
|
for(i=0; i<pList->nExpr; i++){
|
||||||
|
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3TreeViewPop(pView);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SQLITE_DEBUG */
|
@ -280,7 +280,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
|
|||||||
** SQLITE_AFF_TEXT:
|
** SQLITE_AFF_TEXT:
|
||||||
** Convert pRec to a text representation.
|
** Convert pRec to a text representation.
|
||||||
**
|
**
|
||||||
** SQLITE_AFF_NONE:
|
** SQLITE_AFF_BLOB:
|
||||||
** No-op. pRec is unchanged.
|
** No-op. pRec is unchanged.
|
||||||
*/
|
*/
|
||||||
static void applyAffinity(
|
static void applyAffinity(
|
||||||
@ -1790,9 +1790,9 @@ case OP_RealAffinity: { /* in1 */
|
|||||||
** A NULL value is not changed by this routine. It remains NULL.
|
** A NULL value is not changed by this routine. It remains NULL.
|
||||||
*/
|
*/
|
||||||
case OP_Cast: { /* in1 */
|
case OP_Cast: { /* in1 */
|
||||||
assert( pOp->p2>=SQLITE_AFF_NONE && pOp->p2<=SQLITE_AFF_REAL );
|
assert( pOp->p2>=SQLITE_AFF_BLOB && pOp->p2<=SQLITE_AFF_REAL );
|
||||||
testcase( pOp->p2==SQLITE_AFF_TEXT );
|
testcase( pOp->p2==SQLITE_AFF_TEXT );
|
||||||
testcase( pOp->p2==SQLITE_AFF_NONE );
|
testcase( pOp->p2==SQLITE_AFF_BLOB );
|
||||||
testcase( pOp->p2==SQLITE_AFF_NUMERIC );
|
testcase( pOp->p2==SQLITE_AFF_NUMERIC );
|
||||||
testcase( pOp->p2==SQLITE_AFF_INTEGER );
|
testcase( pOp->p2==SQLITE_AFF_INTEGER );
|
||||||
testcase( pOp->p2==SQLITE_AFF_REAL );
|
testcase( pOp->p2==SQLITE_AFF_REAL );
|
||||||
@ -2603,7 +2603,7 @@ case OP_Affinity: {
|
|||||||
** The mapping from character to affinity is given by the SQLITE_AFF_
|
** The mapping from character to affinity is given by the SQLITE_AFF_
|
||||||
** macros defined in sqliteInt.h.
|
** macros defined in sqliteInt.h.
|
||||||
**
|
**
|
||||||
** If P4 is NULL then all index fields have the affinity NONE.
|
** If P4 is NULL then all index fields have the affinity BLOB.
|
||||||
*/
|
*/
|
||||||
case OP_MakeRecord: {
|
case OP_MakeRecord: {
|
||||||
u8 *zNewRecord; /* A buffer to hold the data for the new record */
|
u8 *zNewRecord; /* A buffer to hold the data for the new record */
|
||||||
|
@ -588,7 +588,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
|
|||||||
void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
|
void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
|
||||||
if( pMem->flags & MEM_Null ) return;
|
if( pMem->flags & MEM_Null ) return;
|
||||||
switch( aff ){
|
switch( aff ){
|
||||||
case SQLITE_AFF_NONE: { /* Really a cast to BLOB */
|
case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
|
||||||
if( (pMem->flags & MEM_Blob)==0 ){
|
if( (pMem->flags & MEM_Blob)==0 ){
|
||||||
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
|
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
|
||||||
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
|
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
|
||||||
@ -1307,7 +1307,7 @@ static int valueFromExpr(
|
|||||||
if( zVal==0 ) goto no_mem;
|
if( zVal==0 ) goto no_mem;
|
||||||
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
|
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
|
||||||
}
|
}
|
||||||
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
|
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){
|
||||||
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
|
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
|
||||||
}else{
|
}else{
|
||||||
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
|
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
|
||||||
|
2851
src/where.c
2851
src/where.c
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,7 @@
|
|||||||
** Trace output macros
|
** Trace output macros
|
||||||
*/
|
*/
|
||||||
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
|
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
|
||||||
/***/ int sqlite3WhereTrace = 0;
|
/***/ int sqlite3WhereTrace;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SQLITE_DEBUG) \
|
#if defined(SQLITE_DEBUG) \
|
||||||
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
|
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
|
||||||
@ -161,10 +161,6 @@ struct WhereOrSet {
|
|||||||
WhereOrCost a[N_OR_COST]; /* Set of best costs */
|
WhereOrCost a[N_OR_COST]; /* Set of best costs */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Forward declaration of methods */
|
|
||||||
static int whereLoopResize(sqlite3*, WhereLoop*, int);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Each instance of this object holds a sequence of WhereLoop objects
|
** Each instance of this object holds a sequence of WhereLoop objects
|
||||||
** that implement some or all of a query plan.
|
** that implement some or all of a query plan.
|
||||||
@ -372,6 +368,11 @@ struct WhereMaskSet {
|
|||||||
int ix[BMS]; /* Cursor assigned to each bit */
|
int ix[BMS]; /* Cursor assigned to each bit */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Initialize a WhereMaskSet object
|
||||||
|
*/
|
||||||
|
#define initMaskSet(P) (P)->n=0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This object is a convenience wrapper holding all information needed
|
** This object is a convenience wrapper holding all information needed
|
||||||
** to construct WhereLoop objects for a particular query.
|
** to construct WhereLoop objects for a particular query.
|
||||||
@ -423,6 +424,62 @@ struct WhereInfo {
|
|||||||
WhereLevel a[1]; /* Information about each nest loop in WHERE */
|
WhereLevel a[1]; /* Information about each nest loop in WHERE */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Private interfaces - callable only by other where.c routines.
|
||||||
|
**
|
||||||
|
** where.c:
|
||||||
|
*/
|
||||||
|
Bitmask sqlite3WhereGetMask(WhereMaskSet*,int);
|
||||||
|
WhereTerm *sqlite3WhereFindTerm(
|
||||||
|
WhereClause *pWC, /* The WHERE clause to be searched */
|
||||||
|
int iCur, /* Cursor number of LHS */
|
||||||
|
int iColumn, /* Column number of LHS */
|
||||||
|
Bitmask notReady, /* RHS must not overlap with this mask */
|
||||||
|
u32 op, /* Mask of WO_xx values describing operator */
|
||||||
|
Index *pIdx /* Must be compatible with this index, if not NULL */
|
||||||
|
);
|
||||||
|
|
||||||
|
/* wherecode.c: */
|
||||||
|
#ifndef SQLITE_OMIT_EXPLAIN
|
||||||
|
int sqlite3WhereExplainOneScan(
|
||||||
|
Parse *pParse, /* Parse context */
|
||||||
|
SrcList *pTabList, /* Table list this loop refers to */
|
||||||
|
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
|
||||||
|
int iLevel, /* Value for "level" column of output */
|
||||||
|
int iFrom, /* Value for "from" column of output */
|
||||||
|
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0
|
||||||
|
#endif /* SQLITE_OMIT_EXPLAIN */
|
||||||
|
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||||
|
void sqlite3WhereAddScanStatus(
|
||||||
|
Vdbe *v, /* Vdbe to add scanstatus entry to */
|
||||||
|
SrcList *pSrclist, /* FROM clause pLvl reads data from */
|
||||||
|
WhereLevel *pLvl, /* Level to add scanstatus() entry for */
|
||||||
|
int addrExplain /* Address of OP_Explain (or 0) */
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
# define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d)
|
||||||
|
#endif
|
||||||
|
Bitmask sqlite3WhereCodeOneLoopStart(
|
||||||
|
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
|
||||||
|
int iLevel, /* Which level of pWInfo->a[] should be coded */
|
||||||
|
Bitmask notReady /* Which tables are currently available */
|
||||||
|
);
|
||||||
|
|
||||||
|
/* whereexpr.c: */
|
||||||
|
void sqlite3WhereClauseInit(WhereClause*,WhereInfo*);
|
||||||
|
void sqlite3WhereClauseClear(WhereClause*);
|
||||||
|
void sqlite3WhereSplit(WhereClause*,Expr*,u8);
|
||||||
|
Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
|
||||||
|
Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
|
||||||
|
void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Bitmasks for the operators on WhereTerm objects. These are all
|
** Bitmasks for the operators on WhereTerm objects. These are all
|
||||||
** operators that are of interest to the query planner. An
|
** operators that are of interest to the query planner. An
|
||||||
|
1501
src/wherecode.c
Normal file
1501
src/wherecode.c
Normal file
File diff suppressed because it is too large
Load Diff
1249
src/whereexpr.c
Normal file
1249
src/whereexpr.c
Normal file
File diff suppressed because it is too large
Load Diff
61
test/affinity2.test
Normal file
61
test/affinity2.test
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# 2015-06-02
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source code. In place of
|
||||||
|
# a legal notice, here is a blessing:
|
||||||
|
#
|
||||||
|
# May you do good and not evil.
|
||||||
|
# May you find forgiveness for yourself and forgive others.
|
||||||
|
# May you share freely, never taking more than you give.
|
||||||
|
#
|
||||||
|
#***********************************************************************
|
||||||
|
# This file implements regression tests for SQLite library. The
|
||||||
|
# focus of this file is type affinity in comparison operations.
|
||||||
|
#
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
|
||||||
|
do_execsql_test affinity2-100 {
|
||||||
|
CREATE TABLE t1(
|
||||||
|
xi INTEGER,
|
||||||
|
xr REAL,
|
||||||
|
xb BLOB,
|
||||||
|
xn NUMERIC,
|
||||||
|
xt TEXT
|
||||||
|
);
|
||||||
|
INSERT INTO t1(rowid,xi,xr,xb,xn,xt) VALUES(1,1,1,1,1,1);
|
||||||
|
INSERT INTO t1(rowid,xi,xr,xb,xn,xt) VALUES(2,'2','2','2','2','2');
|
||||||
|
INSERT INTO t1(rowid,xi,xr,xb,xn,xt) VALUES(3,'03','03','03','03','03');
|
||||||
|
|
||||||
|
} {}
|
||||||
|
do_execsql_test affinity2-110 {
|
||||||
|
SELECT xi, typeof(xi) FROM t1 ORDER BY rowid;
|
||||||
|
} {1 integer 2 integer 3 integer}
|
||||||
|
do_execsql_test affinity2-120 {
|
||||||
|
SELECT xr, typeof(xr) FROM t1 ORDER BY rowid;
|
||||||
|
} {1.0 real 2.0 real 3.0 real}
|
||||||
|
do_execsql_test affinity2-130 {
|
||||||
|
SELECT xb, typeof(xb) FROM t1 ORDER BY rowid;
|
||||||
|
} {1 integer 2 text 03 text}
|
||||||
|
do_execsql_test affinity2-140 {
|
||||||
|
SELECT xn, typeof(xn) FROM t1 ORDER BY rowid;
|
||||||
|
} {1 integer 2 integer 3 integer}
|
||||||
|
do_execsql_test affinity2-150 {
|
||||||
|
SELECT xt, typeof(xt) FROM t1 ORDER BY rowid;
|
||||||
|
} {1 text 2 text 03 text}
|
||||||
|
|
||||||
|
do_execsql_test affinity2-200 {
|
||||||
|
SELECT rowid, xi==xt, xi==xb, xi==+xt FROM t1 ORDER BY rowid;
|
||||||
|
} {1 1 1 1 2 1 1 1 3 1 1 1}
|
||||||
|
do_execsql_test affinity2-210 {
|
||||||
|
SELECT rowid, xr==xt, xr==xb, xr==+xt FROM t1 ORDER BY rowid;
|
||||||
|
} {1 1 1 1 2 1 1 1 3 1 1 1}
|
||||||
|
do_execsql_test affinity2-220 {
|
||||||
|
SELECT rowid, xn==xt, xn==xb, xn==+xt FROM t1 ORDER BY rowid;
|
||||||
|
} {1 1 1 1 2 1 1 1 3 1 1 1}
|
||||||
|
|
||||||
|
do_execsql_test affinity2-300 {
|
||||||
|
SELECT rowid, xt==+xi, xt==xi, xt==xb FROM t1 ORDER BY rowid;
|
||||||
|
} {1 1 1 0 2 1 1 1 3 0 1 1}
|
||||||
|
|
||||||
|
finish_test
|
@ -24,6 +24,11 @@ if {$tcl_platform(platform)=="windows"} {
|
|||||||
} else {
|
} else {
|
||||||
set PROG "./sqlite3_analyzer"
|
set PROG "./sqlite3_analyzer"
|
||||||
}
|
}
|
||||||
|
if {![file exe $PROG]} {
|
||||||
|
puts "analyzer1 cannot run because $PROG is not available"
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
db close
|
db close
|
||||||
forcedelete test.db test.db-journal test.db-wal
|
forcedelete test.db test.db-journal test.db-wal
|
||||||
sqlite3 db test.db
|
sqlite3 db test.db
|
||||||
|
@ -171,7 +171,6 @@ foreach {tn code} {
|
|||||||
#
|
#
|
||||||
set ::busy_callback_count 0
|
set ::busy_callback_count 0
|
||||||
proc busy_callback {args} {
|
proc busy_callback {args} {
|
||||||
puts Hello
|
|
||||||
incr ::busy_callback_count
|
incr ::busy_callback_count
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
16
test/extraquick.test
Normal file
16
test/extraquick.test
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# 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 runs most of the tests run by veryquick.test except for those
|
||||||
|
# that take a long time.
|
||||||
|
#
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/permutations.test
|
||||||
|
|
||||||
|
run_test_suite extraquick
|
||||||
|
|
||||||
|
finish_test
|
@ -39,7 +39,6 @@ do_test filectrl-1.5 {
|
|||||||
do_test filectrl-1.6 {
|
do_test filectrl-1.6 {
|
||||||
sqlite3 db test.db
|
sqlite3 db test.db
|
||||||
set fn [file_control_tempfilename db]
|
set fn [file_control_tempfilename db]
|
||||||
puts -nonewline \[$fn\]
|
|
||||||
set fn
|
set fn
|
||||||
} {/etilqs_/}
|
} {/etilqs_/}
|
||||||
db close
|
db close
|
||||||
|
@ -213,7 +213,7 @@ do_test fts3d-4.matches {
|
|||||||
{0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4} \
|
{0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4} \
|
||||||
{0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4}]
|
{0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4}]
|
||||||
|
|
||||||
puts [db eval {SELECT c FROM t1 } ]
|
db eval {SELECT c FROM t1 }
|
||||||
check_terms_all fts3d-4.1 {a four is test that this was}
|
check_terms_all fts3d-4.1 {a four is test that this was}
|
||||||
check_doclist_all fts3d-4.1.1 a {[1 0[2]] [2 0[2]] [3 0[2]]}
|
check_doclist_all fts3d-4.1.1 a {[1 0[2]] [2 0[2]] [3 0[2]]}
|
||||||
check_doclist_all fts3d-4.1.2 four {}
|
check_doclist_all fts3d-4.1.2 four {}
|
||||||
|
@ -47,7 +47,9 @@ foreach {tn q res} {
|
|||||||
do_execsql_test 2.$tn.$s $q $res
|
do_execsql_test 2.$tn.$s $q $res
|
||||||
set t($s) [lindex [time [list execsql $q] 100] 0]
|
set t($s) [lindex [time [list execsql $q] 100] 0]
|
||||||
}
|
}
|
||||||
puts "with optimization: $t(0) without: $t(1)"
|
if {0} {
|
||||||
|
puts "with optimization: $t(0) without: $t(1)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_test 2.1 {
|
do_test 2.1 {
|
||||||
|
Binary file not shown.
@ -67,8 +67,10 @@ do_test 1.3 {
|
|||||||
}
|
}
|
||||||
set iPrev $iNext
|
set iPrev $iNext
|
||||||
}
|
}
|
||||||
puts -nonewline \
|
if {0} {
|
||||||
" (forward=$nForward, back=$nBackward, noncontiguous=$nNoncont)"
|
puts -nonewline \
|
||||||
|
" (forward=$nForward, back=$nBackward, noncontiguous=$nNoncont)"
|
||||||
|
}
|
||||||
|
|
||||||
expr {$nForward > 2*($nBackward + $nNoncont)}
|
expr {$nForward > 2*($nBackward + $nNoncont)}
|
||||||
} {1}
|
} {1}
|
||||||
|
@ -327,4 +327,23 @@ do_execsql_test index6-8.2 {
|
|||||||
3 three value 3
|
3 three value 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 2015-06-11. Assertion fault found by AFL
|
||||||
|
#
|
||||||
|
do_execsql_test index6-9.1 {
|
||||||
|
CREATE TABLE t9(a int, b int, c int);
|
||||||
|
CREATE INDEX t9ca ON t9(c,a) WHERE a in (10,12,20);
|
||||||
|
INSERT INTO t9 VALUES(1,1,9),(10,2,35),(11,15,82),(20,19,5),(NULL,7,3);
|
||||||
|
UPDATE t9 SET b=c WHERE a in (10,12,20);
|
||||||
|
SELECT a,b,c,'|' FROM t9 ORDER BY a;
|
||||||
|
} {{} 7 3 | 1 1 9 | 10 35 35 | 11 15 82 | 20 5 5 |}
|
||||||
|
do_execsql_test index6-9.2 {
|
||||||
|
DROP TABLE t9;
|
||||||
|
CREATE TABLE t9(a int, b int, c int, PRIMARY KEY(a)) WITHOUT ROWID;
|
||||||
|
CREATE INDEX t9ca ON t9(c,a) WHERE a in (10,12,20);
|
||||||
|
INSERT INTO t9 VALUES(1,1,9),(10,2,35),(11,15,82),(20,19,5);
|
||||||
|
UPDATE t9 SET b=c WHERE a in (10,12,20);
|
||||||
|
SELECT a,b,c,'|' FROM t9 ORDER BY a;
|
||||||
|
} {1 1 9 | 10 35 35 | 11 15 82 | 20 5 5 |}
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@ -687,4 +687,30 @@ ifcapable pragma&&compileoption_diags {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Test a problem with reordering tables following a LEFT JOIN.
|
||||||
|
#
|
||||||
|
do_execsql_test join-13.0 {
|
||||||
|
CREATE TABLE aa(a);
|
||||||
|
CREATE TABLE bb(b);
|
||||||
|
CREATE TABLE cc(c);
|
||||||
|
|
||||||
|
INSERT INTO aa VALUES(45);
|
||||||
|
INSERT INTO cc VALUES(45);
|
||||||
|
INSERT INTO cc VALUES(45);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test join-13.1 {
|
||||||
|
SELECT * FROM aa LEFT JOIN bb, cc WHERE cc.c=aa.a;
|
||||||
|
} {45 {} 45 45 {} 45}
|
||||||
|
|
||||||
|
# In the following, the order of [cc] and [bb] must not be exchanged, even
|
||||||
|
# though this would be helpful if the query used an inner join.
|
||||||
|
do_execsql_test join-13.2 {
|
||||||
|
CREATE INDEX ccc ON cc(c);
|
||||||
|
SELECT * FROM aa LEFT JOIN bb, cc WHERE cc.c=aa.a;
|
||||||
|
} {45 {} 45 45 {} 45}
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@ -99,7 +99,8 @@ if {$::tcl_platform(platform)!="unix"} {
|
|||||||
set alltests [test_set $alltests -exclude {
|
set alltests [test_set $alltests -exclude {
|
||||||
all.test async.test quick.test veryquick.test
|
all.test async.test quick.test veryquick.test
|
||||||
memleak.test permutations.test soak.test fts3.test
|
memleak.test permutations.test soak.test fts3.test
|
||||||
mallocAll.test rtree.test full.test session.test
|
mallocAll.test rtree.test full.test extraquick.test
|
||||||
|
session.test
|
||||||
}]
|
}]
|
||||||
|
|
||||||
set allquicktests [test_set $alltests -exclude {
|
set allquicktests [test_set $alltests -exclude {
|
||||||
@ -149,11 +150,22 @@ if {[info exists ::env(TEST_FAILURE)]} {
|
|||||||
lappend ::testsuitelist xxx
|
lappend ::testsuitelist xxx
|
||||||
|
|
||||||
test_suite "veryquick" -prefix "" -description {
|
test_suite "veryquick" -prefix "" -description {
|
||||||
"Very" quick test suite. Runs in less than 5 minutes on a workstation.
|
"Very" quick test suite. Runs in minutes on a workstation.
|
||||||
This test suite is the same as the "quick" tests, except that some files
|
This test suite is the same as the "quick" tests, except that some files
|
||||||
that test malloc and IO errors are omitted.
|
that test malloc and IO errors are omitted.
|
||||||
} -files [
|
} -files [
|
||||||
test_set $allquicktests -exclude *malloc* *ioerr* *fault*
|
test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile*
|
||||||
|
]
|
||||||
|
|
||||||
|
test_suite "extraquick" -prefix "" -description {
|
||||||
|
"Extra" quick test suite. Runs in a few minutes on a workstation.
|
||||||
|
This test suite is the same as the "veryquick" tests, except that
|
||||||
|
slower tests are omitted.
|
||||||
|
} -files [
|
||||||
|
test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* \
|
||||||
|
wal3.test fts4merge* sort2.test mmap1.test walcrash* \
|
||||||
|
percentile.test where8m.test walcksum.test savepoint3.test \
|
||||||
|
fuzzer1.test fuzzer3.test fts3expr3.test
|
||||||
]
|
]
|
||||||
|
|
||||||
test_suite "mmap" -prefix "mm-" -description {
|
test_suite "mmap" -prefix "mm-" -description {
|
||||||
|
@ -164,7 +164,6 @@ do_test progress-1.7 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set ::res [list]
|
set ::res [list]
|
||||||
explain {SELECT a, b, c FROM abc}
|
|
||||||
db eval {SELECT a, b, c FROM abc} {
|
db eval {SELECT a, b, c FROM abc} {
|
||||||
lappend ::res $a $b $c
|
lappend ::res $a $b $c
|
||||||
db progress 5 "expr 1"
|
db progress 5 "expr 1"
|
||||||
|
@ -547,7 +547,10 @@ proc process_options {argv} {
|
|||||||
puts " --srcdir $::SRCDIR"
|
puts " --srcdir $::SRCDIR"
|
||||||
puts " --platform [list $platform]"
|
puts " --platform [list $platform]"
|
||||||
puts " --config [list $config]"
|
puts " --config [list $config]"
|
||||||
if {$::QUICK} {puts " --quick"}
|
if {$::QUICK} {
|
||||||
|
if {$::QUICK==1} {puts " --quick"}
|
||||||
|
if {$::QUICK==2} {puts " --veryquick"}
|
||||||
|
}
|
||||||
if {$::MSVC} {puts " --msvc"}
|
if {$::MSVC} {puts " --msvc"}
|
||||||
if {$::BUILDONLY} {puts " --buildonly"}
|
if {$::BUILDONLY} {puts " --buildonly"}
|
||||||
if {$::DRYRUN} {puts " --dryrun"}
|
if {$::DRYRUN} {puts " --dryrun"}
|
||||||
@ -645,7 +648,7 @@ proc main {argv} {
|
|||||||
}
|
}
|
||||||
if {$target ne "checksymbols"} {
|
if {$target ne "checksymbols"} {
|
||||||
switch -- $::QUICK {
|
switch -- $::QUICK {
|
||||||
1 {set target test}
|
1 {set target quicktest}
|
||||||
2 {set target smoketest}
|
2 {set target smoketest}
|
||||||
}
|
}
|
||||||
if {$::BUILDONLY} {
|
if {$::BUILDONLY} {
|
||||||
|
@ -32,7 +32,6 @@ set result [execsql {
|
|||||||
FROM songs
|
FROM songs
|
||||||
GROUP BY LOWER(artist)
|
GROUP BY LOWER(artist)
|
||||||
}]
|
}]
|
||||||
puts result=$result
|
|
||||||
do_test select8-1.1 {
|
do_test select8-1.1 {
|
||||||
execsql {
|
execsql {
|
||||||
SELECT DISTINCT artist,sum(timesplayed) AS total
|
SELECT DISTINCT artist,sum(timesplayed) AS total
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
db close
|
db close
|
||||||
puts hello
|
|
||||||
|
|
||||||
# This script is only valid if we are running shared-cache mode in a
|
# This script is only valid if we are running shared-cache mode in a
|
||||||
# threadsafe-capable database engine.
|
# threadsafe-capable database engine.
|
||||||
|
@ -19,6 +19,11 @@ if {$tcl_platform(platform)=="windows"} {
|
|||||||
} else {
|
} else {
|
||||||
set PROG "./sqldiff"
|
set PROG "./sqldiff"
|
||||||
}
|
}
|
||||||
|
if {![file exe $PROG]} {
|
||||||
|
puts "sqldiff cannot run because $PROG is not available"
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
db close
|
db close
|
||||||
forcedelete test.db test2.db
|
forcedelete test.db test2.db
|
||||||
sqlite3 db test.db
|
sqlite3 db test.db
|
||||||
|
220
test/tester.tcl
220
test/tester.tcl
@ -81,6 +81,12 @@
|
|||||||
# permutation
|
# permutation
|
||||||
# presql
|
# presql
|
||||||
#
|
#
|
||||||
|
# Command to test whether or not --verbose=1 was specified on the command
|
||||||
|
# line (returns 0 for not-verbose, 1 for verbose and 2 for "verbose in the
|
||||||
|
# output file only").
|
||||||
|
#
|
||||||
|
# verbose
|
||||||
|
#
|
||||||
|
|
||||||
# Set the precision of FP arithmatic used by the interpreter. And
|
# Set the precision of FP arithmatic used by the interpreter. And
|
||||||
# configure SQLite to take database file locks on the page that begins
|
# configure SQLite to take database file locks on the page that begins
|
||||||
@ -388,6 +394,9 @@ if {[info exists cmdlinearg]==0} {
|
|||||||
# --file-retry-delay=N
|
# --file-retry-delay=N
|
||||||
# --start=[$permutation:]$testfile
|
# --start=[$permutation:]$testfile
|
||||||
# --match=$pattern
|
# --match=$pattern
|
||||||
|
# --verbose=$val
|
||||||
|
# --output=$filename
|
||||||
|
# --help
|
||||||
#
|
#
|
||||||
set cmdlinearg(soft-heap-limit) 0
|
set cmdlinearg(soft-heap-limit) 0
|
||||||
set cmdlinearg(maxerror) 1000
|
set cmdlinearg(maxerror) 1000
|
||||||
@ -399,6 +408,8 @@ if {[info exists cmdlinearg]==0} {
|
|||||||
set cmdlinearg(file-retry-delay) 0
|
set cmdlinearg(file-retry-delay) 0
|
||||||
set cmdlinearg(start) ""
|
set cmdlinearg(start) ""
|
||||||
set cmdlinearg(match) ""
|
set cmdlinearg(match) ""
|
||||||
|
set cmdlinearg(verbose) ""
|
||||||
|
set cmdlinearg(output) ""
|
||||||
|
|
||||||
set leftover [list]
|
set leftover [list]
|
||||||
foreach a $argv {
|
foreach a $argv {
|
||||||
@ -457,6 +468,22 @@ if {[info exists cmdlinearg]==0} {
|
|||||||
set ::G(match) $cmdlinearg(match)
|
set ::G(match) $cmdlinearg(match)
|
||||||
if {$::G(match) == ""} {unset ::G(match)}
|
if {$::G(match) == ""} {unset ::G(match)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{^-+output=.+$} {
|
||||||
|
foreach {dummy cmdlinearg(output)} [split $a =] break
|
||||||
|
if {$cmdlinearg(verbose)==""} {
|
||||||
|
set cmdlinearg(verbose) 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{^-+verbose=.+$} {
|
||||||
|
foreach {dummy cmdlinearg(verbose)} [split $a =] break
|
||||||
|
if {$cmdlinearg(verbose)=="file"} {
|
||||||
|
set cmdlinearg(verbose) 2
|
||||||
|
} elseif {[string is boolean -strict $cmdlinearg(verbose)]==0} {
|
||||||
|
error "option --verbose= must be set to a boolean or to \"file\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default {
|
default {
|
||||||
lappend leftover $a
|
lappend leftover $a
|
||||||
}
|
}
|
||||||
@ -484,6 +511,16 @@ if {[info exists cmdlinearg]==0} {
|
|||||||
if {$cmdlinearg(malloctrace)} {
|
if {$cmdlinearg(malloctrace)} {
|
||||||
sqlite3_memdebug_backtrace $cmdlinearg(backtrace)
|
sqlite3_memdebug_backtrace $cmdlinearg(backtrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if {$cmdlinearg(output)!=""} {
|
||||||
|
puts "Copying output to file $cmdlinearg(output)"
|
||||||
|
set ::G(output_fd) [open $cmdlinearg(output) w]
|
||||||
|
fconfigure $::G(output_fd) -buffering line
|
||||||
|
}
|
||||||
|
|
||||||
|
if {$cmdlinearg(verbose)==""} {
|
||||||
|
set cmdlinearg(verbose) 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update the soft-heap-limit each time this script is run. In that
|
# Update the soft-heap-limit each time this script is run. In that
|
||||||
@ -554,7 +591,7 @@ proc fail_test {name} {
|
|||||||
|
|
||||||
set nFail [set_test_counter errors]
|
set nFail [set_test_counter errors]
|
||||||
if {$nFail>=$::cmdlinearg(maxerror)} {
|
if {$nFail>=$::cmdlinearg(maxerror)} {
|
||||||
puts "*** Giving up..."
|
output2 "*** Giving up..."
|
||||||
finalize_testing
|
finalize_testing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -562,7 +599,7 @@ proc fail_test {name} {
|
|||||||
# Remember a warning message to be displayed at the conclusion of all testing
|
# Remember a warning message to be displayed at the conclusion of all testing
|
||||||
#
|
#
|
||||||
proc warning {msg {append 1}} {
|
proc warning {msg {append 1}} {
|
||||||
puts "Warning: $msg"
|
output2 "Warning: $msg"
|
||||||
set warnList [set_test_counter warn_list]
|
set warnList [set_test_counter warn_list]
|
||||||
if {$append} {
|
if {$append} {
|
||||||
lappend warnList $msg
|
lappend warnList $msg
|
||||||
@ -577,6 +614,61 @@ proc incr_ntest {} {
|
|||||||
set_test_counter count [expr [set_test_counter count] + 1]
|
set_test_counter count [expr [set_test_counter count] + 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Return true if --verbose=1 was specified on the command line. Otherwise,
|
||||||
|
# return false.
|
||||||
|
#
|
||||||
|
proc verbose {} {
|
||||||
|
return $::cmdlinearg(verbose)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use the following commands instead of [puts] for test output within
|
||||||
|
# this file. Test scripts can still use regular [puts], which is directed
|
||||||
|
# to stdout and, if one is open, the --output file.
|
||||||
|
#
|
||||||
|
# output1: output that should be printed if --verbose=1 was specified.
|
||||||
|
# output2: output that should be printed unconditionally.
|
||||||
|
# output2_if_no_verbose: output that should be printed only if --verbose=0.
|
||||||
|
#
|
||||||
|
proc output1 {args} {
|
||||||
|
set v [verbose]
|
||||||
|
if {$v==1} {
|
||||||
|
uplevel output2 $args
|
||||||
|
} elseif {$v==2} {
|
||||||
|
uplevel puts [lrange $args 0 end-1] $::G(output_fd) [lrange $args end end]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proc output2 {args} {
|
||||||
|
set nArg [llength $args]
|
||||||
|
uplevel puts $args
|
||||||
|
}
|
||||||
|
proc output2_if_no_verbose {args} {
|
||||||
|
set v [verbose]
|
||||||
|
if {$v==0} {
|
||||||
|
uplevel output2 $args
|
||||||
|
} elseif {$v==2} {
|
||||||
|
uplevel puts [lrange $args 0 end-1] stdout [lrange $args end end]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Override the [puts] command so that if no channel is explicitly
|
||||||
|
# specified the string is written to both stdout and to the file
|
||||||
|
# specified by "--output=", if any.
|
||||||
|
#
|
||||||
|
proc puts_override {args} {
|
||||||
|
set nArg [llength $args]
|
||||||
|
if {$nArg==1 || ($nArg==2 && [string first [lindex $args 0] -nonewline]==0)} {
|
||||||
|
uplevel puts_original $args
|
||||||
|
if {[info exists ::G(output_fd)]} {
|
||||||
|
uplevel puts [lrange $args 0 end-1] $::G(output_fd) [lrange $args end end]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# A channel was explicitly specified.
|
||||||
|
uplevel puts_original $args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rename puts puts_original
|
||||||
|
proc puts {args} { uplevel puts_override $args }
|
||||||
|
|
||||||
|
|
||||||
# Invoke the do_test procedure to run a single test
|
# Invoke the do_test procedure to run a single test
|
||||||
#
|
#
|
||||||
@ -604,12 +696,13 @@ proc do_test {name cmd expected} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
incr_ntest
|
incr_ntest
|
||||||
puts -nonewline $name...
|
output1 -nonewline $name...
|
||||||
flush stdout
|
flush stdout
|
||||||
|
|
||||||
if {![info exists ::G(match)] || [string match $::G(match) $name]} {
|
if {![info exists ::G(match)] || [string match $::G(match) $name]} {
|
||||||
if {[catch {uplevel #0 "$cmd;\n"} result]} {
|
if {[catch {uplevel #0 "$cmd;\n"} result]} {
|
||||||
puts "\nError: $result"
|
output2_if_no_verbose -nonewline $name...
|
||||||
|
output2 "\nError: $result"
|
||||||
fail_test $name
|
fail_test $name
|
||||||
} else {
|
} else {
|
||||||
if {[regexp {^~?/.*/$} $expected]} {
|
if {[regexp {^~?/.*/$} $expected]} {
|
||||||
@ -653,14 +746,15 @@ proc do_test {name cmd expected} {
|
|||||||
# if {![info exists ::testprefix] || $::testprefix eq ""} {
|
# if {![info exists ::testprefix] || $::testprefix eq ""} {
|
||||||
# error "no test prefix"
|
# error "no test prefix"
|
||||||
# }
|
# }
|
||||||
puts "\nExpected: \[$expected\]\n Got: \[$result\]"
|
output2_if_no_verbose -nonewline $name...
|
||||||
|
output2 "\nExpected: \[$expected\]\n Got: \[$result\]"
|
||||||
fail_test $name
|
fail_test $name
|
||||||
} else {
|
} else {
|
||||||
puts " Ok"
|
output1 " Ok"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
puts " Omitted"
|
output1 " Omitted"
|
||||||
omit_test $name "pattern mismatch" 0
|
omit_test $name "pattern mismatch" 0
|
||||||
}
|
}
|
||||||
flush stdout
|
flush stdout
|
||||||
@ -843,7 +937,7 @@ proc delete_all_data {} {
|
|||||||
# Return the number of microseconds per statement.
|
# Return the number of microseconds per statement.
|
||||||
#
|
#
|
||||||
proc speed_trial {name numstmt units sql} {
|
proc speed_trial {name numstmt units sql} {
|
||||||
puts -nonewline [format {%-21.21s } $name...]
|
output2 -nonewline [format {%-21.21s } $name...]
|
||||||
flush stdout
|
flush stdout
|
||||||
set speed [time {sqlite3_exec_nr db $sql}]
|
set speed [time {sqlite3_exec_nr db $sql}]
|
||||||
set tm [lindex $speed 0]
|
set tm [lindex $speed 0]
|
||||||
@ -853,13 +947,13 @@ proc speed_trial {name numstmt units sql} {
|
|||||||
set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]]
|
set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]]
|
||||||
}
|
}
|
||||||
set u2 $units/s
|
set u2 $units/s
|
||||||
puts [format {%12d uS %s %s} $tm $rate $u2]
|
output2 [format {%12d uS %s %s} $tm $rate $u2]
|
||||||
global total_time
|
global total_time
|
||||||
set total_time [expr {$total_time+$tm}]
|
set total_time [expr {$total_time+$tm}]
|
||||||
lappend ::speed_trial_times $name $tm
|
lappend ::speed_trial_times $name $tm
|
||||||
}
|
}
|
||||||
proc speed_trial_tcl {name numstmt units script} {
|
proc speed_trial_tcl {name numstmt units script} {
|
||||||
puts -nonewline [format {%-21.21s } $name...]
|
output2 -nonewline [format {%-21.21s } $name...]
|
||||||
flush stdout
|
flush stdout
|
||||||
set speed [time {eval $script}]
|
set speed [time {eval $script}]
|
||||||
set tm [lindex $speed 0]
|
set tm [lindex $speed 0]
|
||||||
@ -869,7 +963,7 @@ proc speed_trial_tcl {name numstmt units script} {
|
|||||||
set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]]
|
set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]]
|
||||||
}
|
}
|
||||||
set u2 $units/s
|
set u2 $units/s
|
||||||
puts [format {%12d uS %s %s} $tm $rate $u2]
|
output2 [format {%12d uS %s %s} $tm $rate $u2]
|
||||||
global total_time
|
global total_time
|
||||||
set total_time [expr {$total_time+$tm}]
|
set total_time [expr {$total_time+$tm}]
|
||||||
lappend ::speed_trial_times $name $tm
|
lappend ::speed_trial_times $name $tm
|
||||||
@ -881,19 +975,19 @@ proc speed_trial_init {name} {
|
|||||||
sqlite3 versdb :memory:
|
sqlite3 versdb :memory:
|
||||||
set vers [versdb one {SELECT sqlite_source_id()}]
|
set vers [versdb one {SELECT sqlite_source_id()}]
|
||||||
versdb close
|
versdb close
|
||||||
puts "SQLite $vers"
|
output2 "SQLite $vers"
|
||||||
}
|
}
|
||||||
proc speed_trial_summary {name} {
|
proc speed_trial_summary {name} {
|
||||||
global total_time
|
global total_time
|
||||||
puts [format {%-21.21s %12d uS TOTAL} $name $total_time]
|
output2 [format {%-21.21s %12d uS TOTAL} $name $total_time]
|
||||||
|
|
||||||
if { 0 } {
|
if { 0 } {
|
||||||
sqlite3 versdb :memory:
|
sqlite3 versdb :memory:
|
||||||
set vers [lindex [versdb one {SELECT sqlite_source_id()}] 0]
|
set vers [lindex [versdb one {SELECT sqlite_source_id()}] 0]
|
||||||
versdb close
|
versdb close
|
||||||
puts "CREATE TABLE IF NOT EXISTS time(version, script, test, us);"
|
output2 "CREATE TABLE IF NOT EXISTS time(version, script, test, us);"
|
||||||
foreach {test us} $::speed_trial_times {
|
foreach {test us} $::speed_trial_times {
|
||||||
puts "INSERT INTO time VALUES('$vers', '$name', '$test', $us);"
|
output2 "INSERT INTO time VALUES('$vers', '$name', '$test', $us);"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -937,75 +1031,75 @@ proc finalize_testing {} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if {$nKnown>0} {
|
if {$nKnown>0} {
|
||||||
puts "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\
|
output2 "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\
|
||||||
out of $nTest tests"
|
out of $nTest tests"
|
||||||
} else {
|
} else {
|
||||||
puts "$nErr errors out of $nTest tests"
|
output2 "$nErr errors out of $nTest tests"
|
||||||
}
|
}
|
||||||
if {$nErr>$nKnown} {
|
if {$nErr>$nKnown} {
|
||||||
puts -nonewline "Failures on these tests:"
|
output2 -nonewline "Failures on these tests:"
|
||||||
foreach x [set_test_counter fail_list] {
|
foreach x [set_test_counter fail_list] {
|
||||||
if {![info exists known_error($x)]} {puts -nonewline " $x"}
|
if {![info exists known_error($x)]} {output2 -nonewline " $x"}
|
||||||
}
|
}
|
||||||
puts ""
|
output2 ""
|
||||||
}
|
}
|
||||||
foreach warning [set_test_counter warn_list] {
|
foreach warning [set_test_counter warn_list] {
|
||||||
puts "Warning: $warning"
|
output2 "Warning: $warning"
|
||||||
}
|
}
|
||||||
run_thread_tests 1
|
run_thread_tests 1
|
||||||
if {[llength $omitList]>0} {
|
if {[llength $omitList]>0} {
|
||||||
puts "Omitted test cases:"
|
output2 "Omitted test cases:"
|
||||||
set prec {}
|
set prec {}
|
||||||
foreach {rec} [lsort $omitList] {
|
foreach {rec} [lsort $omitList] {
|
||||||
if {$rec==$prec} continue
|
if {$rec==$prec} continue
|
||||||
set prec $rec
|
set prec $rec
|
||||||
puts [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]]
|
output2 [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if {$nErr>0 && ![working_64bit_int]} {
|
if {$nErr>0 && ![working_64bit_int]} {
|
||||||
puts "******************************************************************"
|
output2 "******************************************************************"
|
||||||
puts "N.B.: The version of TCL that you used to build this test harness"
|
output2 "N.B.: The version of TCL that you used to build this test harness"
|
||||||
puts "is defective in that it does not support 64-bit integers. Some or"
|
output2 "is defective in that it does not support 64-bit integers. Some or"
|
||||||
puts "all of the test failures above might be a result from this defect"
|
output2 "all of the test failures above might be a result from this defect"
|
||||||
puts "in your TCL build."
|
output2 "in your TCL build."
|
||||||
puts "******************************************************************"
|
output2 "******************************************************************"
|
||||||
}
|
}
|
||||||
if {$::cmdlinearg(binarylog)} {
|
if {$::cmdlinearg(binarylog)} {
|
||||||
vfslog finalize binarylog
|
vfslog finalize binarylog
|
||||||
}
|
}
|
||||||
if {$sqlite_open_file_count} {
|
if {$sqlite_open_file_count} {
|
||||||
puts "$sqlite_open_file_count files were left open"
|
output2 "$sqlite_open_file_count files were left open"
|
||||||
incr nErr
|
incr nErr
|
||||||
}
|
}
|
||||||
if {[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]>0 ||
|
if {[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]>0 ||
|
||||||
[sqlite3_memory_used]>0} {
|
[sqlite3_memory_used]>0} {
|
||||||
puts "Unfreed memory: [sqlite3_memory_used] bytes in\
|
output2 "Unfreed memory: [sqlite3_memory_used] bytes in\
|
||||||
[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations"
|
[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations"
|
||||||
incr nErr
|
incr nErr
|
||||||
ifcapable memdebug||mem5||(mem3&&debug) {
|
ifcapable memdebug||mem5||(mem3&&debug) {
|
||||||
puts "Writing unfreed memory log to \"./memleak.txt\""
|
output2 "Writing unfreed memory log to \"./memleak.txt\""
|
||||||
sqlite3_memdebug_dump ./memleak.txt
|
sqlite3_memdebug_dump ./memleak.txt
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
puts "All memory allocations freed - no leaks"
|
output2 "All memory allocations freed - no leaks"
|
||||||
ifcapable memdebug||mem5 {
|
ifcapable memdebug||mem5 {
|
||||||
sqlite3_memdebug_dump ./memusage.txt
|
sqlite3_memdebug_dump ./memusage.txt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
show_memstats
|
show_memstats
|
||||||
puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes"
|
output2 "Maximum memory usage: [sqlite3_memory_highwater 1] bytes"
|
||||||
puts "Current memory usage: [sqlite3_memory_highwater] bytes"
|
output2 "Current memory usage: [sqlite3_memory_highwater] bytes"
|
||||||
if {[info commands sqlite3_memdebug_malloc_count] ne ""} {
|
if {[info commands sqlite3_memdebug_malloc_count] ne ""} {
|
||||||
puts "Number of malloc() : [sqlite3_memdebug_malloc_count] calls"
|
output2 "Number of malloc() : [sqlite3_memdebug_malloc_count] calls"
|
||||||
}
|
}
|
||||||
if {$::cmdlinearg(malloctrace)} {
|
if {$::cmdlinearg(malloctrace)} {
|
||||||
puts "Writing mallocs.sql..."
|
output2 "Writing mallocs.sql..."
|
||||||
memdebug_log_sql
|
memdebug_log_sql
|
||||||
sqlite3_memdebug_log stop
|
sqlite3_memdebug_log stop
|
||||||
sqlite3_memdebug_log clear
|
sqlite3_memdebug_log clear
|
||||||
|
|
||||||
if {[sqlite3_memory_used]>0} {
|
if {[sqlite3_memory_used]>0} {
|
||||||
puts "Writing leaks.sql..."
|
output2 "Writing leaks.sql..."
|
||||||
sqlite3_memdebug_log sync
|
sqlite3_memdebug_log sync
|
||||||
memdebug_log_sql leaks.sql
|
memdebug_log_sql leaks.sql
|
||||||
}
|
}
|
||||||
@ -1026,30 +1120,30 @@ proc show_memstats {} {
|
|||||||
set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
|
set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
|
||||||
set val [format {now %10d max %10d max-size %10d} \
|
set val [format {now %10d max %10d max-size %10d} \
|
||||||
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
|
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
|
||||||
puts "Memory used: $val"
|
output1 "Memory used: $val"
|
||||||
set x [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0]
|
set x [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0]
|
||||||
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
|
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
|
||||||
puts "Allocation count: $val"
|
output1 "Allocation count: $val"
|
||||||
set x [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0]
|
set x [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0]
|
||||||
set y [sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 0]
|
set y [sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 0]
|
||||||
set val [format {now %10d max %10d max-size %10d} \
|
set val [format {now %10d max %10d max-size %10d} \
|
||||||
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
|
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
|
||||||
puts "Page-cache used: $val"
|
output1 "Page-cache used: $val"
|
||||||
set x [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0]
|
set x [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0]
|
||||||
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
|
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
|
||||||
puts "Page-cache overflow: $val"
|
output1 "Page-cache overflow: $val"
|
||||||
set x [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0]
|
set x [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0]
|
||||||
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
|
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
|
||||||
puts "Scratch memory used: $val"
|
output1 "Scratch memory used: $val"
|
||||||
set x [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0]
|
set x [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0]
|
||||||
set y [sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 0]
|
set y [sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 0]
|
||||||
set val [format {now %10d max %10d max-size %10d} \
|
set val [format {now %10d max %10d max-size %10d} \
|
||||||
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
|
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
|
||||||
puts "Scratch overflow: $val"
|
output1 "Scratch overflow: $val"
|
||||||
ifcapable yytrackmaxstackdepth {
|
ifcapable yytrackmaxstackdepth {
|
||||||
set x [sqlite3_status SQLITE_STATUS_PARSER_STACK 0]
|
set x [sqlite3_status SQLITE_STATUS_PARSER_STACK 0]
|
||||||
set val [format { max %10d} [lindex $x 2]]
|
set val [format { max %10d} [lindex $x 2]]
|
||||||
puts "Parser stack depth: $val"
|
output2 "Parser stack depth: $val"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1064,7 +1158,7 @@ proc execsql_timed {sql {db db}} {
|
|||||||
set x [uplevel [list $db eval $sql]]
|
set x [uplevel [list $db eval $sql]]
|
||||||
} 1]
|
} 1]
|
||||||
set tm [lindex $tm 0]
|
set tm [lindex $tm 0]
|
||||||
puts -nonewline " ([expr {$tm*0.001}]ms) "
|
output1 -nonewline " ([expr {$tm*0.001}]ms) "
|
||||||
set x
|
set x
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1080,20 +1174,20 @@ proc catchsql {sql {db db}} {
|
|||||||
# Do an VDBE code dump on the SQL given
|
# Do an VDBE code dump on the SQL given
|
||||||
#
|
#
|
||||||
proc explain {sql {db db}} {
|
proc explain {sql {db db}} {
|
||||||
puts ""
|
output2 ""
|
||||||
puts "addr opcode p1 p2 p3 p4 p5 #"
|
output2 "addr opcode p1 p2 p3 p4 p5 #"
|
||||||
puts "---- ------------ ------ ------ ------ --------------- -- -"
|
output2 "---- ------------ ------ ------ ------ --------------- -- -"
|
||||||
$db eval "explain $sql" {} {
|
$db eval "explain $sql" {} {
|
||||||
puts [format {%-4d %-12.12s %-6d %-6d %-6d % -17s %s %s} \
|
output2 [format {%-4d %-12.12s %-6d %-6d %-6d % -17s %s %s} \
|
||||||
$addr $opcode $p1 $p2 $p3 $p4 $p5 $comment
|
$addr $opcode $p1 $p2 $p3 $p4 $p5 $comment
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc explain_i {sql {db db}} {
|
proc explain_i {sql {db db}} {
|
||||||
puts ""
|
output2 ""
|
||||||
puts "addr opcode p1 p2 p3 p4 p5 #"
|
output2 "addr opcode p1 p2 p3 p4 p5 #"
|
||||||
puts "---- ------------ ------ ------ ------ ---------------- -- -"
|
output2 "---- ------------ ------ ------ ------ ---------------- -- -"
|
||||||
|
|
||||||
|
|
||||||
# Set up colors for the different opcodes. Scheme is as follows:
|
# Set up colors for the different opcodes. Scheme is as follows:
|
||||||
@ -1159,18 +1253,18 @@ proc explain_i {sql {db db}} {
|
|||||||
|
|
||||||
$db eval "explain $sql" {} {
|
$db eval "explain $sql" {} {
|
||||||
if {[info exists linebreak($addr)]} {
|
if {[info exists linebreak($addr)]} {
|
||||||
puts ""
|
output2 ""
|
||||||
}
|
}
|
||||||
set I [string repeat " " $x($addr)]
|
set I [string repeat " " $x($addr)]
|
||||||
|
|
||||||
set col ""
|
set col ""
|
||||||
catch { set col $color($opcode) }
|
catch { set col $color($opcode) }
|
||||||
|
|
||||||
puts [format {%-4d %s%s%-12.12s%s %-6d %-6d %-6d % -17s %s %s} \
|
output2 [format {%-4d %s%s%-12.12s%s %-6d %-6d %-6d % -17s %s %s} \
|
||||||
$addr $I $col $opcode $D $p1 $p2 $p3 $p4 $p5 $comment
|
$addr $I $col $opcode $D $p1 $p2 $p3 $p4 $p5 $comment
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
puts "---- ------------ ------ ------ ------ ---------------- -- -"
|
output2 "---- ------------ ------ ------ ------ ---------------- -- -"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Show the VDBE program for an SQL statement but omit the Trace
|
# Show the VDBE program for an SQL statement but omit the Trace
|
||||||
@ -1601,9 +1695,9 @@ proc do_ioerr_test {testname args} {
|
|||||||
set nowcksum [cksum]
|
set nowcksum [cksum]
|
||||||
set res [expr {$nowcksum==$::checksum || $nowcksum==$::goodcksum}]
|
set res [expr {$nowcksum==$::checksum || $nowcksum==$::goodcksum}]
|
||||||
if {$res==0} {
|
if {$res==0} {
|
||||||
puts "now=$nowcksum"
|
output2 "now=$nowcksum"
|
||||||
puts "the=$::checksum"
|
output2 "the=$::checksum"
|
||||||
puts "fwd=$::goodcksum"
|
output2 "fwd=$::goodcksum"
|
||||||
}
|
}
|
||||||
set res
|
set res
|
||||||
} 1
|
} 1
|
||||||
@ -1827,6 +1921,12 @@ proc slave_test_script {script} {
|
|||||||
interp eval tinterp [list set $var $value]
|
interp eval tinterp [list set $var $value]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# If output is being copied into a file, share the file-descriptor with
|
||||||
|
# the interpreter.
|
||||||
|
if {[info exists ::G(output_fd)]} {
|
||||||
|
interp share {} $::G(output_fd) tinterp
|
||||||
|
}
|
||||||
|
|
||||||
# The alias used to access the global test counters.
|
# The alias used to access the global test counters.
|
||||||
tinterp alias set_test_counter set_test_counter
|
tinterp alias set_test_counter set_test_counter
|
||||||
|
|
||||||
@ -1895,7 +1995,7 @@ proc slave_test_file {zFile} {
|
|||||||
|
|
||||||
# Add some info to the output.
|
# Add some info to the output.
|
||||||
#
|
#
|
||||||
puts "Time: $tail $ms ms"
|
output2 "Time: $tail $ms ms"
|
||||||
show_memstats
|
show_memstats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,9 +56,6 @@ ifcapable !vtab||!schema_pragmas {
|
|||||||
# We cannot create a virtual table if the module has not been registered.
|
# We cannot create a virtual table if the module has not been registered.
|
||||||
#
|
#
|
||||||
do_test vtab1-1.1.1 {
|
do_test vtab1-1.1.1 {
|
||||||
explain {
|
|
||||||
CREATE VIRTUAL TABLE t1 USING echo;
|
|
||||||
}
|
|
||||||
catchsql {
|
catchsql {
|
||||||
CREATE VIRTUAL TABLE t1 USING echo;
|
CREATE VIRTUAL TABLE t1 USING echo;
|
||||||
}
|
}
|
||||||
|
@ -292,6 +292,7 @@ foreach file {
|
|||||||
mutex_w32.c
|
mutex_w32.c
|
||||||
malloc.c
|
malloc.c
|
||||||
printf.c
|
printf.c
|
||||||
|
treeview.c
|
||||||
random.c
|
random.c
|
||||||
threads.c
|
threads.c
|
||||||
utf.c
|
utf.c
|
||||||
@ -346,6 +347,8 @@ foreach file {
|
|||||||
update.c
|
update.c
|
||||||
vacuum.c
|
vacuum.c
|
||||||
vtab.c
|
vtab.c
|
||||||
|
wherecode.c
|
||||||
|
whereexpr.c
|
||||||
where.c
|
where.c
|
||||||
|
|
||||||
parse.c
|
parse.c
|
||||||
|
Reference in New Issue
Block a user