1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Merge recent enhancements from trunk.

FossilOrigin-Name: 5fbcb208d24d45169fc53ad8738dd3545d9bbd26b7434e31afc7f6419cd4e958
This commit is contained in:
drh
2021-01-27 20:35:22 +00:00
27 changed files with 951 additions and 310 deletions

View File

@@ -1077,7 +1077,7 @@ can choose a different start symbol using the
<a id='syntax_error'></a> <a id='syntax_error'></a>
<h4>4.4.19 The <tt>%syntax_error</tt> directive</h4> <h4>4.4.19 The <tt>%syntax_error</tt> directive</h4>
<p>See <a href='#error_processing'>Error Processing</a>.</p> <p>See <a href='#errors'>Error Processing</a>.</p>
<a id='token_class'></a> <a id='token_class'></a>
<h4>4.4.20 The <tt>%token_class</tt> directive</h4> <h4>4.4.20 The <tt>%token_class</tt> directive</h4>
@@ -1176,7 +1176,7 @@ match any input token.</p>
the wildcard token and some other token, the other token is always used. the wildcard token and some other token, the other token is always used.
The wildcard token is only matched if there are no alternatives.</p> The wildcard token is only matched if there are no alternatives.</p>
<a id='error_processing'></a> <a id='errors'></a>
<h2>5.0 Error Processing</h2> <h2>5.0 Error Processing</h2>
<p>After extensive experimentation over several years, it has been <p>After extensive experimentation over several years, it has been

View File

@@ -0,0 +1,57 @@
# 2020 December 23
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for the SQLite sessions module
# Specifically, for the sqlite3session_memory_used() API.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionmem
do_execsql_test 1.0 {
CREATE TABLE t1(i INTEGER PRIMARY KEY, x, y);
CREATE TABLE t2(i INTEGER, x, y, PRIMARY KEY(x, y));
}
do_test 1.1 {
sqlite3session S db main
S attach *
} {}
foreach {tn sql eRes} {
1 { INSERT INTO t1 VALUES(1, 2, 3) } 1
2 { UPDATE t1 SET x=5 } 0
3 { UPDATE t1 SET i=5 } 1
4 { DELETE FROM t1 } 0
5 { INSERT INTO t1 VALUES(1, 2, 3) } 0
6 { INSERT INTO t1 VALUES(5, 2, 3) } 0
7 { INSERT INTO t2 VALUES('a', 'b', 'c') } 1
8 { INSERT INTO t2 VALUES('d', 'e', 'f') } 1
9 { UPDATE t2 SET i='e' } 0
} {
set mem1 [S memory_used]
do_test 1.2.$tn.(mu=$mem1) {
execsql $sql
set mem2 [S memory_used]
expr {$mem2 > $mem1}
} $eRes
}
do_test 1.3 {
S delete
} {}
finish_test

12
main.mk
View File

@@ -550,13 +550,13 @@ ST_OPT = -DSQLITE_THREADSAFE=0
# This is the default Makefile target. The objects listed here # This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments. # are what get build when you type just "make" with no arguments.
# #
all: sqlite3.h libsqlite3.a sqlite3$(EXE) all: sqlite3.h sqlite3ext.h libsqlite3.a sqlite3$(EXE)
libsqlite3.a: $(LIBOBJ) libsqlite3.a: sqlite3.h $(LIBOBJ)
$(AR) libsqlite3.a $(LIBOBJ) $(AR) libsqlite3.a $(LIBOBJ)
$(RANLIB) libsqlite3.a $(RANLIB) libsqlite3.a
sqlite3$(EXE): shell.c libsqlite3.a sqlite3.h sqlite3$(EXE): sqlite3.h libsqlite3.a shell.c
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \ $(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB) shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
@@ -824,13 +824,13 @@ fts3_unicode2.o: $(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR) fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
fts5.o: fts5.c fts5.o: fts5.c sqlite3ext.h sqlite3.h
$(TCCX) -DSQLITE_CORE -c fts5.c $(TCCX) -DSQLITE_CORE -c fts5.c
json1.o: $(TOP)/ext/misc/json1.c json1.o: $(TOP)/ext/misc/json1.c sqlite3ext.h sqlite3.h
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
stmt.o: $(TOP)/ext/misc/stmt.c stmt.o: $(TOP)/ext/misc/stmt.c sqlite3ext.h sqlite3.h
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR) rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)

View File

