1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-10-28 10:57:26 +03:00

Merge the 3.39.0 release candidate 1 changes into the reuse-schema branch.

FossilOrigin-Name: 506a3e6f242f42d3106f80ad4385a5ef458461fbd056258e65c82dd4e0a80e8c
This commit is contained in:
drh
2022-06-24 16:15:20 +00:00
22 changed files with 405 additions and 135 deletions

View File

@@ -733,4 +733,27 @@ do_execsql_test 19.1 {
SELECT v0.x FROM v0, rt0 WHERE v0.x = rt0.b;
} {0.0}
# 2022-06-20 https://sqlite.org/forum/forumpost/57bdf2217d
#
reset_db
do_execsql_test 20.0 {
CREATE VIRTUAL TABLE rt0 USING rtree(id, x0, x1);
CREATE TABLE t0(a INT);
CREATE TABLE t1(b INT);
INSERT INTO rt0 VALUES(0, 0, 0);
}
do_catchsql_test 20.1 {
SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE +x0 = 0;
} {1 {ON clause references tables to its right}}
do_catchsql_test 20.2 {
SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE x0 = 0;
} {1 {ON clause references tables to its right}}
db null -
do_execsql_test 20.3 {
SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE +x0 = 0;
} {- - 0 0.0 0.0}
do_execsql_test 20.4 {
SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE x0 = 0;
} {- - 0 0.0 0.0}
finish_test

View File

