mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-05 04:30:38 +03:00
Merge updates from trunk.
FossilOrigin-Name: 3e363f405655e2e39588029d797496a952cca11d
This commit is contained in:
18
Makefile.in
18
Makefile.in
@@ -287,6 +287,7 @@ SRC = \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vtab.c \
|
||||
$(TOP)/src/vxworks.h \
|
||||
$(TOP)/src/wal.c \
|
||||
$(TOP)/src/wal.h \
|
||||
$(TOP)/src/walker.c \
|
||||
@@ -482,6 +483,7 @@ HDR = \
|
||||
$(TOP)/src/sqliteLimit.h \
|
||||
$(TOP)/src/vdbe.h \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vxworks.h \
|
||||
$(TOP)/src/whereInt.h \
|
||||
config.h
|
||||
|
||||
@@ -538,11 +540,19 @@ mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) -rpath "$(libdir)"
|
||||
|
||||
MPTEST1=./mptester$(EXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
|
||||
MPTEST2=./mptester$(EXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
|
||||
mptest: mptester$(EXE)
|
||||
rm -f mptest1.db
|
||||
./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test
|
||||
rm -f mptest2.db
|
||||
./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test
|
||||
rm -f mptest.db
|
||||
$(MPTEST1) --journalmode DELETE
|
||||
$(MPTEST2) --journalmode WAL
|
||||
$(MPTEST1) --journalmode WAL
|
||||
$(MPTEST2) --journalmode PERSIST
|
||||
$(MPTEST1) --journalmode PERSIST
|
||||
$(MPTEST2) --journalmode TRUNCATE
|
||||
$(MPTEST1) --journalmode TRUNCATE
|
||||
$(MPTEST2) --journalmode DELETE
|
||||
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
# copies of all of the C source code and header files needed to
|
||||
|
||||
@@ -805,6 +805,7 @@ SRC2 = \
|
||||
$(TOP)\src\vdbetrace.c \
|
||||
$(TOP)\src\vdbeInt.h \
|
||||
$(TOP)\src\vtab.c \
|
||||
$(TOP)\src\vxworks.h \
|
||||
$(TOP)\src\wal.c \
|
||||
$(TOP)\src\wal.h \
|
||||
$(TOP)\src\walker.c \
|
||||
@@ -1004,6 +1005,7 @@ HDR = \
|
||||
$(TOP)\src\sqliteLimit.h \
|
||||
$(TOP)\src\vdbe.h \
|
||||
$(TOP)\src\vdbeInt.h \
|
||||
$(TOP)\src\vxworks.h \
|
||||
$(TOP)\src\whereInt.h
|
||||
|
||||
# Header files used by extensions
|
||||
|
||||
18
configure
vendored
18
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.8.8.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.8.9.
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
@@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.8.8'
|
||||
PACKAGE_STRING='sqlite 3.8.8'
|
||||
PACKAGE_VERSION='3.8.9'
|
||||
PACKAGE_STRING='sqlite 3.8.9'
|
||||
PACKAGE_BUGREPORT=''
|
||||
|
||||
# Factoring default headers for most tests.
|
||||
@@ -1480,7 +1480,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.8.8 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.8.9 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1545,7 +1545,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.8:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.9:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1659,7 +1659,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.8.8
|
||||
sqlite configure 3.8.9
|
||||
generated by GNU Autoconf 2.62
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
@@ -1673,7 +1673,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.8.8, which was
|
||||
It was created by sqlite $as_me 3.8.9, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -13951,7 +13951,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.8.8, which was
|
||||
This file was extended by sqlite $as_me 3.8.9, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -14004,7 +14004,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.8.8
|
||||
sqlite config.status 3.8.9
|
||||
configured by $0, generated by GNU Autoconf 2.62,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
||||
@@ -1253,7 +1253,7 @@ void sqlite3Fts3Snippet(
|
||||
*/
|
||||
for(iRead=0; iRead<pTab->nColumn; iRead++){
|
||||
SnippetFragment sF = {0, 0, 0, 0};
|
||||
int iS;
|
||||
int iS = 0;
|
||||
if( iCol>=0 && iRead!=iCol ) continue;
|
||||
|
||||
/* Find the best snippet of nFToken tokens in column iRead. */
|
||||
|
||||
2
main.mk
2
main.mk
@@ -165,6 +165,7 @@ SRC = \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vtab.c \
|
||||
$(TOP)/src/vxworks.h \
|
||||
$(TOP)/src/wal.c \
|
||||
$(TOP)/src/wal.h \
|
||||
$(TOP)/src/walker.c \
|
||||
@@ -364,6 +365,7 @@ HDR = \
|
||||
$(TOP)/src/sqliteLimit.h \
|
||||
$(TOP)/src/vdbe.h \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vxworks.h \
|
||||
$(TOP)/src/whereInt.h
|
||||
|
||||
# Header files used by extensions
|
||||
|
||||
137
manifest
137
manifest
@@ -1,12 +1,12 @@
|
||||
C Merge\supdates\sfrom\strunk.
|
||||
D 2015-02-27T19:40:08.070
|
||||
D 2015-03-19T14:46:52.931
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46
|
||||
F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc edbe2e2a9d27a4a56bd2891808a7c013bc322f6e
|
||||
F Makefile.msc 529e61cd9d29a3934758b4b3a0bb649b6c653481
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
|
||||
F VERSION d846487aff892625eb8e75960234e7285f0462fe
|
||||
F VERSION 319eb1ced4b4d17a67730f2b7b85f15c1346cb60
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
@@ -38,7 +38,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure b2882796ddebd33ac4e9d4ccf5c5ca11888fc30e x
|
||||
F configure 613b220c2f2c7adcd50eb5ee4144ab581a150b47 x
|
||||
F configure.ac 6a8d145aea6d81f0b90013340780e43ed74fd5f4
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
@@ -87,7 +87,7 @@ F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
|
||||
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
|
||||
F ext/fts3/fts3_snippet.c f16ef6425f92339a8fecc87d9aaf2b12355c78e4
|
||||
F ext/fts3/fts3_snippet.c 52c2dcf410b1f9af5a44d81a2cf8c68ed1cb5283
|
||||
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
|
||||
F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038
|
||||
F ext/fts3/fts3_tokenize_vtab.c becc661223db7898b213f9e8a23d75bac02408c9
|
||||
@@ -152,21 +152,21 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 0bae136db3f3ce451079ae335124b46163d37020
|
||||
F main.mk 04c49c495795b18a7b70053eef285be1e4d43fa4
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test cce8e306d8596d5a2e497e27112dae1f6e5e3538
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
|
||||
F mptest/mptest.c 24c5f72415df2eab7088ef8c9f99f163aed590c8
|
||||
F mptest/multiwrite01.test 499ad0310da8dff8e8f98d2e272fc2a8aa741b2e
|
||||
F mptest/mptest.c 0c0c82c1d9aea0b1a60ef9456a04c35ab1106622
|
||||
F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb
|
||||
F src/alter.c d23d6b6991f66b383934f137fd4384d93fb98c81
|
||||
F src/analyze.c 91540f835163d5369ccbae78e2e6c74d0dd53c1d
|
||||
F src/attach.c 880f9b8641a829c563e52dd13c452ce457ae4dd8
|
||||
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
@@ -185,7 +185,7 @@ F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e
|
||||
F src/expr.c 3ef111b88ae2941b84b6b6ea4be8d501ba1af0cb
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12
|
||||
F src/func.c f7f0f44b0a2cb568a9c42b1b07e613380ee0b9c6
|
||||
F src/func.c 1414c24c873c48796ad45942257a179a423ba42f
|
||||
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
@@ -195,7 +195,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
||||
F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
|
||||
F src/main.c 80edeba383aac89f72498b2572a115e21d0ecbbd
|
||||
F src/main.c fa997fa27d95febc16d57095299384b667a7f762
|
||||
F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
|
||||
@@ -214,32 +214,32 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
|
||||
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c c06b1b263d52e14473ccc619422af6b64570a3b8
|
||||
F src/os_unix.c cc903ecc6ebda90ef703d043ddaa7f33de0cab0f
|
||||
F src/os_win.c 8223e7db5b7c4a81d8b161098ac3959400434cdb
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 4120a49ecd37697e28f5ed807f470b9c0b88410c
|
||||
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
|
||||
F src/parse.y 0f8e7d60f0ab3cb53d270adef69259ac307d83a8
|
||||
F src/pcache.c d210cf90d04365a74f85d21374dded65af67b0cb
|
||||
F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4
|
||||
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
|
||||
F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf
|
||||
F src/pragma.c ea0be138a99784b14e87bd4522fea40e7b979e9c
|
||||
F src/pragma.c ac4f3f856b4234e85f55b0f069698a4766011100
|
||||
F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f
|
||||
F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9
|
||||
F src/printf.c 8da9a2687a396daa19860f4dc90975d319304744
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c f4d79e31ffa5820c2e3d1740baa5e9b190425f2b
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c e46cef4c224549b439384c88fc7f57ba064dad54
|
||||
F src/shell.c 7929bf046ae5ea2a245f8e4ba0f3bc85e76e65dd
|
||||
F src/sqlite.h.in 62d3997824038cc32335b04aaa18cc8f4c19e9be
|
||||
F src/select.c 94e016b6733b1d39a2f4c8d431155b4c2897d907
|
||||
F src/shell.c c8b054cf359d90d809d05929944fbe5ff138019a
|
||||
F src/sqlite.h.in 2d48e05677d0f9b06b7757662eef3cebea02d837
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
|
||||
F src/sqliteInt.h 57a405ae6d2ed10fff52de376d18f21e04d96609
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/sqliteInt.h fae682c2b4dfbe489b134d74521c41c088f16ab1
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c 81712116e826b0089bb221b018929536b2b5406f
|
||||
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
|
||||
F src/tclsqlite.c b290774586f022e16e04ba8ed2f0b8edd86b5b77
|
||||
F src/tclsqlite.c fa72a7c5278662357c105ba7925c1d0972506ff9
|
||||
F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
|
||||
@@ -254,11 +254,11 @@ F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803
|
||||
F src/test_blob.c 1f2e3e25255b731c4fcf15ee7990d06347cb6c09
|
||||
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
|
||||
F src/test_config.c e7b2e1634324d746aa5e1c7e0929470e8be27953
|
||||
F src/test_config.c c2d3ff6c129d50183900c7eff14158ff7e9b3f03
|
||||
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
F src/test_func.c 14e543ae4d905ee31dc322b2f8d31bfac1769d45
|
||||
F src/test_func.c f1ac201465472e76a73e2f3695c3553c63e7322a
|
||||
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
|
||||
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
|
||||
F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
|
||||
@@ -266,7 +266,7 @@ F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
|
||||
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
|
||||
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
|
||||
F src/test_malloc.c b9495384e74923aefde8311de974bf9b0f5ba570
|
||||
F src/test_multiplex.c 72c0ad1e97af3d6d19975bbd81813072b40c7290
|
||||
F src/test_multiplex.c 97813565daa7ee480abcc5dd1e9984ed1f71eb8c
|
||||
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
|
||||
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
|
||||
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
|
||||
@@ -283,7 +283,7 @@ F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
|
||||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
|
||||
F src/test_vfs.c 5a14c63da9579ba148138c1fb233100f2eb58ebb
|
||||
F src/test_vfs.c b7e6831e6fcf04c5090accff30640ec5c9630739
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
|
||||
@@ -293,21 +293,22 @@ F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
|
||||
F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec
|
||||
F src/vdbe.c ddfc977981cd6324668aa6b114045eb1c677421a
|
||||
F src/vdbe.c a2725107658fd9572637e8e09d46dcfe851edb96
|
||||
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
|
||||
F src/vdbeInt.h bb56fd199d8af1a2c1b9639ee2f70724b4338e3a
|
||||
F src/vdbeapi.c dac0d0d8009a8aa549cd77d9c29da44c0344f0c4
|
||||
F src/vdbeaux.c 97911edb61074b871ec4aa2d6bb779071643dee5
|
||||
F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75
|
||||
F src/vdbeaux.c 23390670e64f011f3fed8f38a2f25aaccacb74d2
|
||||
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
|
||||
F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f
|
||||
F src/vdbesort.c 6d64c5448b64851b99931ede980addc3af70d5e2
|
||||
F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9
|
||||
F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6
|
||||
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
|
||||
F src/vtab.c 699f2b8d509cfe379c33dde33827875d5b030e01
|
||||
F src/wal.c 39303f2c9db02a4e422cd8eb2c8760420c6a51fe
|
||||
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||
F src/where.c a50d5082b0fecd2bcf1725cdd012732d9d1e9d5c
|
||||
F src/whereInt.h d3633e9b592103241b74b0ec76185f3e5b8b62e0
|
||||
F src/where.c 42ce3fd5ec9fe050f623be358cfddee01c1f6286
|
||||
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
|
||||
@@ -320,18 +321,19 @@ F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
|
||||
F test/analyze3.test bf41f0f680dd1e0d44eed5e769531e93a5320275
|
||||
F test/analyze3.test 75b9e42ea1e4edc919250450dc5762186965d4e6
|
||||
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82
|
||||
F test/analyze9.test 72795c8113604b5dcd47a1498a61d6d7fb5d041a
|
||||
F test/analyze9.test 3dd9e203fad353ec8027b18a6d9a92af59f4e727
|
||||
F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a
|
||||
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
|
||||
F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
|
||||
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
|
||||
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
|
||||
F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||
@@ -347,7 +349,7 @@ F test/auth.test 855233ef26eb3601b6886567ea4e326c72959360
|
||||
F test/auth2.test 264c6af53cad9aba5218c68bbe18036e39007bfa
|
||||
F test/auth3.test 5cfa94ed90c6617c42b7ba4b133fd79678b251c7
|
||||
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
|
||||
F test/autoindex1.test 6ff78b94f43a59616c06c11c55b12935173506d7
|
||||
F test/autoindex1.test 7008c9f604141fdabe31b7bb95b5ff31b518251f
|
||||
F test/autoindex2.test af7e595c6864cc6ef5fc38d5db579a3e34940cb8
|
||||
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
|
||||
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
|
||||
@@ -441,6 +443,7 @@ F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219
|
||||
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
|
||||
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
|
||||
F test/crash8.test 61442a9964ab6b124fc5254e4258b45747842e6f
|
||||
F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
|
||||
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
@@ -470,7 +473,7 @@ F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
|
||||
F test/e_expr.test 8f5fdd7261e2d746813b0c6a1c0e34824ad3c5ad
|
||||
F test/e_fkey.test a1783fe1f759e1990e6a11adfcf0702dac4d0707
|
||||
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
||||
F test/e_insert.test 7b2fa9cd1456f83474d6c5d27db3abaeb8be2023
|
||||
F test/e_insert.test 0e63edc037afe738bb81a626a676811ed7862c90
|
||||
F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
|
||||
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
|
||||
F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
|
||||
@@ -503,7 +506,7 @@ F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b
|
||||
F test/fkey2.test 1db212cda86b0d3ce72714001f7b6381c321341c
|
||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
F test/fkey5.test 488601fbda8350619b3029487e56830447056fd2
|
||||
F test/fkey5.test 56bcb5a6e8b725b17febc267fb041a6695e86853
|
||||
F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48
|
||||
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
|
||||
F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0
|
||||
@@ -591,7 +594,7 @@ F test/fts3matchinfo.test 58544fa4d254000fa4e7f494b0a832f7ba61d45e
|
||||
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
|
||||
F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
|
||||
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
|
||||
F test/fts3query.test d81ffb0ab1d4e1a2a330b8eb1e160b60603f4745
|
||||
F test/fts3query.test c838b18f2b859e15fd31c64be3d79ef1556803ca
|
||||
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
|
||||
F test/fts3snippet.test 03c2f3be7d3b7c8bb105ed237f204833392bd57f
|
||||
@@ -638,11 +641,12 @@ F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
|
||||
F test/in5.test 1de657472fa9ac2924be25c2c959ac5ca1aae554
|
||||
F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
|
||||
F test/incrblob2.test 0d8821730a84f90af78a9dd547fe7a2480a06240
|
||||
F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5
|
||||
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
|
||||
F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab
|
||||
F test/incrblob_err.test af1f12ba60d220c9752073ff2bda2ad59e88960d
|
||||
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
|
||||
F test/incrcorrupt.test 9786cba68c5832f01887fde1c06b43c3904d86f6
|
||||
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
|
||||
F test/incrvacuum2.test 676c41428765d58f1da7dbe659ef27726d3d30ac
|
||||
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
|
||||
@@ -653,8 +657,8 @@ F test/index3.test 55a90cff99834305e8141df7afaef39674b57062
|
||||
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
||||
F test/index5.test 25b0b451aceed4ac5f7d49f856f6de7257470b3e
|
||||
F test/index6.test 3ae54e53c53f2adcacda269237d8e52bdb05a481
|
||||
F test/index7.test 917cf1e1c7439bb155abbeabec511b28945e157b
|
||||
F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec
|
||||
F test/index7.test 3d54dce09344c4530ea39a458aa304da044c887a
|
||||
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
@@ -688,26 +692,27 @@ F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test e191e536d0fcd722a6b965e7cd1ee0bfd12a5991
|
||||
F test/like.test 4f2a71d36a536233727f71995fef900756705e56
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/limit.test 3d7df19c35ac672a11f7de406cd3205d592babbb
|
||||
F test/like3.test 7b0525a39e4f25c4fd113de7e2e28eb712dcdedf
|
||||
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
|
||||
F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b
|
||||
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
|
||||
F test/lock.test 87af515b0c4cf928576d0f89946d67d7c265dfb4
|
||||
F test/lock.test b984ab9034e7389be0d863fe4e64cbbc4d2028f5
|
||||
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
|
||||
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
|
||||
F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12
|
||||
F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
|
||||
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
|
||||
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
|
||||
F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95
|
||||
F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
|
||||
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
|
||||
F test/main.test 16131264ea0c2b93b95201f0c92958e85f2ba11a
|
||||
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test 96939d2d1a6f39667bbebe5bc27c6525f2ab614e
|
||||
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
|
||||
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
|
||||
F test/malloc5.test fafce0aa9157060445cd1a56ad50fc79d82f28c3
|
||||
F test/malloc5.test 79182b8bffd6d62f77b1a5a8ba8e6bf0e5053b8e
|
||||
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
|
||||
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
|
||||
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
|
||||
@@ -723,7 +728,7 @@ F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f
|
||||
F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
|
||||
F test/mallocI.test a88c2b9627c8506bf4703d8397420043a786cdb6
|
||||
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
|
||||
F test/mallocK.test 223cc80c870c80d4a9c2014e94133efdf0123f82
|
||||
F test/mallocK.test da01dcdd316767b8356741f8d33a23a06a23def5
|
||||
F test/mallocL.test 252ddc7eb4fbf75364eab17b938816085ff1fc17
|
||||
F test/malloc_common.tcl 3663f9001ce3e29bbaa9677ffe15cd468e3ec7e3
|
||||
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
@@ -752,7 +757,7 @@ F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
|
||||
F test/multiplex.test efd015ca0b5b4a57dc9535b8feb1273eebeadb60
|
||||
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
|
||||
F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
|
||||
F test/multiplex4.test d3e8a5a522c51cbf3ed1c5b0bd496be02c29d7b1
|
||||
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
|
||||
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
|
||||
@@ -787,8 +792,8 @@ F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test f9cc1dd987986c9d4949211c7a4ed55ec9aecba1
|
||||
F test/pragma.test 6cf0f0ce4618e841457aa42745afda55ddbc95fe
|
||||
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
|
||||
F test/pragma.test ad99d05e411c7687302124be56f3b362204be041
|
||||
F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028
|
||||
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/printf2.test b4acd4bf8734243257f01ddefa17c4fb090acc8a
|
||||
@@ -802,7 +807,7 @@ F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
|
||||
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
|
||||
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rdonly.test dd30a4858d8e0fbad2304c2bd74a33d4df36412a
|
||||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl 13f401c10dd4fe1a2fb811ae6ed27fd7d1300d3c
|
||||
@@ -832,7 +837,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
|
||||
F test/select1.test fc2a61f226a649393664ad54bc5376631801517c
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test 8c5a60d439e2df824aed56223566877a883c5c84
|
||||
F test/select4.test e20e8ce47b558de80616102ef273704cf0d48a3b
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
||||
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
|
||||
@@ -861,11 +866,11 @@ F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test 0860b92352f061ab075ea099af3ce8ac920b6f65
|
||||
F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862
|
||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||
F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5
|
||||
F test/shell4.test 4cd3bd50200bf2efd6a74175d98da65aa86daf26
|
||||
F test/shell5.test c04e9f9f948305706b88377c464c7f08ce7479f9
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
F test/shrink.test 06deac10d591186017466ce67d10645150bfdeec
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test 2ddfe5d168462170c4487f534e2a99fb006b2076
|
||||
F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
|
||||
@@ -873,11 +878,11 @@ F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
|
||||
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
|
||||
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
|
||||
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
|
||||
F test/sort.test 3f492e5b7be1d3f756728d2ff6edf4f6091e84cb
|
||||
F test/sort2.test 37afbc03f5559f2eb0f18940b55d38dfbb5172ac
|
||||
F test/sort3.test 6178ade30810ac9166fcdf14b7065e49c0f534e2
|
||||
F test/sort4.test d5e8903194ae551551349ce25dc8d0b40ca2b9c3
|
||||
F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c
|
||||
F test/sort5.test a448240a42b49239edc00f85d6d7ac7a1b261e1f
|
||||
F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66
|
||||
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
|
||||
@@ -890,7 +895,7 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c 2b416dca3a155fcaa849540b2e7fc1df12896c23
|
||||
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
|
||||
F test/sqllimits1.test 9014524e7ab16e2a4976b13397db4c29cc29c6d9
|
||||
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
|
||||
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
F test/subquery.test 666fdecceac258f5fd84bed09a64e49d9f37edd9
|
||||
@@ -904,7 +909,7 @@ F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/table.test 06271d61eb13871490d38168433c1ef3dd82bb2a
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
||||
F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||
@@ -1137,6 +1142,7 @@ F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750
|
||||
F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
|
||||
F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877
|
||||
F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434
|
||||
F test/walblock.test f1290524714232c109fb0b14db28f14d81c3ddd0
|
||||
F test/walcksum.test 9afeb96240296c08c72fc524d199c912cfe34daa
|
||||
F test/walcrash.test 451d79e528add5c42764cea74aa2750754171b25
|
||||
F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
|
||||
@@ -1157,7 +1163,7 @@ F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
|
||||
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
|
||||
F test/where8.test 806f1dcec4088be2b826b33f757fe6e17c3236a1
|
||||
F test/where8.test 2eafe74e01cc10355985874e1ff868ac03dbae5e
|
||||
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
|
||||
F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
|
||||
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
|
||||
@@ -1170,6 +1176,7 @@ F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
|
||||
F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767
|
||||
F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
@@ -1206,7 +1213,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 94f196c9961e0ca3513e29f57125a3197808be2d
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 9ef48e1748dce7b844f67e2450ff9dfeb0fb4ab5
|
||||
F tool/mksqlite3c.tcl 6b8e572a90eb4e0086e3ba90d88b76c085919863
|
||||
F tool/mksqlite3c.tcl 95ab31eda659e7ffb091e04bd83178f260d8edfd
|
||||
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105
|
||||
@@ -1239,7 +1246,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 913c41b2cdb7c1ec9eba2c8889715b18f693a2bf d70b0fd4c94f2b70cf31c2ab9ef7a2fb2e71c182
|
||||
R c18fa78cee792514fb2af38b954e20bc
|
||||
P acf7684323da4dc3aaf9746bd13b0f56054a17dd 6a48b5d794e891fdd167547c76835d677eb5e31d
|
||||
R 33a835e4a3288b5fed9ba7fe2398105a
|
||||
U mistachkin
|
||||
Z fb458256c681287c05da541cf55853dd
|
||||
Z df3a91ba83fdf4e9cee85e83987e7d93
|
||||
|
||||
@@ -1 +1 @@
|
||||
acf7684323da4dc3aaf9746bd13b0f56054a17dd
|
||||
3e363f405655e2e39588029d797496a952cca11d
|
||||
@@ -32,6 +32,7 @@
|
||||
--end
|
||||
--wait 1
|
||||
--task 2
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t2 SELECT a, b FROM t1;
|
||||
UPDATE t1 SET b='x'||a||'y';
|
||||
@@ -46,6 +47,7 @@
|
||||
--match 29 28 27 26 25
|
||||
--end
|
||||
--task 3
|
||||
DROP TABLE IF EXISTS t3;
|
||||
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t3 SELECT a, b FROM t1;
|
||||
UPDATE t1 SET b='x'||a||'y';
|
||||
@@ -60,6 +62,7 @@
|
||||
--match 29 28 27 26 25
|
||||
--end
|
||||
--task 4
|
||||
DROP TABLE IF EXISTS t4;
|
||||
CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t4 SELECT a, b FROM t1;
|
||||
UPDATE t1 SET b='x'||a||'y';
|
||||
@@ -74,6 +77,7 @@
|
||||
--match 29 28 27 26 25
|
||||
--end
|
||||
--task 5
|
||||
DROP TABLE IF EXISTS t5;
|
||||
CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t5 SELECT a, b FROM t1;
|
||||
UPDATE t1 SET b='x'||a||'y';
|
||||
|
||||
@@ -1262,6 +1262,9 @@ int main(int argc, char **argv){
|
||||
int taskId;
|
||||
const char *zTrace;
|
||||
const char *zCOption;
|
||||
const char *zJMode;
|
||||
const char *zNRep;
|
||||
int nRep = 1, iRep;
|
||||
|
||||
g.argv0 = argv[0];
|
||||
g.iTrace = 1;
|
||||
@@ -1277,6 +1280,10 @@ int main(int argc, char **argv){
|
||||
}
|
||||
n = argc-2;
|
||||
sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.mptest", GETPID());
|
||||
zJMode = findOption(argv+2, &n, "journalmode", 1);
|
||||
zNRep = findOption(argv+2, &n, "repeat", 1);
|
||||
if( zNRep ) nRep = atoi(zNRep);
|
||||
if( nRep<1 ) nRep = 1;
|
||||
g.zVfs = findOption(argv+2, &n, "vfs", 1);
|
||||
zClient = findOption(argv+2, &n, "client", 1);
|
||||
g.zErrLog = findOption(argv+2, &n, "errlog", 1);
|
||||
@@ -1348,7 +1355,11 @@ int main(int argc, char **argv){
|
||||
fatalError("missing script filename");
|
||||
}
|
||||
if( n>1 ) unrecognizedArguments(argv[0], n, argv+2);
|
||||
if( zJMode ) runSql("PRAGMA journal_mode=%Q;", zJMode);
|
||||
runSql(
|
||||
"DROP TABLE IF EXISTS task;\n"
|
||||
"DROP TABLE IF EXISTS counters;\n"
|
||||
"DROP TABLE IF EXISTS client;\n"
|
||||
"CREATE TABLE task(\n"
|
||||
" id INTEGER PRIMARY KEY,\n"
|
||||
" name TEXT,\n"
|
||||
@@ -1364,10 +1375,12 @@ int main(int argc, char **argv){
|
||||
"CREATE TABLE client(id INTEGER PRIMARY KEY, wantHalt);\n"
|
||||
);
|
||||
zScript = readFile(argv[2]);
|
||||
if( g.iTrace ) logMessage("begin script [%s]\n", argv[2]);
|
||||
runScript(0, 0, zScript, argv[2]);
|
||||
for(iRep=1; iRep<=nRep; iRep++){
|
||||
if( g.iTrace ) logMessage("begin script [%s] cycle %d\n", argv[2], iRep);
|
||||
runScript(0, 0, zScript, argv[2]);
|
||||
if( g.iTrace ) logMessage("end script [%s] cycle %d\n", argv[2], iRep);
|
||||
}
|
||||
sqlite3_free(zScript);
|
||||
if( g.iTrace ) logMessage("end script [%s]\n", argv[2]);
|
||||
waitForClient(0, 2000, "during shutdown...\n");
|
||||
trySql("UPDATE client SET wantHalt=1");
|
||||
sqlite3_sleep(10);
|
||||
@@ -1391,7 +1404,7 @@ int main(int argc, char **argv){
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
sqlite3_close(g.db);
|
||||
sqlite3_close(g.db);
|
||||
maybeClose(g.pLog);
|
||||
maybeClose(g.pErrLog);
|
||||
if( iClient==0 ){
|
||||
|
||||
@@ -361,6 +361,8 @@ PRAGMA integrity_check(10);
|
||||
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||
ORDER BY t3.a LIMIT 7
|
||||
--match 45 46 47 48 49 50 51
|
||||
PRAGMA integrity_check;
|
||||
--match ok
|
||||
--end
|
||||
--task 5
|
||||
SELECT t1.a FROM t1, t2
|
||||
@@ -371,6 +373,8 @@ PRAGMA integrity_check(10);
|
||||
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||
ORDER BY t3.a LIMIT 7
|
||||
--match 45 46 47 48 49 50 51
|
||||
PRAGMA integrity_check;
|
||||
--match ok
|
||||
--end
|
||||
--task 3
|
||||
SELECT t1.a FROM t1, t2
|
||||
@@ -381,6 +385,8 @@ PRAGMA integrity_check(10);
|
||||
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||
ORDER BY t3.a LIMIT 7
|
||||
--match 45 46 47 48 49 50 51
|
||||
PRAGMA integrity_check;
|
||||
--match ok
|
||||
--end
|
||||
--task 2
|
||||
SELECT t1.a FROM t1, t2
|
||||
@@ -391,6 +397,8 @@ PRAGMA integrity_check(10);
|
||||
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||
ORDER BY t3.a LIMIT 7
|
||||
--match 45 46 47 48 49 50 51
|
||||
PRAGMA integrity_check;
|
||||
--match ok
|
||||
--end
|
||||
--task 4
|
||||
SELECT t1.a FROM t1, t2
|
||||
@@ -401,5 +409,7 @@ PRAGMA integrity_check(10);
|
||||
WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
|
||||
ORDER BY t3.a LIMIT 7
|
||||
--match 45 46 47 48 49 50 51
|
||||
PRAGMA integrity_check;
|
||||
--match ok
|
||||
--end
|
||||
--wait all
|
||||
|
||||
@@ -690,7 +690,10 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
||||
*/
|
||||
if( pDflt ){
|
||||
sqlite3_value *pVal = 0;
|
||||
if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
|
||||
int rc;
|
||||
rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal);
|
||||
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
|
||||
if( rc!=SQLITE_OK ){
|
||||
db->mallocFailed = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
** Return the collating function associated with a function.
|
||||
*/
|
||||
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
|
||||
VdbeOp *pOp = &context->pVdbe->aOp[context->iOp-1];
|
||||
VdbeOp *pOp;
|
||||
assert( context->pVdbe!=0 );
|
||||
pOp = &context->pVdbe->aOp[context->iOp-1];
|
||||
assert( pOp->opcode==OP_CollSeq );
|
||||
assert( pOp->p4type==P4_COLLSEQ );
|
||||
return pOp->p4.pColl;
|
||||
@@ -1650,6 +1652,11 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
|
||||
** then set aWc[0] through aWc[2] to the wildcard characters and
|
||||
** return TRUE. If the function is not a LIKE-style function then
|
||||
** return FALSE.
|
||||
**
|
||||
** *pIsNocase is set to true if uppercase and lowercase are equivalent for
|
||||
** the function (default for LIKE). If the function makes the distinction
|
||||
** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to
|
||||
** false.
|
||||
*/
|
||||
int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
||||
FuncDef *pDef;
|
||||
|
||||
52
src/main.c
52
src/main.c
@@ -340,26 +340,28 @@ int sqlite3_config(int op, ...){
|
||||
*/
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */
|
||||
case SQLITE_CONFIG_SINGLETHREAD: {
|
||||
/* Disable all mutexing */
|
||||
sqlite3GlobalConfig.bCoreMutex = 0;
|
||||
sqlite3GlobalConfig.bFullMutex = 0;
|
||||
/* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to
|
||||
** Single-thread. */
|
||||
sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */
|
||||
sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */
|
||||
case SQLITE_CONFIG_MULTITHREAD: {
|
||||
/* Disable mutexing of database connections */
|
||||
/* Enable mutexing of core data structures */
|
||||
sqlite3GlobalConfig.bCoreMutex = 1;
|
||||
sqlite3GlobalConfig.bFullMutex = 0;
|
||||
/* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to
|
||||
** Multi-thread. */
|
||||
sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
|
||||
sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */
|
||||
case SQLITE_CONFIG_SERIALIZED: {
|
||||
/* Enable all mutexing */
|
||||
sqlite3GlobalConfig.bCoreMutex = 1;
|
||||
sqlite3GlobalConfig.bFullMutex = 1;
|
||||
/* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to
|
||||
** Serialized. */
|
||||
sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
|
||||
sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -471,7 +473,8 @@ int sqlite3_config(int op, ...){
|
||||
case SQLITE_CONFIG_HEAP: {
|
||||
/* EVIDENCE-OF: R-19854-42126 There are three arguments to
|
||||
** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the
|
||||
** number of bytes in the memory buffer, and the minimum allocation size. */
|
||||
** number of bytes in the memory buffer, and the minimum allocation size.
|
||||
*/
|
||||
sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
|
||||
sqlite3GlobalConfig.nHeap = va_arg(ap, int);
|
||||
sqlite3GlobalConfig.mnReq = va_arg(ap, int);
|
||||
@@ -576,7 +579,9 @@ int sqlite3_config(int op, ...){
|
||||
** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE
|
||||
** compile-time option.
|
||||
*/
|
||||
if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ) mxMmap = SQLITE_MAX_MMAP_SIZE;
|
||||
if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){
|
||||
mxMmap = SQLITE_MAX_MMAP_SIZE;
|
||||
}
|
||||
if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
|
||||
if( szMmap>mxMmap) szMmap = mxMmap;
|
||||
sqlite3GlobalConfig.mxMmap = mxMmap;
|
||||
@@ -2420,7 +2425,19 @@ int sqlite3ParseUri(
|
||||
if( !zFile ) return SQLITE_NOMEM;
|
||||
|
||||
iIn = 5;
|
||||
#ifndef SQLITE_ALLOW_URI_AUTHORITY
|
||||
#ifdef SQLITE_ALLOW_URI_AUTHORITY
|
||||
if( strncmp(zUri+5, "///", 3)==0 ){
|
||||
iIn = 7;
|
||||
/* The following condition causes URIs with five leading / characters
|
||||
** like file://///host/path to be converted into UNCs like //host/path.
|
||||
** The correct URI for that UNC has only two or four leading / characters
|
||||
** file://host/path or file:////host/path. But 5 leading slashes is a
|
||||
** common error, we are told, so we handle it as a special case. */
|
||||
if( strncmp(zUri+7, "///", 3)==0 ){ iIn++; }
|
||||
}else if( strncmp(zUri+5, "//localhost/", 12)==0 ){
|
||||
iIn = 16;
|
||||
}
|
||||
#else
|
||||
/* Discard the scheme and authority segments of the URI. */
|
||||
if( zUri[5]=='/' && zUri[6]=='/' ){
|
||||
iIn = 7;
|
||||
@@ -2863,7 +2880,8 @@ static int openDatabase(
|
||||
opendb_out:
|
||||
sqlite3_free(zOpen);
|
||||
if( db ){
|
||||
assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
|
||||
assert( db->mutex!=0 || isThreadsafe==0
|
||||
|| sqlite3GlobalConfig.bFullMutex==0 );
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
}
|
||||
rc = sqlite3_errcode(db);
|
||||
@@ -3608,7 +3626,7 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
|
||||
**
|
||||
** This test control is used to create imposter tables. "db" is a pointer
|
||||
** to the database connection. dbName is the database name (ex: "main" or
|
||||
@@ -3617,8 +3635,8 @@ int sqlite3_test_control(int op, ...){
|
||||
** table should connect.
|
||||
**
|
||||
** Enable imposter mode only when the schema has already been parsed. Then
|
||||
** run a single CREATE TABLE statement to construct the imposter table in the
|
||||
** parsed schema. Then turn imposter mode back off again.
|
||||
** run a single CREATE TABLE statement to construct the imposter table in
|
||||
** the parsed schema. Then turn imposter mode back off again.
|
||||
**
|
||||
** If onOff==0 and tnum>0 then reset the schema for all databases, causing
|
||||
** the schema to be reparsed the next time it is needed. This has the
|
||||
|
||||
164
src/os_unix.c
164
src/os_unix.c
@@ -71,18 +71,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Define the OS_VXWORKS pre-processor macro to 1 if building on
|
||||
** vxworks, or 0 otherwise.
|
||||
*/
|
||||
#ifndef OS_VXWORKS
|
||||
# if defined(__RTP__) || defined(_WRS_KERNEL)
|
||||
# define OS_VXWORKS 1
|
||||
# else
|
||||
# define OS_VXWORKS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** standard include files.
|
||||
*/
|
||||
@@ -97,18 +85,19 @@
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
# include <sys/ioctl.h>
|
||||
# if OS_VXWORKS
|
||||
# include <semaphore.h>
|
||||
# include <limits.h>
|
||||
# else
|
||||
# include <sys/file.h>
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# include <sys/file.h>
|
||||
# include <sys/param.h>
|
||||
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
|
||||
|
||||
#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
|
||||
#if OS_VXWORKS
|
||||
# include <sys/ioctl.h>
|
||||
# include <semaphore.h>
|
||||
# include <limits.h>
|
||||
#endif /* OS_VXWORKS */
|
||||
|
||||
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
|
||||
# include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
@@ -149,6 +138,10 @@
|
||||
*/
|
||||
#define MAX_PATHNAME 512
|
||||
|
||||
/* Always cast the getpid() return type for compatibility with
|
||||
** kernel modules in VxWorks. */
|
||||
#define osGetpid(X) (pid_t)getpid()
|
||||
|
||||
/*
|
||||
** Only set the lastErrno if the error code is a real error and not
|
||||
** a normal expected return code of SQLITE_BUSY or SQLITE_OK
|
||||
@@ -237,7 +230,7 @@ struct unixFile {
|
||||
** method was called. If xOpen() is called from a different process id,
|
||||
** indicating that a fork() has occurred, the PRNG will be reset.
|
||||
*/
|
||||
static int randomnessPid = 0;
|
||||
static pid_t randomnessPid = 0;
|
||||
|
||||
/*
|
||||
** Allowed values for the unixFile.ctrlFlags bitmask:
|
||||
@@ -255,6 +248,7 @@ static int randomnessPid = 0;
|
||||
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
|
||||
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
|
||||
#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings issued */
|
||||
#define UNIXFILE_BLOCK 0x0200 /* Next SHM lock might block */
|
||||
|
||||
/*
|
||||
** Include code that is common to all os_*.c files
|
||||
@@ -385,7 +379,7 @@ static struct unix_syscall {
|
||||
{ "read", (sqlite3_syscall_ptr)read, 0 },
|
||||
#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
|
||||
|
||||
#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
|
||||
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
|
||||
{ "pread", (sqlite3_syscall_ptr)pread, 0 },
|
||||
#else
|
||||
{ "pread", (sqlite3_syscall_ptr)0, 0 },
|
||||
@@ -402,7 +396,7 @@ static struct unix_syscall {
|
||||
{ "write", (sqlite3_syscall_ptr)write, 0 },
|
||||
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
|
||||
|
||||
#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
|
||||
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
|
||||
{ "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
|
||||
#else
|
||||
{ "pwrite", (sqlite3_syscall_ptr)0, 0 },
|
||||
@@ -1541,7 +1535,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
||||
assert( pFile );
|
||||
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
|
||||
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
|
||||
azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
|
||||
azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared,
|
||||
osGetpid()));
|
||||
|
||||
/* If there is already a lock of this type or more restrictive on the
|
||||
** unixFile, do nothing. Don't use the end_lock: exit path, as
|
||||
@@ -1749,7 +1744,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
||||
assert( pFile );
|
||||
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
|
||||
getpid()));
|
||||
osGetpid()));
|
||||
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
if( pFile->eFileLock<=eFileLock ){
|
||||
@@ -2176,7 +2171,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, getpid()));
|
||||
pFile->eFileLock, osGetpid()));
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
|
||||
/* no-op if possible */
|
||||
@@ -2239,10 +2234,9 @@ static int dotlockClose(sqlite3_file *id) {
|
||||
** still works when you do this, but concurrency is reduced since
|
||||
** only a single process can be reading the database at a time.
|
||||
**
|
||||
** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
|
||||
** compiling for VXWORKS.
|
||||
** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off
|
||||
*/
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
|
||||
/*
|
||||
** Retry flock() calls that fail with EINTR
|
||||
@@ -2395,7 +2389,7 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, getpid()));
|
||||
pFile->eFileLock, osGetpid()));
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
|
||||
/* no-op if possible */
|
||||
@@ -2456,7 +2450,7 @@ static int flockClose(sqlite3_file *id) {
|
||||
** to a non-zero value otherwise *pResOut is set to zero. The return value
|
||||
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
|
||||
*/
|
||||
static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
||||
static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
||||
int rc = SQLITE_OK;
|
||||
int reserved = 0;
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
@@ -2523,7 +2517,7 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
||||
** This routine will only increase a lock. Use the sqlite3OsUnlock()
|
||||
** routine to lower a locking level.
|
||||
*/
|
||||
static int semLock(sqlite3_file *id, int eFileLock) {
|
||||
static int semXLock(sqlite3_file *id, int eFileLock) {
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
sem_t *pSem = pFile->pInode->pSem;
|
||||
int rc = SQLITE_OK;
|
||||
@@ -2556,14 +2550,14 @@ static int semLock(sqlite3_file *id, int eFileLock) {
|
||||
** If the locking level of the file descriptor is already at or below
|
||||
** the requested locking level, this routine is a no-op.
|
||||
*/
|
||||
static int semUnlock(sqlite3_file *id, int eFileLock) {
|
||||
static int semXUnlock(sqlite3_file *id, int eFileLock) {
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
sem_t *pSem = pFile->pInode->pSem;
|
||||
|
||||
assert( pFile );
|
||||
assert( pSem );
|
||||
OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, getpid()));
|
||||
pFile->eFileLock, osGetpid()));
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
|
||||
/* no-op if possible */
|
||||
@@ -2593,10 +2587,10 @@ static int semUnlock(sqlite3_file *id, int eFileLock) {
|
||||
/*
|
||||
** Close a file.
|
||||
*/
|
||||
static int semClose(sqlite3_file *id) {
|
||||
static int semXClose(sqlite3_file *id) {
|
||||
if( id ){
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
semUnlock(id, NO_LOCK);
|
||||
semXUnlock(id, NO_LOCK);
|
||||
assert( pFile );
|
||||
unixEnterMutex();
|
||||
releaseInodeInfo(pFile);
|
||||
@@ -2777,7 +2771,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
|
||||
assert( pFile );
|
||||
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
|
||||
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
|
||||
azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
|
||||
azFileLock(pInode->eFileLock), pInode->nShared , osGetpid()));
|
||||
|
||||
/* If there is already a lock of this type or more restrictive on the
|
||||
** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
|
||||
@@ -2963,7 +2957,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
||||
assert( pFile );
|
||||
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
|
||||
pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
|
||||
getpid()));
|
||||
osGetpid()));
|
||||
|
||||
assert( eFileLock<=SHARED_LOCK );
|
||||
if( pFile->eFileLock<=eFileLock ){
|
||||
@@ -4002,7 +3996,9 @@ static int unixDeviceCharacteristics(sqlite3_file *id){
|
||||
** Instead, it should be called via macro osGetpagesize().
|
||||
*/
|
||||
static int unixGetpagesize(void){
|
||||
#if defined(_BSD_SOURCE)
|
||||
#if OS_VXWORKS
|
||||
return 1024;
|
||||
#elif defined(_BSD_SOURCE)
|
||||
return getpagesize();
|
||||
#else
|
||||
return (int)sysconf(_SC_PAGESIZE);
|
||||
@@ -4095,15 +4091,17 @@ struct unixShm {
|
||||
** otherwise.
|
||||
*/
|
||||
static int unixShmSystemLock(
|
||||
unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
|
||||
unixFile *pFile, /* Open connection to the WAL file */
|
||||
int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
|
||||
int ofst, /* First byte of the locking range */
|
||||
int n /* Number of bytes to lock */
|
||||
){
|
||||
struct flock f; /* The posix advisory locking structure */
|
||||
int rc = SQLITE_OK; /* Result code form fcntl() */
|
||||
unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */
|
||||
struct flock f; /* The posix advisory locking structure */
|
||||
int rc = SQLITE_OK; /* Result code form fcntl() */
|
||||
|
||||
/* Access to the unixShmNode object is serialized by the caller */
|
||||
pShmNode = pFile->pInode->pShmNode;
|
||||
assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
|
||||
|
||||
/* Shared locks never span more than one byte */
|
||||
@@ -4113,6 +4111,7 @@ static int unixShmSystemLock(
|
||||
assert( n>=1 && n<SQLITE_SHM_NLOCK );
|
||||
|
||||
if( pShmNode->h>=0 ){
|
||||
int lkType;
|
||||
/* Initialize the locking parameters */
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.l_type = lockType;
|
||||
@@ -4120,8 +4119,10 @@ static int unixShmSystemLock(
|
||||
f.l_start = ofst;
|
||||
f.l_len = n;
|
||||
|
||||
rc = osFcntl(pShmNode->h, F_SETLK, &f);
|
||||
lkType = (pFile->ctrlFlags & UNIXFILE_BLOCK)!=0 ? F_SETLKW : F_SETLK;
|
||||
rc = osFcntl(pShmNode->h, lkType, &f);
|
||||
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
|
||||
pFile->ctrlFlags &= ~UNIXFILE_BLOCK;
|
||||
}
|
||||
|
||||
/* Update the global lock state and do debug tracing */
|
||||
@@ -4331,13 +4332,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
** If not, truncate the file to zero length.
|
||||
*/
|
||||
rc = SQLITE_OK;
|
||||
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
|
||||
if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
|
||||
if( robust_ftruncate(pShmNode->h, 0) ){
|
||||
rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
|
||||
rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1);
|
||||
}
|
||||
if( rc ) goto shm_open_err;
|
||||
}
|
||||
@@ -4569,7 +4570,7 @@ static int unixShmLock(
|
||||
|
||||
/* Unlock the system-level locks */
|
||||
if( (mask & allMask)==0 ){
|
||||
rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
|
||||
rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
@@ -4597,7 +4598,7 @@ static int unixShmLock(
|
||||
/* Get shared locks at the system level, if necessary */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( (allShared & mask)==0 ){
|
||||
rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
|
||||
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
@@ -4622,7 +4623,7 @@ static int unixShmLock(
|
||||
** also mark the local connection as being locked.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
|
||||
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( (p->sharedMask & mask)==0 );
|
||||
p->exclMask |= mask;
|
||||
@@ -4631,7 +4632,7 @@ static int unixShmLock(
|
||||
}
|
||||
sqlite3_mutex_leave(pShmNode->mutex);
|
||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
|
||||
p->id, getpid(), p->sharedMask, p->exclMask));
|
||||
p->id, osGetpid(), p->sharedMask, p->exclMask));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -5034,7 +5035,7 @@ IOMETHODS(
|
||||
0 /* xShmMap method */
|
||||
)
|
||||
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
IOMETHODS(
|
||||
flockIoFinder, /* Finder function name */
|
||||
flockIoMethods, /* sqlite3_io_methods object name */
|
||||
@@ -5052,10 +5053,10 @@ IOMETHODS(
|
||||
semIoFinder, /* Finder function name */
|
||||
semIoMethods, /* sqlite3_io_methods object name */
|
||||
1, /* shared memory is disabled */
|
||||
semClose, /* xClose method */
|
||||
semLock, /* xLock method */
|
||||
semUnlock, /* xUnlock method */
|
||||
semCheckReservedLock, /* xCheckReservedLock method */
|
||||
semXClose, /* xClose method */
|
||||
semXLock, /* xLock method */
|
||||
semXUnlock, /* xUnlock method */
|
||||
semXCheckReservedLock, /* xCheckReservedLock method */
|
||||
0 /* xShmMap method */
|
||||
)
|
||||
#endif
|
||||
@@ -5179,15 +5180,13 @@ static const sqlite3_io_methods
|
||||
|
||||
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
|
||||
|
||||
#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
|
||||
/*
|
||||
** This "finder" function attempts to determine the best locking strategy
|
||||
** for the database file "filePath". It then returns the sqlite3_io_methods
|
||||
** object that implements that strategy.
|
||||
**
|
||||
** This is for VXWorks only.
|
||||
#if OS_VXWORKS
|
||||
/*
|
||||
** This "finder" function for VxWorks checks to see if posix advisory
|
||||
** locking works. If it does, then that is what is used. If it does not
|
||||
** work, then fallback to named semaphore locking.
|
||||
*/
|
||||
static const sqlite3_io_methods *autolockIoFinderImpl(
|
||||
static const sqlite3_io_methods *vxworksIoFinderImpl(
|
||||
const char *filePath, /* name of the database file */
|
||||
unixFile *pNew /* the open file object */
|
||||
){
|
||||
@@ -5213,9 +5212,9 @@ static const sqlite3_io_methods *autolockIoFinderImpl(
|
||||
}
|
||||
}
|
||||
static const sqlite3_io_methods
|
||||
*(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
|
||||
*(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl;
|
||||
|
||||
#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
|
||||
#endif /* OS_VXWORKS */
|
||||
|
||||
/*
|
||||
** An abstract type for a pointer to an IO method finder function:
|
||||
@@ -5728,8 +5727,8 @@ static int unixOpen(
|
||||
** the same instant might all reset the PRNG. But multiple resets
|
||||
** are harmless.
|
||||
*/
|
||||
if( randomnessPid!=getpid() ){
|
||||
randomnessPid = getpid();
|
||||
if( randomnessPid!=osGetpid() ){
|
||||
randomnessPid = osGetpid();
|
||||
sqlite3_randomness(0,0);
|
||||
}
|
||||
|
||||
@@ -6120,7 +6119,7 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
|
||||
** tests repeatable.
|
||||
*/
|
||||
memset(zBuf, 0, nBuf);
|
||||
randomnessPid = getpid();
|
||||
randomnessPid = osGetpid();
|
||||
#if !defined(SQLITE_TEST)
|
||||
{
|
||||
int fd, got;
|
||||
@@ -6441,7 +6440,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
|
||||
{
|
||||
if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
|
||||
OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
|
||||
lPath, errno, getpid()));
|
||||
lPath, errno, osGetpid()));
|
||||
return SQLITE_IOERR_LOCK;
|
||||
}
|
||||
len = strlcat(lPath, "sqliteplocks", maxLen);
|
||||
@@ -6463,7 +6462,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
|
||||
}
|
||||
lPath[i+len]='\0';
|
||||
strlcat(lPath, ":auto:", maxLen);
|
||||
OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()));
|
||||
OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid()));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -6490,7 +6489,7 @@ static int proxyCreateLockPath(const char *lockPath){
|
||||
if( err!=EEXIST ) {
|
||||
OSTRACE(("CREATELOCKPATH FAILED creating %s, "
|
||||
"'%s' proxy lock path=%s pid=%d\n",
|
||||
buf, strerror(err), lockPath, getpid()));
|
||||
buf, strerror(err), lockPath, osGetpid()));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@@ -6499,7 +6498,7 @@ static int proxyCreateLockPath(const char *lockPath){
|
||||
}
|
||||
buf[i] = lockPath[i];
|
||||
}
|
||||
OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()));
|
||||
OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, osGetpid()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6804,7 +6803,8 @@ static int proxyTakeConch(unixFile *pFile){
|
||||
int forceNewLockPath = 0;
|
||||
|
||||
OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
|
||||
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
|
||||
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
|
||||
osGetpid()));
|
||||
|
||||
rc = proxyGetHostID(myHostID, &pError);
|
||||
if( (rc&0xff)==SQLITE_IOERR ){
|
||||
@@ -7014,7 +7014,7 @@ static int proxyReleaseConch(unixFile *pFile){
|
||||
conchFile = pCtx->conchFile;
|
||||
OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
|
||||
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
|
||||
getpid()));
|
||||
osGetpid()));
|
||||
if( pCtx->conchHeld>0 ){
|
||||
rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
|
||||
}
|
||||
@@ -7156,7 +7156,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
|
||||
}
|
||||
|
||||
OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
|
||||
(lockPath ? lockPath : ":auto:"), getpid()));
|
||||
(lockPath ? lockPath : ":auto:"), osGetpid()));
|
||||
|
||||
pCtx = sqlite3_malloc( sizeof(*pCtx) );
|
||||
if( pCtx==0 ){
|
||||
@@ -7228,6 +7228,10 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
|
||||
*/
|
||||
static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_WAL_BLOCK: {
|
||||
id->ctrlFlags |= UNIXFILE_BLOCK;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
if( pFile->pMethod == &proxyIoMethods ){
|
||||
@@ -7497,8 +7501,10 @@ int sqlite3_os_init(void){
|
||||
** array cannot be const.
|
||||
*/
|
||||
static sqlite3_vfs aVfs[] = {
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
|
||||
UNIXVFS("unix", autolockIoFinder ),
|
||||
#elif OS_VXWORKS
|
||||
UNIXVFS("unix", vxworksIoFinder ),
|
||||
#else
|
||||
UNIXVFS("unix", posixIoFinder ),
|
||||
#endif
|
||||
@@ -7508,11 +7514,11 @@ int sqlite3_os_init(void){
|
||||
#if OS_VXWORKS
|
||||
UNIXVFS("unix-namedsem", semIoFinder ),
|
||||
#endif
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
|
||||
UNIXVFS("unix-posix", posixIoFinder ),
|
||||
#if !OS_VXWORKS
|
||||
UNIXVFS("unix-flock", flockIoFinder ),
|
||||
#endif
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
UNIXVFS("unix-flock", flockIoFinder ),
|
||||
#endif
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
|
||||
UNIXVFS("unix-afp", afpIoFinder ),
|
||||
|
||||
10
src/pcache.c
10
src/pcache.c
@@ -114,12 +114,20 @@ static void pcacheUnpin(PgHdr *p){
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute the number of pages of cache requested.
|
||||
** Compute the number of pages of cache requested. p->szCache is the
|
||||
** cache size requested by the "PRAGMA cache_size" statement.
|
||||
**
|
||||
**
|
||||
*/
|
||||
static int numberOfCachePages(PCache *p){
|
||||
if( p->szCache>=0 ){
|
||||
/* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the
|
||||
** suggested cache size is set to N. */
|
||||
return p->szCache;
|
||||
}else{
|
||||
/* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then
|
||||
** the number of cache pages is adjusted to use approximately abs(N*1024)
|
||||
** bytes of memory. */
|
||||
return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
|
||||
}
|
||||
}
|
||||
|
||||
56
src/pragma.c
56
src/pragma.c
@@ -317,6 +317,17 @@ void sqlite3Pragma(
|
||||
/* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
|
||||
** connection. If it returns SQLITE_OK, then assume that the VFS
|
||||
** handled the pragma and generate a no-op prepared statement.
|
||||
**
|
||||
** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed,
|
||||
** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file
|
||||
** object corresponding to the database file to which the pragma
|
||||
** statement refers.
|
||||
**
|
||||
** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA
|
||||
** file control is an array of pointers to strings (char**) in which the
|
||||
** second element of the array is the name of the pragma and the third
|
||||
** element is the argument to the pragma or NULL if the pragma has no
|
||||
** argument.
|
||||
*/
|
||||
aFcntl[0] = 0;
|
||||
aFcntl[1] = zLeft;
|
||||
@@ -1077,17 +1088,27 @@ void sqlite3Pragma(
|
||||
pIdx = sqlite3FindIndex(db, zRight, zDb);
|
||||
if( pIdx ){
|
||||
int i;
|
||||
int mx = pPragma->iArg ? pIdx->nColumn : pIdx->nKeyCol;
|
||||
int mx;
|
||||
if( pPragma->iArg ){
|
||||
/* PRAGMA index_xinfo (newer version with more rows and columns) */
|
||||
mx = pIdx->nColumn;
|
||||
pParse->nMem = 6;
|
||||
}else{
|
||||
/* PRAGMA index_info (legacy version) */
|
||||
mx = pIdx->nKeyCol;
|
||||
pParse->nMem = 3;
|
||||
}
|
||||
pTab = pIdx->pTable;
|
||||
sqlite3VdbeSetNumCols(v, 6);
|
||||
pParse->nMem = 6;
|
||||
sqlite3VdbeSetNumCols(v, pParse->nMem);
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC);
|
||||
if( pPragma->iArg ){
|
||||
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC);
|
||||
}
|
||||
for(i=0; i<mx; i++){
|
||||
i16 cnum = pIdx->aiColumn[i];
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
|
||||
@@ -1097,10 +1118,12 @@ void sqlite3Pragma(
|
||||
}else{
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i<pIdx->nKeyCol, 6);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
|
||||
if( pPragma->iArg ){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i<pIdx->nKeyCol, 6);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1802,8 +1825,9 @@ void sqlite3Pragma(
|
||||
/*
|
||||
** PRAGMA shrink_memory
|
||||
**
|
||||
** This pragma attempts to free as much memory as possible from the
|
||||
** current database connection.
|
||||
** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database
|
||||
** connection on which it is invoked to free up as much memory as it
|
||||
** can, by calling sqlite3_db_release_memory().
|
||||
*/
|
||||
case PragTyp_SHRINK_MEMORY: {
|
||||
sqlite3_db_release_memory(db);
|
||||
@@ -1832,8 +1856,12 @@ void sqlite3Pragma(
|
||||
** PRAGMA soft_heap_limit
|
||||
** PRAGMA soft_heap_limit = N
|
||||
**
|
||||
** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted,
|
||||
** use -1.
|
||||
** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the
|
||||
** sqlite3_soft_heap_limit64() interface with the argument N, if N is
|
||||
** specified and is a non-negative integer.
|
||||
** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always
|
||||
** returns the same integer that would be returned by the
|
||||
** sqlite3_soft_heap_limit64(-1) C-language function.
|
||||
*/
|
||||
case PragTyp_SOFT_HEAP_LIMIT: {
|
||||
sqlite3_int64 N;
|
||||
|
||||
19
src/select.c
19
src/select.c
@@ -563,20 +563,17 @@ static void pushOntoSorter(
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
|
||||
if( pSelect->iLimit ){
|
||||
int addr1, addr2;
|
||||
int addr;
|
||||
int iLimit;
|
||||
if( pSelect->iOffset ){
|
||||
iLimit = pSelect->iOffset+1;
|
||||
}else{
|
||||
iLimit = pSelect->iLimit;
|
||||
}
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
|
||||
addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
|
||||
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
|
||||
sqlite3VdbeJumpHere(v, addr2);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -973,7 +970,7 @@ static void selectInnerLoop(
|
||||
** the output for us.
|
||||
*/
|
||||
if( pSort==0 && p->iLimit ){
|
||||
sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1826,7 +1823,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
sqlite3ExprCode(pParse, p->pLimit, iLimit);
|
||||
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
|
||||
VdbeComment((v, "LIMIT counter"));
|
||||
sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
|
||||
}
|
||||
if( p->pOffset ){
|
||||
p->iOffset = iOffset = ++pParse->nMem;
|
||||
@@ -2045,7 +2042,7 @@ static void generateWithRecursiveQuery(
|
||||
selectInnerLoop(pParse, p, p->pEList, iCurrent,
|
||||
0, 0, pDest, addrCont, addrBreak);
|
||||
if( regLimit ){
|
||||
sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1);
|
||||
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, addrCont);
|
||||
@@ -2270,7 +2267,7 @@ static int multiSelect(
|
||||
p->iLimit = pPrior->iLimit;
|
||||
p->iOffset = pPrior->iOffset;
|
||||
if( p->iLimit ){
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v);
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
|
||||
VdbeComment((v, "Jump ahead if LIMIT reached"));
|
||||
}
|
||||
explainSetInteger(iSub2, pParse->iNextSelectId);
|
||||
@@ -2671,7 +2668,7 @@ static int generateOutputSubroutine(
|
||||
/* Jump to the end of the loop if the LIMIT is reached.
|
||||
*/
|
||||
if( p->iLimit ){
|
||||
sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
|
||||
}
|
||||
|
||||
/* Generate the subroutine return
|
||||
|
||||
67
src/shell.c
67
src/shell.c
@@ -24,6 +24,13 @@
|
||||
#include "msvc.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** No support for loadable extensions in VxWorks.
|
||||
*/
|
||||
#if defined(_WRS_KERNEL) && !SQLITE_OMIT_LOAD_EXTENSION
|
||||
# define SQLITE_OMIT_LOAD_EXTENSION 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Enable large-file support for fopen() and friends on unix.
|
||||
*/
|
||||
@@ -107,10 +114,15 @@
|
||||
*/
|
||||
extern int isatty(int);
|
||||
|
||||
/* popen and pclose are not C89 functions and so are sometimes omitted from
|
||||
** the <stdio.h> header */
|
||||
extern FILE *popen(const char*,const char*);
|
||||
extern int pclose(FILE*);
|
||||
#if !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
/* popen and pclose are not C89 functions and so are sometimes omitted from
|
||||
** the <stdio.h> header */
|
||||
extern FILE *popen(const char*,const char*);
|
||||
extern int pclose(FILE*);
|
||||
#else
|
||||
# define SQLITE_OMIT_POPEN 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
@@ -165,11 +177,19 @@ static sqlite3_int64 timeOfDay(void){
|
||||
return t;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) \
|
||||
&& !defined(__minux)
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/* VxWorks does not support getrusage() as far as we can determine */
|
||||
#if defined(_WRS_KERNEL) || defined(__RTP__)
|
||||
struct rusage {
|
||||
struct timeval ru_utime; /* user CPU time used */
|
||||
struct timeval ru_stime; /* system CPU time used */
|
||||
};
|
||||
#define getrusage(A,B) memset(B,0,sizeof(*B))
|
||||
#endif
|
||||
|
||||
/* Saved resource information for the beginning of an operation */
|
||||
static struct rusage sBegin; /* CPU time at start */
|
||||
static sqlite3_int64 iBegin; /* Wall-clock time at start */
|
||||
@@ -195,8 +215,8 @@ static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
|
||||
*/
|
||||
static void endTimer(void){
|
||||
if( enableTimer ){
|
||||
struct rusage sEnd;
|
||||
sqlite3_int64 iEnd = timeOfDay();
|
||||
struct rusage sEnd;
|
||||
getrusage(RUSAGE_SELF, &sEnd);
|
||||
printf("Run Time: real %.3f user %f sys %f\n",
|
||||
(iEnd - iBegin)*0.001,
|
||||
@@ -2458,7 +2478,9 @@ static void tryToClone(ShellState *p, const char *zNewDb){
|
||||
*/
|
||||
static void output_reset(ShellState *p){
|
||||
if( p->outfile[0]=='|' ){
|
||||
#ifndef SQLITE_OMIT_POPEN
|
||||
pclose(p->out);
|
||||
#endif
|
||||
}else{
|
||||
output_file_close(p->out);
|
||||
}
|
||||
@@ -2964,9 +2986,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sCtx.zFile = zFile;
|
||||
sCtx.nLine = 1;
|
||||
if( sCtx.zFile[0]=='|' ){
|
||||
#ifdef SQLITE_OMIT_POPEN
|
||||
fprintf(stderr, "Error: pipes are not supporte in this OS\n");
|
||||
return 1;
|
||||
#else
|
||||
sCtx.in = popen(sCtx.zFile+1, "r");
|
||||
sCtx.zFile = "<pipe>";
|
||||
xCloser = pclose;
|
||||
#endif
|
||||
}else{
|
||||
sCtx.in = fopen(sCtx.zFile, "rb");
|
||||
xCloser = fclose;
|
||||
@@ -3289,6 +3316,11 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
output_reset(p);
|
||||
if( zFile[0]=='|' ){
|
||||
#ifdef SQLITE_OMIT_POPEN
|
||||
fprintf(stderr,"Error: pipes are not supported in this OS\n");
|
||||
rc = 1;
|
||||
p->out = stdout;
|
||||
#else
|
||||
p->out = popen(zFile + 1, "w");
|
||||
if( p->out==0 ){
|
||||
fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
|
||||
@@ -3297,6 +3329,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else{
|
||||
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
|
||||
}
|
||||
#endif
|
||||
}else{
|
||||
p->out = output_file_open(zFile);
|
||||
if( p->out==0 ){
|
||||
@@ -3840,12 +3873,12 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
|
||||
open_db(p, 0);
|
||||
output_file_close(p->traceOut);
|
||||
if( nArg!=2 ){
|
||||
fprintf(stderr, "Usage: .trace FILE|off\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
output_file_close(p->traceOut);
|
||||
p->traceOut = output_file_open(azArg[1]);
|
||||
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
||||
if( p->traceOut==0 ){
|
||||
@@ -4221,7 +4254,7 @@ static char *find_home_dir(void){
|
||||
**
|
||||
** Returns the number of errors.
|
||||
*/
|
||||
static int process_sqliterc(
|
||||
static void process_sqliterc(
|
||||
ShellState *p, /* Configuration data */
|
||||
const char *sqliterc_override /* Name of config file. NULL to use default */
|
||||
){
|
||||
@@ -4229,15 +4262,13 @@ static int process_sqliterc(
|
||||
const char *sqliterc = sqliterc_override;
|
||||
char *zBuf = 0;
|
||||
FILE *in = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (sqliterc == NULL) {
|
||||
home_dir = find_home_dir();
|
||||
if( home_dir==0 ){
|
||||
#if !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0);
|
||||
#endif
|
||||
return 1;
|
||||
fprintf(stderr, "-- warning: cannot find home directory;"
|
||||
" cannot read ~/.sqliterc\n");
|
||||
return;
|
||||
}
|
||||
sqlite3_initialize();
|
||||
zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
|
||||
@@ -4248,11 +4279,10 @@ static int process_sqliterc(
|
||||
if( stdin_is_interactive ){
|
||||
fprintf(stderr,"-- Loading resources from %s\n",sqliterc);
|
||||
}
|
||||
rc = process_input(p,in);
|
||||
process_input(p,in);
|
||||
fclose(in);
|
||||
}
|
||||
sqlite3_free(zBuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4528,10 +4558,7 @@ int main(int argc, char **argv){
|
||||
** is given on the command line, look for a file named ~/.sqliterc and
|
||||
** try to process it.
|
||||
*/
|
||||
rc = process_sqliterc(&data,zInitFile);
|
||||
if( rc>0 ){
|
||||
return rc;
|
||||
}
|
||||
process_sqliterc(&data,zInitFile);
|
||||
|
||||
/* Make a second pass through the command-line argument and set
|
||||
** options. This second pass is delayed until after the initialization
|
||||
|
||||
@@ -751,14 +751,16 @@ struct sqlite3_io_methods {
|
||||
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
|
||||
** interface.
|
||||
**
|
||||
** <ul>
|
||||
** <li>[[SQLITE_FCNTL_LOCKSTATE]]
|
||||
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
|
||||
** opcode causes the xFileControl method to write the current state of
|
||||
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
|
||||
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
|
||||
** into an integer that the pArg argument points to. This capability
|
||||
** is used during testing and only needs to be supported when SQLITE_TEST
|
||||
** is defined.
|
||||
** <ul>
|
||||
** is used during testing and is only available when the SQLITE_TEST
|
||||
** compile-time option is used.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_SIZE_HINT]]
|
||||
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
|
||||
** layer a hint of how large the database file will grow to be during the
|
||||
@@ -883,7 +885,9 @@ struct sqlite3_io_methods {
|
||||
** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
|
||||
** file control returns [SQLITE_OK], then the parser assumes that the
|
||||
** VFS has handled the PRAGMA itself and the parser generates a no-op
|
||||
** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
|
||||
** prepared statement if result string is NULL, or that returns a copy
|
||||
** of the result string if the string is non-NULL.
|
||||
** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
|
||||
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
|
||||
** that the VFS encountered an error while handling the [PRAGMA] and the
|
||||
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
|
||||
@@ -941,6 +945,13 @@ struct sqlite3_io_methods {
|
||||
** pointed to by the pArg argument. This capability is used during testing
|
||||
** and only needs to be supported when SQLITE_TEST is defined.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_WAL_BLOCK]]
|
||||
** 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
|
||||
** available. The WAL subsystem issues this signal during rare
|
||||
** circumstances in order to fix a problem with priority inversion.
|
||||
** Applications should <em>not</em> use this file-control.
|
||||
**
|
||||
** </ul>
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
@@ -965,6 +976,7 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_SYNC 21
|
||||
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
|
||||
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
|
||||
#define SQLITE_FCNTL_WAL_BLOCK 24
|
||||
|
||||
/* deprecated names */
|
||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||
@@ -1742,7 +1754,6 @@ struct sqlite3_mem_methods {
|
||||
** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
|
||||
** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
|
||||
** that specifies the maximum size of the created heap.
|
||||
** </dl>
|
||||
**
|
||||
** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
|
||||
** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
|
||||
@@ -2989,11 +3000,13 @@ sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
|
||||
/*
|
||||
** CAPI3REF: Error Codes And Messages
|
||||
**
|
||||
** ^The sqlite3_errcode() interface returns the numeric [result code] or
|
||||
** [extended result code] for the most recent failed sqlite3_* API call
|
||||
** associated with a [database connection]. If a prior API call failed
|
||||
** but the most recent API call succeeded, the return value from
|
||||
** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode()
|
||||
** ^If the most recent sqlite3_* API call associated with
|
||||
** [database connection] D failed, then the sqlite3_errcode(D) interface
|
||||
** returns the numeric [result code] or [extended result code] for that
|
||||
** API call.
|
||||
** If the most recent API call was successful,
|
||||
** then the return value from sqlite3_errcode() is undefined.
|
||||
** ^The sqlite3_extended_errcode()
|
||||
** interface is the same except that it always returns the
|
||||
** [extended result code] even when extended result codes are
|
||||
** disabled.
|
||||
@@ -4218,8 +4231,8 @@ int sqlite3_create_function_v2(
|
||||
** These functions are [deprecated]. In order to maintain
|
||||
** backwards compatibility with older code, these functions continue
|
||||
** to be supported. However, new applications should avoid
|
||||
** the use of these functions. To help encourage people to avoid
|
||||
** using these functions, we are not going to tell you what they do.
|
||||
** the use of these functions. To encourage programmers to avoid
|
||||
** these functions, we will not explain what they do.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
|
||||
@@ -6981,20 +6994,20 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
** is not a permanent error and does not affect the return value of
|
||||
** sqlite3_backup_finish().
|
||||
**
|
||||
** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
|
||||
** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]]
|
||||
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
|
||||
**
|
||||
** ^Each call to sqlite3_backup_step() sets two values inside
|
||||
** the [sqlite3_backup] object: the number of pages still to be backed
|
||||
** up and the total number of pages in the source database file.
|
||||
** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
|
||||
** retrieve these two values, respectively.
|
||||
**
|
||||
** ^The values returned by these functions are only updated by
|
||||
** sqlite3_backup_step(). ^If the source database is modified during a backup
|
||||
** operation, then the values are not updated to account for any extra
|
||||
** pages that need to be updated or the size of the source database file
|
||||
** changing.
|
||||
** ^The sqlite3_backup_remaining() routine returns the number of pages still
|
||||
** to be backed up at the conclusion of the most recent sqlite3_backup_step().
|
||||
** ^The sqlite3_backup_pagecount() routine returns the total number of pages
|
||||
** in the source database at the conclusion of the most recent
|
||||
** sqlite3_backup_step().
|
||||
** ^(The values returned by these functions are only updated by
|
||||
** sqlite3_backup_step(). If the source database is modified in a way that
|
||||
** changes the size of the source database or the number of pages remaining,
|
||||
** those changes are not reflected in the output of sqlite3_backup_pagecount()
|
||||
** and sqlite3_backup_remaining() until after the next
|
||||
** sqlite3_backup_step().)^
|
||||
**
|
||||
** <b>Concurrent Usage of Database Handles</b>
|
||||
**
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
*/
|
||||
#include "msvc.h"
|
||||
|
||||
/*
|
||||
** Special setup for VxWorks
|
||||
*/
|
||||
#include "vxworks.h"
|
||||
|
||||
/*
|
||||
** These #defines should enable >2GB file support on POSIX if the
|
||||
** underlying operating system supports it. If the OS lacks
|
||||
@@ -2250,7 +2255,7 @@ struct SrcList {
|
||||
#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
|
||||
#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
|
||||
#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
|
||||
/* 0x0080 // not currently used */
|
||||
#define WHERE_NO_AUTOINDEX 0x0080 /* Disallow automatic indexes */
|
||||
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
|
||||
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
|
||||
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
|
||||
|
||||
@@ -98,15 +98,17 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The maximum number of in-memory pages to use for the main database
|
||||
** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
|
||||
** The suggested maximum number of in-memory pages to use for
|
||||
** the main database table and for temporary tables.
|
||||
**
|
||||
** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size
|
||||
** is 2000 pages.
|
||||
** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be
|
||||
** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options.
|
||||
*/
|
||||
#ifndef SQLITE_DEFAULT_CACHE_SIZE
|
||||
# define SQLITE_DEFAULT_CACHE_SIZE 2000
|
||||
#endif
|
||||
#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
|
||||
# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The default number of frames to accumulate in the log file before
|
||||
|
||||
@@ -2320,34 +2320,49 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
}
|
||||
|
||||
/*
|
||||
** $db function NAME [-argcount N] SCRIPT
|
||||
** $db function NAME [-argcount N] [-deterministic] SCRIPT
|
||||
**
|
||||
** Create a new SQL function called NAME. Whenever that function is
|
||||
** called, invoke SCRIPT to evaluate the function.
|
||||
*/
|
||||
case DB_FUNCTION: {
|
||||
int flags = SQLITE_UTF8;
|
||||
SqlFunc *pFunc;
|
||||
Tcl_Obj *pScript;
|
||||
char *zName;
|
||||
int nArg = -1;
|
||||
if( objc==6 ){
|
||||
const char *z = Tcl_GetString(objv[3]);
|
||||
int i;
|
||||
if( objc<4 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for(i=3; i<(objc-1); i++){
|
||||
const char *z = Tcl_GetString(objv[i]);
|
||||
int n = strlen30(z);
|
||||
if( n>2 && strncmp(z, "-argcount",n)==0 ){
|
||||
if( Tcl_GetIntFromObj(interp, objv[4], &nArg) ) return TCL_ERROR;
|
||||
if( i==(objc-2) ){
|
||||
Tcl_AppendResult(interp, "option requires an argument: ", z, 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR;
|
||||
if( nArg<0 ){
|
||||
Tcl_AppendResult(interp, "number of arguments must be non-negative",
|
||||
(char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
i++;
|
||||
}else
|
||||
if( n>2 && strncmp(z, "-deterministic",n)==0 ){
|
||||
flags |= SQLITE_DETERMINISTIC;
|
||||
}else{
|
||||
Tcl_AppendResult(interp, "bad option \"", z,
|
||||
"\": must be -argcount or -deterministic", 0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pScript = objv[5];
|
||||
}else if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "NAME [-argcount N] SCRIPT");
|
||||
return TCL_ERROR;
|
||||
}else{
|
||||
pScript = objv[3];
|
||||
}
|
||||
|
||||
pScript = objv[objc-1];
|
||||
zName = Tcl_GetStringFromObj(objv[2], 0);
|
||||
pFunc = findSqlFunc(pDb, zName);
|
||||
if( pFunc==0 ) return TCL_ERROR;
|
||||
@@ -2357,7 +2372,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
pFunc->pScript = pScript;
|
||||
Tcl_IncrRefCount(pScript);
|
||||
pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
|
||||
rc = sqlite3_create_function(pDb->db, zName, nArg, SQLITE_UTF8,
|
||||
rc = sqlite3_create_function(pDb->db, zName, nArg, flags,
|
||||
pFunc, tclSqlFunc, 0, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
rc = TCL_ERROR;
|
||||
|
||||
@@ -650,7 +650,6 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
|
||||
LINKVAR( MAX_PAGE_COUNT );
|
||||
LINKVAR( MAX_LIKE_PATTERN_LENGTH );
|
||||
LINKVAR( MAX_TRIGGER_DEPTH );
|
||||
LINKVAR( DEFAULT_TEMP_CACHE_SIZE );
|
||||
LINKVAR( DEFAULT_CACHE_SIZE );
|
||||
LINKVAR( DEFAULT_PAGE_SIZE );
|
||||
LINKVAR( DEFAULT_FILE_FORMAT );
|
||||
|
||||
@@ -600,12 +600,26 @@ static void test_decode(
|
||||
Tcl_DecrRefCount(pRet);
|
||||
}
|
||||
|
||||
/*
|
||||
** The implementation of scalar SQL function "test_zeroblob()". This is
|
||||
** similar to the built-in zeroblob() function, except that it does not
|
||||
** check that the integer parameter is within range before passing it
|
||||
** to sqlite3_result_zeroblob().
|
||||
*/
|
||||
static void test_zeroblob(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int nZero = sqlite3_value_int(argv[0]);
|
||||
sqlite3_result_zeroblob(context, nZero);
|
||||
}
|
||||
|
||||
static int registerTestFunctions(sqlite3 *db){
|
||||
static const struct {
|
||||
char *zName;
|
||||
signed char nArg;
|
||||
unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */
|
||||
unsigned int eTextRep; /* 1: UTF-16. 0: UTF-8 */
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
|
||||
} aFuncs[] = {
|
||||
{ "randstr", 2, SQLITE_UTF8, randStr },
|
||||
@@ -626,6 +640,7 @@ static int registerTestFunctions(sqlite3 *db){
|
||||
{ "real2hex", 1, SQLITE_UTF8, real2hex},
|
||||
{ "test_decode", 1, SQLITE_UTF8, test_decode},
|
||||
{ "test_extract", 2, SQLITE_UTF8, test_extract},
|
||||
{ "test_zeroblob", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, test_zeroblob},
|
||||
};
|
||||
int i;
|
||||
|
||||
|
||||
@@ -573,6 +573,9 @@ static int multiplexOpen(
|
||||
rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
|
||||
if( rc==SQLITE_OK && zName ){
|
||||
int bExists;
|
||||
if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
|
||||
pGroup->bEnabled = 0;
|
||||
}else
|
||||
if( sz==0 ){
|
||||
if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
|
||||
/* If opening a main journal file and the first chunk is zero
|
||||
@@ -1004,6 +1007,13 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
|
||||
break;
|
||||
case SQLITE_FCNTL_PRAGMA: {
|
||||
char **aFcntl = (char**)pArg;
|
||||
/*
|
||||
** EVIDENCE-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA
|
||||
** file control is an array of pointers to strings (char**) in which the
|
||||
** second element of the array is the name of the pragma and the third
|
||||
** element is the argument to the pragma or NULL if the pragma has no
|
||||
** argument.
|
||||
*/
|
||||
if( aFcntl[1] && sqlite3_stricmp(aFcntl[1],"multiplex_truncate")==0 ){
|
||||
if( aFcntl[2] && aFcntl[2][0] ){
|
||||
if( sqlite3_stricmp(aFcntl[2], "on")==0
|
||||
@@ -1015,6 +1025,12 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
|
||||
pGroup->bTruncate = 0;
|
||||
}
|
||||
}
|
||||
/* EVIDENCE-OF: R-27806-26076 The handler for an SQLITE_FCNTL_PRAGMA
|
||||
** file control can optionally make the first element of the char**
|
||||
** argument point to a string obtained from sqlite3_mprintf() or the
|
||||
** equivalent and that string will become the result of the pragma
|
||||
** or the error message if the pragma fails.
|
||||
*/
|
||||
aFcntl[0] = sqlite3_mprintf(pGroup->bTruncate ? "on" : "off");
|
||||
rc = SQLITE_OK;
|
||||
break;
|
||||
|
||||
@@ -967,16 +967,15 @@ static void tvfsShmBarrier(sqlite3_file *pFile){
|
||||
TestvfsFd *pFd = tvfsGetFd(pFile);
|
||||
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
|
||||
const char *z = pFd->pShm ? pFd->pShm->zFile : "";
|
||||
tvfsExecTcl(p, "xShmBarrier", Tcl_NewStringObj(z, -1), pFd->pShmId, 0, 0);
|
||||
}
|
||||
|
||||
if( p->isFullshm ){
|
||||
sqlite3OsShmBarrier(pFd->pReal);
|
||||
return;
|
||||
}
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
|
||||
tvfsExecTcl(p, "xShmBarrier",
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static int tvfsShmUnmap(
|
||||
@@ -1532,7 +1531,7 @@ static int testvfs_cmd(
|
||||
return TCL_OK;
|
||||
|
||||
bad_args:
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?");
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-fullshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
81
src/vdbe.c
81
src/vdbe.c
@@ -1015,7 +1015,7 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
|
||||
** Synopsis: r[P2]='P4'
|
||||
**
|
||||
** P4 points to a nul terminated UTF-8 string. This opcode is transformed
|
||||
** into a String before it is executed for the first time. During
|
||||
** into a String opcode before it is executed for the first time. During
|
||||
** this transformation, the length of string P4 is computed and stored
|
||||
** as the P1 parameter.
|
||||
*/
|
||||
@@ -1047,10 +1047,15 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */
|
||||
/* Fall through to the next case, OP_String */
|
||||
}
|
||||
|
||||
/* Opcode: String P1 P2 * P4 *
|
||||
/* Opcode: String P1 P2 P3 P4 P5
|
||||
** Synopsis: r[P2]='P4' (len=P1)
|
||||
**
|
||||
** The string value P4 of length P1 (bytes) is stored in register P2.
|
||||
**
|
||||
** If P5!=0 and the content of register P3 is greater than zero, then
|
||||
** the datatype of the register P2 is converted to BLOB. The content is
|
||||
** the same sequence of bytes, it is merely interpreted as a BLOB instead
|
||||
** of a string, as if it had been CAST.
|
||||
*/
|
||||
case OP_String: { /* out2-prerelease */
|
||||
assert( pOp->p4.z!=0 );
|
||||
@@ -1059,6 +1064,13 @@ case OP_String: { /* out2-prerelease */
|
||||
pOut->n = pOp->p1;
|
||||
pOut->enc = encoding;
|
||||
UPDATE_MAX_BLOBSIZE(pOut);
|
||||
if( pOp->p5 ){
|
||||
assert( pOp->p3>0 );
|
||||
assert( pOp->p3<=(p->nMem-p->nCursor) );
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
assert( pIn3->flags & MEM_Int );
|
||||
if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1505,7 +1517,7 @@ arithmetic_result_is_null:
|
||||
**
|
||||
** The interface used by the implementation of the aforementioned functions
|
||||
** to retrieve the collation sequence set by this opcode is not available
|
||||
** publicly, only to user functions defined in func.c.
|
||||
** publicly. Only built-in functions have access to this feature.
|
||||
*/
|
||||
case OP_CollSeq: {
|
||||
assert( pOp->p4type==P4_COLLSEQ );
|
||||
@@ -3050,7 +3062,12 @@ case OP_Transaction: {
|
||||
p->nStmtDefImmCons = db->nDeferredImmCons;
|
||||
}
|
||||
|
||||
/* Gather the schema version number for checking */
|
||||
/* Gather the schema version number for checking:
|
||||
** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite
|
||||
** each time a query is executed to ensure that the internal cache of the
|
||||
** schema used when compiling the SQL query matches the schema of the
|
||||
** database against which the compiled query is actually executed.
|
||||
*/
|
||||
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
|
||||
iGen = db->aDb[pOp->p1].pSchema->iGeneration;
|
||||
}else{
|
||||
@@ -5568,10 +5585,12 @@ case OP_MemMax: { /* in2 */
|
||||
/* Opcode: IfPos P1 P2 * * *
|
||||
** Synopsis: if r[P1]>0 goto P2
|
||||
**
|
||||
** If the value of register P1 is 1 or greater, jump to P2.
|
||||
** Register P1 must contain an integer.
|
||||
** If the value of register P1 is 1 or greater, jump to P2 and
|
||||
** add the literal value P3 to register P1.
|
||||
**
|
||||
** It is illegal to use this instruction on a register that does
|
||||
** not contain an integer. An assertion fault will result if you try.
|
||||
** If the initial value of register P1 is less than 1, then the
|
||||
** value is unchanged and control passes through to the next instruction.
|
||||
*/
|
||||
case OP_IfPos: { /* jump, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
@@ -5600,16 +5619,34 @@ case OP_IfNeg: { /* jump, in1 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IfZero P1 P2 P3 * *
|
||||
** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2
|
||||
/* Opcode: IfNotZero P1 P2 P3 * *
|
||||
** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2
|
||||
**
|
||||
** The register P1 must contain an integer. Add literal P3 to the
|
||||
** value in register P1. If the result is exactly 0, jump to P2.
|
||||
** Register P1 must contain an integer. If the content of register P1 is
|
||||
** initially nonzero, then add P3 to P1 and jump to P2. If register P1 is
|
||||
** initially zero, leave it unchanged and fall through.
|
||||
*/
|
||||
case OP_IfZero: { /* jump, in1 */
|
||||
case OP_IfNotZero: { /* jump, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( pIn1->flags&MEM_Int );
|
||||
pIn1->u.i += pOp->p3;
|
||||
VdbeBranchTaken(pIn1->u.i<0, 2);
|
||||
if( pIn1->u.i ){
|
||||
pIn1->u.i += pOp->p3;
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: DecrJumpZero P1 P2 * * *
|
||||
** Synopsis: if (--r[P1])==0 goto P2
|
||||
**
|
||||
** Register P1 must hold an integer. Decrement the value in register P1
|
||||
** then jump to P2 if the new value is exactly zero.
|
||||
*/
|
||||
case OP_DecrJumpZero: { /* jump, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( pIn1->flags&MEM_Int );
|
||||
pIn1->u.i--;
|
||||
VdbeBranchTaken(pIn1->u.i==0, 2);
|
||||
if( pIn1->u.i==0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
@@ -5617,6 +5654,24 @@ case OP_IfZero: { /* jump, in1 */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Opcode: JumpZeroIncr P1 P2 * * *
|
||||
** Synopsis: if (r[P1]++)==0 ) goto P2
|
||||
**
|
||||
** The register P1 must contain an integer. If register P1 is initially
|
||||
** zero, then jump to P2. Increment register P1 regardless of whether or
|
||||
** not the jump is taken.
|
||||
*/
|
||||
case OP_JumpZeroIncr: { /* jump, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( pIn1->flags&MEM_Int );
|
||||
VdbeBranchTaken(pIn1->u.i==0, 2);
|
||||
if( (pIn1->u.i++)==0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: AggStep * P2 P3 P4 P5
|
||||
** Synopsis: accum=r[P3] step(r[P2@P5])
|
||||
**
|
||||
|
||||
@@ -370,7 +370,7 @@ void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
|
||||
pCtx->isError = errCode;
|
||||
pCtx->fErrorOrAux = 1;
|
||||
#ifdef SQLITE_DEBUG
|
||||
pCtx->pVdbe->rcApp = errCode;
|
||||
if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
|
||||
#endif
|
||||
if( pCtx->pOut->flags & MEM_Null ){
|
||||
sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1,
|
||||
@@ -633,16 +633,26 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current time for a statement
|
||||
** Return the current time for a statement. If the current time
|
||||
** is requested more than once within the same run of a single prepared
|
||||
** statement, the exact same time is returned for each invocation regardless
|
||||
** of the amount of time that elapses between invocations. In other words,
|
||||
** the time returned is always the time of the first call.
|
||||
*/
|
||||
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
|
||||
Vdbe *v = p->pVdbe;
|
||||
int rc;
|
||||
if( v->iCurrentTime==0 ){
|
||||
rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, &v->iCurrentTime);
|
||||
if( rc ) v->iCurrentTime = 0;
|
||||
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
|
||||
assert( p->pVdbe!=0 );
|
||||
#else
|
||||
sqlite3_int64 iTime = 0;
|
||||
sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime;
|
||||
#endif
|
||||
if( *piTime==0 ){
|
||||
rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime);
|
||||
if( rc ) *piTime = 0;
|
||||
}
|
||||
return v->iCurrentTime;
|
||||
return *piTime;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -712,6 +722,11 @@ void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
|
||||
AuxData *pAuxData;
|
||||
|
||||
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
||||
#if SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
if( pCtx->pVdbe==0 ) return 0;
|
||||
#else
|
||||
assert( pCtx->pVdbe!=0 );
|
||||
#endif
|
||||
for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
|
||||
if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
|
||||
}
|
||||
@@ -735,6 +750,11 @@ void sqlite3_set_auxdata(
|
||||
|
||||
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
||||
if( iArg<0 ) goto failed;
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
if( pVdbe==0 ) goto failed;
|
||||
#else
|
||||
assert( pVdbe!=0 );
|
||||
#endif
|
||||
|
||||
for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
|
||||
if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
|
||||
|
||||
@@ -2143,7 +2143,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
|
||||
** doing this the directory is synced again before any individual
|
||||
** transaction files are deleted.
|
||||
*/
|
||||
rc = sqlite3OsDelete(pVfs, zMaster, 1);
|
||||
rc = sqlite3OsDelete(pVfs, zMaster, needSync);
|
||||
sqlite3DbFree(db, zMaster);
|
||||
zMaster = 0;
|
||||
if( rc ){
|
||||
|
||||
121
src/vdbemem.c
121
src/vdbemem.c
@@ -1090,7 +1090,7 @@ struct ValueNewStat4Ctx {
|
||||
** Otherwise, if the second argument is non-zero, then this function is
|
||||
** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
|
||||
** already been allocated, allocate the UnpackedRecord structure that
|
||||
** that function will return to its caller here. Then return a pointer
|
||||
** that function will return to its caller here. Then return a pointer to
|
||||
** an sqlite3_value within the UnpackedRecord.a[] array.
|
||||
*/
|
||||
static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
|
||||
@@ -1134,6 +1134,113 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
|
||||
return sqlite3ValueNew(db);
|
||||
}
|
||||
|
||||
/*
|
||||
** The expression object indicated by the second argument is guaranteed
|
||||
** to be a scalar SQL function. If
|
||||
**
|
||||
** * all function arguments are SQL literals,
|
||||
** * the SQLITE_FUNC_CONSTANT function flag is set, and
|
||||
** * the SQLITE_FUNC_NEEDCOLL function flag is not set,
|
||||
**
|
||||
** then this routine attempts to invoke the SQL function. Assuming no
|
||||
** error occurs, output parameter (*ppVal) is set to point to a value
|
||||
** object containing the result before returning SQLITE_OK.
|
||||
**
|
||||
** Affinity aff is applied to the result of the function before returning.
|
||||
** If the result is a text value, the sqlite3_value object uses encoding
|
||||
** enc.
|
||||
**
|
||||
** If the conditions above are not met, this function returns SQLITE_OK
|
||||
** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to
|
||||
** NULL and an SQLite error code returned.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
static int valueFromFunction(
|
||||
sqlite3 *db, /* The database connection */
|
||||
Expr *p, /* The expression to evaluate */
|
||||
u8 enc, /* Encoding to use */
|
||||
u8 aff, /* Affinity to use */
|
||||
sqlite3_value **ppVal, /* Write the new value here */
|
||||
struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */
|
||||
){
|
||||
sqlite3_context ctx; /* Context object for function invocation */
|
||||
sqlite3_value **apVal = 0; /* Function arguments */
|
||||
int nVal = 0; /* Size of apVal[] array */
|
||||
FuncDef *pFunc = 0; /* Function definition */
|
||||
sqlite3_value *pVal = 0; /* New value */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int nName; /* Size of function name in bytes */
|
||||
ExprList *pList = 0; /* Function arguments */
|
||||
int i; /* Iterator variable */
|
||||
|
||||
assert( pCtx!=0 );
|
||||
assert( (p->flags & EP_TokenOnly)==0 );
|
||||
pList = p->x.pList;
|
||||
if( pList ) nVal = pList->nExpr;
|
||||
nName = sqlite3Strlen30(p->u.zToken);
|
||||
pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0);
|
||||
assert( pFunc );
|
||||
if( (pFunc->funcFlags & SQLITE_FUNC_CONSTANT)==0
|
||||
|| (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
|
||||
){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
if( pList ){
|
||||
apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal);
|
||||
if( apVal==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto value_from_function_out;
|
||||
}
|
||||
for(i=0; i<nVal; i++){
|
||||
rc = sqlite3ValueFromExpr(db, pList->a[i].pExpr, enc, aff, &apVal[i]);
|
||||
if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
|
||||
}
|
||||
}
|
||||
|
||||
pVal = valueNew(db, pCtx);
|
||||
if( pVal==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto value_from_function_out;
|
||||
}
|
||||
|
||||
assert( pCtx->pParse->rc==SQLITE_OK );
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.pOut = pVal;
|
||||
ctx.pFunc = pFunc;
|
||||
pFunc->xFunc(&ctx, nVal, apVal);
|
||||
if( ctx.isError ){
|
||||
rc = ctx.isError;
|
||||
sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
|
||||
}else{
|
||||
sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
|
||||
assert( rc==SQLITE_OK );
|
||||
rc = sqlite3VdbeChangeEncoding(pVal, enc);
|
||||
if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
|
||||
rc = SQLITE_TOOBIG;
|
||||
pCtx->pParse->nErr++;
|
||||
}
|
||||
}
|
||||
pCtx->pParse->rc = rc;
|
||||
|
||||
value_from_function_out:
|
||||
if( rc!=SQLITE_OK ){
|
||||
pVal = 0;
|
||||
}
|
||||
if( apVal ){
|
||||
for(i=0; i<nVal; i++){
|
||||
sqlite3ValueFree(apVal[i]);
|
||||
}
|
||||
sqlite3DbFree(db, apVal);
|
||||
}
|
||||
|
||||
*ppVal = pVal;
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
# define valueFromFunction(a,b,c,d,e,f) SQLITE_OK
|
||||
#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
|
||||
|
||||
/*
|
||||
** Extract a value from the supplied expression in the manner described
|
||||
** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
|
||||
@@ -1166,6 +1273,12 @@ static int valueFromExpr(
|
||||
while( (op = pExpr->op)==TK_UPLUS ) pExpr = pExpr->pLeft;
|
||||
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
|
||||
|
||||
/* Compressed expressions only appear when parsing the DEFAULT clause
|
||||
** on a table column definition, and hence only when pCtx==0. This
|
||||
** check ensures that an EP_TokenOnly expression is never passed down
|
||||
** into valueFromFunction(). */
|
||||
assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 );
|
||||
|
||||
if( op==TK_CAST ){
|
||||
u8 aff = sqlite3AffinityType(pExpr->u.zToken,0);
|
||||
rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
|
||||
@@ -1242,6 +1355,12 @@ static int valueFromExpr(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
else if( op==TK_FUNCTION && pCtx!=0 ){
|
||||
rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
|
||||
}
|
||||
#endif
|
||||
|
||||
*ppVal = pVal;
|
||||
return rc;
|
||||
|
||||
|
||||
@@ -1151,6 +1151,7 @@ static int vdbeSorterOpenTempFile(
|
||||
sqlite3_file **ppFd
|
||||
){
|
||||
int rc;
|
||||
if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS;
|
||||
rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd,
|
||||
SQLITE_OPEN_TEMP_JOURNAL |
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
|
||||
|
||||
29
src/vxworks.h
Normal file
29
src/vxworks.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
** 2015-03-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 contains code that is specific to Wind River's VxWorks
|
||||
*/
|
||||
#if defined(__RTP__) || defined(_WRS_KERNEL)
|
||||
/* This is VxWorks. Set up things specially for that OS
|
||||
*/
|
||||
#include <vxWorks.h>
|
||||
#include <pthread.h> /* amalgamator: dontcache */
|
||||
#define OS_VXWORKS 1
|
||||
#define SQLITE_OS_OTHER 0
|
||||
#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1
|
||||
#define SQLITE_OMIT_LOAD_EXTENSION 1
|
||||
#define SQLITE_ENABLE_LOCKING_STYLE 0
|
||||
#define HAVE_UTIME 1
|
||||
#else
|
||||
/* This is not VxWorks. */
|
||||
#define OS_VXWORKS 0
|
||||
#endif /* defined(_WRS_KERNEL) */
|
||||
17
src/wal.c
17
src/wal.c
@@ -788,9 +788,10 @@ static void walUnlockShared(Wal *pWal, int lockIdx){
|
||||
SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
|
||||
WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
|
||||
}
|
||||
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
|
||||
static int walLockExclusive(Wal *pWal, int lockIdx, int n, int fBlock){
|
||||
int rc;
|
||||
if( pWal->exclusiveMode ) return SQLITE_OK;
|
||||
if( fBlock ) sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_WAL_BLOCK, 0);
|
||||
rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
|
||||
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
|
||||
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
|
||||
@@ -1076,7 +1077,7 @@ static int walIndexRecover(Wal *pWal){
|
||||
assert( pWal->writeLock );
|
||||
iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
|
||||
nLock = SQLITE_SHM_NLOCK - iLock;
|
||||
rc = walLockExclusive(pWal, iLock, nLock);
|
||||
rc = walLockExclusive(pWal, iLock, nLock, 0);
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
@@ -1610,7 +1611,7 @@ static int walBusyLock(
|
||||
){
|
||||
int rc;
|
||||
do {
|
||||
rc = walLockExclusive(pWal, lockIdx, n);
|
||||
rc = walLockExclusive(pWal, lockIdx, n, 0);
|
||||
}while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
|
||||
return rc;
|
||||
}
|
||||
@@ -2043,7 +2044,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
|
||||
walUnlockShared(pWal, WAL_WRITE_LOCK);
|
||||
rc = SQLITE_READONLY_RECOVERY;
|
||||
}
|
||||
}else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
|
||||
}else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 1)) ){
|
||||
pWal->writeLock = 1;
|
||||
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
|
||||
badHdr = walIndexTryHdr(pWal, pChanged);
|
||||
@@ -2249,7 +2250,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
&& (mxReadMark<pWal->hdr.mxFrame || mxI==0)
|
||||
){
|
||||
for(i=1; i<WAL_NREADER; i++){
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame;
|
||||
mxI = i;
|
||||
@@ -2505,7 +2506,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){
|
||||
/* Only one writer allowed at a time. Get the write lock. Return
|
||||
** SQLITE_BUSY if unable.
|
||||
*/
|
||||
rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
||||
rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 0);
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
@@ -2650,7 +2651,7 @@ static int walRestartLog(Wal *pWal){
|
||||
if( pInfo->nBackfill>0 ){
|
||||
u32 salt1;
|
||||
sqlite3_randomness(4, &salt1);
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* If all readers are using WAL_READ_LOCK(0) (in other words if no
|
||||
** readers are currently using the WAL), then the transactions
|
||||
@@ -2975,7 +2976,7 @@ int sqlite3WalCheckpoint(
|
||||
|
||||
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
|
||||
** "checkpoint" lock on the database file. */
|
||||
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
||||
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1, 0);
|
||||
if( rc ){
|
||||
/* EVIDENCE-OF: R-10421-19736 If any other process is running a
|
||||
** checkpoint operation at the same time, the lock cannot be obtained and
|
||||
|
||||
444
src/where.c
444
src/where.c
@@ -202,7 +202,7 @@ static void whereClauseClear(WhereClause *pWC){
|
||||
** calling this routine. Such pointers may be reinitialized by referencing
|
||||
** the pWC->a[] array.
|
||||
*/
|
||||
static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
|
||||
static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
|
||||
WhereTerm *pTerm;
|
||||
int idx;
|
||||
testcase( wtFlags & TERM_VIRTUAL );
|
||||
@@ -627,7 +627,11 @@ static void exprAnalyzeAll(
|
||||
** so and false if not.
|
||||
**
|
||||
** In order for the operator to be optimizible, the RHS must be a string
|
||||
** literal that does not begin with a wildcard.
|
||||
** literal that does not begin with a wildcard. The LHS must be a column
|
||||
** that may only be NULL, a string, or a BLOB, never a number. (This means
|
||||
** that virtual tables cannot participate in the LIKE optimization.) If the
|
||||
** collating sequence for the column on the LHS must be appropriate for
|
||||
** the operator.
|
||||
*/
|
||||
static int isLikeOrGlob(
|
||||
Parse *pParse, /* Parsing and code generating context */
|
||||
@@ -656,7 +660,7 @@ static int isLikeOrGlob(
|
||||
pLeft = pList->a[1].pExpr;
|
||||
if( pLeft->op!=TK_COLUMN
|
||||
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|
||||
|| IsVirtual(pLeft->pTab)
|
||||
|| IsVirtual(pLeft->pTab) /* Value might be numeric */
|
||||
){
|
||||
/* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
|
||||
** be the name of an indexed column with TEXT affinity. */
|
||||
@@ -766,6 +770,79 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
|
||||
pWC->a[iParent].nChild++;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not
|
||||
** a conjunction, then return just pTerm when N==0. If N is exceeds
|
||||
** the number of available subterms, return NULL.
|
||||
*/
|
||||
static WhereTerm *whereNthSubterm(WhereTerm *pTerm, int N){
|
||||
if( pTerm->eOperator!=WO_AND ){
|
||||
return N==0 ? pTerm : 0;
|
||||
}
|
||||
if( N<pTerm->u.pAndInfo->wc.nTerm ){
|
||||
return &pTerm->u.pAndInfo->wc.a[N];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Subterms pOne and pTwo are contained within WHERE clause pWC. The
|
||||
** two subterms are in disjunction - they are OR-ed together.
|
||||
**
|
||||
** If these two terms are both of the form: "A op B" with the same
|
||||
** A and B values but different operators and if the operators are
|
||||
** compatible (if one is = and the other is <, for example) then
|
||||
** add a new virtual AND term to pWC that is the combination of the
|
||||
** two.
|
||||
**
|
||||
** Some examples:
|
||||
**
|
||||
** x<y OR x=y --> x<=y
|
||||
** x=y OR x=y --> x=y
|
||||
** x<=y OR x<y --> x<=y
|
||||
**
|
||||
** The following is NOT generated:
|
||||
**
|
||||
** x<y OR x>y --> x!=y
|
||||
*/
|
||||
static void whereCombineDisjuncts(
|
||||
SrcList *pSrc, /* the FROM clause */
|
||||
WhereClause *pWC, /* The complete WHERE clause */
|
||||
WhereTerm *pOne, /* First disjunct */
|
||||
WhereTerm *pTwo /* Second disjunct */
|
||||
){
|
||||
u16 eOp = pOne->eOperator | pTwo->eOperator;
|
||||
sqlite3 *db; /* Database connection (for malloc) */
|
||||
Expr *pNew; /* New virtual expression */
|
||||
int op; /* Operator for the combined expression */
|
||||
int idxNew; /* Index in pWC of the next virtual term */
|
||||
|
||||
if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
|
||||
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
|
||||
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
|
||||
&& (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
|
||||
assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
|
||||
assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
|
||||
if( sqlite3ExprCompare(pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
|
||||
if( sqlite3ExprCompare(pOne->pExpr->pRight, pTwo->pExpr->pRight, -1) )return;
|
||||
/* If we reach this point, it means the two subterms can be combined */
|
||||
if( (eOp & (eOp-1))!=0 ){
|
||||
if( eOp & (WO_LT|WO_LE) ){
|
||||
eOp = WO_LE;
|
||||
}else{
|
||||
assert( eOp & (WO_GT|WO_GE) );
|
||||
eOp = WO_GE;
|
||||
}
|
||||
}
|
||||
db = pWC->pWInfo->pParse->db;
|
||||
pNew = sqlite3ExprDup(db, pOne->pExpr, 0);
|
||||
if( pNew==0 ) return;
|
||||
for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( op<TK_GE ); }
|
||||
pNew->op = op;
|
||||
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
exprAnalyze(pSrc, pWC, idxNew);
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
|
||||
/*
|
||||
** Analyze a term that consists of two or more OR-connected
|
||||
@@ -790,6 +867,7 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
|
||||
** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
|
||||
** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
|
||||
** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
|
||||
** (F) x>A OR (x=A AND y>=B)
|
||||
**
|
||||
** CASE 1:
|
||||
**
|
||||
@@ -806,6 +884,16 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
|
||||
**
|
||||
** CASE 2:
|
||||
**
|
||||
** If there are exactly two disjuncts one side has x>A and the other side
|
||||
** has x=A (for the same x and A) then add a new virtual conjunct term to the
|
||||
** WHERE clause of the form "x>=A". Example:
|
||||
**
|
||||
** x>A OR (x=A AND y>B) adds: x>=A
|
||||
**
|
||||
** The added conjunct can sometimes be helpful in query planning.
|
||||
**
|
||||
** CASE 3:
|
||||
**
|
||||
** If all subterms are indexable by a single table T, then set
|
||||
**
|
||||
** WhereTerm.eOperator = WO_OR
|
||||
@@ -932,12 +1020,26 @@ static void exprAnalyzeOrTerm(
|
||||
}
|
||||
|
||||
/*
|
||||
** Record the set of tables that satisfy case 2. The set might be
|
||||
** Record the set of tables that satisfy case 3. The set might be
|
||||
** empty.
|
||||
*/
|
||||
pOrInfo->indexable = indexable;
|
||||
pTerm->eOperator = indexable==0 ? 0 : WO_OR;
|
||||
|
||||
/* For a two-way OR, attempt to implementation case 2.
|
||||
*/
|
||||
if( indexable && pOrWc->nTerm==2 ){
|
||||
int iOne = 0;
|
||||
WhereTerm *pOne;
|
||||
while( (pOne = whereNthSubterm(&pOrWc->a[0],iOne++))!=0 ){
|
||||
int iTwo = 0;
|
||||
WhereTerm *pTwo;
|
||||
while( (pTwo = whereNthSubterm(&pOrWc->a[1],iTwo++))!=0 ){
|
||||
whereCombineDisjuncts(pSrc, pWC, pOne, pTwo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** chngToIN holds a set of tables that *might* satisfy case 1. But
|
||||
** we have to do some additional checking to see if case 1 really
|
||||
@@ -1067,7 +1169,7 @@ static void exprAnalyzeOrTerm(
|
||||
}else{
|
||||
sqlite3ExprListDelete(db, pList);
|
||||
}
|
||||
pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */
|
||||
pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1105,7 +1207,7 @@ static void exprAnalyze(
|
||||
Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
|
||||
Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
|
||||
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
|
||||
int noCase = 0; /* LIKE/GLOB distinguishes case */
|
||||
int noCase = 0; /* uppercase equivalent to lowercase */
|
||||
int op; /* Top-level operator. pExpr->op */
|
||||
Parse *pParse = pWInfo->pParse; /* Parsing context */
|
||||
sqlite3 *db = pParse->db; /* Database connection */
|
||||
@@ -1243,12 +1345,15 @@ static void exprAnalyze(
|
||||
/* Add constraints to reduce the search space on a LIKE or GLOB
|
||||
** operator.
|
||||
**
|
||||
** A like pattern of the form "x LIKE 'abc%'" is changed into constraints
|
||||
** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints
|
||||
**
|
||||
** x>='abc' AND x<'abd' AND x LIKE 'abc%'
|
||||
** x>='ABC' AND x<'abd' AND x LIKE 'aBc%'
|
||||
**
|
||||
** The last character of the prefix "abc" is incremented to form the
|
||||
** termination condition "abd".
|
||||
** termination condition "abd". If case is not significant (the default
|
||||
** for LIKE) then the lower-bound is made all uppercase and the upper-
|
||||
** bound is made all lowercase so that the bounds also work when comparing
|
||||
** BLOBs.
|
||||
*/
|
||||
if( pWC->op==TK_AND
|
||||
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
|
||||
@@ -1260,9 +1365,25 @@ static void exprAnalyze(
|
||||
int idxNew1;
|
||||
int idxNew2;
|
||||
Token sCollSeqName; /* Name of collating sequence */
|
||||
const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
|
||||
|
||||
pLeft = pExpr->x.pList->a[1].pExpr;
|
||||
pStr2 = sqlite3ExprDup(db, pStr1, 0);
|
||||
|
||||
/* Convert the lower bound to upper-case and the upper bound to
|
||||
** lower-case (upper-case is less than lower-case in ASCII) so that
|
||||
** the range constraints also work for BLOBs
|
||||
*/
|
||||
if( noCase && !pParse->db->mallocFailed ){
|
||||
int i;
|
||||
char c;
|
||||
pTerm->wtFlags |= TERM_LIKE;
|
||||
for(i=0; (c = pStr1->u.zToken[i])!=0; i++){
|
||||
pStr1->u.zToken[i] = sqlite3Toupper(c);
|
||||
pStr2->u.zToken[i] = sqlite3Tolower(c);
|
||||
}
|
||||
}
|
||||
|
||||
if( !db->mallocFailed ){
|
||||
u8 c, *pC; /* Last character before the first wildcard */
|
||||
pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
|
||||
@@ -1282,11 +1403,11 @@ static void exprAnalyze(
|
||||
sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
|
||||
sCollSeqName.n = 6;
|
||||
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
|
||||
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
|
||||
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
|
||||
sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
|
||||
pStr1, 0);
|
||||
transferJoinMarkings(pNewExpr1, pExpr);
|
||||
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags);
|
||||
testcase( idxNew1==0 );
|
||||
exprAnalyze(pSrc, pWC, idxNew1);
|
||||
pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
|
||||
@@ -1294,7 +1415,7 @@ static void exprAnalyze(
|
||||
sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
|
||||
pStr2, 0);
|
||||
transferJoinMarkings(pNewExpr2, pExpr);
|
||||
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags);
|
||||
testcase( idxNew2==0 );
|
||||
exprAnalyze(pSrc, pWC, idxNew2);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
@@ -1908,11 +2029,14 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
** Estimate the location of a particular key among all keys in an
|
||||
** index. Store the results in aStat as follows:
|
||||
**
|
||||
** aStat[0] Est. number of rows less than pVal
|
||||
** aStat[1] Est. number of rows equal to pVal
|
||||
** aStat[0] Est. number of rows less than pRec
|
||||
** aStat[1] Est. number of rows equal to pRec
|
||||
**
|
||||
** Return the index of the sample that is the smallest sample that
|
||||
** is greater than or equal to pRec.
|
||||
** is greater than or equal to pRec. Note that this index is not an index
|
||||
** into the aSample[] array - it is an index into a virtual set of samples
|
||||
** based on the contents of aSample[] and the number of fields in record
|
||||
** pRec.
|
||||
*/
|
||||
static int whereKeyStats(
|
||||
Parse *pParse, /* Database connection */
|
||||
@@ -1923,67 +2047,158 @@ static int whereKeyStats(
|
||||
){
|
||||
IndexSample *aSample = pIdx->aSample;
|
||||
int iCol; /* Index of required stats in anEq[] etc. */
|
||||
int i; /* Index of first sample >= pRec */
|
||||
int iSample; /* Smallest sample larger than or equal to pRec */
|
||||
int iMin = 0; /* Smallest sample not yet tested */
|
||||
int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */
|
||||
int iTest; /* Next sample to test */
|
||||
int res; /* Result of comparison operation */
|
||||
int nField; /* Number of fields in pRec */
|
||||
tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */
|
||||
|
||||
#ifndef SQLITE_DEBUG
|
||||
UNUSED_PARAMETER( pParse );
|
||||
#endif
|
||||
assert( pRec!=0 );
|
||||
iCol = pRec->nField - 1;
|
||||
assert( pIdx->nSample>0 );
|
||||
assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
|
||||
assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol );
|
||||
|
||||
/* Do a binary search to find the first sample greater than or equal
|
||||
** to pRec. If pRec contains a single field, the set of samples to search
|
||||
** is simply the aSample[] array. If the samples in aSample[] contain more
|
||||
** than one fields, all fields following the first are ignored.
|
||||
**
|
||||
** If pRec contains N fields, where N is more than one, then as well as the
|
||||
** samples in aSample[] (truncated to N fields), the search also has to
|
||||
** consider prefixes of those samples. For example, if the set of samples
|
||||
** in aSample is:
|
||||
**
|
||||
** aSample[0] = (a, 5)
|
||||
** aSample[1] = (a, 10)
|
||||
** aSample[2] = (b, 5)
|
||||
** aSample[3] = (c, 100)
|
||||
** aSample[4] = (c, 105)
|
||||
**
|
||||
** Then the search space should ideally be the samples above and the
|
||||
** unique prefixes [a], [b] and [c]. But since that is hard to organize,
|
||||
** the code actually searches this set:
|
||||
**
|
||||
** 0: (a)
|
||||
** 1: (a, 5)
|
||||
** 2: (a, 10)
|
||||
** 3: (a, 10)
|
||||
** 4: (b)
|
||||
** 5: (b, 5)
|
||||
** 6: (c)
|
||||
** 7: (c, 100)
|
||||
** 8: (c, 105)
|
||||
** 9: (c, 105)
|
||||
**
|
||||
** For each sample in the aSample[] array, N samples are present in the
|
||||
** effective sample array. In the above, samples 0 and 1 are based on
|
||||
** sample aSample[0]. Samples 2 and 3 on aSample[1] etc.
|
||||
**
|
||||
** Often, sample i of each block of N effective samples has (i+1) fields.
|
||||
** Except, each sample may be extended to ensure that it is greater than or
|
||||
** equal to the previous sample in the array. For example, in the above,
|
||||
** sample 2 is the first sample of a block of N samples, so at first it
|
||||
** appears that it should be 1 field in size. However, that would make it
|
||||
** smaller than sample 1, so the binary search would not work. As a result,
|
||||
** it is extended to two fields. The duplicates that this creates do not
|
||||
** cause any problems.
|
||||
*/
|
||||
nField = pRec->nField;
|
||||
iCol = 0;
|
||||
iSample = pIdx->nSample * nField;
|
||||
do{
|
||||
iTest = (iMin+i)/2;
|
||||
res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
|
||||
if( res<0 ){
|
||||
iMin = iTest+1;
|
||||
int iSamp; /* Index in aSample[] of test sample */
|
||||
int n; /* Number of fields in test sample */
|
||||
|
||||
iTest = (iMin+iSample)/2;
|
||||
iSamp = iTest / nField;
|
||||
if( iSamp>0 ){
|
||||
/* The proposed effective sample is a prefix of sample aSample[iSamp].
|
||||
** Specifically, the shortest prefix of at least (1 + iTest%nField)
|
||||
** fields that is greater than the previous effective sample. */
|
||||
for(n=(iTest % nField) + 1; n<nField; n++){
|
||||
if( aSample[iSamp-1].anLt[n-1]!=aSample[iSamp].anLt[n-1] ) break;
|
||||
}
|
||||
}else{
|
||||
i = iTest;
|
||||
n = iTest + 1;
|
||||
}
|
||||
}while( res && iMin<i );
|
||||
|
||||
pRec->nField = n;
|
||||
res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec);
|
||||
if( res<0 ){
|
||||
iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1];
|
||||
iMin = iTest+1;
|
||||
}else if( res==0 && n<nField ){
|
||||
iLower = aSample[iSamp].anLt[n-1];
|
||||
iMin = iTest+1;
|
||||
res = -1;
|
||||
}else{
|
||||
iSample = iTest;
|
||||
iCol = n-1;
|
||||
}
|
||||
}while( res && iMin<iSample );
|
||||
i = iSample / nField;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* The following assert statements check that the binary search code
|
||||
** above found the right answer. This block serves no purpose other
|
||||
** than to invoke the asserts. */
|
||||
if( res==0 ){
|
||||
/* If (res==0) is true, then sample $i must be equal to pRec */
|
||||
assert( i<pIdx->nSample );
|
||||
assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
|
||||
|| pParse->db->mallocFailed );
|
||||
}else{
|
||||
/* Otherwise, pRec must be smaller than sample $i and larger than
|
||||
** sample ($i-1). */
|
||||
assert( i==pIdx->nSample
|
||||
|| sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
|
||||
|| pParse->db->mallocFailed );
|
||||
assert( i==0
|
||||
|| sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
|
||||
|| pParse->db->mallocFailed );
|
||||
if( pParse->db->mallocFailed==0 ){
|
||||
if( res==0 ){
|
||||
/* If (res==0) is true, then pRec must be equal to sample i. */
|
||||
assert( i<pIdx->nSample );
|
||||
assert( iCol==nField-1 );
|
||||
pRec->nField = nField;
|
||||
assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
|
||||
|| pParse->db->mallocFailed
|
||||
);
|
||||
}else{
|
||||
/* Unless i==pIdx->nSample, indicating that pRec is larger than
|
||||
** all samples in the aSample[] array, pRec must be smaller than the
|
||||
** (iCol+1) field prefix of sample i. */
|
||||
assert( i<=pIdx->nSample && i>=0 );
|
||||
pRec->nField = iCol+1;
|
||||
assert( i==pIdx->nSample
|
||||
|| sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
|
||||
|| pParse->db->mallocFailed );
|
||||
|
||||
/* if i==0 and iCol==0, then record pRec is smaller than all samples
|
||||
** in the aSample[] array. Otherwise, if (iCol>0) then pRec must
|
||||
** be greater than or equal to the (iCol) field prefix of sample i.
|
||||
** If (i>0), then pRec must also be greater than sample (i-1). */
|
||||
if( iCol>0 ){
|
||||
pRec->nField = iCol;
|
||||
assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0
|
||||
|| pParse->db->mallocFailed );
|
||||
}
|
||||
if( i>0 ){
|
||||
pRec->nField = nField;
|
||||
assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
|
||||
|| pParse->db->mallocFailed );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ifdef SQLITE_DEBUG */
|
||||
|
||||
/* At this point, aSample[i] is the first sample that is greater than
|
||||
** or equal to pVal. Or if i==pIdx->nSample, then all samples are less
|
||||
** than pVal. If aSample[i]==pVal, then res==0.
|
||||
*/
|
||||
if( res==0 ){
|
||||
/* Record pRec is equal to sample i */
|
||||
assert( iCol==nField-1 );
|
||||
aStat[0] = aSample[i].anLt[iCol];
|
||||
aStat[1] = aSample[i].anEq[iCol];
|
||||
}else{
|
||||
tRowcnt iLower, iUpper, iGap;
|
||||
if( i==0 ){
|
||||
iLower = 0;
|
||||
iUpper = aSample[0].anLt[iCol];
|
||||
/* At this point, the (iCol+1) field prefix of aSample[i] is the first
|
||||
** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec
|
||||
** is larger than all samples in the array. */
|
||||
tRowcnt iUpper, iGap;
|
||||
if( i>=pIdx->nSample ){
|
||||
iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
|
||||
}else{
|
||||
i64 nRow0 = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
|
||||
iUpper = i>=pIdx->nSample ? nRow0 : aSample[i].anLt[iCol];
|
||||
iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol];
|
||||
iUpper = aSample[i].anLt[iCol];
|
||||
}
|
||||
aStat[1] = pIdx->aAvgEq[iCol];
|
||||
|
||||
if( iLower>=iUpper ){
|
||||
iGap = 0;
|
||||
}else{
|
||||
@@ -1995,7 +2210,11 @@ static int whereKeyStats(
|
||||
iGap = iGap/3;
|
||||
}
|
||||
aStat[0] = iLower + iGap;
|
||||
aStat[1] = pIdx->aAvgEq[iCol];
|
||||
}
|
||||
|
||||
/* Restore the pRec->nField value before returning. */
|
||||
pRec->nField = nField;
|
||||
return i;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
||||
@@ -2469,20 +2688,43 @@ static int whereInScanEst(
|
||||
** but joins might run a little slower. The trick is to disable as much
|
||||
** as we can without disabling too much. If we disabled in (1), we'd get
|
||||
** the wrong answer. See ticket #813.
|
||||
**
|
||||
** If all the children of a term are disabled, then that term is also
|
||||
** automatically disabled. In this way, terms get disabled if derived
|
||||
** virtual terms are tested first. For example:
|
||||
**
|
||||
** x GLOB 'abc*' AND x>='abc' AND x<'acd'
|
||||
** \___________/ \______/ \_____/
|
||||
** parent child1 child2
|
||||
**
|
||||
** Only the parent term was in the original WHERE clause. The child1
|
||||
** and child2 terms were added by the LIKE optimization. If both of
|
||||
** the virtual child terms are valid, then testing of the parent can be
|
||||
** skipped.
|
||||
**
|
||||
** Usually the parent term is marked as TERM_CODED. But if the parent
|
||||
** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead.
|
||||
** The TERM_LIKECOND marking indicates that the term should be coded inside
|
||||
** a conditional such that is only evaluated on the second pass of a
|
||||
** LIKE-optimization loop, when scanning BLOBs instead of strings.
|
||||
*/
|
||||
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
|
||||
if( pTerm
|
||||
int nLoop = 0;
|
||||
while( pTerm
|
||||
&& (pTerm->wtFlags & TERM_CODED)==0
|
||||
&& (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
|
||||
&& (pLevel->notReady & pTerm->prereqAll)==0
|
||||
){
|
||||
pTerm->wtFlags |= TERM_CODED;
|
||||
if( pTerm->iParent>=0 ){
|
||||
WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
|
||||
if( (--pOther->nChild)==0 ){
|
||||
disableTerm(pLevel, pOther);
|
||||
}
|
||||
if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
|
||||
pTerm->wtFlags |= TERM_LIKECOND;
|
||||
}else{
|
||||
pTerm->wtFlags |= TERM_CODED;
|
||||
}
|
||||
if( pTerm->iParent<0 ) break;
|
||||
pTerm = &pTerm->pWC->a[pTerm->iParent];
|
||||
pTerm->nChild--;
|
||||
if( pTerm->nChild!=0 ) break;
|
||||
nLoop++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2966,7 +3208,34 @@ static void addScanStatus(
|
||||
# define addScanStatus(a, b, c, d) ((void)d)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** If the most recently coded instruction is a constant range contraint
|
||||
** that originated from the LIKE optimization, then change the P3 to be
|
||||
** pLoop->iLikeRepCntr and set P5.
|
||||
**
|
||||
** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range
|
||||
** expression: "x>='ABC' AND x<'abd'". But this requires that the range
|
||||
** scan loop run twice, once for strings and a second time for BLOBs.
|
||||
** The OP_String opcodes on the second pass convert the upper and lower
|
||||
** bound string contants to blobs. This routine makes the necessary changes
|
||||
** to the OP_String opcodes for that to happen.
|
||||
*/
|
||||
static void whereLikeOptimizationStringFixup(
|
||||
Vdbe *v, /* prepared statement under construction */
|
||||
WhereLevel *pLevel, /* The loop that contains the LIKE operator */
|
||||
WhereTerm *pTerm /* The upper or lower bound just coded */
|
||||
){
|
||||
if( pTerm->wtFlags & TERM_LIKEOPT ){
|
||||
VdbeOp *pOp;
|
||||
assert( pLevel->iLikeRepCntr>0 );
|
||||
pOp = sqlite3VdbeGetOp(v, -1);
|
||||
assert( pOp!=0 );
|
||||
assert( pOp->opcode==OP_String8
|
||||
|| pTerm->pWC->pWInfo->pParse->db->mallocFailed );
|
||||
pOp->p3 = pLevel->iLikeRepCntr;
|
||||
pOp->p5 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
||||
@@ -3296,10 +3565,25 @@ static Bitmask codeOneLoopStart(
|
||||
if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
|
||||
pRangeStart = pLoop->aLTerm[j++];
|
||||
nExtraReg = 1;
|
||||
/* Like optimization range constraints always occur in pairs */
|
||||
assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 ||
|
||||
(pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 );
|
||||
}
|
||||
if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
|
||||
pRangeEnd = pLoop->aLTerm[j++];
|
||||
nExtraReg = 1;
|
||||
if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){
|
||||
assert( pRangeStart!=0 ); /* LIKE opt constraints */
|
||||
assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */
|
||||
pLevel->iLikeRepCntr = ++pParse->nMem;
|
||||
testcase( bRev );
|
||||
testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
|
||||
sqlite3VdbeAddOp2(v, OP_Integer,
|
||||
bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC),
|
||||
pLevel->iLikeRepCntr);
|
||||
VdbeComment((v, "LIKE loop counter"));
|
||||
pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v);
|
||||
}
|
||||
if( pRangeStart==0
|
||||
&& (j = pIdx->aiColumn[nEq])>=0
|
||||
&& pIdx->pTable->aCol[j].notNull==0
|
||||
@@ -3342,6 +3626,7 @@ static Bitmask codeOneLoopStart(
|
||||
if( pRangeStart ){
|
||||
Expr *pRight = pRangeStart->pExpr->pRight;
|
||||
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||
whereLikeOptimizationStringFixup(v, pLevel, pRangeStart);
|
||||
if( (pRangeStart->wtFlags & TERM_VNULL)==0
|
||||
&& sqlite3ExprCanBeNull(pRight)
|
||||
){
|
||||
@@ -3387,6 +3672,7 @@ static Bitmask codeOneLoopStart(
|
||||
Expr *pRight = pRangeEnd->pExpr->pRight;
|
||||
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
|
||||
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
|
||||
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
|
||||
&& sqlite3ExprCanBeNull(pRight)
|
||||
){
|
||||
@@ -3614,7 +3900,8 @@ static Bitmask codeOneLoopStart(
|
||||
*/
|
||||
wctrlFlags = WHERE_OMIT_OPEN_CLOSE
|
||||
| WHERE_FORCE_TABLE
|
||||
| WHERE_ONETABLE_ONLY;
|
||||
| WHERE_ONETABLE_ONLY
|
||||
| WHERE_NO_AUTOINDEX;
|
||||
for(ii=0; ii<pOrWc->nTerm; ii++){
|
||||
WhereTerm *pOrTerm = &pOrWc->a[ii];
|
||||
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
|
||||
@@ -3776,6 +4063,7 @@ static Bitmask codeOneLoopStart(
|
||||
*/
|
||||
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
|
||||
Expr *pE;
|
||||
int skipLikeAddr = 0;
|
||||
testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
||||
testcase( pTerm->wtFlags & TERM_CODED );
|
||||
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
||||
@@ -3790,7 +4078,13 @@ static Bitmask codeOneLoopStart(
|
||||
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
|
||||
continue;
|
||||
}
|
||||
if( pTerm->wtFlags & TERM_LIKECOND ){
|
||||
assert( pLevel->iLikeRepCntr>0 );
|
||||
skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
|
||||
if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
|
||||
pTerm->wtFlags |= TERM_CODED;
|
||||
}
|
||||
|
||||
@@ -4455,6 +4749,10 @@ static int whereLoopAddBtreeIndex(
|
||||
}
|
||||
if( pTerm->prereqRight & pNew->maskSelf ) continue;
|
||||
|
||||
/* Do not allow the upper bound of a LIKE optimization range constraint
|
||||
** to mix with a lower range bound from some other source */
|
||||
if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
|
||||
|
||||
pNew->wsFlags = saved_wsFlags;
|
||||
pNew->u.btree.nEq = saved_nEq;
|
||||
pNew->nLTerm = saved_nLTerm;
|
||||
@@ -4498,6 +4796,17 @@ static int whereLoopAddBtreeIndex(
|
||||
pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
|
||||
pBtm = pTerm;
|
||||
pTop = 0;
|
||||
if( pTerm->wtFlags & TERM_LIKEOPT ){
|
||||
/* Range contraints that come from the LIKE optimization are
|
||||
** always used in pairs. */
|
||||
pTop = &pTerm[1];
|
||||
assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
|
||||
assert( pTop->wtFlags & TERM_LIKEOPT );
|
||||
assert( pTop->eOperator==WO_LT );
|
||||
if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
|
||||
pNew->aLTerm[pNew->nLTerm++] = pTop;
|
||||
pNew->wsFlags |= WHERE_TOP_LIMIT;
|
||||
}
|
||||
}else{
|
||||
assert( eOp & (WO_LT|WO_LE) );
|
||||
testcase( eOp & WO_LT );
|
||||
@@ -4808,6 +5117,7 @@ static int whereLoopAddBtree(
|
||||
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
/* Automatic indexes */
|
||||
if( !pBuilder->pOrSet
|
||||
&& (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0
|
||||
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
|
||||
&& pSrc->pIndex==0
|
||||
&& !pSrc->viaCoroutine
|
||||
@@ -5691,10 +6001,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
|
||||
/* Seed the search with a single WherePath containing zero WhereLoops.
|
||||
**
|
||||
** TUNING: Do not let the number of iterations go above 25. If the cost
|
||||
** of computing an automatic index is not paid back within the first 25
|
||||
** TUNING: Do not let the number of iterations go above 28. If the cost
|
||||
** of computing an automatic index is not paid back within the first 28
|
||||
** rows, then do not use the automatic index. */
|
||||
aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
|
||||
aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28) );
|
||||
nFrom = 1;
|
||||
assert( aFrom[0].isOrdered==0 );
|
||||
if( nOrderBy ){
|
||||
@@ -6593,6 +6903,16 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
sqlite3VdbeJumpHere(v, pLevel->addrSkip);
|
||||
sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
|
||||
}
|
||||
if( pLevel->addrLikeRep ){
|
||||
int op;
|
||||
if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){
|
||||
op = OP_DecrJumpZero;
|
||||
}else{
|
||||
op = OP_JumpZeroIncr;
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( pLevel->iLeftJoin ){
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
|
||||
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|
||||
|
||||
@@ -69,6 +69,8 @@ struct WhereLevel {
|
||||
int addrCont; /* Jump here to continue with the next loop cycle */
|
||||
int addrFirst; /* First instruction of interior of the loop */
|
||||
int addrBody; /* Beginning of the body of this loop */
|
||||
int iLikeRepCntr; /* LIKE range processing counter register */
|
||||
int addrLikeRep; /* LIKE range processing address */
|
||||
u8 iFrom; /* Which entry in the FROM clause */
|
||||
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
|
||||
int p1, p2; /* Operands of the opcode used to ends the loop */
|
||||
@@ -253,7 +255,7 @@ struct WhereTerm {
|
||||
} u;
|
||||
LogEst truthProb; /* Probability of truth for this expression */
|
||||
u16 eOperator; /* A WO_xx value describing <op> */
|
||||
u8 wtFlags; /* TERM_xxx bit flags. See below */
|
||||
u16 wtFlags; /* TERM_xxx bit flags. See below */
|
||||
u8 nChild; /* Number of children that must disable us */
|
||||
WhereClause *pWC; /* The clause this term is part of */
|
||||
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
|
||||
@@ -275,6 +277,9 @@ struct WhereTerm {
|
||||
#else
|
||||
# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
|
||||
#endif
|
||||
#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
|
||||
#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
|
||||
#define TERM_LIKE 0x400 /* The original LIKE operator */
|
||||
|
||||
/*
|
||||
** An instance of the WhereScan object is used as an iterator for locating
|
||||
|
||||
@@ -281,35 +281,35 @@ do_eqp_test analyze3-2.3 {
|
||||
|
||||
do_test analyze3-2.4 {
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE 'a%' }
|
||||
} {101 0 100}
|
||||
} {102 0 100}
|
||||
do_test analyze3-2.5 {
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE '%a' }
|
||||
} {999 999 100}
|
||||
|
||||
do_test analyze3-2.4 {
|
||||
do_test analyze3-2.6 {
|
||||
set like "a%"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {101 0 100}
|
||||
do_test analyze3-2.5 {
|
||||
} {102 0 100}
|
||||
do_test analyze3-2.7 {
|
||||
set like "%a"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {999 999 100}
|
||||
do_test analyze3-2.6 {
|
||||
do_test analyze3-2.8 {
|
||||
set like "a"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {101 0 0}
|
||||
do_test analyze3-2.7 {
|
||||
} {102 0 0}
|
||||
do_test analyze3-2.9 {
|
||||
set like "ab"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {11 0 0}
|
||||
do_test analyze3-2.8 {
|
||||
} {12 0 0}
|
||||
do_test analyze3-2.10 {
|
||||
set like "abc"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {2 0 1}
|
||||
do_test analyze3-2.9 {
|
||||
} {3 0 1}
|
||||
do_test analyze3-2.11 {
|
||||
set like "a_c"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} {101 0 10}
|
||||
} {102 0 10}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -1134,4 +1134,116 @@ ifcapable stat4&&cte {
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that a problem in they way stat4 data is used has been
|
||||
# resolved (see below).
|
||||
#
|
||||
reset_db
|
||||
do_test 26.1.1 {
|
||||
db transaction {
|
||||
execsql {
|
||||
CREATE TABLE t1(x, y, z);
|
||||
CREATE INDEX t1xy ON t1(x, y);
|
||||
CREATE INDEX t1z ON t1(z);
|
||||
}
|
||||
for {set i 0} {$i < 10000} {incr i} {
|
||||
execsql { INSERT INTO t1(x, y) VALUES($i, $i) }
|
||||
}
|
||||
for {set i 0} {$i < 10} {incr i} {
|
||||
execsql {
|
||||
WITH cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt WHERE x<100)
|
||||
INSERT INTO t1(x, y) SELECT 10000+$i, x FROM cnt;
|
||||
INSERT INTO t1(x, y) SELECT 10000+$i, 100;
|
||||
}
|
||||
}
|
||||
execsql {
|
||||
UPDATE t1 SET z = rowid / 20;
|
||||
ANALYZE;
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 26.1.2 {
|
||||
SELECT count(*) FROM t1 WHERE x = 10000 AND y < 50;
|
||||
} {49}
|
||||
do_execsql_test 26.1.3 {
|
||||
SELECT count(*) FROM t1 WHERE z = 444;
|
||||
} {20}
|
||||
|
||||
# The analyzer knows that any (z=?) expression matches 20 rows. So it
|
||||
# will use index "t1z" if the estimate of hits for (x=10000 AND y<50)
|
||||
# is greater than 20 rows.
|
||||
#
|
||||
# And it should be. The analyzer has a stat4 sample as follows:
|
||||
#
|
||||
# sample=(x=10000, y=100) nLt=(10000 10099)
|
||||
#
|
||||
# There should be no other samples that start with (x=10000). So it knows
|
||||
# that (x=10000 AND y<50) must match somewhere between 0 and 99 rows, but
|
||||
# know more than that. Guessing less than 20 is therefore unreasonable.
|
||||
#
|
||||
# At one point though, due to a problem in whereKeyStats(), the planner was
|
||||
# estimating that (x=10000 AND y<50) would match only 2 rows.
|
||||
#
|
||||
do_eqp_test 26.1.4 {
|
||||
SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1z (z=?)}
|
||||
}
|
||||
|
||||
|
||||
# This test - 26.2.* - tests that another manifestation of the same problem
|
||||
# is no longer present in the library. Assuming:
|
||||
#
|
||||
# CREATE INDEX t1xy ON t1(x, y)
|
||||
#
|
||||
# and that have samples for index t1xy as follows:
|
||||
#
|
||||
#
|
||||
# sample=('A', 70) nEq=(100, 2) nLt=(900, 970)
|
||||
# sample=('B', 70) nEq=(100, 2) nLt=(1000, 1070)
|
||||
#
|
||||
# the planner should estimate that (x = 'B' AND y > 25) matches 76 rows
|
||||
# (70 * 2/3 + 30). Before, due to the problem, the planner was estimating
|
||||
# that this matched 100 rows.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 26.2.1 {
|
||||
BEGIN;
|
||||
CREATE TABLE t1(x, y, z);
|
||||
CREATE INDEX i1 ON t1(x, y);
|
||||
CREATE INDEX i2 ON t1(z);
|
||||
|
||||
WITH
|
||||
cnt(y) AS (SELECT 0 UNION ALL SELECT y+1 FROM cnt WHERE y<99),
|
||||
letters(x) AS (
|
||||
SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D'
|
||||
)
|
||||
INSERT INTO t1(x, y) SELECT x, y FROM letters, cnt;
|
||||
|
||||
WITH
|
||||
letters(x) AS (
|
||||
SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D'
|
||||
)
|
||||
INSERT INTO t1(x, y) SELECT x, 70 FROM letters;
|
||||
|
||||
WITH
|
||||
cnt(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM cnt WHERE i<9999)
|
||||
INSERT INTO t1(x, y) SELECT i, i FROM cnt;
|
||||
|
||||
UPDATE t1 SET z = (rowid / 95);
|
||||
ANALYZE;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_eqp_test 26.2.2 {
|
||||
SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
127
test/analyzeF.test
Normal file
127
test/analyzeF.test
Normal file
@@ -0,0 +1,127 @@
|
||||
# 2015-03-12
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# Test that deterministic scalar functions passed constant arguments
|
||||
# are used with stat4 data.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix analyzeF
|
||||
|
||||
ifcapable {!stat4} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc isqrt {i} { expr { int(sqrt($i)) } }
|
||||
db func isqrt isqrt
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x INTEGER, y INTEGER);
|
||||
WITH data(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM data
|
||||
)
|
||||
INSERT INTO t1 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400;
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
ANALYZE;
|
||||
}
|
||||
|
||||
proc str {a} { return $a }
|
||||
db func str str
|
||||
|
||||
# Note: tests 7 to 12 might be unstable - as they assume SQLite will
|
||||
# prefer the expression to the right of the AND clause. Which of
|
||||
# course could change.
|
||||
#
|
||||
# Note 2: tests 9 and 10 depend on the tcl interface creating functions
|
||||
# without the SQLITE_DETERMINISTIC flag set.
|
||||
#
|
||||
foreach {tn where idx} {
|
||||
1 "x = 4 AND y = 19" {t1x (x=?)}
|
||||
2 "x = 19 AND y = 4" {t1y (y=?)}
|
||||
3 "x = '4' AND y = '19'" {t1x (x=?)}
|
||||
4 "x = '19' AND y = '4'" {t1y (y=?)}
|
||||
5 "x = substr('5195', 2, 2) AND y = substr('145', 2, 1)" {t1y (y=?)}
|
||||
6 "x = substr('145', 2, 1) AND y = substr('5195', 2, 2)" {t1x (x=?)}
|
||||
|
||||
7 "x = substr('5195', 2, 2+0) AND y = substr('145', 2, 1+0)" {t1y (y=?)}
|
||||
8 "x = substr('145', 2, 1+0) AND y = substr('5195', 2, 2+0)" {t1y (y=?)}
|
||||
|
||||
9 "x = str('19') AND y = str('4')" {t1y (y=?)}
|
||||
10 "x = str('4') AND y = str('19')" {t1y (y=?)}
|
||||
|
||||
11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
|
||||
12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
|
||||
} {
|
||||
set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
|
||||
do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
|
||||
}
|
||||
|
||||
# Test that functions that do not exist - "func()" - do not cause an error.
|
||||
#
|
||||
do_catchsql_test 2.1 {
|
||||
SELECT * FROM t1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
|
||||
} {1 {no such function: func}}
|
||||
do_catchsql_test 2.2 {
|
||||
UPDATE t1 SET y=y+1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
|
||||
} {1 {no such function: func}}
|
||||
|
||||
|
||||
# Check that functions that accept zero arguments do not cause problems.
|
||||
#
|
||||
proc ret {x} { return $x }
|
||||
|
||||
db func det4 -deterministic [list ret 4]
|
||||
db func nondet4 [list ret 4]
|
||||
db func det19 -deterministic [list ret 19]
|
||||
db func nondet19 [list ret 19]
|
||||
|
||||
foreach {tn where idx} {
|
||||
1 "x = det4() AND y = det19()" {t1x (x=?)}
|
||||
2 "x = det19() AND y = det4()" {t1y (y=?)}
|
||||
|
||||
3 "x = nondet4() AND y = nondet19()" {t1y (y=?)}
|
||||
4 "x = nondet19() AND y = nondet4()" {t1y (y=?)}
|
||||
} {
|
||||
set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
|
||||
do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
|
||||
}
|
||||
|
||||
|
||||
execsql { DELETE FROM t1 }
|
||||
|
||||
proc throw_error {err} { error $err }
|
||||
db func error -deterministic throw_error
|
||||
do_catchsql_test 4.1 {
|
||||
SELECT * FROM t1 WHERE x = error('error one') AND y = 4;
|
||||
} {1 {error one}}
|
||||
|
||||
do_catchsql_test 4.2 {
|
||||
SELECT * FROM t1 WHERE x = zeroblob(2000000000) AND y = 4;
|
||||
} {1 {string or blob too big}}
|
||||
|
||||
sqlite3_limit db SQLITE_LIMIT_LENGTH 1000000
|
||||
proc dstr {} { return [string repeat x 1100000] }
|
||||
db func dstr -deterministic dstr
|
||||
do_catchsql_test 4.3 {
|
||||
SELECT * FROM t1 WHERE x = dstr() AND y = 11;
|
||||
} {1 {string or blob too big}}
|
||||
|
||||
do_catchsql_test 4.4 {
|
||||
SELECT * FROM t1 WHERE x = test_zeroblob(1100000) AND y = 4;
|
||||
} {1 {string or blob too big}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing automatic index creation logic.
|
||||
#
|
||||
# EVIDENCE-OF: R-34271-33106 PRAGMA automatic_index; PRAGMA
|
||||
# automatic_index = boolean; Query, set, or clear the automatic indexing
|
||||
# capability.
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
80
test/crashM.test
Normal file
80
test/crashM.test
Normal file
@@ -0,0 +1,80 @@
|
||||
# 2015 Mar 13
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Crash tests for the multiplex module with 8.3 filenames enabled.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix crashM
|
||||
|
||||
ifcapable !crashtest||!8_3_names {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
|
||||
foreach f [glob -nocomplain test1.* test2.*] { forcedelete $f }
|
||||
sqlite3_multiplex_initialize "" 1
|
||||
sqlite3 db file:test1.db?8_3_names=1
|
||||
sqlite3_multiplex_control db main chunk_size [expr 64*1024]
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
ATTACH 'file:test2.db?8_3_names=1' AS aux;
|
||||
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
|
||||
CREATE TABLE aux.t2(x, y);
|
||||
CREATE INDEX aux.t2x ON t2(x);
|
||||
CREATE INDEX aux.t2y ON t2(y);
|
||||
|
||||
WITH s(a) AS (
|
||||
SELECT 1 UNION ALL SELECT a+1 FROM s WHERE a<1000
|
||||
)
|
||||
INSERT INTO t1 SELECT a, randomblob(500) FROM s;
|
||||
|
||||
WITH s(a) AS (
|
||||
SELECT 1 UNION ALL SELECT a+1 FROM s WHERE a<1000
|
||||
)
|
||||
INSERT INTO t2 SELECT a, randomblob(500) FROM s;
|
||||
} {}
|
||||
|
||||
for {set i 0} {$i < 20} {incr i} {
|
||||
do_test 2.$i.1 {
|
||||
crashsql -delay 1 -file test1.db -opendb {
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
sqlite3_multiplex_initialize crash 1
|
||||
sqlite3 db file:test1.db?8_3_names=1
|
||||
sqlite3_multiplex_control db main chunk_size [expr 64*1024]
|
||||
} {
|
||||
ATTACH 'file:test2.db?8_3_names=1' AS aux;
|
||||
BEGIN;
|
||||
UPDATE t1 SET y = randomblob(500) WHERE (x%10)==0;
|
||||
UPDATE t2 SET y = randomblob(500) WHERE (x%10)==0;
|
||||
COMMIT;
|
||||
}
|
||||
} {1 {child process exited abnormally}}
|
||||
|
||||
do_execsql_test 2.$i.2 {
|
||||
PRAGMA main.integrity_check;
|
||||
PRAGMA aux.integrity_check;
|
||||
} {ok ok}
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
sqlite3_multiplex_shutdown
|
||||
finish_test
|
||||
@@ -348,9 +348,9 @@ do_insert_tests e_insert-3.2 {
|
||||
6.2 "SELECT * FROM a1" {{} {} {} {}}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-46928-50290 The optional conflict-clause allows the
|
||||
# specification of an alternative constraint conflict resolution
|
||||
# algorithm to use during this one INSERT command.
|
||||
# EVIDENCE-OF: R-03235-45250 The "REPLACE" and "INSERT OR action" forms
|
||||
# specify an alternative constraint conflict resolution algorithm to use
|
||||
# during this one INSERT command.
|
||||
#
|
||||
# EVIDENCE-OF: R-23110-47146 the parser allows the use of the single
|
||||
# keyword REPLACE as an alias for "INSERT OR REPLACE".
|
||||
|
||||
@@ -12,8 +12,13 @@
|
||||
#
|
||||
# This file tests the PRAGMA foreign_key_check command.
|
||||
#
|
||||
# EVIDENCE-OF: R-05426-18119 PRAGMA foreign_key_check; PRAGMA
|
||||
# foreign_key_check(table-name);
|
||||
# EVIDENCE-OF: R-01427-50262 PRAGMA database.foreign_key_check; PRAGMA
|
||||
# database.foreign_key_check(table-name);
|
||||
#
|
||||
# EVIDENCE-OF: R-23918-17301 The foreign_key_check pragma checks the
|
||||
# database, or the table called "table-name", for foreign key
|
||||
# constraints that are violated and returns one row of output for each
|
||||
# violation.
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -74,6 +79,16 @@ do_test fkey5-1.2 {
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c1 87 p1 0 c1 90 p1 0}
|
||||
do_test fkey5-1.2b {
|
||||
db eval {
|
||||
PRAGMA main.foreign_key_check;
|
||||
}
|
||||
} {c1 87 p1 0 c1 90 p1 0}
|
||||
do_test fkey5-1.2c {
|
||||
db eval {
|
||||
PRAGMA temp.foreign_key_check;
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-1.3 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c1);
|
||||
@@ -84,6 +99,16 @@ do_test fkey5-1.4 {
|
||||
PRAGMA foreign_key_check(c2);
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-1.5 {
|
||||
db eval {
|
||||
PRAGMA main.foreign_key_check(c2);
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-1.6 {
|
||||
catchsql {
|
||||
PRAGMA temp.foreign_key_check(c2);
|
||||
}
|
||||
} {1 {no such table: temp.c2}}
|
||||
|
||||
# EVIDENCE-OF: R-45728-08709 There are four columns in each result row.
|
||||
#
|
||||
|
||||
@@ -252,15 +252,21 @@ foreach {tn iFirst iLast} [subst {
|
||||
do_execsql_test 7.2.$tn.1.[llength $res] {
|
||||
SELECT rowid FROM ft4 WHERE rowid BETWEEN $iFirst AND $iLast
|
||||
} $res
|
||||
set res [db eval {
|
||||
SELECT rowid FROM t4 WHERE rowid BETWEEN $iFirst AND $iLast
|
||||
ORDER BY +rowid DESC
|
||||
} ]
|
||||
do_execsql_test 7.2.$tn.2.[llength $res] {
|
||||
SELECT rowid FROM ft4 WHERE rowid BETWEEN $iFirst AND $iLast
|
||||
ORDER BY rowid DESC
|
||||
} [lsort -decr -integer $res]
|
||||
} $res
|
||||
}
|
||||
|
||||
foreach ii [db eval {SELECT rowid FROM t4}] {
|
||||
set res1 [db eval {SELECT rowid FROM t4 WHERE rowid > $ii}]
|
||||
set res2 [db eval {SELECT rowid FROM t4 WHERE rowid < $ii}]
|
||||
set res1s [db eval {SELECT rowid FROM t4 WHERE rowid > $ii ORDER BY +rowid DESC}]
|
||||
set res2s [db eval {SELECT rowid FROM t4 WHERE rowid < $ii ORDER BY +rowid DESC}]
|
||||
|
||||
do_execsql_test 7.3.$ii.1 {
|
||||
SELECT rowid FROM ft4 WHERE rowid > $ii
|
||||
@@ -272,13 +278,11 @@ foreach ii [db eval {SELECT rowid FROM t4}] {
|
||||
|
||||
do_execsql_test 7.3.$ii.3 {
|
||||
SELECT rowid FROM ft4 WHERE rowid > $ii ORDER BY rowid DESC
|
||||
} [lsort -integer -decr $res1]
|
||||
} $res1s
|
||||
|
||||
do_execsql_test 7.3.$ii.4 {
|
||||
SELECT rowid FROM ft4 WHERE rowid < $ii ORDER BY rowid DESC
|
||||
} [lsort -integer -decr $res2]
|
||||
} $res2s
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -324,11 +324,21 @@ do_test incrblob2-6.2 {
|
||||
sqlite3_blob_read $rdHandle 0 2
|
||||
} {AB}
|
||||
|
||||
do_test incrblob2-6.2b {
|
||||
if {$::tcl_platform(pointerSize)>=8} {
|
||||
do_test incrblob2-6.2b {
|
||||
set rc [catch {
|
||||
# Prior to 2015-02-07, the following caused a segfault due to
|
||||
# integer overflow.
|
||||
sqlite3_blob_read $rdHandle 2147483647 2147483647
|
||||
} errmsg]
|
||||
lappend rc $errmsg
|
||||
} {1 SQLITE_ERROR}
|
||||
}
|
||||
do_test incrblob2-6.2c {
|
||||
set rc [catch {
|
||||
# Prior to 2015-02-07, the following caused a segfault due to
|
||||
# integer overflow.
|
||||
sqlite3_blob_read $rdHandle 2147483647 2147483647
|
||||
sqlite3_blob_read $rdHandle 2147483647 100
|
||||
} errmsg]
|
||||
lappend rc $errmsg
|
||||
} {1 SQLITE_ERROR}
|
||||
|
||||
127
test/incrcorrupt.test
Normal file
127
test/incrcorrupt.test
Normal file
@@ -0,0 +1,127 @@
|
||||
# 2001 October 12
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# Test that "PRAGMA incremental_vacuum" detects and reports database
|
||||
# corruption properly. And that "PRAGMA auto_vacuum = INCREMENTAL"
|
||||
# does as well.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix incrcorrupt
|
||||
|
||||
# If this build of the library does not support auto-vacuum, omit this
|
||||
# whole file.
|
||||
ifcapable {!autovacuum} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA auto_vacuum = 2;
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
|
||||
WITH data(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM data
|
||||
)
|
||||
INSERT INTO t1 SELECT i, randomblob(600) FROM data LIMIT 20;
|
||||
PRAGMA page_count;
|
||||
} {24}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
PRAGMA incremental_vacuum;
|
||||
} {}
|
||||
|
||||
do_test 1.2 {
|
||||
db_save
|
||||
hexio_write test.db 36 00000019
|
||||
catchsql { PRAGMA incremental_vacuum; }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_test 1.3 {
|
||||
set stmt [sqlite3_prepare_v2 db "PRAGMA incremental_vacuum" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_CORRUPT}
|
||||
do_test 1.4 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 1.5 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
do_test 1.6 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
|
||||
do_test 1.7 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 1.8 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
do_test 1.9 {
|
||||
set stmt [sqlite3_prepare_v2 db "PRAGMA incremental_vacuum" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_CORRUPT}
|
||||
do_test 1.10 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 1.11 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
do_test 1.12 {
|
||||
set stmt2 [sqlite3_prepare_v2 db "SELECT 1" -1 dummy]
|
||||
sqlite3_finalize $stmt2
|
||||
} {SQLITE_OK}
|
||||
do_test 1.13 { sqlite3_errcode db } {SQLITE_OK}
|
||||
do_test 1.14 { sqlite3_errmsg db } {not an error}
|
||||
|
||||
do_test 1.15 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
|
||||
do_test 1.16 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 1.17 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA auto_vacuum = 1;
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
WITH data(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM data
|
||||
)
|
||||
INSERT INTO t1 SELECT i, randomblob(600) FROM data LIMIT 20;
|
||||
PRAGMA page_count;
|
||||
} {24}
|
||||
|
||||
do_test 2.2 {
|
||||
db_save
|
||||
set fd [open test.db r+]
|
||||
chan truncate $fd [expr 22*1024]
|
||||
close $fd
|
||||
catchsql { PRAGMA incremental_vacuum; }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_test 2.3 {
|
||||
set stmt [sqlite3_prepare_v2 db "PRAGMA auto_vacuum = INCREMENTAL" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_CORRUPT}
|
||||
do_test 2.4 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 2.5 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
do_test 2.6 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
|
||||
do_test 2.7 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 2.8 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
do_test 2.9 {
|
||||
set stmt [sqlite3_prepare_v2 db "PRAGMA auto_vacuum = INCREMENTAL" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_CORRUPT}
|
||||
do_test 2.10 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 2.11 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
do_test 2.12 {
|
||||
set stmt2 [sqlite3_prepare_v2 db "SELECT 1" -1 dummy]
|
||||
sqlite3_finalize $stmt2
|
||||
} {SQLITE_OK}
|
||||
do_test 2.13 { sqlite3_errcode db } {SQLITE_OK}
|
||||
do_test 2.14 { sqlite3_errmsg db } {not an error}
|
||||
|
||||
do_test 2.15 { sqlite3_finalize $stmt } {SQLITE_CORRUPT}
|
||||
do_test 2.16 { sqlite3_errcode db } {SQLITE_CORRUPT}
|
||||
do_test 2.17 { sqlite3_errmsg db } {database disk image is malformed}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -21,6 +21,31 @@ ifcapable !vtab {
|
||||
return
|
||||
}
|
||||
|
||||
# Capture the output of a pragma in a TEMP table.
|
||||
#
|
||||
proc capture_pragma {db tabname sql} {
|
||||
$db eval "DROP TABLE IF EXISTS temp.$tabname"
|
||||
set once 1
|
||||
$db eval $sql x {
|
||||
if {$once} {
|
||||
set once 0
|
||||
set ins "INSERT INTO $tabname VALUES"
|
||||
set crtab "CREATE TEMP TABLE $tabname "
|
||||
set sep "("
|
||||
foreach col $x(*) {
|
||||
append ins ${sep}\$x($col)
|
||||
append crtab ${sep}\"$col\"
|
||||
set sep ,
|
||||
}
|
||||
append ins )
|
||||
append crtab )
|
||||
$db eval $crtab
|
||||
}
|
||||
$db eval $ins
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
load_static_extension db wholenumber;
|
||||
do_test index7-1.1 {
|
||||
# Able to parse and manage partial indices
|
||||
@@ -37,6 +62,15 @@ do_test index7-1.1 {
|
||||
}
|
||||
} {14 20 ok}
|
||||
|
||||
# (The "partial" column of the PRAGMA index_list output is...)
|
||||
# EVIDENCE-OF: R-34457-09668 "1" if the index is a partial index and "0"
|
||||
# if not.
|
||||
#
|
||||
do_test index7-1.1a {
|
||||
capture_pragma db out {PRAGMA index_list(t1)}
|
||||
db eval {SELECT "name", "partial", '|' FROM out ORDER BY "name"}
|
||||
} {sqlite_autoindex_t1_1 0 | t1a 1 | t1b 1 |}
|
||||
|
||||
# Make sure the count(*) optimization works correctly with
|
||||
# partial indices. Ticket [a5c8ed66cae16243be6] 2013-10-03.
|
||||
#
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 2008 October 4
|
||||
# 2008-10-04
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
@@ -9,7 +9,6 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# $Id: indexedby.test,v 1.5 2009/03/22 20:36:19 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -58,20 +57,45 @@ do_execsql_test indexedby-1.4 {
|
||||
# attached to a table in the FROM clause, but not to a sub-select or
|
||||
# SQL view. Also test that specifying an index that does not exist or
|
||||
# is attached to a different table is detected as an error.
|
||||
#
|
||||
# EVIDENCE-OF: R-63761-48810 -- syntax diagram qualified-table-name
|
||||
#
|
||||
# EVIDENCE-OF: R-58230-57098 The "INDEXED BY index-name" phrase
|
||||
# specifies that the named index must be used in order to look up values
|
||||
# on the preceding table.
|
||||
#
|
||||
do_test indexedby-2.1 {
|
||||
execsql { SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
do_test indexedby-2.1b {
|
||||
execsql { SELECT * FROM main.t1 NOT INDEXED WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
do_test indexedby-2.2 {
|
||||
execsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
do_test indexedby-2.2b {
|
||||
execsql { SELECT * FROM main.t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
do_test indexedby-2.3 {
|
||||
execsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'}
|
||||
} {}
|
||||
|
||||
# EVIDENCE-OF: R-44699-55558 The INDEXED BY clause does not give the
|
||||
# optimizer hints about which index to use; it gives the optimizer a
|
||||
# requirement of which index to use.
|
||||
# EVIDENCE-OF: R-15800-25719 If index-name does not exist or cannot be
|
||||
# used for the query, then the preparation of the SQL statement fails.
|
||||
#
|
||||
do_test indexedby-2.4 {
|
||||
catchsql { SELECT * FROM t1 INDEXED BY i3 WHERE a = 'one' AND b = 'two'}
|
||||
} {1 {no such index: i3}}
|
||||
|
||||
# EVIDENCE-OF: R-62112-42456 If the query optimizer is unable to use the
|
||||
# index specified by the INDEX BY clause, then the query will fail with
|
||||
# an error.
|
||||
do_test indexedby-2.4.1 {
|
||||
catchsql { SELECT b FROM t1 INDEXED BY i1 WHERE b = 'two' }
|
||||
} {1 {no query solution}}
|
||||
|
||||
do_test indexedby-2.5 {
|
||||
catchsql { SELECT * FROM t1 INDEXED BY i5 WHERE a = 'one' AND b = 'two'}
|
||||
} {1 {no such index: i5}}
|
||||
@@ -82,11 +106,26 @@ do_test indexedby-2.7 {
|
||||
catchsql { SELECT * FROM v1 INDEXED BY i1 WHERE a = 'one' }
|
||||
} {1 {no such index: i1}}
|
||||
|
||||
|
||||
# Tests for single table cases.
|
||||
#
|
||||
# EVIDENCE-OF: R-37002-28871 The "NOT INDEXED" clause specifies that no
|
||||
# index shall be used when accessing the preceding table, including
|
||||
# implied indices create by UNIQUE and PRIMARY KEY constraints. However,
|
||||
# the rowid can still be used to look up entries even when "NOT INDEXED"
|
||||
# is specified.
|
||||
#
|
||||
do_execsql_test indexedby-3.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a = 'one' AND b = 'two'
|
||||
} {/SEARCH TABLE t1 USING INDEX/}
|
||||
do_execsql_test indexedby-3.1.1 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
do_execsql_test indexedby-3.1.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE rowid=1
|
||||
} {/SEARCH TABLE t1 USING INTEGER PRIMARY KEY .rowid=/}
|
||||
|
||||
|
||||
do_execsql_test indexedby-3.2 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'
|
||||
@@ -184,6 +223,10 @@ do_execsql_test indexedby-6.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
|
||||
# EVIDENCE-OF: R-40297-14464 The INDEXED BY phrase forces the SQLite
|
||||
# query planner to use a particular named index on a DELETE, SELECT, or
|
||||
# UPDATE statement.
|
||||
#
|
||||
# Test that "INDEXED BY" can be used in a DELETE statement.
|
||||
#
|
||||
do_execsql_test indexedby-7.1 {
|
||||
|
||||
@@ -749,7 +749,7 @@ ifcapable like_opt&&!icu {
|
||||
count {
|
||||
SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 3 like 0}
|
||||
} {12 123 scan 4 like 0}
|
||||
do_test like-10.6 {
|
||||
count {
|
||||
SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY +a;
|
||||
@@ -790,7 +790,7 @@ ifcapable like_opt&&!icu {
|
||||
count {
|
||||
SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 3 like 0}
|
||||
} {12 123 scan 4 like 0}
|
||||
do_test like-10.15 {
|
||||
count {
|
||||
SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY +a;
|
||||
|
||||
112
test/like3.test
Normal file
112
test/like3.test
Normal file
@@ -0,0 +1,112 @@
|
||||
# 2015-03-06
|
||||
#
|
||||
# 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 testing the LIKE and GLOB operators and
|
||||
# in particular the optimizations that occur to help those operators
|
||||
# run faster and that those optimizations work correctly when there
|
||||
# are both strings and blobs being tested.
|
||||
#
|
||||
# Ticket 05f43be8fdda9fbd948d374319b99b054140bc36 shows that the following
|
||||
# SQL was not working correctly:
|
||||
#
|
||||
# CREATE TABLE t1(x TEXT UNIQUE COLLATE nocase);
|
||||
# INSERT INTO t1(x) VALUES(x'616263');
|
||||
# SELECT 'query-1', x FROM t1 WHERE x LIKE 'a%';
|
||||
# SELECT 'query-2', x FROM t1 WHERE +x LIKE 'a%';
|
||||
#
|
||||
# This script verifies that it works right now.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test like3-1.1 {
|
||||
PRAGMA encoding=UTF8;
|
||||
CREATE TABLE t1(a,b TEXT COLLATE nocase);
|
||||
INSERT INTO t1(a,b)
|
||||
VALUES(1,'abc'),
|
||||
(2,'ABX'),
|
||||
(3,'BCD'),
|
||||
(4,x'616263'),
|
||||
(5,x'414258'),
|
||||
(6,x'424344');
|
||||
CREATE INDEX t1ba ON t1(b,a);
|
||||
|
||||
SELECT a, b FROM t1 WHERE b LIKE 'aB%' ORDER BY +a;
|
||||
} {1 abc 2 ABX 4 abc 5 ABX}
|
||||
do_execsql_test like3-1.2 {
|
||||
SELECT a, b FROM t1 WHERE +b LIKE 'aB%' ORDER BY +a;
|
||||
} {1 abc 2 ABX 4 abc 5 ABX}
|
||||
|
||||
do_execsql_test like3-2.0 {
|
||||
CREATE TABLE t2(a, b TEXT);
|
||||
INSERT INTO t2 SELECT a, b FROM t1;
|
||||
CREATE INDEX t2ba ON t2(b,a);
|
||||
SELECT a, b FROM t2 WHERE b GLOB 'ab*' ORDER BY +a;
|
||||
} {1 abc 4 abc}
|
||||
do_execsql_test like3-2.1 {
|
||||
SELECT a, b FROM t2 WHERE +b GLOB 'ab*' ORDER BY +a;
|
||||
} {1 abc 4 abc}
|
||||
do_execsql_test like3-2.2 {
|
||||
SELECT a, b FROM t2 WHERE b>=x'6162' AND b GLOB 'ab*'
|
||||
} {4 abc}
|
||||
do_execsql_test like3-2.3 {
|
||||
SELECT a, b FROM t2 WHERE +b>=x'6162' AND +b GLOB 'ab*'
|
||||
} {4 abc}
|
||||
do_execsql_test like3-2.4 {
|
||||
SELECT a, b FROM t2 WHERE b GLOB 'ab*' AND b>=x'6162'
|
||||
} {4 abc}
|
||||
do_execsql_test like3-2.5 {
|
||||
SELECT a, b FROM t2 WHERE +b GLOB 'ab*' AND +b>=x'6162'
|
||||
} {4 abc}
|
||||
|
||||
do_execsql_test like3-3.0 {
|
||||
CREATE TABLE t3(x TEXT PRIMARY KEY COLLATE nocase);
|
||||
INSERT INTO t3(x) VALUES('aaa'),('abc'),('abd'),('abe'),('acz');
|
||||
INSERT INTO t3(x) SELECT CAST(x AS blob) FROM t3;
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY x;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
do_execsql_test like3-3.1 {
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY x DESC;
|
||||
} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'}
|
||||
do_execsql_test like3-3.1ck {
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY +x DESC;
|
||||
} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'}
|
||||
do_execsql_test like3-3.2 {
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY x ASC;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
do_execsql_test like3-3.2ck {
|
||||
SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY +x ASC;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
|
||||
do_execsql_test like3-4.0 {
|
||||
CREATE TABLE t4(x TEXT COLLATE nocase);
|
||||
CREATE INDEX t4x ON t4(x DESC);
|
||||
INSERT INTO t4(x) SELECT x FROM t3;
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY x;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
do_execsql_test like3-4.1 {
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY x DESC;
|
||||
} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'}
|
||||
do_execsql_test like3-4.1ck {
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY +x DESC;
|
||||
} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'}
|
||||
do_execsql_test like3-4.2 {
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY x ASC;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
do_execsql_test like3-4.2ck {
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY +x ASC;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -251,6 +251,12 @@ do_test limit-6.8 {
|
||||
# Make sure LIMIT works well with compound SELECT statements.
|
||||
# Ticket #393
|
||||
#
|
||||
# EVIDENCE-OF: R-13512-64012 In a compound SELECT, only the last or
|
||||
# right-most simple SELECT may contain a LIMIT clause.
|
||||
#
|
||||
# EVIDENCE-OF: R-03782-50113 In a compound SELECT, the LIMIT clause
|
||||
# applies to the entire compound, not just the final SELECT.
|
||||
#
|
||||
ifcapable compound {
|
||||
do_test limit-7.1.1 {
|
||||
catchsql {
|
||||
|
||||
@@ -241,6 +241,9 @@ execsql {ROLLBACK}
|
||||
|
||||
# Test the built-in busy timeout handler
|
||||
#
|
||||
# EVIDENCE-OF: R-23579-05241 PRAGMA busy_timeout; PRAGMA busy_timeout =
|
||||
# milliseconds; Query or change the setting of the busy timeout.
|
||||
#
|
||||
do_test lock-2.8 {
|
||||
db2 timeout 400
|
||||
execsql BEGIN
|
||||
|
||||
@@ -86,21 +86,51 @@ proc launch_testfixture {{prg ""}} {
|
||||
# Execute a command in a child testfixture process, connected by two-way
|
||||
# channel $chan. Return the result of the command, or an error message.
|
||||
#
|
||||
proc testfixture {chan cmd} {
|
||||
puts $chan $cmd
|
||||
puts $chan OVER
|
||||
set r ""
|
||||
while { 1 } {
|
||||
proc testfixture {chan cmd args} {
|
||||
|
||||
if {[llength $args] == 0} {
|
||||
fconfigure $chan -blocking 1
|
||||
puts $chan $cmd
|
||||
puts $chan OVER
|
||||
|
||||
set r ""
|
||||
while { 1 } {
|
||||
set line [gets $chan]
|
||||
if { $line == "OVER" } {
|
||||
set res [lindex $r 1]
|
||||
if { [lindex $r 0] } { error $res }
|
||||
return $res
|
||||
}
|
||||
if {[eof $chan]} {
|
||||
return "ERROR: Child process hung up"
|
||||
}
|
||||
append r $line
|
||||
}
|
||||
return $r
|
||||
} else {
|
||||
set ::tfnb($chan) ""
|
||||
fconfigure $chan -blocking 0 -buffering none
|
||||
puts $chan $cmd
|
||||
puts $chan OVER
|
||||
fileevent $chan readable [list testfixture_script_cb $chan [lindex $args 0]]
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
proc testfixture_script_cb {chan script} {
|
||||
if {[eof $chan]} {
|
||||
append ::tfnb($chan) "ERROR: Child process hung up"
|
||||
set line "OVER"
|
||||
} else {
|
||||
set line [gets $chan]
|
||||
if { $line == "OVER" } {
|
||||
set res [lindex $r 1]
|
||||
if { [lindex $r 0] } { error $res }
|
||||
return $res
|
||||
}
|
||||
if {[eof $chan]} {
|
||||
return "ERROR: Child process hung up"
|
||||
}
|
||||
append r $line
|
||||
}
|
||||
|
||||
if { $line == "OVER" } {
|
||||
uplevel #0 $script [list [lindex $::tfnb($chan) 1]]
|
||||
unset ::tfnb($chan)
|
||||
fileevent $chan readable ""
|
||||
} else {
|
||||
append ::tfnb($chan) $line
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,23 @@ do_test malloc5-1.3 {
|
||||
expr $::pgalloc > 0
|
||||
} {1}
|
||||
|
||||
# The sizes of memory allocations from system malloc() might vary,
|
||||
# depending on the memory allocator algorithms used. The following
|
||||
# routine is designed to support answers that fall within a range
|
||||
# of values while also supplying easy-to-understand "expected" values
|
||||
# when errors occur.
|
||||
#
|
||||
proc value_in_range {target x args} {
|
||||
set v [lindex $args 0]
|
||||
if {$v!=""} {
|
||||
if {$v<$target*$x} {return $v}
|
||||
if {$v>$target/$x} {return $v}
|
||||
}
|
||||
return "number between [expr {int($target*$x)}] and [expr {int($target/$x)}]"
|
||||
}
|
||||
set mrange 0.98 ;# plus or minus 2%
|
||||
|
||||
|
||||
do_test malloc5-1.4 {
|
||||
# Commit the transaction and open a new one. Read 1 page into the cache.
|
||||
# Because the page is not dirty, it is eligible for collection even
|
||||
@@ -81,16 +98,16 @@ do_test malloc5-1.4 {
|
||||
BEGIN;
|
||||
SELECT * FROM abc;
|
||||
}
|
||||
sqlite3_release_memory
|
||||
} $::pgalloc
|
||||
value_in_range $::pgalloc $::mrange [sqlite3_release_memory]
|
||||
} [value_in_range $::pgalloc $::mrange]
|
||||
|
||||
do_test malloc5-1.5 {
|
||||
# Conclude the transaction opened in the previous [do_test] block. This
|
||||
# causes another page (page 1) to become eligible for recycling.
|
||||
#
|
||||
execsql { COMMIT }
|
||||
sqlite3_release_memory
|
||||
} $::pgalloc
|
||||
value_in_range $::pgalloc $::mrange [sqlite3_release_memory]
|
||||
} [value_in_range $::pgalloc $::mrange]
|
||||
|
||||
do_test malloc5-1.6 {
|
||||
# Manipulate the cache so that it contains two unused pages. One requires
|
||||
@@ -101,8 +118,8 @@ do_test malloc5-1.6 {
|
||||
SELECT * FROM abc;
|
||||
CREATE TABLE def(d, e, f);
|
||||
}
|
||||
sqlite3_release_memory 500
|
||||
} $::pgalloc
|
||||
value_in_range $::pgalloc $::mrange [sqlite3_release_memory 500]
|
||||
} [value_in_range $::pgalloc $::mrange]
|
||||
|
||||
do_test malloc5-1.7 {
|
||||
# Database should not be locked this time.
|
||||
|
||||
@@ -143,6 +143,33 @@ do_faultsim_test 7.2 -faults oom* -body {
|
||||
faultsim_test_result [list 0 {}]
|
||||
}
|
||||
|
||||
reset_db
|
||||
|
||||
proc isqrt {i} { expr { int(sqrt($i)) } }
|
||||
db func isqrt isqrt
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
PRAGMA encoding = 'utf-16';
|
||||
CREATE TABLE x2(x TEXT, y TEXT);
|
||||
WITH data(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM data
|
||||
)
|
||||
INSERT INTO x2 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400;
|
||||
CREATE INDEX x2x ON x2(x);
|
||||
CREATE INDEX x2y ON x2(y);
|
||||
ANALYZE;
|
||||
DELETE FROM x2;
|
||||
}
|
||||
|
||||
proc str {a} { return $a }
|
||||
db func str -deterministic str
|
||||
|
||||
do_faultsim_test 8 -faults oom* -body {
|
||||
execsql { SELECT * FROM x2 WHERE x = str('19') AND y = str('4') }
|
||||
} -test {
|
||||
faultsim_test_result [list 0 {}]
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -59,6 +59,14 @@ do_test multiplex4-1.1 {
|
||||
multiplex_file_list mx4test
|
||||
} {mx4test.db}
|
||||
|
||||
# NB: The PRAGMA multiplex_truncate command is implemented using the
|
||||
# SQLITE_FCNTL_PRAGMA file-control...
|
||||
#
|
||||
# EVIDENCE-OF: R-12238-55120 Whenever a PRAGMA statement is parsed, an
|
||||
# SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file
|
||||
# object corresponding to the database file to which the pragma
|
||||
# statement refers.
|
||||
#
|
||||
do_test multiplex4-1.2 {
|
||||
db eval {PRAGMA multiplex_truncate}
|
||||
} {on}
|
||||
@@ -84,6 +92,16 @@ do_test multiplex4-1.9 {
|
||||
db eval {PRAGMA multiplex_truncate=0}
|
||||
} {off}
|
||||
|
||||
# EVIDENCE-OF: R-26188-08449 If the SQLITE_FCNTL_PRAGMA file control
|
||||
# returns SQLITE_OK, then the parser assumes that the VFS has handled
|
||||
# the PRAGMA itself and the parser generates a no-op prepared statement
|
||||
# if result string is NULL, or that returns a copy of the result string
|
||||
# if the string is non-NULL.
|
||||
#
|
||||
do_test multiplex4-1.9-explain {
|
||||
db eval {EXPLAIN PRAGMA multiplex_truncate=0;}
|
||||
} {/String8 \d \d \d off/}
|
||||
|
||||
do_test multiplex4-1.10 {
|
||||
db eval {
|
||||
INSERT INTO t1(x) VALUES(randomblob(250000));
|
||||
|
||||
127
test/pragma.test
127
test/pragma.test
@@ -83,7 +83,11 @@ delete_file test.db test.db-journal
|
||||
delete_file test3.db test3.db-journal
|
||||
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-24197-42751 PRAGMA database.cache_size; PRAGMA
|
||||
# database.cache_size = pages; PRAGMA database.cache_size = -kibibytes;
|
||||
# Query or change the suggested maximum number of database disk pages
|
||||
# that SQLite will hold in memory at once per open database file.
|
||||
#
|
||||
ifcapable pager_pragmas {
|
||||
set DFLT_CACHE_SZ [db one {PRAGMA default_cache_size}]
|
||||
set TEMP_CACHE_SZ [db one {PRAGMA temp.default_cache_size}]
|
||||
@@ -95,6 +99,8 @@ do_test pragma-1.1 {
|
||||
}
|
||||
} [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ 2]
|
||||
do_test pragma-1.2 {
|
||||
# EVIDENCE-OF: R-42059-47211 If the argument N is positive then the
|
||||
# suggested cache size is set to N.
|
||||
execsql {
|
||||
PRAGMA synchronous=OFF;
|
||||
PRAGMA cache_size=1234;
|
||||
@@ -662,6 +668,37 @@ do_test pragma-6.5.1 {
|
||||
}
|
||||
db eval {SELECT seqno, cid, name FROM out ORDER BY seqno}
|
||||
} {0 0 a 1 1 b}
|
||||
|
||||
# EVIDENCE-OF: R-23114-21695 The auxiliary index-columns are not shown
|
||||
# by the index_info pragma, but they are listed by the index_xinfo
|
||||
# pragma.
|
||||
#
|
||||
do_test pragma-6.5.1b {
|
||||
capture_pragma db out {PRAGMA index_xinfo(t3i1)}
|
||||
db eval {SELECT seqno, cid, name FROM out ORDER BY seqno}
|
||||
} {0 0 a 1 1 b 2 -1 {}}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-62725-03366 PRAGMA database.index_info(index-name);
|
||||
# This pragma returns one row for each key column in the named index.
|
||||
#
|
||||
# (The first column of output from PRAGMA index_info is...)
|
||||
# EVIDENCE-OF: R-34186-52914 The rank of the column within the index. (0
|
||||
# means left-most.)
|
||||
#
|
||||
# (The second column of output from PRAGMA index_info is...)
|
||||
# EVIDENCE-OF: R-65019-08383 The rank of the column within the table
|
||||
# being indexed.
|
||||
#
|
||||
# (The third column of output from PRAGMA index_info is...)
|
||||
# EVIDENCE-OF: R-09773-34266 The name of the column being indexed.
|
||||
#
|
||||
do_execsql_test pragma-6.5.1c {
|
||||
CREATE INDEX t3i2 ON t3(b,a);
|
||||
PRAGMA index_info='t3i2';
|
||||
DROP INDEX t3i2;
|
||||
} {0 1 b 1 0 a}
|
||||
|
||||
do_test pragma-6.5.2 {
|
||||
execsql {
|
||||
pragma index_info(t3i1_bogus);
|
||||
@@ -719,6 +756,9 @@ do_test pragma-6.7 {
|
||||
# Miscellaneous tests
|
||||
#
|
||||
ifcapable schema_pragmas {
|
||||
# EVIDENCE-OF: R-63500-32024 PRAGMA database.index_list(table-name);
|
||||
# This pragma returns one row for each index associated with the given
|
||||
# table.
|
||||
do_test pragma-7.1.1 {
|
||||
# Make sure a pragma knows to read the schema if it needs to
|
||||
db close
|
||||
@@ -1310,18 +1350,23 @@ ifcapable pager_pragmas {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-13905-26312 PRAGMA database.page_count; Return the
|
||||
# total number of pages in the database file.
|
||||
#
|
||||
do_test pragma-14.1 {
|
||||
execsql { pragma auto_vacuum = 0 }
|
||||
execsql { pragma page_count }
|
||||
} {0}
|
||||
execsql { pragma page_count; pragma main.page_count }
|
||||
} {0 0}
|
||||
|
||||
do_test pragma-14.2 {
|
||||
execsql {
|
||||
CREATE TABLE abc(a, b, c);
|
||||
PRAGMA page_count;
|
||||
PRAGMA main.page_count;
|
||||
PRAGMA temp.page_count;
|
||||
}
|
||||
} {2}
|
||||
} {2 2 0}
|
||||
do_test pragma-14.2uc {
|
||||
execsql {pragma PAGE_COUNT}
|
||||
} {2}
|
||||
@@ -1730,30 +1775,90 @@ do_test 23.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d);
|
||||
CREATE INDEX i1 ON t1(b,c);
|
||||
CREATE INDEX i2 ON t1(c,d);
|
||||
CREATE INDEX i2x ON t1(d COLLATE nocase, c DESC);
|
||||
CREATE TABLE t2(x INTEGER REFERENCES t1);
|
||||
}
|
||||
db2 eval {SELECT name FROM sqlite_master}
|
||||
} {t1 i1 i2 t2}
|
||||
} {t1 i1 i2 i2x t2}
|
||||
do_test 23.2a {
|
||||
db eval {
|
||||
DROP INDEX i2;
|
||||
CREATE INDEX i2 ON t1(c,d,b);
|
||||
}
|
||||
capture_pragma db2 out {PRAGMA index_info(i2)}
|
||||
db2 eval {SELECT cid, name, "desc", coll, "key", '|' FROM out ORDER BY seqno}
|
||||
} {2 c 0 BINARY 1 | 3 d 0 BINARY 1 | 1 b 0 BINARY 1 |}
|
||||
db2 eval {SELECT cid, name, '|' FROM out ORDER BY seqno}
|
||||
} {2 c | 3 d | 1 b |}
|
||||
|
||||
# EVIDENCE-OF: R-44874-46325 PRAGMA database.index_xinfo(index-name);
|
||||
# This pragma returns information about every column in an index.
|
||||
#
|
||||
# EVIDENCE-OF: R-45970-35618 Unlike this index_info pragma, this pragma
|
||||
# returns information about every column in the index, not just the key
|
||||
# columns.
|
||||
#
|
||||
do_test 23.2b {
|
||||
breakpoint;
|
||||
capture_pragma db2 out {PRAGMA index_xinfo(i2)}
|
||||
db2 eval {SELECT cid, name, "desc", coll, "key", '|' FROM out ORDER BY seqno}
|
||||
} {2 c 0 BINARY 1 | 3 d 0 BINARY 1 | 1 b 0 BINARY 1 | -1 {} 0 BINARY 0 |}
|
||||
|
||||
# (The first column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-00197-14279 The rank of the column within the index. (0
|
||||
# means left-most. Key columns come before auxiliary columns.)
|
||||
#
|
||||
# (The second column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-40889-06838 The rank of the column within the table
|
||||
# being indexed, or -1 if the index-column is the rowid of the table
|
||||
# being indexed.
|
||||
#
|
||||
# (The third column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-22751-28901 The name of the column being indexed, or
|
||||
# NULL if the index-column is the rowid of the table being indexed.
|
||||
#
|
||||
# (The fourth column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-11847-09179 1 if the index-column is sorted in reverse
|
||||
# (DESC) order by the index and 0 otherwise.
|
||||
#
|
||||
# (The fifth column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-15313-19540 The name for the collating sequence used to
|
||||
# compare values in the index-column.
|
||||
#
|
||||
# (The sixth column of output from PRAGMA index_xinfo is...)
|
||||
# EVIDENCE-OF: R-14310-64553 1 if the index-column is a key column and 0
|
||||
# if the index-column is an auxiliary column.
|
||||
#
|
||||
do_test 23.2c {
|
||||
db2 eval {PRAGMA index_xinfo(i2)}
|
||||
} {0 2 c 0 BINARY 1 1 3 d 0 BINARY 1 2 1 b 0 BINARY 1 3 -1 {} 0 BINARY 0}
|
||||
do_test 23.2d {
|
||||
db2 eval {PRAGMA index_xinfo(i2x)}
|
||||
} {0 3 d 0 nocase 1 1 2 c 1 BINARY 1 2 -1 {} 0 BINARY 0}
|
||||
|
||||
# EVIDENCE-OF: R-63500-32024 PRAGMA database.index_list(table-name);
|
||||
# This pragma returns one row for each index associated with the given
|
||||
# table.
|
||||
#
|
||||
# (The first column of output from PRAGMA index_list is...)
|
||||
# EVIDENCE-OF: R-02753-24748 A sequence number assigned to each index
|
||||
# for internal tracking purposes.
|
||||
#
|
||||
# (The second column of output from PRAGMA index_list is...)
|
||||
# EVIDENCE-OF: R-35496-03635 The name of the index.
|
||||
#
|
||||
# (The third column of output from PRAGMA index_list is...)
|
||||
# EVIDENCE-OF: R-57301-64506 "1" if the index is UNIQUE and "0" if not.
|
||||
#
|
||||
# (The fourth column of output from PRAGMA index_list is...)
|
||||
# EVIDENCE-OF: R-36609-39554 "c" if the index was created by a CREATE
|
||||
# INDEX statement, "u" if the index was created by a UNIQUE constraint,
|
||||
# or "pk" if the index was created by a PRIMARY KEY constraint.
|
||||
#
|
||||
do_test 23.3 {
|
||||
db eval {
|
||||
CREATE INDEX i3 ON t1(d,b,c);
|
||||
}
|
||||
capture_pragma db2 out {PRAGMA index_list(t1)}
|
||||
db2 eval {SELECT name, "unique", origin FROM out ORDER BY seq}
|
||||
} {i3 0 c i2 0 c i1 0 c}
|
||||
db2 eval {SELECT seq, name, "unique", origin, '|' FROM out ORDER BY seq}
|
||||
} {0 i3 0 c | 1 i2 0 c | 2 i2x 0 c | 3 i1 0 c |}
|
||||
do_test 23.4 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN e;
|
||||
|
||||
@@ -39,6 +39,10 @@ delete_file test3.db test3.db-journal
|
||||
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
|
||||
db eval {PRAGMA auto_vacuum=0}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-17887-14874 PRAGMA database.freelist_count; Return the
|
||||
# number of unused pages in the database file.
|
||||
#
|
||||
do_test pragma2-1.1 {
|
||||
execsql {
|
||||
PRAGMA freelist_count;
|
||||
|
||||
@@ -32,6 +32,11 @@ do_test rdonly-1.1 {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1}
|
||||
|
||||
# EVIDENCE-OF: R-29639-16887 The sqlite3_db_readonly(D,N) interface
|
||||
# returns 1 if the database N of connection D is read-only, 0 if it is
|
||||
# read/write, or -1 if N is not the name of a database on connection D.
|
||||
#
|
||||
do_test rdonly-1.1.1 {
|
||||
sqlite3_db_readonly db main
|
||||
} {0}
|
||||
|
||||
@@ -105,6 +105,10 @@ ifcapable subquery {
|
||||
}
|
||||
} {0 1 2 2 3 3 3 3}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-02644-22131 In a compound SELECT statement, only the
|
||||
# last or right-most simple SELECT may have an ORDER BY clause.
|
||||
#
|
||||
do_test select4-1.3 {
|
||||
set v [catch {execsql {
|
||||
SELECT DISTINCT log FROM t1 ORDER BY log
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
# The focus of this file is testing the CLI shell tool.
|
||||
# These tests are specific to the .stats command.
|
||||
#
|
||||
# $Id: shell4.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $
|
||||
#
|
||||
# 2015-03-19: Added tests for .trace
|
||||
|
||||
# Test plan:
|
||||
#
|
||||
# shell4-1.*: Basic tests specific to the "stats" command.
|
||||
# shell4-2.*: Basic tests for ".trace"
|
||||
#
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -113,4 +113,22 @@ SELECT 1;
|
||||
[regexp {Autoindex Inserts} $res]
|
||||
} {1 1 1}
|
||||
|
||||
do_test shell4-2.1 {
|
||||
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace"
|
||||
} {1 {Usage: .trace FILE|off}}
|
||||
do_test shell4-2.2 {
|
||||
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace off\n.trace off\n"
|
||||
} {0 {}}
|
||||
do_test shell4-2.3 {
|
||||
catchcmd ":memory:" ".trace stdout\n.trace\n.trace off\n.dump\n"
|
||||
} {/^1 {PRAGMA.*Usage:.*}$/}
|
||||
do_test shell4-2.4 {
|
||||
catchcmd ":memory:" ".trace stdout\nCREATE TABLE t1(x);SELECT * FROM t1;"
|
||||
} {0 {CREATE TABLE t1(x);
|
||||
SELECT * FROM t1;}}
|
||||
do_test shell4-2.5 {
|
||||
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace stdout\nSELECT * FROM t1;"
|
||||
} {0 {SELECT * FROM t1;}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -24,6 +24,9 @@ do_test shrink-1.1 {
|
||||
INSERT INTO t1 VALUES(randomblob(1000000),1);
|
||||
}
|
||||
set ::baseline sqlite3_memory_used
|
||||
# EVIDENCE-OF: R-58814-63508 The sqlite3_db_release_memory(D) interface
|
||||
# attempts to free as much heap memory as possible from database
|
||||
# connection D.
|
||||
sqlite3_db_release_memory db
|
||||
expr {$::baseline > [sqlite3_memory_used]+500000}
|
||||
} {1}
|
||||
|
||||
@@ -24,6 +24,14 @@ ifcapable !integrityck {
|
||||
return
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-26343-45930 This pragma invokes the
|
||||
# sqlite3_soft_heap_limit64() interface with the argument N, if N is
|
||||
# specified and is a non-negative integer.
|
||||
#
|
||||
# EVIDENCE-OF: R-64451-07163 The soft_heap_limit pragma always returns
|
||||
# the same integer that would be returned by the
|
||||
# sqlite3_soft_heap_limit64(-1) C-language function.
|
||||
#
|
||||
do_test softheap1-1.0 {
|
||||
execsql {PRAGMA soft_heap_limit}
|
||||
} [sqlite3_soft_heap_limit -1]
|
||||
|
||||
@@ -25,7 +25,20 @@ sqlite3 db test.db
|
||||
|
||||
|
||||
# Configure the sorter to use 3 background threads.
|
||||
db eval {PRAGMA threads=3}
|
||||
#
|
||||
# EVIDENCE-OF: R-19249-32353 SQLITE_LIMIT_WORKER_THREADS The maximum
|
||||
# number of auxiliary worker threads that a single prepared statement
|
||||
# may start.
|
||||
#
|
||||
do_test sort4-init001 {
|
||||
db eval {PRAGMA threads=5}
|
||||
sqlite3_limit db SQLITE_LIMIT_WORKER_THREADS -1
|
||||
} {5}
|
||||
do_test sort4-init002 {
|
||||
sqlite3_limit db SQLITE_LIMIT_WORKER_THREADS 3
|
||||
db eval {PRAGMA threads}
|
||||
} {3}
|
||||
|
||||
|
||||
# Minimum number of seconds to run for. If the value is 0, each test
|
||||
# is run exactly once. Otherwise, tests are repeated until the timeout
|
||||
|
||||
@@ -250,6 +250,9 @@ do_test sqllimits1-4.10.1 {
|
||||
# Test cases sqllimits1-5.* test that the SQLITE_MAX_LENGTH limit
|
||||
# is enforced.
|
||||
#
|
||||
# EVIDENCE-OF: R-61987-00541 SQLITE_LIMIT_LENGTH The maximum size of any
|
||||
# string or BLOB or table row, in bytes.
|
||||
#
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set LARGESIZE 99999
|
||||
@@ -406,6 +409,9 @@ unset strvalue
|
||||
# Test cases sqllimits1-6.* test that the SQLITE_MAX_SQL_LENGTH limit
|
||||
# is enforced.
|
||||
#
|
||||
# EVIDENCE-OF: R-09808-17554 SQLITE_LIMIT_SQL_LENGTH The maximum length
|
||||
# of an SQL statement, in bytes.
|
||||
#
|
||||
do_test sqllimits1-6.1 {
|
||||
sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH 50000
|
||||
set sql "SELECT 1 WHERE 1==1"
|
||||
@@ -567,6 +573,11 @@ do_test sqllimits1-7.7.4 {
|
||||
#--------------------------------------------------------------------
|
||||
# Test cases sqllimits1-8.* test the SQLITE_MAX_COLUMN limit.
|
||||
#
|
||||
# EVIDENCE-OF: R-43996-29471 SQLITE_LIMIT_COLUMN The maximum number of
|
||||
# columns in a table definition or in the result set of a SELECT or the
|
||||
# maximum number of columns in an index or in an ORDER BY or GROUP BY
|
||||
# clause.
|
||||
#
|
||||
set SQLITE_LIMIT_COLUMN 200
|
||||
sqlite3_limit db SQLITE_LIMIT_COLUMN $SQLITE_LIMIT_COLUMN
|
||||
do_test sqllimits1-8.1 {
|
||||
@@ -670,6 +681,9 @@ do_test sqllimits1-8.11 {
|
||||
# limit is enforced. The limit refers to the number of terms in
|
||||
# the expression.
|
||||
#
|
||||
# EVIDENCE-OF: R-12723-08526 SQLITE_LIMIT_EXPR_DEPTH The maximum depth
|
||||
# of the parse tree on any expression.
|
||||
#
|
||||
if {$SQLITE_MAX_EXPR_DEPTH==0} {
|
||||
puts -nonewline stderr "WARNING: Compile with -DSQLITE_MAX_EXPR_DEPTH to run "
|
||||
puts stderr "tests sqllimits1-9.X"
|
||||
@@ -729,6 +743,9 @@ if 0 {
|
||||
# Test the SQLITE_LIMIT_FUNCTION_ARG limit works. Test case names
|
||||
# match the pattern "sqllimits1-11.*".
|
||||
#
|
||||
# EVIDENCE-OF: R-59001-45278 SQLITE_LIMIT_FUNCTION_ARG The maximum
|
||||
# number of arguments on a function.
|
||||
#
|
||||
for {set max 5} {$max<=$SQLITE_MAX_FUNCTION_ARG} {incr max} {
|
||||
do_test sqllimits1-11.$max.1 {
|
||||
set vals [list]
|
||||
@@ -762,6 +779,9 @@ for {set max 5} {$max<=$SQLITE_MAX_FUNCTION_ARG} {incr max} {
|
||||
#--------------------------------------------------------------------
|
||||
# Test cases sqllimits1-12.*: Test the SQLITE_MAX_ATTACHED limit.
|
||||
#
|
||||
# EVIDENCE-OF: R-41778-26203 SQLITE_LIMIT_ATTACHED The maximum number of
|
||||
# attached databases.
|
||||
#
|
||||
ifcapable attach {
|
||||
do_test sqllimits1-12.1 {
|
||||
set max $::SQLITE_MAX_ATTACHED
|
||||
@@ -785,6 +805,9 @@ ifcapable attach {
|
||||
# Test cases sqllimits1-13.*: Check that the SQLITE_MAX_VARIABLE_NUMBER
|
||||
# limit works.
|
||||
#
|
||||
# EVIDENCE-OF: R-42363-29104 SQLITE_LIMIT_VARIABLE_NUMBER The maximum
|
||||
# index number of any parameter in an SQL statement.
|
||||
#
|
||||
do_test sqllimits1-13.1 {
|
||||
set max $::SQLITE_MAX_VARIABLE_NUMBER
|
||||
catchsql "SELECT ?[expr {$max+1}] FROM t1"
|
||||
@@ -806,6 +829,9 @@ do_test sqllimits1-13.2 {
|
||||
# implementation by overriding the like() scalar function bypasses
|
||||
# this limitation.
|
||||
#
|
||||
# EVIDENCE-OF: R-12940-37052 SQLITE_LIMIT_LIKE_PATTERN_LENGTH The
|
||||
# maximum length of the pattern argument to the LIKE or GLOB operators.
|
||||
#
|
||||
# These tests check that the limit is not incorrectly applied to
|
||||
# the left-hand-side of the LIKE operator (the string being tested
|
||||
# against the pattern).
|
||||
|
||||
@@ -118,7 +118,7 @@ do_test tcl-1.14 {
|
||||
do_test tcl-1.15 {
|
||||
set v [catch {db function} msg]
|
||||
lappend v $msg
|
||||
} {1 {wrong # args: should be "db function NAME [-argcount N] SCRIPT"}}
|
||||
} {1 {wrong # args: should be "db function NAME ?SWITCHES? SCRIPT"}}
|
||||
do_test tcl-1.16 {
|
||||
set v [catch {db last_insert_rowid xyz} msg]
|
||||
lappend v $msg
|
||||
|
||||
117
test/walblock.test
Normal file
117
test/walblock.test
Normal file
@@ -0,0 +1,117 @@
|
||||
# 2015 Mar 17
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
ifcapable !wal {finish_test ; return }
|
||||
if {$::tcl_platform(platform)!="unix"} { finish_test ; return }
|
||||
set testprefix walblock
|
||||
|
||||
catch { db close }
|
||||
testvfs tvfs -fullshm 1
|
||||
foreach f [glob test.db*] { forcedelete $f }
|
||||
|
||||
sqlite3 db test.db -vfs tvfs
|
||||
do_execsql_test 1.1.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
PRAGMA journal_mode = wal;
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
} {wal}
|
||||
|
||||
do_test 1.1.1 {
|
||||
lsort [glob test.db*]
|
||||
} {test.db test.db-shm test.db-wal}
|
||||
|
||||
do_test 1.1.2 {
|
||||
set C [launch_testfixture]
|
||||
testfixture $C {
|
||||
sqlite3 db test.db
|
||||
db eval { SELECT * FROM t1 }
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
|
||||
do_test 1.1.3 {
|
||||
set ::out [list]
|
||||
testfixture $C {
|
||||
db eval { SELECT * FROM t1 }
|
||||
} [list set ::out]
|
||||
set ::out
|
||||
} {}
|
||||
|
||||
do_test 1.1.4 {
|
||||
vwait ::out
|
||||
set ::out
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
|
||||
#
|
||||
# Test that if a read client cannot read the wal-index header because a
|
||||
# write client is in the middle of updating it, the reader blocks until
|
||||
# the writer finishes.
|
||||
#
|
||||
# 1. Open a write transaction using client [db] in this process.
|
||||
#
|
||||
# 2. Attempt to commit the write transaction. Intercept the xShmBarrier()
|
||||
# call made by the writer between updating the two copies of the
|
||||
# wal-index header.
|
||||
#
|
||||
# 3. Within the xShmBarrier() callback, make an asynchronous request to
|
||||
# the other process to read from the database. It should block, as it
|
||||
# cannot get read the wal-index header.
|
||||
#
|
||||
# 4. Still in xShmBarrier(), wait for 5 seconds. Check that the other
|
||||
# process has not answered the request.
|
||||
#
|
||||
# 5: Finish committing the transaction. Then wait for 0.5 seconds more.
|
||||
# Ensure that the second process has by this stage read the database
|
||||
# and that the snapshot it read included the transaction committed in
|
||||
# step (4).
|
||||
#
|
||||
do_execsql_test 1.2.1 {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(9, 10);
|
||||
} {}
|
||||
|
||||
tvfs script barrier_callback
|
||||
tvfs filter xShmBarrier
|
||||
proc barrier_callback {method args} {
|
||||
set ::out ""
|
||||
testfixture $::C { db eval { SELECT * FROM t1 } } {set ::out}
|
||||
|
||||
do_test "1.2.2.(blocking 5 seconds)" {
|
||||
set ::continue 0
|
||||
after 5000 {set ::continue 1}
|
||||
vwait ::continue
|
||||
set ::out
|
||||
} {}
|
||||
}
|
||||
|
||||
execsql COMMIT
|
||||
|
||||
do_test "1.2.3.(blocking 0.5 seconds)" {
|
||||
set ::continue 0
|
||||
after 500 {set ::continue 1}
|
||||
vwait ::continue
|
||||
set ::out
|
||||
} {1 2 3 4 5 6 7 8 9 10}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -66,11 +66,11 @@ do_test where8-1.3 {
|
||||
|
||||
do_test where8-1.4 {
|
||||
execsql_status2 { SELECT c FROM t1 WHERE a > 8 OR b GLOB 't*' }
|
||||
} {IX X III II 0 0 9}
|
||||
} {IX X III II 0 0 10}
|
||||
|
||||
do_test where8-1.5 {
|
||||
execsql_status2 { SELECT c FROM t1 WHERE a > 8 OR b GLOB 'f*' }
|
||||
} {IX X V IV 0 0 9}
|
||||
} {IX X V IV 0 0 10}
|
||||
|
||||
do_test where8-1.6 {
|
||||
execsql_status { SELECT c FROM t1 WHERE a = 1 OR b = 'three' ORDER BY rowid }
|
||||
|
||||
72
test/whereK.test
Normal file
72
test/whereK.test
Normal file
@@ -0,0 +1,72 @@
|
||||
# 2015-03-16
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing OR expressions where terms can be
|
||||
# factored from either side of the OR and combined into a single new
|
||||
# AND term that is beneficial to the search. Examples:
|
||||
#
|
||||
# (x>A OR x=A) --> ... AND (x>=A)
|
||||
# (x>A OR (x=A AND y>=B) --> ... AND (x>=A)
|
||||
#
|
||||
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix whereK
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<99)
|
||||
INSERT INTO t1(a,b,c) SELECT x, x/10, x%10 FROM c;
|
||||
CREATE INDEX t1bc ON t1(b,c);
|
||||
SELECT a FROM t1 WHERE b>9 OR b=9 ORDER BY +a;
|
||||
} {90 91 92 93 94 95 96 97 98 99}
|
||||
do_execsql_test 1.1eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE b>9 OR b=9 ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a;
|
||||
} {88 89 90 91 92 93 94 95 96 97 98 99}
|
||||
do_execsql_test 1.2eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a;
|
||||
} {88 89 90 91 92 93 94 95 96 97 98 99}
|
||||
do_execsql_test 1.3eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR 8<b ORDER BY +a;
|
||||
} {88 89 90 91 92 93 94 95 96 97 98 99}
|
||||
do_execsql_test 1.4eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR 8<b ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR (b>8 AND c NOT IN (4,5,6))
|
||||
ORDER BY +a;
|
||||
} {88 89 90 91 92 93 97 98 99}
|
||||
do_execsql_test 1.5eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE (b=8 AND c>7) OR (b>8 AND c NOT IN (4,5,6))
|
||||
ORDER BY +a;
|
||||
} {/SEARCH TABLE t1 USING INDEX t1bc/}
|
||||
|
||||
finish_test
|
||||
@@ -119,6 +119,7 @@ foreach hdr {
|
||||
sqliteLimit.h
|
||||
vdbe.h
|
||||
vdbeInt.h
|
||||
vxworks.h
|
||||
wal.h
|
||||
whereInt.h
|
||||
} {
|
||||
|
||||
Reference in New Issue
Block a user