@@ -1,5 +1,5 @@
C Lexer\sand\sgrammar\srules\sfor\sa\sRETURNING\sclause\son\sDELETE/INSERT/UPDATE.\nActually\smaking\sthis\swork,\sthough,\swill\sinvolve\sa\slot\smore\scode\swhich\swill\nlikely\sslow\sdown\sprocessing\sfor\sthe\scommon\scase\swhere\sthere\sis\sno\nRETURNING\sclause.\s\sFurthermore,\sRETURNING\sseems\sto\sbe\sof\slimited\susefulness\nand\sit\sis\snot\sstandard\sSQL.\s\sSo\swe\sabandon\sit\shere.\s\sThese\sexperimental\nchanges\sare\sparked\sin\sa\sbranch\sas\san\shistorical\sreference.\s\sIf\scircumstances\nchanges,\swe\smight\stake\sup\sthe\scause\sagain\ssome\sday. C Merge\srecent\senhancements\sfrom\strunk.
D 2021-01-12T20:16:31.150 D 2021-01-27T20:35:22.698
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -38,7 +38,7 @@ F configure 91893a81f698778dda4d8fb24bfca606ded31ef02bcfbc2ab072d30fb67138d6 x
F configure.ac 412b65c6107e41c098ad7f5f2e6a3f74ac02ffc6e92b9a6264b9f1060c235a04 F configure.ac 412b65c6107e41c098ad7f5f2e6a3f74ac02ffc6e92b9a6264b9f1060c235a04
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/lemon.html c5d8ba85ac1daef7be8c2d389899480eb62451ff5c09b0c28ff8157bb8770746 F doc/lemon.html 1bb72ece6271df0d901d233551dd985f2c6ba30d09382cf2d321ed951ab57491
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56 F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
@@ -450,6 +450,7 @@ F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7 F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
F ext/session/sessionfault2.test dd593f80b6b4786f7adfe83c5939620bc505559770cc181332da26f29cddd7bb F ext/session/sessionfault2.test dd593f80b6b4786f7adfe83c5939620bc505559770cc181332da26f29cddd7bb
F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2c52219819bc105a25 F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2c52219819bc105a25
F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810 F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5 F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d
@@ -462,7 +463,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 57451ea5b3d5cd86e9c5324b10c9de184b12e8dcccc31c65d24fbcb55ccd9c53 F main.mk 443a4ec1ca89ad267cbde45dadc68861154b99c7bd26e7b7dc74303a664002b8
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -476,12 +477,12 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 36cae0d6e3e91a1996e1a472f8c7242c31a4e38ba4295e3056da198c04fd2a87 F src/alter.c 36cae0d6e3e91a1996e1a472f8c7242c31a4e38ba4295e3056da198c04fd2a87
F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
F src/attach.c 0f497c15c4cfe3bdcb214f0dbdbbb6c5ed7e8a9308ac445c7959f5e5780437a9 F src/attach.c 87102aba5ddac8ef3a8a033ab657e4cae9cc8e846efe93b14029cfffaaf8831e
F src/auth.c 8d1df0e2ef8bafbedd4f1fe4baff03eb27507da4bf6e449df3613d383c4018b2 F src/auth.c 8d1df0e2ef8bafbedd4f1fe4baff03eb27507da4bf6e449df3613d383c4018b2
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 0f9cb686871ae668817673f0823b55d1bcadbc86ea28bd22c590b064a8322d5a F src/btree.c 47d9fe97d5c0d74506154e3597f8a23b81a00080751dc4d11fec91ee22796f4c
F src/btree.h 285f8377aa1353185a32bf455faafa9ff9a0d40d074d60509534d14990c7829e F src/btree.h 285f8377aa1353185a32bf455faafa9ff9a0d40d074d60509534d14990c7829e
F src/btreeInt.h 7614cae30f95b6aed0c7cac7718276a55cfe2c77058cbfd8bef5b75329757331 F src/btreeInt.h 7614cae30f95b6aed0c7cac7718276a55cfe2c77058cbfd8bef5b75329757331
F src/build.c ba8af18891c07501a185ecd02a2bc13a593de9bfd59dbffa5d126780c0c9fb8e F src/build.c ba8af18891c07501a185ecd02a2bc13a593de9bfd59dbffa5d126780c0c9fb8e
@@ -492,19 +493,19 @@ F src/date.c dace306a10d9b02ee553d454c8e1cf8d3c9b932e137738a6b15b90253a9bfc10
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
F src/delete.c 927cf8f900583e79aca8f1a321979e0a8f053babd9a690b44b38f79de2cc09fe F src/delete.c 927cf8f900583e79aca8f1a321979e0a8f053babd9a690b44b38f79de2cc09fe
F src/expr.c 0d196ed5a2ebf96be7e8df88add4fabfad0dce16c0fed81a4b8f6a26e259797f F src/expr.c 47c85263e6d179424e6b09e2c79db5704ab5b8cbc2fae2ee3285faa2566f2e74
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 83372403298e6a7dd989a47aaacdbaa5b4307b5199dbd56e07d4896066b3de72 F src/fkey.c 83372403298e6a7dd989a47aaacdbaa5b4307b5199dbd56e07d4896066b3de72
F src/func.c 251b5953cecd0ce3e282213c5e623134415793d3569d7804d13460559d7e45ff F src/func.c 796a7a4a0ff5eee82a04ee3c8265c5ebf9c6a9f5625621c5f97ed94f6224d7d9
F src/global.c ed55af196a9b66e198aaeda3f5454c3aa7d7d050c6c938181fd044b70d180a81 F src/global.c ed55af196a9b66e198aaeda3f5454c3aa7d7d050c6c938181fd044b70d180a81
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c c5e0c25cfb9960d9b7d49043de6adc12748853bc6dea76f5adef059e366f2f70 F src/insert.c 9b970eff058a858fbd9f2db71425ef195942c2610855daa66ae23024432d52f5
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067 F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
F src/main.c 97e9f137354bc1f76dc9bb60a0a24f8c45cf73b33e80d3ee4c64155336fb820d F src/main.c 1c5de7b3fabcdf05f4fe563aab5d81d175b89c67a8678a12ba86629356afa356
F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -535,17 +536,17 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
F src/pragma.c 6daaaecc26a4b09481d21722525b079ce756751a43a79cc1d8f122d686806193 F src/pragma.c 6daaaecc26a4b09481d21722525b079ce756751a43a79cc1d8f122d686806193
F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf
F src/prepare.c cfe5a0ec9fd612c89b4d50acfd4b796bd5fe850441cab0d866d72fa3aa982c45 F src/prepare.c f288cbc35f79eb32e162de7e80a63ebe00d80e639dcfac071bee11570cbdb16f
F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 1948a92ca9eab776632816b97e57c61d933474a78aad4f4ef835c916a83dbb1c F src/resolve.c 1948a92ca9eab776632816b97e57c61d933474a78aad4f4ef835c916a83dbb1c
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c a9c38abfbaaf1230fa9079b4d1d43694cac335a85efa39684bd4969a5c877a19 F src/select.c 738cb746189f721f59972993c13085fa2975c4cbfd04ba26445f3b42c81237dc
F src/shell.c.in 79bceb990e4bac23a09bb8dd65783ea4867b8bfca9242b5a82b884043e65109a F src/shell.c.in 9ebc74e4f05cfbd0f4a36060fdaeff1da4e9af4458358722bc08c5a1ab9a0879
F src/sqlite.h.in 0af968a1fa3c717261e1df0ed105fa7bddb4d82de7e0adb3eab49e6aa81b4de7 F src/sqlite.h.in 0af968a1fa3c717261e1df0ed105fa7bddb4d82de7e0adb3eab49e6aa81b4de7
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
F src/sqliteInt.h de0ba6b4f9bcddd665b4aa8feead3108e737536f061bad85992ffbad8050239f F src/sqliteInt.h c005efbb5f58d5dc41d1b61ffe253d6cd02b3f58b7126a59311a452df00a007a
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -612,7 +613,7 @@ F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048 F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048
F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286 F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
F src/vdbe.c 67de20067fa3a2ee8566342c751e941a2fe3fd88940fd9886ca5115f04165cce F src/vdbe.c 102d21260bddbb43c845603c3a2d6b4f3762e72f836ccda12991f291485d2539
F src/vdbe.h 83603854bfa5851af601fc0947671eb260f4363e62e960e8a994fb9bbcd2aaa1 F src/vdbe.h 83603854bfa5851af601fc0947671eb260f4363e62e960e8a994fb9bbcd2aaa1
F src/vdbeInt.h 3ca5e9fd6e095a8b6cf6bc3587a46fc93499503b2fe48951e1034ba9e2ce2f6e F src/vdbeInt.h 3ca5e9fd6e095a8b6cf6bc3587a46fc93499503b2fe48951e1034ba9e2ce2f6e
F src/vdbeapi.c c5e7cb2ab89a24d7f723e87b508f21bfb1359a04db5277d8a99fd1e015c12eb9 F src/vdbeapi.c c5e7cb2ab89a24d7f723e87b508f21bfb1359a04db5277d8a99fd1e015c12eb9
@@ -627,10 +628,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14 F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c d9c4e454ebb9499e908aa62d55b8994c375cf5355ac78f60d45af17f7890701c F src/walker.c d9c4e454ebb9499e908aa62d55b8994c375cf5355ac78f60d45af17f7890701c
F src/where.c 3d31871d03906312d7d71a9c0b28c97bcbaead7606dfc15f9b3d080b18702385 F src/where.c 0e6abb22a2323fec80b450825593c26a2ad8f4815d1ee3af9969d8f6144bf681
F src/whereInt.h 9a3f577619f07700d16d89eeb2f3d94d6b7ed7f109c2dacf0ce8844921549506 F src/whereInt.h ae03b5e3a4cca9bd9cb1b7d3c63faf8f1f177200fc8cecc87d3d0cab6ca338e6
F src/wherecode.c a3a1aff30fe99a818d8e7c607980f033f40c68d890e03ed25838b9dbb7908bee F src/wherecode.c 43a63441f8662ddf86b15975683a502ec33f08167e9636f4d19e38e265e95fd9
F src/whereexpr.c 3a463e156ea388083c501502229c2c7f4f5c6b5330ea59bdf40d6eb6e155a25f F src/whereexpr.c a182038cf7d10aa9a95a96b8563a34f34990323cf307dee6559e995961966d43
F src/window.c edd6f5e25a1e8f2b6f5305b7f5f7da7bb35f07f0d432b255b1d4c2fcab4205aa F src/window.c edd6f5e25a1e8f2b6f5305b7f5f7da7bb35f07f0d432b255b1d4c2fcab4205aa
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@@ -651,7 +652,7 @@ F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
F test/altertab.test 6d7bbac2c4a6ef71b775094a3298fa3a92274d95034ee23157ffba92768e47e6 F test/altertab.test 6d7bbac2c4a6ef71b775094a3298fa3a92274d95034ee23157ffba92768e47e6
F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
F test/altertab3.test 1db384eb85b4a30b0b332842f5c596b0dc0126f7c61959be3f85ae8b1c271d9a F test/altertab3.test 2b82fa2236a3a91553d53ae5555d8e723c7eec174c41f1fa62ff497355398479
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7 F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7
F test/analyze3.test fca2a9de0017becfdcc201647f03b1cfd5ba0e7b5b5c852936e4ec62780cde49 F test/analyze3.test fca2a9de0017becfdcc201647f03b1cfd5ba0e7b5b5c852936e4ec62780cde49
@@ -800,7 +801,7 @@ F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651 F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418 F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
F test/crash5.test 98f77ad22bceaea9043bf87088d5b61d004a1f40bb7c9dc3b6a7c70bd502c0bb F test/crash5.test 4aa55e7ac3c4bc511873e457aa65d2827d52da9b51e061511899dadcfe22b1e8
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100 F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100
@@ -874,6 +875,8 @@ F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650
F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7 F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/exists2.test 3e5726d6a67ebd4bd3466db58be424c09156c1f276c7594abb260cbf6ad494d3
F test/existsfault.test 74f7edc713f5a335e7ff47adf503067bf05c6f8630f88b2a19c24f0fa5486ab8
F test/expr.test 26cd01e8485bc48c8aa6a1add598e9ce1e706b4eb4f3f554e0b0223022e8c2cf F test/expr.test 26cd01e8485bc48c8aa6a1add598e9ce1e706b4eb4f3f554e0b0223022e8c2cf
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8 F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9 F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
@@ -1061,7 +1064,7 @@ F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
F test/in.test 688ed2011d922d83141a45af431601738674a4c0bdde34b6351f688b82a169b3 F test/in.test 688ed2011d922d83141a45af431601738674a4c0bdde34b6351f688b82a169b3
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test 65460600d48933adba4283c6ebd089aae173d16136ab9d01f74c89089090c5a5 F test/in4.test 64ac9c767ac5af562f066a40163d4202f8fa3be05d264ec65d6258e74606b30c
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
F test/in6.test 8562d0945195cab3cc4ab3794e9118e72cb44c43f785c2b04d48a9d06ca6b4ec F test/in6.test 8562d0945195cab3cc4ab3794e9118e72cb44c43f785c2b04d48a9d06ca6b4ec
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822 F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
@@ -1435,7 +1438,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637 F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 56c059c88c5b96a624f1193ba48b0bac034190b79cd9c75cb4acbfe84baf7ec5 F test/tester.tcl e5e4f5707fbf791ff8e06438fd0d4d71fe4c1d48753b7dd415efe72e853ef877
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1614,7 +1617,7 @@ F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d36
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 29f5a28d0fe39e6e2c01f6e1f53f08c0955170ae10a63ad023e33cb0a1682a51 F test/triggerC.test 29f5a28d0fe39e6e2c01f6e1f53f08c0955170ae10a63ad023e33cb0a1682a51
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650 F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
F test/triggerE.test ede2e4bce4ba802337bd69d39447fa04a938e06d84a8bfc53c76850fc36ed86d F test/triggerE.test 612969cb57a4ef792059ad6d01af0117e1ae862c283753ffcc9a6428642b22ee
F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad
F test/triggerG.test 2b816093c91ba73c733cfa8aedcc210ad819d72a98b1da30768a3c56505233e9 F test/triggerG.test 2b816093c91ba73c733cfa8aedcc210ad819d72a98b1da30768a3c56505233e9
F test/triggerupfrom.test d25961fa70a99b6736193da7b49a36d8c1d28d56188f0be6406d4366315cd6e4 F test/triggerupfrom.test d25961fa70a99b6736193da7b49a36d8c1d28d56188f0be6406d4366315cd6e4
@@ -1895,10 +1898,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 35824c1bcbd89ae4a94acfbe511bfbd888c418b981819e72bc9a991fc82d136c P abf8da815646055df5b871d54b99994c1470182dee7952fc5fd627e4379406cb 9dc7fc9f04d5c14fc436e5ff5b4c06c1969ddde5857ebeb5dccd59b7c748c339
R f88ede067372ddc1781e1314bfb966d4 R c54312b71d94f0a561db44774385038e
T *branch * returning
T *sym-returning *
T -sym-trunk *
U drh U drh
Z a56a87fefbb361b1248407b671a1766d Z 06a1968b90bf816dd044f7df827fd184