@@ -1,5 +1,5 @@
C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sreuse-schema\sbranch.
D 2022-06-16T13:57:58.147
C Merge\sthe\s3.39.0\srelease\scandidate\s1\schanges\sinto\sthe\sreuse-schema\sbranch.
D 2022-06-24T16:15:20.115
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -417,7 +417,7 @@ F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/geopoly.c cc3f89c11abcf114fa60d74709ae8b5bc1eae5a261b30bc1bb7085089c03bfab
F ext/rtree/rtree.c d7b4b8b81d8d54376a7f81de5be85ec58b37c11604bcf42984a8418b34158d93
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 35c3bc0def71317b7601ee0d1149e7df2cd8fc4f13ec89a64761ac3f46ca123f
F ext/rtree/rtree1.test d47f58832145fcfed9067bc457ca8664962196c4566c17a1ebd679367db55d11
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
@@ -511,7 +511,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c cc49f394c156f101ff12449a21ec1478f60e1bbd287fbf5fec8c2322dc55cccd
F src/btree.c b5a74c39d3123dadd190019c0afadd7f62b43dfe0712a39e9d0ff2fe26be5d93
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btreeInt.h 8ce1332edd89dfd2461d561ac10a0ab5601c8e06200cb5230596c3caaf54482e
F src/build.c 255067b8c8480a1ce8c6e37b581028d662751ea5141ff6426b72a369658bc708
@@ -569,9 +569,9 @@ F src/pragma.h 50f6d3b408ed56bde4f4e4aead8c0b2022030b692e8de237c1b7a0b5ce87a0c8
F src/prepare.c d91f59db086b7b738ada7f06c1c09e151a40ca219565d1937da3968b299166e6
F src/printf.c 6166a30417b05c5b2f82e1f183f75faa2926ad60531c0b688a57dbc951441a20
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c a4eb3c617027fd049b07432f3b942ea7151fa793a332a11a7d0f58c9539e104f
F src/resolve.c 1655e44c77c51ebbe82924287528a78bd4a4aaaf34189dbae28d19ccf2ca615c
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c ee3113de67330163a35307eacb4188b6778fcae1e2d2f738a9dda2daa0346e24
F src/select.c 2db8bbf13f57cc9872f9b927546e98f5ea583e9e364182426492a434a994421b
F src/shell.c.in a3b9c4725ab245a6532f095258ca37c3e6d678f47bc7e0bb3f036ca6ac710609
F src/sqlite.h.in 625ce4544e658f8a9e64d5f07fe632c7a86ef62ef2dafeb4671cda56ee273feb
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@@ -637,18 +637,18 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c a38f52058b517929e264094abd0b5fd1e8e145a1aa43bc6f6a72ae5218f96c98
F src/treeview.c c48bbb4b04a951dcecf95b464d0fe94930339af56688a77f18ee50a526bc1706
F src/treeview.c 0bd550f5974565eba541db339906be7a3f9e91beafb879cb40705382887f08e1
F src/trigger.c 45a863a534dea1744642bfb68da2441333179252b16f0cacf8d4c52172378b18
F src/update.c c52a7991bece0453d22c77c08469512ee2f1391c12503fd347d1c939220c5877
F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 602fe229f32a96ceccae4f40824129669582096f7c355f53dbac156c9fecef23
F src/vacuum.c 50f980eee45f25faf1faedc5be27a561c0df086e27bef12618485f10b3bae40b
F src/vdbe.c 0e1db512c8cddd8c7d5cbd3dd2137497582fd81994a1c117f61b94277da084d6
F src/vdbe.c e8793796792a70d9aab3560f8fb1c25f51d60d64bcb7c3f03be35823d81d156a
F src/vdbe.h f521a8218438c6c41e84276ac668c1c3a5bf530e37d20d1021e8c8af533ea69e
F src/vdbeInt.h 2cad0aeeb106371ed0e0946bab89f60627087068847afc2451c05056961c18da
F src/vdbeapi.c 354c893f1500cf524cc45c32879b9c68893a28b77e3442c24668d6afe4236217
F src/vdbeaux.c 89d9ac1b6e00bf0509f09da5abcf4547cbe10abb7ff0c736c556d319b488232d
F src/vdbeapi.c 602610f1252d59cd69742f78a1e2f6fbae40a4b407f5506a6a7b869b0df08ff2
F src/vdbeaux.c bba838cf3d368019f0bea9eccd80c23d6affa6d8dd3442ae297933cc75cac301
F src/vdbeblob.c aa23a326ff86bdde8f7ba74cf23c3e1795b13bee749314feaf26273be2f63e89
F src/vdbemem.c 3db315458f8dc158aff58719795441437dd6c0fd302e9d9379a8f2a61e185ad6
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
@@ -659,10 +659,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
F src/where.c 267caa227dd38ede46959468118ef4067316dae589d889c200911ff77df53ef1
F src/where.c 9a44063e60d8f42dd9dc8147b8e8dcfc315bbd13e25c395211292c36d828c869
F src/whereInt.h b48ca529ffe293c18cbfa8326af18a09e39910de66fb3e96ef788c7cbf8ef3a7
F src/wherecode.c 0b09abfcb88c61c6a6984a3e065786631ff35495e9bdf865e6b74ab0a1299c5b
F src/whereexpr.c 20255cf03e0b765b742301197d165511ff99e95da0d7ee9c8a2ebc1e888dd049
F src/whereexpr.c 55a39f42aaf982574fbf52906371a84cceed98a994422198dfd03db4fce4cc46
F src/window.c fff1b51757438c664e471d5184634e48dcdf8ea34b640f3b1b0810b1e06de18c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@@ -840,7 +840,7 @@ F test/corruptL.test ecce40d7b9b909a670a42a45d86e30d927735d7e7f09041af438b19529d
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
F test/corruptN.test 60b5a62944b4f0029ba07edaa5fd8e670539d6b0a8d99db26c068d435675cbfe
F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576
F test/count.test 013d64569c15563c59472d17ec4ddc681034aaee65e8b01880bc88315fd4c673
F test/count.test cd4bd531066e8d77ef8fe1e3fc8253d042072e117ccab214b290cf83f1602249
F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
F test/coveridxscan.test f35c7208dedc4f98e471c569df64c0f95a49f6e072d8dc7c8f99bdee2697de1b
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
@@ -905,7 +905,7 @@ F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test c927f7499dc3aa28b9b556b7d6d115a2f0fe41f012b128d16bf1f3b30e9b41e4
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
F test/e_uri.test a3d30c7d6d7700150055b6660ee42da7f05dee2c150ce08bf6a9ededc26468cc
F test/e_vacuum.test 0d8832a2ce92350db0d0cff47b419465fd9772562e1f77ff7d9478c07a4980d2
F test/e_vacuum.test 89fc48e8beee2f9dfd6de1fbb2edea6542dae9121dc0fbe6313764169e742104
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
@@ -1087,7 +1087,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c 609152902fb51e718554719f44d13677f68c53d98d15fb359fbefdd134be153b
F test/fuzzcheck.c 7b501d55631c2d759e0bed02ed329904a35690fc6563d7b6cc69b7788a024f26
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1099,7 +1099,7 @@ F test/fuzzdata8.db ca9a97f401b06b0d5376139ec7e1f9e773e13345a9a2d9ccc0032cdbfede
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
F test/fuzzinvariants.c cd5a4c9b891a5c843e0f97a513c095490e974f1ea51392b13c0a7d77fff8e46d
F test/fuzzinvariants.c c1c7ae6be4c5fe4e5b845ce2b166c17a3d0f8ef545ab0248c9990505010070da
F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
F test/gencol1.test cc0dbb0ee116e5602e18ea7d47f2a0f76b26e09a823b7c36ef254370c2b0f3c1
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@@ -1170,7 +1170,7 @@ F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test d22b6cba8fb59ab3f1c82701434c360705eb12d4ce200c449f37b018fc47681a
F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
F test/join7.test 2268dcbb54b724391dda3748ea95c60d960607ffeed67885675998e7117697f6
F test/join8.test e3c8ca1419e3519596a7ef129246ed118d2508b1ebb69ea83b51ea0eda32037c
F test/join8.test d0e75bf880a1b1ee8fda57d8187170c5b2ff0c0cd0e1d6d474faa99fe1283d8d
F test/join9.test 9056ddd3b0c0f4f9d658f4521038d9a37dc23ead8ca9a505d0b0db2b6a471e05
F test/joinA.test 7eab225dc1c1ab258a5e62513a4ed7cabbd3db971d59d5d92f4fb6fa14c12f6a
F test/joinB.test 1b2ba3fc8568b49411787fccbf540570c148e9b6a53a30f80691cb6268098ded
@@ -1178,6 +1178,7 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
F test/joinD.test 1a430af8dac5b68663f13df534ffe98775e582bac2305b80f1e8eb4ab778672a
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test e67d1d6a8c7141caf981a07386caa7fda0362baa09e03669f9a4fbee812806d0
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
@@ -1398,7 +1399,7 @@ F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2f
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test 692e84cfa29c405854c69e8a4027183d64c22952866a123fabbce741a379e889
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test c49fbb758903f3718e2de5aa4655eda4838131cbea24a86db908f8b6889aa68c
F test/select3.test 399a0b23f8618bfe07ea24fb67f2952f620d6eba662bccabf6f4f71c2d89e6c9
F test/select4.test f0684d3da3bccacbe2a1ebadf6fb49d9df6f53acb4c6ebc228a88d0d6054cc7b
F test/select5.test 8afc5e5dcdebc2be54472e73ebd9cd1adef1225fd15d37a1c62f969159f390ae
F test/select6.test 9b2fb4ffedf52e1b5703cfcae1212e7a4a063f014c0458d78d29aca3db766d1f
@@ -1840,7 +1841,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 18aadea36d7a9fab1474b1d80002d82304a342e0471793841c66afde14a381b8
F test/window1.test ae87c4ea4e689725c7e1c826ab2b10704d5b6d31f9b9e5abadded996ba53a1d4
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@@ -1892,7 +1893,7 @@ F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/dbhash.c 5da0c61032d23d74f2ab84ffc5740f0e8abec94f2c45c0b4306be7eb3ae96df0
F tool/dbtotxt.c b2221864a20fb391c46bd31bc1fbdc4a96f5c8a89bef58f421eb9b9c36b1702c
F tool/dbtotxt.c 2620a354d109b70d71bf758d2a64e042d74e0aaa5bd6e447900ed3542410d7f9
F tool/dbtotxt.md c9a57af8739957ef36d2cfad5c4b1443ff3688ed33e4901ee200c8b651f43f3c
F tool/enlargedb.c 3e8b2612b985cfa7e3e8800031ee191b43ae80de96abb5abbd5eada62651ee21
F tool/extract-sqlite3h.tcl 069ceab0cee26cba99952bfa08c0b23e35941c837acabe143f0c355d96c9e2eb x
@@ -1951,7 +1952,7 @@ F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c
F tool/split-sqlite3c.tcl 6b02bb5444cabc477c0d6eb3ecedcc827063e9ac41954831e90c72c481aa9d30
F tool/sqldiff.c 4f967c199c5f93eec64978e3a625d6c07fb1162212b1d48f65740d9eb4607eee
F tool/sqlite3_analyzer.c.in f88615bf33098945e0a42f17733f472083d150b58bdaaa5555a7129d0a51621c
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
@@ -1987,8 +1988,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 4d46296ef6c2e7d63d2d2dc59af1e7d62c951b3c40784688811a6b4f230fc869 3a461f61b47e6ba6d5dcc2b7470ebde512b57bc68086f65050e07b06f42b7351
R 2b209feb8fa61a4d12d9541697eecb2d
P 7f405fe209d141435562b69ff161a545c63c5804f7de37871d24d7b6ee80ecec e93fd170ce4ae91d572c46d03f68f55d00091d0188030517455017d90d212587
R f49e1c8881997b8ad28c72b3c51eb2f2
U drh
Z 53d88be798f8ef43005ea95c115c0ad2
Z f28042d46818ae2d322f4229ce34dcd1
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
7f405fe209d141435562b69ff161a545c63c5804f7de37871d24d7b6ee80ecec
506a3e6f242f42d3106f80ad4385a5ef458461fbd056258e65c82dd4e0a80e8c