View File

@@ -1 +1 @@
abf8da815646055df5b871d54b99994c1470182dee7952fc5fd627e4379406cb 5fbcb208d24d45169fc53ad8738dd3545d9bbd26b7434e31afc7f6419cd4e958

View File

@@ -433,6 +433,63 @@ void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
} }
#endif /* SQLITE_OMIT_ATTACH */ #endif /* SQLITE_OMIT_ATTACH */
/*
** Expression callback used by sqlite3FixAAAA() routines.
*/
static int fixExprCb(Walker *p, Expr *pExpr){
DbFixer *pFix = p->u.pFix;
if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
if( pExpr->op==TK_VARIABLE ){
if( pFix->pParse->db->init.busy ){
pExpr->op = TK_NULL;
}else{
sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
return WRC_Abort;
}
}
return WRC_Continue;
}
/*
** Select callback used by sqlite3FixAAAA() routines.
*/
static int fixSelectCb(Walker *p, Select *pSelect){
DbFixer *pFix = p->u.pFix;
int i;
struct SrcList_item *pItem;
sqlite3 *db = pFix->pParse->db;
int iDb = sqlite3FindDbName(db, pFix->zDb);
SrcList *pList = pSelect->pSrc;
if( NEVER(pList==0) ) return WRC_Continue;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pFix->bTemp==0 ){
if( pItem->zDatabase && iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
pFix->zType, pFix->pName, pItem->zDatabase);
return WRC_Abort;
}
sqlite3DbFree(db, pItem->zDatabase);
pItem->zDatabase = 0;
pItem->pSchema = pFix->pSchema;
pItem->fg.fromDDL = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3WalkExpr(&pFix->w, pList->a[i].pOn) ) return WRC_Abort;
#endif
}
if( pSelect->pWith ){
int i;
for(i=0; i<pSelect->pWith->nCte; i++){
if( sqlite3WalkSelect(p, pSelect->pWith->a[i].pSelect) ){
return WRC_Abort;
}
}
}
return WRC_Continue;
}
/* /*
** Initialize a DbFixer structure. This routine must be called prior ** Initialize a DbFixer structure. This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below. ** to passing the structure to one of the sqliteFixAAAA() routines below.
@@ -444,9 +501,7 @@ void sqlite3FixInit(
const char *zType, /* "view", "trigger", or "index" */ const char *zType, /* "view", "trigger", or "index" */
const Token *pName /* Name of the view, trigger, or index */ const Token *pName /* Name of the view, trigger, or index */
){ ){
sqlite3 *db; sqlite3 *db = pParse->db;
db = pParse->db;
assert( db->nDb>iDb ); assert( db->nDb>iDb );
pFix->pParse = pParse; pFix->pParse = pParse;
pFix->zDb = db->aDb[iDb].zDbSName; pFix->zDb = db->aDb[iDb].zDbSName;
@@ -454,6 +509,13 @@ void sqlite3FixInit(
pFix->zType = zType; pFix->zType = zType;
pFix->pName = pName; pFix->pName = pName;
pFix->bTemp = (iDb==1); pFix->bTemp = (iDb==1);
pFix->w.pParse = pParse;
pFix->w.xExprCallback = fixExprCb;
pFix->w.xSelectCallback = fixSelectCb;
pFix->w.xSelectCallback2 = 0;
pFix->w.walkerDepth = 0;
pFix->w.eCode = 0;
pFix->w.u.pFix = pFix;
} }
/* /*
@@ -474,115 +536,27 @@ int sqlite3FixSrcList(
DbFixer *pFix, /* Context of the fixation */ DbFixer *pFix, /* Context of the fixation */
SrcList *pList /* The Source list to check and modify */ SrcList *pList /* The Source list to check and modify */
){ ){
int i; int res = 0;
struct SrcList_item *pItem; if( pList ){
sqlite3 *db = pFix->pParse->db; Select s;
int iDb = sqlite3FindDbName(db, pFix->zDb); memset(&s, 0, sizeof(s));
s.pSrc = pList;
if( NEVER(pList==0) ) return 0; res = sqlite3WalkSelect(&pFix->w, &s);
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pFix->bTemp==0 ){
if( pItem->zDatabase && iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
pFix->zType, pFix->pName, pItem->zDatabase);
return 1;
}
sqlite3DbFree(db, pItem->zDatabase);
pItem->zDatabase = 0;
pItem->pSchema = pFix->pSchema;
pItem->fg.fromDDL = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
#endif
if( pItem->fg.isTabFunc && sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){
return 1;
}
} }
return 0; return res;
} }
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
int sqlite3FixSelect( int sqlite3FixSelect(
DbFixer *pFix, /* Context of the fixation */ DbFixer *pFix, /* Context of the fixation */
Select *pSelect /* The SELECT statement to be fixed to one database */ Select *pSelect /* The SELECT statement to be fixed to one database */
){ ){
while( pSelect ){ return sqlite3WalkSelect(&pFix->w, pSelect);
if( sqlite3FixExprList(pFix, pSelect->pEList) ){
return 1;
}
if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
return 1;
}
if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
return 1;
}
if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
return 1;
}
if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
return 1;
}
if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
return 1;
}
if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
return 1;
}
if( pSelect->pWith ){
int i;
for(i=0; i<pSelect->pWith->nCte; i++){
if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){
return 1;
}
}
}
pSelect = pSelect->pPrior;
}
return 0;
} }
int sqlite3FixExpr( int sqlite3FixExpr(
DbFixer *pFix, /* Context of the fixation */ DbFixer *pFix, /* Context of the fixation */
Expr *pExpr /* The expression to be fixed to one database */ Expr *pExpr /* The expression to be fixed to one database */
){ ){
while( pExpr ){ return sqlite3WalkExpr(&pFix->w, pExpr);
if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
if( pExpr->op==TK_VARIABLE ){
if( pFix->pParse->db->init.busy ){
pExpr->op = TK_NULL;
}else{
sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
return 1;
}
}
if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
}else{
if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
}
if( sqlite3FixExpr(pFix, pExpr->pRight) ){
return 1;
}
pExpr = pExpr->pLeft;
}
return 0;
}
int sqlite3FixExprList(
DbFixer *pFix, /* Context of the fixation */
ExprList *pList /* The expression to be fixed to one database */
){
int i;
struct ExprList_item *pItem;
if( pList==0 ) return 0;
for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
if( sqlite3FixExpr(pFix, pItem->pExpr) ){
return 1;
}
}
return 0;
} }
#endif #endif
@@ -592,25 +566,20 @@ int sqlite3FixTriggerStep(
TriggerStep *pStep /* The trigger step be fixed to one database */ TriggerStep *pStep /* The trigger step be fixed to one database */
){ ){
while( pStep ){ while( pStep ){
if( sqlite3FixSelect(pFix, pStep->pSelect) ){ if( sqlite3WalkSelect(&pFix->w, pStep->pSelect)
return 1; || sqlite3WalkExpr(&pFix->w, pStep->pWhere)
} || sqlite3WalkExprList(&pFix->w, pStep->pExprList)
if( sqlite3FixExpr(pFix, pStep->pWhere) ){ || sqlite3FixSrcList(pFix, pStep->pFrom)
return 1; ){
}
if( sqlite3FixExprList(pFix, pStep->pExprList) ){
return 1;
}
if( pStep->pFrom && sqlite3FixSrcList(pFix, pStep->pFrom) ){
return 1; return 1;
} }
#ifndef SQLITE_OMIT_UPSERT #ifndef SQLITE_OMIT_UPSERT
if( pStep->pUpsert ){ if( pStep->pUpsert ){
Upsert *pUp = pStep->pUpsert; Upsert *pUp = pStep->pUpsert;
if( sqlite3FixExprList(pFix, pUp->pUpsertTarget) if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
|| sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere) || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
|| sqlite3FixExprList(pFix, pUp->pUpsertSet) || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
|| sqlite3FixExpr(pFix, pUp->pUpsertWhere) || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
){ ){
return 1; return 1;
} }
@@ -618,6 +587,7 @@ int sqlite3FixTriggerStep(
#endif #endif
pStep = pStep->pNext; pStep = pStep->pNext;
} }
return 0; return 0;
} }
#endif #endif

View File

@@ -2901,6 +2901,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
((pageSize-1)&pageSize)==0 ){ ((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 ); assert( (pageSize & 7)==0 );
assert( !pBt->pCursor ); assert( !pBt->pCursor );
if( nReserve>32 && pageSize==512 ) pageSize = 1024;
pBt->pageSize = (u32)pageSize; pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt); freeTempSpace(pBt);
} }

View File

@@ -95,7 +95,18 @@ Expr *sqlite3ExprAddCollateToken(
const Token *pCollName, /* Name of collating sequence */ const Token *pCollName, /* Name of collating sequence */
int dequote /* True to dequote pCollName */ int dequote /* True to dequote pCollName */
){ ){
if( pCollName->n>0 ){ assert( pExpr!=0 || pParse->db->mallocFailed );
if( pExpr==0 ) return 0;
if( pExpr->op==TK_VECTOR ){
ExprList *pList = pExpr->x.pList;
if( ALWAYS(pList!=0) ){
int i;
for(i=0; i<pList->nExpr; i++){
pList->a[i].pExpr = sqlite3ExprAddCollateToken(pParse,pList->a[i].pExpr,
pCollName, dequote);
}
}
}else if( pCollName->n>0 ){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote); Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
if( pNew ){ if( pNew ){
pNew->pLeft = pExpr; pNew->pLeft = pExpr;

View File

@@ -1865,7 +1865,9 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef; FuncDef *pDef;
int nExpr; int nExpr;
if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){ assert( pExpr!=0 );
assert( pExpr->op==TK_FUNCTION );
if( !pExpr->x.pList ){
return 0; return 0;
} }
assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); assert( !ExprHasProperty(pExpr, EP_xIsSelect) );

View File

@@ -1301,7 +1301,9 @@ void sqlite3Insert(
sqlite3VdbeJumpHere(v, addrInsTop); sqlite3VdbeJumpHere(v, addrInsTop);
} }
#ifndef SQLITE_OMIT_XFER_OPT
insert_end: insert_end:
#endif /* SQLITE_OMIT_XFER_OPT */
/* Update the sqlite_sequence table by storing the content of the /* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into ** maximum rowid counter values recorded while inserting into
** autoincrement tables. ** autoincrement tables.

View File

@@ -4080,7 +4080,7 @@ int sqlite3_test_control(int op, ...){
*/ */
case SQLITE_TESTCTRL_OPTIMIZATIONS: { case SQLITE_TESTCTRL_OPTIMIZATIONS: {
sqlite3 *db = va_arg(ap, sqlite3*); sqlite3 *db = va_arg(ap, sqlite3*);
db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff); db->dbOptFlags = va_arg(ap, u32);
break; break;
} }

View File