View File

@@ -5847,6 +5847,9 @@ int sqlite3BtreeIndexMoveto(
&& pIdxKey->errCode==SQLITE_OK
){
pCur->curFlags &= ~BTCF_ValidOvfl;
if( !pCur->pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
goto bypass_moveto_root; /* Start search on the current page */
}
pIdxKey->errCode = SQLITE_OK;

View File

@@ -1824,8 +1824,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
sNC.uNC.pEList = p->pEList;
sNC.ncFlags |= NC_UEList;
if( p->pHaving ){
if( !pGroupBy ){
sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
if( (p->selFlags & SF_Aggregate)==0 ){
sqlite3ErrorMsg(pParse, "HAVING clause on a non-aggregate query");
return WRC_Abort;
}
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;

View File

@@ -424,11 +424,13 @@ void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
}
}
/* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every
** term that is marked with EP_OuterON and w.iJoin==iTable into
** an ordinary term that omits the EP_OuterON mark.
/* Undo the work of sqlite3SetJoinExpr(). This is used when a LEFT JOIN
** is simplified into an ordinary JOIN, and when an ON expression is
** "pushed down" into the WHERE clause of a subquery.
**
** This happens when a LEFT JOIN is simplified into an ordinary JOIN.
** Convert every term that is marked with EP_OuterON and w.iJoin==iTable into
** an ordinary term that omits the EP_OuterON mark. Or if iTable<0, then
** just clear every EP_OuterON and EP_InnerON mark from the expression tree.
**
** If nullable is true, that means that Expr p might evaluate to NULL even
** if it is a reference to a NOT NULL column. This can happen, for example,
@@ -438,10 +440,9 @@ void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
*/
static void unsetJoinExpr(Expr *p, int iTable, int nullable){
while( p ){
if( ExprHasProperty(p, EP_OuterON)
&& (iTable<0 || p->w.iJoin==iTable) ){
ExprClearProperty(p, EP_OuterON);
ExprSetProperty(p, EP_InnerON);
if( iTable<0 || (ExprHasProperty(p, EP_OuterON) && p->w.iJoin==iTable) ){
ExprClearProperty(p, EP_OuterON|EP_InnerON);
if( iTable>=0 ) ExprSetProperty(p, EP_InnerON);
}
if( p->op==TK_COLUMN && p->iTable==iTable && !nullable ){
ExprClearProperty(p, EP_CanBeNull);
@@ -4281,8 +4282,8 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
if( pSubSrc->nSrc>1 /* (3a) */
|| isAgg /* (3b) */
|| IsVirtual(pSubSrc->a[0].pTab) /* (3c) */
|| isAgg /* (3c) */
|| IsVirtual(pSubSrc->a[0].pTab) /* (3b) */
|| (p->selFlags & SF_Distinct)!=0 /* (3d) */
|| (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
){
@@ -4666,6 +4667,8 @@ struct WhereConst {
int nConst; /* Number for COLUMN=CONSTANT terms */
int nChng; /* Number of times a constant is propagated */
int bHasAffBlob; /* At least one column in apExpr[] as affinity BLOB */
u32 mExcludeOn; /* Which ON expressions to exclude from considertion.
** Either EP_OuterON or EP_InnerON|EP_OuterON */
Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */
};
@@ -4728,7 +4731,7 @@ static void constInsert(
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
Expr *pRight, *pLeft;
if( NEVER(pExpr==0) ) return;
if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){
if( ExprHasProperty(pExpr, pConst->mExcludeOn) ){
testcase( ExprHasProperty(pExpr, EP_OuterON) );
testcase( ExprHasProperty(pExpr, EP_InnerON) );
return;
@@ -4768,9 +4771,10 @@ static int propagateConstantExprRewriteOne(
int i;
if( pConst->pOomFault[0] ) return WRC_Prune;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
if( ExprHasProperty(pExpr, EP_FixedCol|EP_OuterON) ){
if( ExprHasProperty(pExpr, EP_FixedCol|pConst->mExcludeOn) ){
testcase( ExprHasProperty(pExpr, EP_FixedCol) );
testcase( ExprHasProperty(pExpr, EP_OuterON) );
testcase( ExprHasProperty(pExpr, EP_InnerON) );
return WRC_Continue;
}
for(i=0; i<pConst->nConst; i++){
@@ -4894,6 +4898,17 @@ static int propagateConstants(
x.nChng = 0;
x.apExpr = 0;
x.bHasAffBlob = 0;
if( ALWAYS(p->pSrc!=0)
&& p->pSrc->nSrc>0
&& (p->pSrc->a[0].fg.jointype & JT_LTORJ)!=0
){
/* Do not propagate constants on any ON clause if there is a
** RIGHT JOIN anywhere in the query */
x.mExcludeOn = EP_InnerON | EP_OuterON;
}else{
/* Do not propagate constants through the ON clause of a LEFT JOIN */
x.mExcludeOn = EP_OuterON;
}
findConstInWhere(&x, p->pWhere);
if( x.nConst ){
memset(&w, 0, sizeof(w));
@@ -6757,6 +6772,7 @@ int sqlite3Select(
SELECTTRACE(0x100,pParse,p,
("LEFT-JOIN simplifies to JOIN on term %d\n",i));
pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER);
assert( pItem->iCursor>=0 );
unsetJoinExpr(p->pWhere, pItem->iCursor,
pTabList->a[0].fg.jointype & JT_LTORJ);
}
@@ -6978,7 +6994,7 @@ int sqlite3Select(
/* Generate code to implement the subquery
**
** The subquery is implemented as a co-routine all if the following are
** The subquery is implemented as a co-routine if all of the following are
** true:
**
** (1) the subquery is guaranteed to be the outer loop (so that

View File

@@ -58,7 +58,7 @@ void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
char zBuf[500];
char zBuf[1000];
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
if( p ){
for(i=0; i<p->iLevel && i<(int)sizeof(p->bLine)-1; i++){
@@ -189,7 +189,7 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
const SrcItem *pItem = &pSrc->a[i];
StrAccum x;
int n = 0;
char zLine[100];
char zLine[1000];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
x.printfFlags |= SQLITE_PRINTF_INTERNAL;
sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);

View File

@@ -1004,7 +1004,7 @@ case OP_Gosub: { /* jump */
** and also less than the current address, then the "EXPLAIN" output
** formatter in the CLI will indent all opcodes from the P2 opcode up
** to be not including the current Return. P2 should be the first opcode
** in the subroutine from which this opcode is returnning. Thus the P2
** in the subroutine from which this opcode is returning. Thus the P2
** value is a byte-code indentation hint. See tag-20220407a in
** wherecode.c and shell.c.
*/
@@ -1666,7 +1666,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
if( sqlite3VdbeMemGrow(pOut, (int)nByte+3, pOut==pIn2) ){
if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
goto no_mem;
}
MemSetTypeFlag(pOut, MEM_Str);
@@ -1678,9 +1678,9 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
pIn1->flags = flags1;
if( encoding>SQLITE_UTF8 ) nByte &= ~1;
pOut->z[nByte]=0;
pOut->z[nByte+1] = 0;
pOut->z[nByte+2] = 0;
pOut->flags |= MEM_Term;
pOut->n = (int)nByte;
pOut->enc = encoding;
@@ -3959,7 +3959,7 @@ case OP_SetCookie: {
rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3);
if( pOp->p2==BTREE_SCHEMA_VERSION ){
/* When the schema cookie changes, record the new cookie internally */
pDb->pSchema->schema_cookie = pOp->p3 - pOp->p5;
*(u32*)&pDb->pSchema->schema_cookie = *(u32*)&pOp->p3 - pOp->p5;
db->mDbFlags |= DBFLAG_SchemaChange;
sqlite3FkClearTriggerCache(db, pOp->p1);
}else if( pOp->p2==BTREE_FILE_FORMAT ){

View File

@@ -818,9 +818,9 @@ int sqlite3_step(sqlite3_stmt *pStmt){
sqlite3_reset(pStmt);
if( savedPc>=0 ){
/* Setting minWriteFileFormat to 254 is a signal to the OP_Init and
** OP_Trace opcodes to *not* perform SQLITE_TRACE_STMT because one
** should output has already occurred due to SQLITE_SCHEMA.
** tag-20220401a */
** OP_Trace opcodes to *not* perform SQLITE_TRACE_STMT because it has
** already been done once on a prior invocation that failed due to
** SQLITE_SCHEMA. tag-20220401a */
v->minWriteFileFormat = 254;
}
assert( v->expired==0 );

View File

@@ -594,7 +594,7 @@ void sqlite3VdbeRunOnlyOnce(Vdbe *p){
}
/*
** Mark the VDBE as one that can only be run multiple times.
** Mark the VDBE as one that can be run multiple times.
*/
void sqlite3VdbeReusable(Vdbe *p){
int i;

View File

@@ -4180,11 +4180,21 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
pNew->iTab = iTab;
pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
if( bFirstPastRJ || (pItem->fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){
if( bFirstPastRJ
|| (pItem->fg.jointype & (JT_OUTER|JT_CROSS|JT_LTORJ))!=0
){
/* Add prerequisites to prevent reordering of FROM clause terms
** across CROSS joins and outer joins. The bFirstPastRJ boolean
** prevents the right operand of a RIGHT JOIN from being swapped with
** other elements even further to the right. */
** other elements even further to the right.
**
** The JT_LTORJ term prevents any FROM-clause term reordering for terms
** to the left of a RIGHT JOIN. This is conservative. Relaxing this
** constraint somewhat to prevent terms from crossing from the right
** side of a LEFT JOIN over to the left side when they are on the
** left side of a RIGHT JOIN would be sufficient for all known failure
** cases. FIX ME: Implement this optimization.
*/
mPrereq |= mPrior;
bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0;
}
@@ -5073,7 +5083,11 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
pItem = pWInfo->pTabList->a;
pTab = pItem->pTab;
if( IsVirtual(pTab) ) return 0;
if( pItem->fg.isIndexedBy ) return 0;
if( pItem->fg.isIndexedBy || pItem->fg.notIndexed ){
testcase( pItem->fg.isIndexedBy );
testcase( pItem->fg.notIndexed );
return 0;
}
iCur = pItem->iCursor;
pWC = &pWInfo->sWC;
pLoop = pBuilder->pNew;
@@ -5246,7 +5260,7 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
WhereLoop *pLoop;
pLoop = pWInfo->a[i].pWLoop;
pItem = &pWInfo->pTabList->a[pLoop->iTab];
if( (pItem->fg.jointype & JT_LEFT)==0 ) continue;
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue;
if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)==0
&& (pLoop->wsFlags & WHERE_ONEROW)==0
){
@@ -5578,7 +5592,7 @@ WhereInfo *sqlite3WhereBegin(
/* Analyze all of the subexpressions. */
sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC);
sqlite3WhereAddLimit(&pWInfo->sWC, pLimit);
if( db->mallocFailed ) goto whereBeginError;
if( pParse->nErr ) goto whereBeginError;
/* Special case: WHERE terms that do not refer to any tables in the join
** (constant expressions). Evaluate each such term, and jump over all the

View File

@@ -1121,9 +1121,15 @@ static void exprAnalyze(
}
}else if( (prereqAll>>1)>=x ){
/* The ON clause of an INNER JOIN references a table to its right.
** Most other SQL database engines raise an error. But all versions
** of SQLite going back to 3.0.0 have just put the ON clause constraint
** into the WHERE clause and carried on. */
** Most other SQL database engines raise an error. But SQLite versions
** 3.0 through 3.38 just put the ON clause constraint into the WHERE
** clause and carried on. Beginning with 3.39, raise an error only
** if there is a RIGHT or FULL JOIN in the query. This makes SQLite
** more like other systems, and also preserves legacy. */
if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
return;
}
ExprClearProperty(pExpr, EP_InnerON);
}
}

View File

@@ -126,9 +126,12 @@ do_test count-2.7 {
do_test count-2.8 {
uses_op_count {SELECT count(*) FROM t2 WHERE a IS NOT NULL}
} {0}
do_test count-2.9 {
catchsql {SELECT count(*) FROM t2 HAVING count(*)>1}
} {1 {a GROUP BY clause is required before HAVING}}
do_execsql_test count-2.9a {
SELECT count(*) FROM t2 HAVING count(*)>1;
} {}
do_execsql_test count-2.9b {
SELECT count(*) FROM t2 HAVING count(*)<10;
} {0}
do_test count-2.10 {
uses_op_count {SELECT count(*) FROM (SELECT 1)}
} {0}

View File

@@ -190,8 +190,8 @@ if {![nonzero_reserved_bytes]} {
}
}
# EVIDENCE-OF: R-55119-57913 By default, VACUUM only works only on the
# main database.
# EVIDENCE-OF: R-40347-36128 By default, VACUUM operates on the main
# database.
forcedelete test.db2
create_db { PRAGMA auto_vacuum = NONE }
do_execsql_test e_vacuum-2.1.1 {

View File

@@ -153,7 +153,6 @@ static struct GlobalVars {
int nSql; /* Number of SQL scripts */
Blob *pFirstSql; /* First SQL script */
unsigned int uRandom; /* Seed for the SQLite PRNG */
unsigned char doInvariantChecks; /* True to run query invariant checks */
unsigned int nInvariant; /* Number of invariant checks run */
char zTestName[100]; /* Name of current test */
} g;
@@ -838,6 +837,7 @@ static int progress_handler(void *pClientData) {
#define BTS_SELECT 0x000001
#define BTS_NONSELECT 0x000002
#define BTS_BADFUNC 0x000004
#define BTS_BADPRAGMA 0x000008 /* Sticky for rest of the script */
/*
** Disallow debugging pragmas such as "PRAGMA vdbe_debug" and
@@ -854,7 +854,8 @@ static int block_troublesome_sql(
const char *zArg3,
const char *zArg4
){
unsigned int *pFlags = (unsigned int*)pClientData;
unsigned int *pBtsFlags = (unsigned int*)pClientData;
(void)zArg3;
(void)zArg4;
switch( eCode ){
@@ -863,24 +864,31 @@ static int block_troublesome_sql(
&& (zArg2==0 || strtoll(zArg2,0,0)>100 || strtoll(zArg2,0,10)>100)
){
return SQLITE_DENY;
}else if( sqlite3_stricmp("hard_heap_limit", zArg1)==0
|| sqlite3_stricmp("reverse_unordered_selects", zArg1)==0
){
/* BTS_BADPRAGMA is sticky. A hard_heap_limit or
** revert_unordered_selects should inhibit all future attempts
** at verifying query invariants */
*pBtsFlags |= BTS_BADPRAGMA;
}else if( eVerbosity==0 ){
if( sqlite3_strnicmp("vdbe_", zArg1, 5)==0
|| sqlite3_stricmp("parser_trace", zArg1)==0
|| sqlite3_stricmp("temp_store_directory", zArg1)==0
){
return SQLITE_DENY;
}
}
}else if( sqlite3_stricmp("oom",zArg1)==0
&& zArg2!=0 && zArg2[0]!=0 ){
oomCounter = atoi(zArg2);
}
*pFlags |= BTS_NONSELECT;
*pBtsFlags |= BTS_NONSELECT;
break;
}
case SQLITE_ATTACH: {
/* Deny the ATTACH if it is attaching anything other than an in-memory
** database. */
*pFlags |= BTS_NONSELECT;
*pBtsFlags |= BTS_NONSELECT;
if( zArg1==0 ) return SQLITE_DENY;
if( strcmp(zArg1,":memory:")==0 ) return SQLITE_OK;
if( sqlite3_strglob("file:*[?]vfs=memdb", zArg1)==0
@@ -891,22 +899,62 @@ static int block_troublesome_sql(
return SQLITE_DENY;
}
case SQLITE_SELECT: {
*pFlags |= BTS_SELECT;
*pBtsFlags |= BTS_SELECT;
break;
}
case SQLITE_FUNCTION: {
static const char *azBadFuncs[] = {
"avg",
"count",
"cume_dist",
"current_date",
"current_time",
"current_timestamp",
"date",
"datetime",
"decimal_sum",
"dense_rank",
"first_value",
"geopoly_group_bbox",
"group_concat",
"implies_nonnull_row",
"json_group_array",
"json_group_object",
"julianday",
"lag",
"last_value",
"lead",
"max",
"min",
"nth_value",
"ntile",
"percent_rank",
"random",
"randomblob",
"rtreedepth",
"rank",
"row_number",
"sqlite_offset",
"strftime",
"sum",
"time",
"total",
"unixepoch",
};
int i;
for(i=0; i<sizeof(azBadFuncs)/sizeof(azBadFuncs[0]); i++){
if( sqlite3_stricmp(azBadFuncs[i], zArg2)==0 ){
*pFlags |= BTS_BADFUNC;
int first, last;
first = 0;
last = sizeof(azBadFuncs)/sizeof(azBadFuncs[0]) - 1;
do{
int mid = (first+last)/2;
int c = sqlite3_stricmp(azBadFuncs[mid], zArg2);
if( c<0 ){
first = mid+1;
}else if( c>0 ){
last = mid-1;
}else{
*pBtsFlags |= BTS_BADFUNC;
break;
}
}
}while( first<=last );
break;
}
case SQLITE_READ: {
@@ -914,7 +962,7 @@ static int block_troublesome_sql(
break;
}
default: {
*pFlags |= BTS_NONSELECT;
*pBtsFlags |= BTS_NONSELECT;
}
}
return SQLITE_OK;
@@ -926,6 +974,7 @@ int fuzz_invariant(
sqlite3_stmt *pStmt, /* Test statement stopped on an SQLITE_ROW */
int iCnt, /* Invariant sequence number, starting at 0 */
int iRow, /* The row number for pStmt */
int nRow, /* Total number of output rows */
int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */
int eVerbosity /* How much debugging output */
);
@@ -943,31 +992,13 @@ static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
printf("RUNNING-SQL: [%s]\n", zSql);
fflush(stdout);
}
(*pBtsFlags) = 0;
(*pBtsFlags) &= ~BTS_BADPRAGMA;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
int nRow = 0;
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
nRow++;
if( (*pBtsFlags)==BTS_SELECT
&& g.doInvariantChecks
&& !sqlite3_stmt_isexplain(pStmt)
){
int iCnt = 0;
for(iCnt=0; iCnt<99999; iCnt++){
rc = fuzz_invariant(db, pStmt, iCnt, nRow, &bCorrupt, eVerbosity);
if( rc==SQLITE_DONE ) break;
if( rc!=SQLITE_ERROR ) g.nInvariant++;
if( eVerbosity>0 ){
if( rc==SQLITE_OK ){
printf("invariant-check: ok\n");
}else if( rc==SQLITE_CORRUPT ){
printf("invariant-check: failed due to database corruption\n");
}
}
}
}
if( eVerbosity>=5 ){
if( eVerbosity>=4 ){
int j;
for(j=0; j<sqlite3_column_count(pStmt); j++){
if( j ) printf(",");
@@ -1015,7 +1046,32 @@ static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
fflush(stdout);
} /* End if( eVerbosity>=5 ) */
} /* End while( SQLITE_ROW */
if( rc!=SQLITE_DONE && eVerbosity>=4 ){
if( rc==SQLITE_DONE ){
if( (*pBtsFlags)==BTS_SELECT
&& !sqlite3_stmt_isexplain(pStmt)
&& nRow>0
){
int iRow = 0;
sqlite3_reset(pStmt);
while( sqlite3_step(pStmt)==SQLITE_ROW ){
int iCnt = 0;
iRow++;
for(iCnt=0; iCnt<99999; iCnt++){
rc = fuzz_invariant(db, pStmt, iCnt, iRow, nRow,
&bCorrupt, eVerbosity);
if( rc==SQLITE_DONE ) break;
if( rc!=SQLITE_ERROR ) g.nInvariant++;
if( eVerbosity>0 ){
if( rc==SQLITE_OK ){
printf("invariant-check: ok\n");
}else if( rc==SQLITE_CORRUPT ){
printf("invariant-check: failed due to database corruption\n");
}
}
}
}
}
}else if( eVerbosity>=4 ){
printf("SQL-ERROR: (%d) %s\n", rc, sqlite3_errmsg(db));
fflush(stdout);
}
@@ -1647,7 +1703,6 @@ static void showHelp(void){
" --oss-fuzz Enable OSS-FUZZ testing\n"
" --prng-seed N Seed value for the PRGN inside of SQLite\n"
" -q|--quiet Reduced output\n"
" --query-invariants Run query invariant checks\n"
" --rebuild Rebuild and vacuum the database file\n"
" --result-trace Show the results of each SQL command\n"
" --script Output CLI script instead of running tests\n"
@@ -1808,9 +1863,6 @@ int main(int argc, char **argv){
verboseFlag = 0;
eVerbosity = 0;
}else
if( strcmp(z,"query-invariants")==0 ){
g.doInvariantChecks = 1;
}else
if( strcmp(z,"rebuild")==0 ){
rebuildFlag = 1;
openFlags4Data = SQLITE_OPEN_READWRITE;

View File

@@ -29,7 +29,7 @@
/* Forward references */
static char *fuzz_invariant_sql(sqlite3_stmt*, int);
static int sameValue(sqlite3_value*,sqlite3_value*);
static int sameValue(sqlite3_stmt*,int,sqlite3_stmt*,int);
static void reportInvariantFailed(sqlite3_stmt*,sqlite3_stmt*,int);
/*
@@ -62,7 +62,8 @@ int fuzz_invariant(
sqlite3 *db, /* The database connection */
sqlite3_stmt *pStmt, /* Test statement stopped on an SQLITE_ROW */
int iCnt, /* Invariant sequence number, starting at 0 */
int iRow, /* The row number for pStmt */
int iRow, /* Current row number */
int nRow, /* Number of output rows from pStmt */
int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */
int eVerbosity /* How much debugging output */
){
@@ -71,8 +72,11 @@ int fuzz_invariant(
int rc;
int i;
int nCol;
int nParam;
if( *pbCorrupt ) return SQLITE_DONE;
nParam = sqlite3_bind_parameter_count(pStmt);
if( nParam>100 ) return SQLITE_DONE;
zTest = fuzz_invariant_sql(pStmt, iCnt);
if( zTest==0 ) return SQLITE_DONE;
rc = sqlite3_prepare_v2(db, zTest, -1, &pTestStmt, 0);
@@ -88,7 +92,11 @@ int fuzz_invariant(
sqlite3_free(zTest);
nCol = sqlite3_column_count(pStmt);
for(i=0; i<nCol; i++){
sqlite3_bind_value(pTestStmt, i+1, sqlite3_column_value(pStmt,i));
rc = sqlite3_bind_value(pTestStmt,i+1+nParam,sqlite3_column_value(pStmt,i));
if( rc!=SQLITE_OK && rc!=SQLITE_RANGE ){
sqlite3_finalize(pTestStmt);
return rc;
}
}
if( eVerbosity>=2 ){
char *zSql = sqlite3_expanded_sql(pTestStmt);
@@ -97,12 +105,11 @@ int fuzz_invariant(
}
while( (rc = sqlite3_step(pTestStmt))==SQLITE_ROW ){
for(i=0; i<nCol; i++){
if( !sameValue(sqlite3_column_value(pStmt,i),
sqlite3_column_value(pTestStmt,i)) ) break;
if( !sameValue(pStmt, i, pTestStmt, i) ) break;
}
if( i>=nCol ) break;
}
if( rc!=SQLITE_ROW ){
if( rc==SQLITE_DONE ){
/* No matching output row found */
sqlite3_stmt *pCk = 0;
rc = sqlite3_prepare_v2(db, "PRAGMA integrity_check", -1, &pCk, 0);
@@ -124,7 +131,10 @@ int fuzz_invariant(
sqlite3_finalize(pCk);
rc = sqlite3_prepare_v2(db,
"SELECT 1 FROM bytecode(?1) WHERE opcode='VOpen'", -1, &pCk, 0);
if( rc==SQLITE_OK ) rc = sqlite3_step(pCk);
if( rc==SQLITE_OK ){
sqlite3_bind_pointer(pCk, 1, pStmt, "stmt-pointer", 0);
rc = sqlite3_step(pCk);
}
sqlite3_finalize(pCk);
if( rc==SQLITE_DONE ){
reportInvariantFailed(pStmt, pTestStmt, iRow);
@@ -156,18 +166,16 @@ static char *fuzz_invariant_sql(sqlite3_stmt *pStmt, int iCnt){
int mxCnt;
int bDistinct = 0;
int bOrderBy = 0;
int nParam = sqlite3_bind_parameter_count(pStmt);
iCnt++;
switch( iCnt % 4 ){
case 1: bDistinct = 1; break;
case 2: bOrderBy = 1; break;
case 3: bDistinct = bOrderBy = 1; break;
}
iCnt /= 4;
if( nCol==1 ){
mxCnt = 0;
}else{
mxCnt = nCol;
}
mxCnt = nCol;
if( iCnt<0 || iCnt>mxCnt ) return 0;
zIn = sqlite3_sql(pStmt);
if( zIn==0 ) return 0;
@@ -175,8 +183,9 @@ static char *fuzz_invariant_sql(sqlite3_stmt *pStmt, int iCnt){
while( nIn>0 && (isspace(zIn[nIn-1]) || zIn[nIn-1]==';') ) nIn--;
if( strchr(zIn, '?') ) return 0;
pTest = sqlite3_str_new(0);
sqlite3_str_appendf(pTest, "SELECT %s* FROM (%.*s)",
bDistinct ? "DISTINCT " : "", (int)nIn, zIn);
sqlite3_str_appendf(pTest, "SELECT %s* FROM (%s",
bDistinct ? "DISTINCT " : "", zIn);
sqlite3_str_appendf(pTest, ")");
rc = sqlite3_prepare_v2(db, sqlite3_str_value(pTest), -1, &pBase, 0);
if( rc ){
sqlite3_finalize(pBase);
@@ -184,7 +193,7 @@ static char *fuzz_invariant_sql(sqlite3_stmt *pStmt, int iCnt){
}
for(i=0; i<sqlite3_column_count(pStmt); i++){
const char *zColName = sqlite3_column_name(pBase,i);
const char *zSuffix = strchr(zColName, ':');
const char *zSuffix = zColName ? strrchr(zColName, ':') : 0;
if( zSuffix
&& isdigit(zSuffix[1])
&& (zSuffix[1]>'3' || isdigit(zSuffix[2]))
@@ -193,11 +202,13 @@ static char *fuzz_invariant_sql(sqlite3_stmt *pStmt, int iCnt){
** WHERE clause. */
continue;
}
if( iCnt>0 && i+1!=iCnt ) continue;
if( i+1!=iCnt ) continue;
if( zColName==0 ) continue;
if( sqlite3_column_type(pStmt, i)==SQLITE_NULL ){
sqlite3_str_appendf(pTest, " %s \"%w\" ISNULL", zAnd, zColName);
}else{
sqlite3_str_appendf(pTest, " %s \"%w\"=?%d", zAnd, zColName, i+1);
sqlite3_str_appendf(pTest, " %s \"%w\"=?%d", zAnd, zColName,
i+1+nParam);
}
zAnd = "AND";
}
@@ -211,29 +222,39 @@ static char *fuzz_invariant_sql(sqlite3_stmt *pStmt, int iCnt){
/*
** Return true if and only if v1 and is the same as v2.
*/
static int sameValue(sqlite3_value *v1, sqlite3_value *v2){
static int sameValue(sqlite3_stmt *pS1, int i1, sqlite3_stmt *pS2, int i2){
int x = 1;
if( sqlite3_value_type(v1)!=sqlite3_value_type(v2) ) return 0;
switch( sqlite3_value_type(v1) ){
int t1 = sqlite3_column_type(pS1,i1);
int t2 = sqlite3_column_type(pS2,i2);
if( t1!=t2 ){
if( (t1==SQLITE_INTEGER && t2==SQLITE_FLOAT)
|| (t1==SQLITE_FLOAT && t2==SQLITE_INTEGER)
){
/* Comparison of numerics is ok */
}else{
return 0;
}
}
switch( sqlite3_column_type(pS1,i1) ){
case SQLITE_INTEGER: {
x = sqlite3_value_int64(v1)==sqlite3_value_int64(v2);
x = sqlite3_column_int64(pS1,i1)==sqlite3_column_int64(pS2,i2);
break;
}
case SQLITE_FLOAT: {
x = sqlite3_value_double(v1)==sqlite3_value_double(v2);
x = sqlite3_column_double(pS1,i1)==sqlite3_column_double(pS2,i2);
break;
}
case SQLITE_TEXT: {
const char *z1 = (const char*)sqlite3_value_text(v1);
const char *z2 = (const char*)sqlite3_value_text(v2);
const char *z1 = (const char*)sqlite3_column_text(pS1,i1);
const char *z2 = (const char*)sqlite3_column_text(pS2,i2);
x = ((z1==0 && z2==0) || (z1!=0 && z2!=0 && strcmp(z1,z1)==0));
break;
}
case SQLITE_BLOB: {
int len1 = sqlite3_value_bytes(v1);
const unsigned char *b1 = sqlite3_value_blob(v1);
int len2 = sqlite3_value_bytes(v2);
const unsigned char *b2 = sqlite3_value_blob(v2);
int len1 = sqlite3_column_bytes(pS1,i1);
const unsigned char *b1 = sqlite3_column_blob(pS1,i1);
int len2 = sqlite3_column_bytes(pS2,i2);
const unsigned char *b2 = sqlite3_column_blob(pS2,i2);
if( len1!=len2 ){
x = 0;
}else if( len1==0 ){
@@ -254,7 +275,7 @@ static void printRow(sqlite3_stmt *pStmt, int iRow){
int i, nCol;
nCol = sqlite3_column_count(pStmt);
for(i=0; i<nCol; i++){
printf("row%d.col%d] = ", iRow, i);
printf("row%d.col%d = ", iRow, i);
switch( sqlite3_column_type(pStmt, i) ){
case SQLITE_NULL: {
printf("NULL\n");

View File

@@ -661,6 +661,7 @@ do_execsql_test join8-20060 {
# https://sqlite.org/forum/forumpost/8e4c352937e82929
#
# Do not allow constant propagation between ON and WHERE clause terms.
# (Updated 2022-06-20) See also https://sqlite.org/forum/forumpost/57bdf2217d
#
reset_db
do_execsql_test join8-21000 {
@@ -674,6 +675,23 @@ do_execsql_test join8-21010 {
do_execsql_test join8-22020 {
SELECT * FROM t1 JOIN t3 ON (b=TRUE) RIGHT JOIN t2 ON TRUE WHERE (b IS TRUE);
} {}
do_execsql_test join8-22030 {
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t3;
CREATE TABLE t1(a INT);
CREATE TABLE t2(b INT);
CREATE TABLE t3(c INTEGER PRIMARY KEY, d INT);
CREATE INDEX t3d ON t3(d);
INSERT INTO t3 VALUES(0, 0);
}
do_catchsql_test join8-22031 {
SELECT * FROM t1 JOIN t2 ON d>b RIGHT JOIN t3 ON true WHERE +d = 0;
} {1 {ON clause references tables to its right}}
do_catchsql_test join8-22040 {
SELECT * FROM t1 JOIN t2 ON d>b RIGHT JOIN t3 ON true WHERE d = 0;
} {1 {ON clause references tables to its right}}
# 2022-06-10
# https://sqlite.org/forum/forumpost/51e6959f61
@@ -746,5 +764,26 @@ do_execsql_test join8-24000 {
SELECT * FROM t4 JOIN t7 ON true RIGHT JOIN (SELECT y AS z FROM t7) AS t6 ON (x=z);
} {- - - - 200}
# 2022-06-20
# forum/forumpost/6650cd40b5634f35
#
reset_db
do_execsql_test join8-25000 {
CREATE TABLE t1(a1 INT);
CREATE TABLE t2(b2 INT);
CREATE TABLE t3(c3 INT, d3 INT UNIQUE);
CREATE TABLE t4(e4 INT, f4 TEXT);
INSERT INTO t3(c3, d3) VALUES (2, 1);
INSERT INTO t4(f4) VALUES ('x');
CREATE INDEX i0 ON t3(c3) WHERE d3 ISNULL;
ANALYZE main;
}
db null -
do_execsql_test join8-25010 {
SELECT * FROM t1 LEFT JOIN t2 ON true JOIN t3 ON (b2 IN (a1)) FULL JOIN t4 ON true;
} {- - - - - x}
do_execsql_test join8-25020 {
SELECT 1 FROM t1 LEFT JOIN t2 ON true JOIN t3 ON (b2 IN (a1)) FULL JOIN t4 ON true;
} {1}
finish_test

72
test/joinH.test Normal file
View File

@@ -0,0 +1,72 @@
# 2022 May 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix joinH
do_execsql_test 1.0 {
CREATE TABLE t1(a INT);
CREATE TABLE t2(b INT);
INSERT INTO t2(b) VALUES(NULL);
}
db nullvalue NULL
do_execsql_test 1.1 {
SELECT DISTINCT a FROM t1 FULL JOIN t2 ON true WHERE (b ISNULL);
} {NULL}
do_execsql_test 1.2 {
SELECT a FROM t1 FULL JOIN t2 ON true;
} {NULL}
do_execsql_test 1.3 {
SELECT a FROM t1 FULL JOIN t2 ON true WHERE (b ISNULL);
} {NULL}
do_execsql_test 1.4 {
SELECT DISTINCT a FROM t1 FULL JOIN t2 ON true;
} {NULL}
#-----------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE TABLE r3(x);
CREATE TABLE r4(y INTEGER PRIMARY KEY);
INSERT INTO r4 VALUES(55);
}
do_execsql_test 2.1 {
SELECT 'value!' FROM r3 FULL JOIN r4 ON (y=x);
} {value!}
do_execsql_test 2.2 {
SELECT 'value!' FROM r3 FULL JOIN r4 ON (y=x) WHERE +y=55;
} {value!}
#-----------------------------------------------------------
reset_db
do_execsql_test 3.1 {
CREATE TABLE t0 (c0);
CREATE TABLE t1 (c0);
CREATE TABLE t2 (c0 , c1 , c2 , UNIQUE (c0), UNIQUE (c2 DESC));
INSERT INTO t2 VALUES ('x', 'y', 'z');
ANALYZE;
CREATE VIEW v0(c0) AS SELECT FALSE;
}
do_catchsql_test 3.2 {
SELECT * FROM t0 LEFT OUTER JOIN t1 ON v0.c0 INNER JOIN v0 INNER JOIN t2 ON (t2.c2 NOT NULL);
} {1 {ON clause references tables to its right}}
finish_test

View File

@@ -119,10 +119,9 @@ do_test select3-2.14 {
# Cannot have a HAVING without a GROUP BY
#
do_test select3-3.1 {
set v [catch {execsql {SELECT log, count(*) FROM t1 HAVING log>=4}} msg]
lappend v $msg
} {1 {a GROUP BY clause is required before HAVING}}
do_execsql_test select3-3.1 {
SELECT log, count(*) FROM t1 HAVING log>=4
} {}
# Toss in some HAVING clauses
#

View File

@@ -2203,5 +2203,10 @@ do_catchsql_test 71.0 {
ORDER BY b;
} {/1 {.*}/}
do_execsql_test 72.1 {
CREATE TABLE dual(dummy); INSERT INTO dual VALUES('X');
CREATE VIEW v1(x,y) AS SELECT RANK() OVER (PARTITION BY 0), SUM(0) FROM dual;
SELECT * FROM v1 WHERE true;
} {1 0}
finish_test

View File

@@ -10,7 +10,11 @@
**
** Usage:
**
** dbtotxt [--pagesize N] FILENAME
** dbtotxt [OPTIONS] FILENAME
**
** where OPTIONS are zero or more of:
** --pagesize N => setting the database page size for later readin
** --for-cli => prepending '.open --hexdb' to the output
**
** The translation of the database appears on standard output. If the
** --pagesize command-line option is omitted, then the page size is taken
@@ -38,6 +42,7 @@ static int allZero(unsigned char *aLine){
int main(int argc, char **argv){
int pgsz = 0; /* page size */
int forCli = 0; /* whether to prepend with .open */
long szFile; /* Size of the input file in bytes */
FILE *in; /* Input file */
int i, j; /* Loop counters */
@@ -67,6 +72,9 @@ int main(int argc, char **argv){
nErr++;
}
continue;
}else if( strcmp(z,"for-cli")==0 ){
forCli = 1;
continue;
}
fprintf(stderr, "Unknown option: %s\n", argv[i]);
nErr++;
@@ -114,6 +122,9 @@ int main(int argc, char **argv){
for(i=0; zInputFile[i]; i++){
if( zInputFile[i]=='/' && zInputFile[i+1]!=0 ) zBaseName = zInputFile+i+1;
}
if( forCli ){
printf(".open --hexdb\n");
}
printf("| size %d pagesize %d filename %s\n",(int)szFile,pgsz,zBaseName);
for(i=0; i<szFile; i+=16){
int got = (int)fread(aLine, 1, 16, in);

View File

@@ -74,6 +74,11 @@ while {[regexp $BEGIN $line]} {
incr N $n
while {[gets $in line]>=0} {
if {[regexp $BEGIN $line]} break
if {$N>0} {
write_one_file $all
set N 0
set all {}
}
puts $out1 $line
}
}