@@ -571,10 +571,10 @@ void sqlite3ParserReset(Parse *pParse){
pThis = pNext; pThis = pNext;
} }
while( pParse->pCleanup ){ while( pParse->pCleanup ){
ParseCleanup *pThis = pParse->pCleanup; ParseCleanup *pCleanup = pParse->pCleanup;
pParse->pCleanup = pThis->pNext; pParse->pCleanup = pCleanup->pNext;
pThis->xCleanup(db, pThis->pPtr); pCleanup->xCleanup(db, pCleanup->pPtr);
sqlite3DbFree(db, pThis); sqlite3DbFree(db, pCleanup);
} }
sqlite3DbFree(db, pParse->aLabel); sqlite3DbFree(db, pParse->aLabel);
if( pParse->pConstExpr ){ if( pParse->pConstExpr ){

View File

@@ -4640,7 +4640,11 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
assert( *ppMinMax==0 ); assert( *ppMinMax==0 );
assert( pFunc->op==TK_AGG_FUNCTION ); assert( pFunc->op==TK_AGG_FUNCTION );
assert( !IsWindowFunc(pFunc) ); assert( !IsWindowFunc(pFunc) );
if( pEList==0 || pEList->nExpr!=1 || ExprHasProperty(pFunc, EP_WinFunc) ){ if( pEList==0
|| pEList->nExpr!=1
|| ExprHasProperty(pFunc, EP_WinFunc)
|| OptimizationDisabled(db, SQLITE_MinMaxOpt)
){
return eRet; return eRet;
} }
zFunc = pFunc->u.zToken; zFunc = pFunc->u.zToken;
@@ -6580,6 +6584,10 @@ int sqlite3Select(
int ii; int ii;
SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo)); SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
sqlite3TreeViewSelect(0, p, 0); sqlite3TreeViewSelect(0, p, 0);
if( minMaxFlag ){
sqlite3DebugPrintf("MIN/MAX Optimization (0x%02x) adds:\n", minMaxFlag);
sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY");
}
for(ii=0; ii<pAggInfo->nColumn; ii++){ for(ii=0; ii<pAggInfo->nColumn; ii++){
sqlite3DebugPrintf("agg-column[%d] iMem=%d\n", sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
ii, pAggInfo->aCol[ii].iMem); ii, pAggInfo->aCol[ii].iMem);
@@ -6769,7 +6777,7 @@ int sqlite3Select(
/* End of the loop /* End of the loop
*/ */
if( groupBySort ){ if( groupBySort ){
sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx, addrTopOfLoop); sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
VdbeCoverage(v); VdbeCoverage(v);
}else{ }else{
sqlite3WhereEnd(pWInfo); sqlite3WhereEnd(pWInfo);
@@ -6881,7 +6889,6 @@ int sqlite3Select(
explainSimpleCount(pParse, pTab, pBest); explainSimpleCount(pParse, pTab, pBest);
}else{ }else{
int regAcc = 0; /* "populate accumulators" flag */ int regAcc = 0; /* "populate accumulators" flag */
int addrSkip;
/* If there are accumulator registers but no min() or max() functions /* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc ** without FILTER clauses, allocate register regAcc. Register regAcc
@@ -6930,9 +6937,8 @@ int sqlite3Select(
} }
updateAccumulator(pParse, regAcc, pAggInfo); updateAccumulator(pParse, regAcc, pAggInfo);
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
addrSkip = sqlite3WhereOrderByLimitOptLabel(pWInfo); if( minMaxFlag ){
if( addrSkip!=sqlite3WhereContinueLabel(pWInfo) ){ sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
sqlite3VdbeGoto(v, addrSkip);
} }
sqlite3WhereEnd(pWInfo); sqlite3WhereEnd(pWInfo);
finalizeAggFunctions(pParse, pAggInfo); finalizeAggFunctions(pParse, pAggInfo);

View File

@@ -2027,6 +2027,7 @@ static int shell_callback(
if( azArg==0 ) break; if( azArg==0 ) break;
for(i=0; i<nArg; i++){ for(i=0; i<nArg; i++){
int w = aExplainWidth[i]; int w = aExplainWidth[i];
if( i==nArg-1 ) w = 0;
if( azArg[i] && strlenChar(azArg[i])>w ){ if( azArg[i] && strlenChar(azArg[i])>w ){
w = strlenChar(azArg[i]); w = strlenChar(azArg[i]);
} }
@@ -9994,7 +9995,7 @@ static int do_meta_command(char *zLine, ShellState *p){
/* sqlite3_test_control(int, db, int) */ /* sqlite3_test_control(int, db, int) */
case SQLITE_TESTCTRL_OPTIMIZATIONS: case SQLITE_TESTCTRL_OPTIMIZATIONS:
if( nArg==3 ){ if( nArg==3 ){
int opt = (int)strtol(azArg[2], 0, 0); unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
rc2 = sqlite3_test_control(testctrl, p->db, opt); rc2 = sqlite3_test_control(testctrl, p->db, opt);
isOk = 3; isOk = 3;
} }

View File

@@ -1137,6 +1137,7 @@ typedef struct Bitvec Bitvec;
typedef struct CollSeq CollSeq; typedef struct CollSeq CollSeq;
typedef struct Column Column; typedef struct Column Column;
typedef struct Db Db; typedef struct Db Db;
typedef struct DbFixer DbFixer;
typedef struct Schema Schema; typedef struct Schema Schema;
typedef struct Expr Expr; typedef struct Expr Expr;
typedef struct ExprList ExprList; typedef struct ExprList ExprList;
@@ -1496,7 +1497,7 @@ struct sqlite3 {
int errCode; /* Most recent error code (SQLITE_*) */ int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */ int errMask; /* & result codes with this before returning */
int iSysErrno; /* Errno value from last system error */ int iSysErrno; /* Errno value from last system error */
u16 dbOptFlags; /* Flags to enable/disable optimizations */ u32 dbOptFlags; /* Flags to enable/disable optimizations */
u8 enc; /* Text encoding */ u8 enc; /* Text encoding */
u8 autoCommit; /* The auto-commit flag. */ u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */ u8 temp_store; /* 1: file 2: memory 0: default */
@@ -1703,24 +1704,26 @@ struct sqlite3 {
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
** selectively disable various optimizations. ** selectively disable various optimizations.
*/ */
#define SQLITE_QueryFlattener 0x0001 /* Query flattening */ #define SQLITE_QueryFlattener 0x00000001 /* Query flattening */
#define SQLITE_WindowFunc 0x0002 /* Use xInverse for window functions */ #define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */
#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_FactorOutConst 0x00000008 /* Constant factoring */
#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */ #define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */
#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */ #define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */
#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */ #define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
#define SQLITE_Transitive 0x0080 /* Transitive constraints */ #define SQLITE_Transitive 0x00000080 /* Transitive constraints */
#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */ #define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */ #define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */ #define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat4 0x0800 /* Use STAT4 data */ #define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
/* TH3 expects the Stat4 ^^^^^^ value to be 0x0800. Don't change it */ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
#define SQLITE_PushDown 0x1000 /* The push-down optimization */ #define SQLITE_PushDown 0x00001000 /* The push-down optimization */
#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */ #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan 0x4000 /* Skip-scans */ #define SQLITE_SkipScan 0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x8000 /* The constant propagation opt */ #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
#define SQLITE_AllOpts 0xffff /* All optimizations */ #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
#define SQLITE_ExistsToIN 0x00020000 /* The EXISTS-to-IN optimization */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/* /*
** Macros for testing whether or not optimizations are enabled or disabled. ** Macros for testing whether or not optimizations are enabled or disabled.
@@ -3649,21 +3652,6 @@ struct TriggerStep {
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
}; };
/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.
*/
typedef struct DbFixer DbFixer;
struct DbFixer {
Parse *pParse; /* The parsing context. Error messages written here */
Schema *pSchema; /* Fix items to this schema */
u8 bTemp; /* True for TEMP schema entries */
const char *zDb; /* Make sure all objects are contained in this database */
const char *zType; /* Type of the container - used for error messages */
const Token *pName; /* Name of the container - used for error messages */
};
/* /*
** An objected used to accumulate the text of a string where we ** An objected used to accumulate the text of a string where we
** do not necessarily know how big the string will be in the end. ** do not necessarily know how big the string will be in the end.
@@ -3814,9 +3802,25 @@ struct Walker {
struct RenameCtx *pRename; /* RENAME COLUMN context */ struct RenameCtx *pRename; /* RENAME COLUMN context */
struct Table *pTab; /* Table of generated column */ struct Table *pTab; /* Table of generated column */
struct SrcList_item *pSrcItem; /* A single FROM clause item */ struct SrcList_item *pSrcItem; /* A single FROM clause item */
DbFixer *pFix;
} u; } u;
}; };
/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.
*/
struct DbFixer {
Parse *pParse; /* The parsing context. Error messages written here */
Walker w; /* Walker object */
Schema *pSchema; /* Fix items to this schema */
u8 bTemp; /* True for TEMP schema entries */
const char *zDb; /* Make sure all objects are contained in this database */
const char *zType; /* Type of the container - used for error messages */
const Token *pName; /* Name of the container - used for error messages */
};
/* Forward declarations */ /* Forward declarations */
int sqlite3WalkExpr(Walker*, Expr*); int sqlite3WalkExpr(Walker*, Expr*);
int sqlite3WalkExprList(Walker*, ExprList*); int sqlite3WalkExprList(Walker*, ExprList*);
@@ -4343,6 +4347,7 @@ LogEst sqlite3WhereOutputRowCount(WhereInfo*);
int sqlite3WhereIsDistinct(WhereInfo*); int sqlite3WhereIsDistinct(WhereInfo*);
int sqlite3WhereIsOrdered(WhereInfo*); int sqlite3WhereIsOrdered(WhereInfo*);
int sqlite3WhereOrderByLimitOptLabel(WhereInfo*); int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*);
int sqlite3WhereIsSorted(WhereInfo*); int sqlite3WhereIsSorted(WhereInfo*);
int sqlite3WhereContinueLabel(WhereInfo*); int sqlite3WhereContinueLabel(WhereInfo*);
int sqlite3WhereBreakLabel(WhereInfo*); int sqlite3WhereBreakLabel(WhereInfo*);
@@ -4526,7 +4531,6 @@ void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqlite3FixSrcList(DbFixer*, SrcList*); int sqlite3FixSrcList(DbFixer*, SrcList*);
int sqlite3FixSelect(DbFixer*, Select*); int sqlite3FixSelect(DbFixer*, Select*);
int sqlite3FixExpr(DbFixer*, Expr*); int sqlite3FixExpr(DbFixer*, Expr*);
int sqlite3FixExprList(DbFixer*, ExprList*);
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
int sqlite3RealSameAsInt(double,sqlite3_int64); int sqlite3RealSameAsInt(double,sqlite3_int64);
void sqlite3Int64ToText(i64,char*); void sqlite3Int64ToText(i64,char*);

View File

@@ -4909,8 +4909,10 @@ case OP_NewRowid: { /* out2 */
VdbeCursor *pC; /* Cursor of table to get the new rowid */ VdbeCursor *pC; /* Cursor of table to get the new rowid */
int res; /* Result of an sqlite3BtreeLast() */ int res; /* Result of an sqlite3BtreeLast() */
int cnt; /* Counter to limit the number of searches */ int cnt; /* Counter to limit the number of searches */
#ifndef SQLITE_OMIT_AUTOINCREMENT
Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
VdbeFrame *pFrame; /* Root frame of VDBE */ VdbeFrame *pFrame; /* Root frame of VDBE */
#endif
v = 0; v = 0;
res = 0; res = 0;
@@ -5910,7 +5912,7 @@ case OP_IdxDelete: {
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
if( rc ) goto abort_due_to_error; if( rc ) goto abort_due_to_error;
}else if( pOp->p5 ){ }else if( pOp->p5 ){
rc = SQLITE_CORRUPT_INDEX; rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
goto abort_due_to_error; goto abort_due_to_error;
} }
assert( pC->deferredMoveto==0 ); assert( pC->deferredMoveto==0 );

View File

@@ -99,6 +99,32 @@ int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){
return pInner->addrNxt; return pInner->addrNxt;
} }
/*
** While generating code for the min/max optimization, after handling
** the aggregate-step call to min() or max(), check to see if any
** additional looping is required. If the output order is such that
** we are certain that the correct answer has already been found, then
** code an OP_Goto to by pass subsequent processing.
**
** Any extra OP_Goto that is coded here is an optimization. The
** correct answer should be obtained regardless. This OP_Goto just
** makes the answer appear faster.
*/
void sqlite3WhereMinMaxOptEarlyOut(Vdbe *v, WhereInfo *pWInfo){
WhereLevel *pInner;
int i;
if( !pWInfo->bOrderedInnerLoop ) return;
if( pWInfo->nOBSat==0 ) return;
for(i=pWInfo->nLevel-1; i>=0; i--){
pInner = &pWInfo->a[i];
if( (pInner->pWLoop->wsFlags & WHERE_COLUMN_IN)!=0 ){
sqlite3VdbeGoto(v, pInner->addrNxt);
return;
}
}
sqlite3VdbeGoto(v, pWInfo->iBreak);
}
/* /*
** Return the VDBE address or label to jump to in order to continue ** Return the VDBE address or label to jump to in order to continue
** immediately with the next row of a WHERE clause. ** immediately with the next row of a WHERE clause.

View File

@@ -270,11 +270,7 @@ struct WhereTerm {
#define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */ #define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */ #define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK 0x0040 /* Used during OR-clause processing */ #define TERM_OR_OK 0x0040 /* Used during OR-clause processing */
#ifdef SQLITE_ENABLE_STAT4 #define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
# define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
#else
# define TERM_VNULL 0x0000 /* Disabled if not using stat4 */
#endif
#define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */ #define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */ #define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x0400 /* The original LIKE operator */ #define TERM_LIKE 0x0400 /* The original LIKE operator */

View File

@@ -1743,6 +1743,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
SWAP(u8, nBtm, nTop); SWAP(u8, nBtm, nTop);
} }
if( iLevel>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
/* In case OP_SeekScan is used, ensure that the index cursor does not
** point to a valid row for the first iteration of this loop. */
sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
}
/* Generate code to evaluate all constraint terms using == or IN /* Generate code to evaluate all constraint terms using == or IN
** and store the values of those terms in an array of registers ** and store the values of those terms in an array of registers
** starting at regBase. ** starting at regBase.

View File

@@ -1007,6 +1007,271 @@ static int exprMightBeIndexed(
return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr); return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
} }
/*
** Expression callback for exprUsesSrclist().
*/
static int exprUsesSrclistCb(Walker *p, Expr *pExpr){
if( pExpr->op==TK_COLUMN ){
SrcList *pSrc = p->u.pSrcList;
int iCsr = pExpr->iTable;
int ii;
for(ii=0; ii<pSrc->nSrc; ii++){
if( pSrc->a[ii].iCursor==iCsr ){
return p->eCode ? WRC_Abort : WRC_Continue;
}
}
return p->eCode ? WRC_Continue : WRC_Abort;
}
return WRC_Continue;
}
/*
** Select callback for exprUsesSrclist().
*/
static int exprUsesSrclistSelectCb(Walker *p, Select *pSelect){
return WRC_Abort;
}
/*
** This function always returns true if expression pExpr contains
** a sub-select.
**
** If there is no sub-select in pExpr, then return true if pExpr
** contains a TK_COLUMN node for a table that is (bUses==1)
** or is not (bUses==0) in pSrc.
**
** Said another way:
**
** bUses Return Meaning
** -------- ------ ------------------------------------------------
**
** bUses==1 true pExpr contains either a sub-select or a
** TK_COLUMN referencing pSrc.
**
** bUses==1 false pExpr contains no sub-selects and all TK_COLUMN
** nodes reference tables not found in pSrc
**
** bUses==0 true pExpr contains either a sub-select or a TK_COLUMN
** that references a table not in pSrc.
**
** bUses==0 false pExpr contains no sub-selects and all TK_COLUMN
** nodes reference pSrc
*/
static int exprUsesSrclist(SrcList *pSrc, Expr *pExpr, int bUses){
Walker sWalker;
memset(&sWalker, 0, sizeof(Walker));
sWalker.eCode = bUses;
sWalker.u.pSrcList = pSrc;
sWalker.xExprCallback = exprUsesSrclistCb;
sWalker.xSelectCallback = exprUsesSrclistSelectCb;
return (sqlite3WalkExpr(&sWalker, pExpr)==WRC_Abort);
}
/*
** Context object used by exprExistsToInIter() as it iterates through an
** expression tree.
*/
struct ExistsToInCtx {
SrcList *pSrc; /* The tables in an EXISTS(SELECT ... FROM <here> ...) */
Expr *pInLhs; /* OUT: Use this as the LHS of the IN operator */
Expr *pEq; /* OUT: The == term that include pInLhs */
Expr **ppAnd; /* OUT: The AND operator that includes pEq as a child */
Expr **ppParent; /* The AND operator currently being examined */
};
/*
** Iterate through all AND connected nodes in the expression tree
** headed by (*ppExpr), populating the structure passed as the first
** argument with the values required by exprAnalyzeExistsFindEq().
**
** This function returns non-zero if the expression tree does not meet
** the two conditions described by the header comment for
** exprAnalyzeExistsFindEq(), or zero if it does.
*/
static int exprExistsToInIter(struct ExistsToInCtx *p, Expr **ppExpr){
Expr *pExpr = *ppExpr;
switch( pExpr->op ){
case TK_AND:
p->ppParent = ppExpr;
if( exprExistsToInIter(p, &pExpr->pLeft) ) return 1;
p->ppParent = ppExpr;
if( exprExistsToInIter(p, &pExpr->pRight) ) return 1;
break;
case TK_EQ: {
int bLeft = exprUsesSrclist(p->pSrc, pExpr->pLeft, 0);
int bRight = exprUsesSrclist(p->pSrc, pExpr->pRight, 0);
if( bLeft || bRight ){
if( (bLeft && bRight) || p->pInLhs ) return 1;
p->pInLhs = bLeft ? pExpr->pLeft : pExpr->pRight;
if( exprUsesSrclist(p->pSrc, p->pInLhs, 1) ) return 1;
p->pEq = pExpr;
p->ppAnd = p->ppParent;
}
break;
}
default:
if( exprUsesSrclist(p->pSrc, pExpr, 0) ){
return 1;
}
break;
}
return 0;
}
/*
** This function is used by exprAnalyzeExists() when creating virtual IN(...)
** terms equivalent to user-supplied EXIST(...) clauses. It splits the WHERE
** clause of the Select object passed as the first argument into one or more
** expressions joined by AND operators, and then tests if the following are
** true:
**
** 1. Exactly one of the AND separated terms refers to the outer
** query, and it is an == (TK_EQ) expression.
**
** 2. Only one side of the == expression refers to the outer query, and
** it does not refer to any columns from the inner query.
**
** If both these conditions are true, then a pointer to the side of the ==
** expression that refers to the outer query is returned. The caller will
** use this expression as the LHS of the IN(...) virtual term. Or, if one
** or both of the above conditions are not true, NULL is returned.
**
** If non-NULL is returned and ppEq is non-NULL, *ppEq is set to point
** to the == expression node before returning. If pppAnd is non-NULL and
** the == node is not the root of the WHERE clause, then *pppAnd is set
** to point to the pointer to the AND node that is the parent of the ==
** node within the WHERE expression tree.
*/
static Expr *exprAnalyzeExistsFindEq(
Select *pSel, /* The SELECT of the EXISTS */
Expr **ppEq, /* OUT: == node from WHERE clause */
Expr ***pppAnd /* OUT: Pointer to parent of ==, if any */
){
struct ExistsToInCtx ctx;
memset(&ctx, 0, sizeof(ctx));
ctx.pSrc = pSel->pSrc;
if( exprExistsToInIter(&ctx, &pSel->pWhere) ){
return 0;
}
if( ppEq ) *ppEq = ctx.pEq;
if( pppAnd ) *pppAnd = ctx.ppAnd;
return ctx.pInLhs;
}
/*
** Term idxTerm of the WHERE clause passed as the second argument is an
** EXISTS expression with a correlated SELECT statement on the RHS.
** This function analyzes the SELECT statement, and if possible adds an
** equivalent "? IN(SELECT...)" virtual term to the WHERE clause.
**
** For an EXISTS term such as the following:
**
** EXISTS (SELECT ... FROM <srclist> WHERE <e1> = <e2> AND <e3>)
**
** The virtual IN() term added is:
**
** <e1> IN (SELECT <e2> FROM <srclist> WHERE <e3>)
**
** The virtual term is only added if the following conditions are met:
**
** 1. The sub-select must not be an aggregate or use window functions,
**
** 2. The sub-select must not be a compound SELECT,
**
** 3. Expression <e1> must refer to at least one column from the outer
** query, and must not refer to any column from the inner query
** (i.e. from <srclist>).
**
** 4. <e2> and <e3> must not refer to any values from the outer query.
** In other words, once <e1> has been removed, the inner query
** must not be correlated.
**
*/
static void exprAnalyzeExists(
SrcList *pSrc, /* the FROM clause */
WhereClause *pWC, /* the WHERE clause */
int idxTerm /* Index of the term to be analyzed */
){
Parse *pParse = pWC->pWInfo->pParse;
WhereTerm *pTerm = &pWC->a[idxTerm];
Expr *pExpr = pTerm->pExpr;
Select *pSel = pExpr->x.pSelect;
Expr *pDup = 0;
Expr *pEq = 0;
Expr *pRet = 0;
Expr *pInLhs = 0;
Expr **ppAnd = 0;
int idxNew;
sqlite3 *db = pParse->db;
assert( pExpr->op==TK_EXISTS );
assert( (pExpr->flags & EP_VarSelect) && (pExpr->flags & EP_xIsSelect) );
if( (pSel->selFlags & SF_Aggregate) || pSel->pWin ) return;
if( pSel->pPrior ) return;
if( pSel->pWhere==0 ) return;
if( 0==exprAnalyzeExistsFindEq(pSel, 0, 0) ) return;
pDup = sqlite3ExprDup(db, pExpr, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pDup);
return;
}
pSel = pDup->x.pSelect;
sqlite3ExprListDelete(db, pSel->pEList);
pSel->pEList = 0;
pInLhs = exprAnalyzeExistsFindEq(pSel, &pEq, &ppAnd);
assert( pInLhs && pEq );
assert( pEq==pSel->pWhere || ppAnd );
if( pInLhs==pEq->pLeft ){
pRet = pEq->pRight;
}else{
CollSeq *p = sqlite3ExprCompareCollSeq(pParse, pEq);
pInLhs = sqlite3ExprAddCollateString(pParse, pInLhs, p?p->zName:"BINARY");
pRet = pEq->pLeft;
}
assert( pDup->pLeft==0 );
pDup->op = TK_IN;
pDup->pLeft = pInLhs;
pDup->flags &= ~EP_VarSelect;
if( pRet->op==TK_VECTOR ){
pSel->pEList = pRet->x.pList;
pRet->x.pList = 0;
sqlite3ExprDelete(db, pRet);
}else{
pSel->pEList = sqlite3ExprListAppend(pParse, 0, pRet);
}
pEq->pLeft = 0;
pEq->pRight = 0;
if( ppAnd ){
Expr *pAnd = *ppAnd;
Expr *pOther = (pAnd->pLeft==pEq) ? pAnd->pRight : pAnd->pLeft;
pAnd->pLeft = pAnd->pRight = 0;
sqlite3ExprDelete(db, pAnd);
*ppAnd = pOther;
}else{
assert( pSel->pWhere==pEq );
pSel->pWhere = 0;
}
sqlite3ExprDelete(db, pEq);
#ifdef WHERETRACE_ENABLED /* 0x20 */
if( sqlite3WhereTrace & 0x20 ){
sqlite3DebugPrintf("Convert EXISTS:\n");
sqlite3TreeViewExpr(0, pExpr, 0);
sqlite3DebugPrintf("into IN:\n");
sqlite3TreeViewExpr(0, pDup, 0);
}
#endif
idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew);
markTermAsChild(pWC, idxNew, idxTerm);
pWC->a[idxTerm].wtFlags |= TERM_COPIED;
}
/* /*
** The input to this routine is an WhereTerm structure with only the ** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in. The job of this routine is to analyze the ** "pExpr" field filled in. The job of this routine is to analyze the
@@ -1192,6 +1457,52 @@ static void exprAnalyze(
} }
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ #endif /* SQLITE_OMIT_OR_OPTIMIZATION */
else if( pExpr->op==TK_EXISTS ){
/* Perhaps treat an EXISTS operator as an IN operator */
if( (pExpr->flags & EP_VarSelect)!=0
&& OptimizationEnabled(db, SQLITE_ExistsToIN)
){
exprAnalyzeExists(pSrc, pWC, idxTerm);
}
}
/* The form "x IS NOT NULL" can sometimes be evaluated more efficiently
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
** virtual term of that form.
**
** The virtual term must be tagged with TERM_VNULL.
*/
else if( pExpr->op==TK_NOTNULL ){
if( pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
&& !ExprHasProperty(pExpr, EP_FromJoin)
){
Expr *pNewExpr;
Expr *pLeft = pExpr->pLeft;
int idxNew;
WhereTerm *pNewTerm;
pNewExpr = sqlite3PExpr(pParse, TK_GT,
sqlite3ExprDup(db, pLeft, 0),
sqlite3ExprAlloc(db, TK_NULL, 0, 0));
idxNew = whereClauseInsert(pWC, pNewExpr,
TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
if( idxNew ){
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = 0;
pNewTerm->leftCursor = pLeft->iTable;
pNewTerm->u.x.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_GT;
markTermAsChild(pWC, idxNew, idxTerm);
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_COPIED;
pNewTerm->prereqAll = pTerm->prereqAll;
}
}
}
#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION #ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
/* Add constraints to reduce the search space on a LIKE or GLOB /* Add constraints to reduce the search space on a LIKE or GLOB
** operator. ** operator.
@@ -1206,7 +1517,8 @@ static void exprAnalyze(
** bound is made all lowercase so that the bounds also work when comparing ** bound is made all lowercase so that the bounds also work when comparing
** BLOBs. ** BLOBs.
*/ */
if( pWC->op==TK_AND else if( pExpr->op==TK_FUNCTION
&& pWC->op==TK_AND
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase) && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
){ ){
Expr *pLeft; /* LHS of LIKE/GLOB operator */ Expr *pLeft; /* LHS of LIKE/GLOB operator */
@@ -1276,6 +1588,65 @@ static void exprAnalyze(
} }
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
/* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create
** new terms for each component comparison - "a = ?" and "b = ?". The
** new terms completely replace the original vector comparison, which is
** no longer used.
**
** This is only required if at least one side of the comparison operation
** is not a sub-select. */
if( (pExpr->op==TK_EQ || pExpr->op==TK_IS)
&& (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
&& sqlite3ExprVectorSize(pExpr->pRight)==nLeft
&& ( (pExpr->pLeft->flags & EP_xIsSelect)==0
|| (pExpr->pRight->flags & EP_xIsSelect)==0)
&& pWC->op==TK_AND
){
int i;
for(i=0; i<nLeft; i++){
int idxNew;
Expr *pNew;
Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
transferJoinMarkings(pNew, pExpr);
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew);
}
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */
pTerm->eOperator = 0;
}
/* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
** a virtual term for each vector component. The expression object
** used by each such virtual term is pExpr (the full vector IN(...)
** expression). The WhereTerm.u.x.iField variable identifies the index within
** the vector on the LHS that the virtual term represents.
**
** This only works if the RHS is a simple SELECT (not a compound) that does
** not use window functions.
*/
else if( pExpr->op==TK_IN
&& pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
&& pExpr->x.pSelect->pWin==0
#endif
&& pWC->op==TK_AND
){
int i;
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
int idxNew;
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
pWC->a[idxNew].u.x.iField = i+1;
exprAnalyze(pSrc, pWC, idxNew);
markTermAsChild(pWC, idxNew, idxTerm);
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
/* Add a WO_AUX auxiliary term to the constraint set if the /* Add a WO_AUX auxiliary term to the constraint set if the
** current expression is of the form "column OP expr" where OP ** current expression is of the form "column OP expr" where OP
@@ -1286,7 +1657,7 @@ static void exprAnalyze(
** virtual tables. The native query optimizer does not attempt ** virtual tables. The native query optimizer does not attempt
** to do anything with MATCH functions. ** to do anything with MATCH functions.
*/ */
if( pWC->op==TK_AND ){ else if( pWC->op==TK_AND ){
Expr *pRight = 0, *pLeft = 0; Expr *pRight = 0, *pLeft = 0;
int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight); int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight);
while( res-- > 0 ){ while( res-- > 0 ){
@@ -1322,102 +1693,6 @@ static void exprAnalyze(
} }
#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_VIRTUALTABLE */
/* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create
** new terms for each component comparison - "a = ?" and "b = ?". The
** new terms completely replace the original vector comparison, which is
** no longer used.
**
** This is only required if at least one side of the comparison operation
** is not a sub-select. */
if( pWC->op==TK_AND
&& (pExpr->op==TK_EQ || pExpr->op==TK_IS)
&& (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
&& sqlite3ExprVectorSize(pExpr->pRight)==nLeft
&& ( (pExpr->pLeft->flags & EP_xIsSelect)==0
|| (pExpr->pRight->flags & EP_xIsSelect)==0)
){
int i;
for(i=0; i<nLeft; i++){
int idxNew;
Expr *pNew;
Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
transferJoinMarkings(pNew, pExpr);
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew);
}
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */
pTerm->eOperator = 0;
}
/* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
** a virtual term for each vector component. The expression object
** used by each such virtual term is pExpr (the full vector IN(...)
** expression). The WhereTerm.u.x.iField variable identifies the index within
** the vector on the LHS that the virtual term represents.
**
** This only works if the RHS is a simple SELECT (not a compound) that does
** not use window functions.
*/
if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
&& pExpr->x.pSelect->pWin==0
#endif
){
int i;
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
int idxNew;
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
pWC->a[idxNew].u.x.iField = i+1;
exprAnalyze(pSrc, pWC, idxNew);
markTermAsChild(pWC, idxNew, idxTerm);
}
}
#ifdef SQLITE_ENABLE_STAT4
/* When sqlite_stat4 histogram data is available an operator of the
** form "x IS NOT NULL" can sometimes be evaluated more efficiently
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
** virtual term of that form.
**
** Note that the virtual term must be tagged with TERM_VNULL.
*/
if( pExpr->op==TK_NOTNULL
&& pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
&& !ExprHasProperty(pExpr, EP_FromJoin)
&& OptimizationEnabled(db, SQLITE_Stat4)
){
Expr *pNewExpr;
Expr *pLeft = pExpr->pLeft;
int idxNew;
WhereTerm *pNewTerm;
pNewExpr = sqlite3PExpr(pParse, TK_GT,
sqlite3ExprDup(db, pLeft, 0),
sqlite3ExprAlloc(db, TK_NULL, 0, 0));
idxNew = whereClauseInsert(pWC, pNewExpr,
TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
if( idxNew ){
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = 0;
pNewTerm->leftCursor = pLeft->iTable;
pNewTerm->u.x.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_GT;
markTermAsChild(pWC, idxNew, idxTerm);
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_COPIED;
pNewTerm->prereqAll = pTerm->prereqAll;
}
}
#endif /* SQLITE_ENABLE_STAT4 */
/* Prevent ON clause terms of a LEFT JOIN from being used to drive /* Prevent ON clause terms of a LEFT JOIN from being used to drive
** an index for tables to the left of the join. ** an index for tables to the left of the join.
*/ */

View File

@@ -253,7 +253,7 @@ do_execsql_test 11.1 {
do_catchsql_test 11.2 { do_catchsql_test 11.2 {
ALTER TABLE t1 RENAME TO t1x; ALTER TABLE t1 RENAME TO t1x;
} {1 {error in trigger b: no such table: abc}} } {1 {error in trigger b: no such table: main.abc}}
do_execsql_test 11.3 { do_execsql_test 11.3 {
DROP TRIGGER b; DROP TRIGGER b;

View File

@@ -21,7 +21,7 @@ source $testdir/tester.tcl
# Only run these tests if memory debugging is turned on. # Only run these tests if memory debugging is turned on.
# #
ifcapable !crashtest||!memorymanage { ifcapable !crashtest||!memorymanage {
puts "Skipping crash5 tests: not compiled with -DSQLITE_MEMDEBUG..." puts "Skipping crash5 tests: not compiled with -DSQLITE_ENABLE_MEMORY_MANAGEMENT..."
finish_test finish_test
return return
} }
@@ -49,8 +49,14 @@ for {set ii 0} {$ii < 10} {incr ii} {
[list set iFail $jj] { [list set iFail $jj] {
proc get_pwd {} { proc get_pwd {} {
if {$::tcl_platform(platform) eq "windows"} { if {$::tcl_platform(platform) eq "windows"} {
if {[info exists ::env(ComSpec)]} {
set comSpec $::env(ComSpec)
} else {
# NOTE: Hard-code the typical default value.
set comSpec {C:\Windows\system32\cmd.exe}
}
return [string map [list \\ /] \ return [string map [list \\ /] \
[string trim [exec -- $::env(ComSpec) /c echo %CD%]]] [string trim [exec -- $comSpec /c echo %CD%]]]
} else { } else {
return [pwd] return [pwd]
} }

188
test/exists2.test Normal file
View File

@@ -0,0 +1,188 @@
# 2021 January 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing cases where EXISTS expressions are
# transformed to IN() expressions by where.c
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix exists2
do_execsql_test 1.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(2, 'two');
INSERT INTO t1 VALUES(3, 'three');
INSERT INTO t1 VALUES(4, 'four');
INSERT INTO t1 VALUES(5, 'five');
INSERT INTO t1 VALUES(6, 'six');
INSERT INTO t1 VALUES(7, 'seven');
CREATE TABLE t2(c INTEGER, d INTEGER);
INSERT INTO t2 VALUES(1, 1);
INSERT INTO t2 VALUES(3, 2);
INSERT INTO t2 VALUES(5, 3);
INSERT INTO t2 VALUES(7, 4);
}
proc do_execsql_eqp_test {tn sql eqp res} {
uplevel [list do_eqp_test $tn.1 $sql [string trim $eqp]]
uplevel [list do_execsql_test $tn.2 $sql $res]
}
do_execsql_eqp_test 1.1 {
SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t1.a=t2.c);
} {
USING INTEGER PRIMARY KEY
} {
1 one 3 three 5 five 7 seven
}
do_execsql_eqp_test 1.2 {
SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c=t1.a);
} {
SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
1 one 3 three 5 five 7 seven
}
do_execsql_eqp_test 1.3 {
SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a);
} {
SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
2 two 4 four 6 six
}
do_execsql_eqp_test 1.4 {
SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a+1);
} {
SCAN TABLE t1
} {
1 one 3 three 5 five 7 seven
}
do_execsql_eqp_test 1.5 {
SELECT t1.* FROM t1 WHERE EXISTS(
SELECT * FROM t2 WHERE t1.a=t2.c AND d IN (1, 2, 3)
);
} {
SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
1 one 3 three 5 five
}
do_execsql_eqp_test 1.6 {
SELECT t1.* FROM t1 WHERE EXISTS(
SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c
);
} {
SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
1 one 3 three 5 five
}
do_execsql_eqp_test 1.7 {
SELECT t1.* FROM t1 WHERE EXISTS(
SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c
);
} {
SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
1 one 3 three 5 five
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 2.0 {
CREATE TABLE t3(a TEXT PRIMARY KEY, b TEXT, x INT) WITHOUT ROWID;
CREATE TABLE t4(c TEXT COLLATE nocase, y INT);
INSERT INTO t3 VALUES('one', 'i', 1);
INSERT INTO t3 VALUES('two', 'ii', 2);
INSERT INTO t3 VALUES('three', 'iii', 3);
INSERT INTO t3 VALUES('four', 'iv', 4);
INSERT INTO t3 VALUES('five', 'v', 5);
INSERT INTO t4 VALUES('FIVE',5), ('four',4), ('TWO',2), ('one',1);
}
do_execsql_test 2.1 { SELECT a FROM t3, t4 WHERE a=c } {four one}
do_execsql_test 2.2 { SELECT a FROM t3, t4 WHERE c=a } {five four one two}
do_execsql_eqp_test 2.3 {
SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
} {
SEARCH TABLE t3 USING PRIMARY KEY
} {
four one
}
do_execsql_eqp_test 2.4 {
SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
} {
SCAN TABLE t3
} {
five four one two
}
do_execsql_test 2.5 {
CREATE INDEX t3anc ON t3(a COLLATE nocase, x);
}
do_execsql_eqp_test 2.6 {
SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
} {
SEARCH TABLE t3 USING COVERING INDEX t3anc
} {
five four one two
}
do_execsql_test 2.6a {
SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (c,y)=(a,x))
} {five four one two}
do_execsql_eqp_test 2.7 {
SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
} {
SEARCH TABLE t3 USING PRIMARY KEY
} {
four one
}
do_execsql_test 2.7a {
SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (a,x)=(c,y))
} {
four one
}
# EXISTS clauses using vector expressions in the WHERE clause.
#
reset_db
do_execsql_test 3.0 {
CREATE TABLE t1(a,b);
INSERT INTO t1(a,b) VALUES(1,111),(2,222),(8,888);
CREATE TABLE t2(x INTEGER PRIMARY KEY, y);
INSERT INTO t2(x,y) VALUES(2,222),(3,333),(7,333);
SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,y)=(a,b));
} {222}
do_execsql_test 3.1 {
SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (a,b)=(x,y));
} {222}
do_execsql_test 3.2 {
SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,b)=(a,y));
} {222}
finish_test

52
test/existsfault.test Normal file
View File

@@ -0,0 +1,52 @@
# 2021 January 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing cases where EXISTS expressions are
# transformed to IN() expressions by where.c
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix existsfault
do_execsql_test 1 {
CREATE TABLE t1(a PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(2, 'two');
INSERT INTO t1 VALUES(3, 'three');
INSERT INTO t1 VALUES(4, 'four');
INSERT INTO t1 VALUES(5, 'five');
INSERT INTO t1 VALUES(6, 'six');
INSERT INTO t1 VALUES(7, 'seven');
CREATE TABLE t2(c INTEGER, d INTEGER);
INSERT INTO t2 VALUES(1, 1);
INSERT INTO t2 VALUES(3, 2);
INSERT INTO t2 VALUES(5, 3);
INSERT INTO t2 VALUES(7, 4);
}
faultsim_save_and_close
do_faultsim_test 1 -prep {
faultsim_restore_and_reopen
} -body {
execsql {
SELECT t1.* FROM t1 WHERE EXISTS(
SELECT * FROM t2 WHERE t2.c=t1.a AND d IN (1, 2, 3)
)
}
} -test {
faultsim_test_result {0 {1 one 3 three 5 five}}
}
finish_test

View File

@@ -365,4 +365,32 @@ ifcapable rtree {
} {{} 1 {} {} {}} } {{} 1 {} {} {}}
} }
#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
CREATE UNIQUE INDEX t1y ON t1(y);
INSERT INTO t1 VALUES(111, 'AAA'),(222, 'BBB'),(333, 'CCC');
CREATE TABLE t2(z);
INSERT INTO t2 VALUES('BBB'),('AAA');
ANALYZE sqlite_schema;
INSERT INTO sqlite_stat1 VALUES('t1', 't1y','100 1');
}
db close
sqlite3 db test.db
do_execsql_test 8.1 {
SELECT t1.x FROM t2 CROSS JOIN t1 WHERE t2.z = t1.y;
} {222 111}
do_execsql_test 8.2 {
SELECT t1.x FROM t2 CROSS JOIN t1 WHERE t2.z = t1.y AND +t1.x IN (111, 222);
} {222 111}
do_execsql_test 8.3 {
SELECT t1.x FROM t2 CROSS JOIN t1 WHERE t2.z = t1.y AND t1.x IN (111, 222);
} {222 111}
finish_test finish_test

View File

@@ -174,8 +174,14 @@ proc get_pwd {} {
# case of the result to what Tcl considers canonical, which would # case of the result to what Tcl considers canonical, which would
# defeat the purpose of this procedure. # defeat the purpose of this procedure.
# #
if {[info exists ::env(ComSpec)]} {
set comSpec $::env(ComSpec)
} else {
# NOTE: Hard-code the typical default value.
set comSpec {C:\Windows\system32\cmd.exe}
}
return [string map [list \\ /] \ return [string map [list \\ /] \
[string trim [exec -- $::env(ComSpec) /c echo %CD%]]] [string trim [exec -- $comSpec /c echo %CD%]]]
} else { } else {
return [pwd] return [pwd]
} }

View File

@@ -58,6 +58,8 @@ foreach {tn defn} {
8 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = ?; END; } 8 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = ?; END; }
9 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = 1 WHERE d = ?; END; } 9 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = 1 WHERE d = ?; END; }
10 { AFTER INSERT ON t1 BEGIN SELECT * FROM pragma_stats(?); END; } 10 { AFTER INSERT ON t1 BEGIN SELECT * FROM pragma_stats(?); END; }
11 { BEFORE INSERT ON t1 BEGIN
INSERT INTO t1 SELECT max(b) OVER(ORDER BY $1) FROM t1; END }
} { } {
catchsql {drop trigger tr1} catchsql {drop trigger tr1}
do_catchsql_test 1.1.$tn "CREATE TRIGGER tr1 $defn" [list 1 $errmsg] do_catchsql_test 1.1.$tn "CREATE TRIGGER tr1 $defn" [list 1 $errmsg]