diff --git a/ext/rtree/rtree1.test b/ext/rtree/rtree1.test index 0423bf557c..034155341b 100644 --- a/ext/rtree/rtree1.test +++ b/ext/rtree/rtree1.test @@ -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 diff --git a/manifest b/manifest index 1af3329270..69016e6be3 100644 --- a/manifest +++ b/manifest @@ -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. diff --git a/manifest.uuid b/manifest.uuid index 3fce43cdc8..c9b2fb8ca9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7f405fe209d141435562b69ff161a545c63c5804f7de37871d24d7b6ee80ecec \ No newline at end of file +506a3e6f242f42d3106f80ad4385a5ef458461fbd056258e65c82dd4e0a80e8c \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 8ed4d6cef4..facb951d3c 100644 --- a/src/btree.c +++ b/src/btree.c @@ -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; diff --git a/src/resolve.c b/src/resolve.c index 175f81a10e..6a36c8cf47 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -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; diff --git a/src/select.c b/src/select.c index e4a32efb78..6f5e8c82ab 100644 --- a/src/select.c +++ b/src/select.c @@ -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; inConst; 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 diff --git a/src/treeview.c b/src/treeview.c index cca0ee92aa..366c4afd18 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -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; iiLevel && 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); diff --git a/src/vdbe.c b/src/vdbe.c index 5400716cbe..78f5edfca4 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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 ){ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 39d73288ce..4e719ede36 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -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 ); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 02972f46af..0e06e35902 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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; diff --git a/src/where.c b/src/where.c index 681cdf99a0..de6ea91e3d 100644 --- a/src/where.c +++ b/src/where.c @@ -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 diff --git a/src/whereexpr.c b/src/whereexpr.c index 878e69f633..8c9233ebd3 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -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); } } diff --git a/test/count.test b/test/count.test index fdcb21e81d..6f02074cdc 100644 --- a/test/count.test +++ b/test/count.test @@ -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} diff --git a/test/e_vacuum.test b/test/e_vacuum.test index cfe7f8464f..63bf7c125f 100644 --- a/test/e_vacuum.test +++ b/test/e_vacuum.test @@ -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 { diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index d09afe6a00..fe56262211 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -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; i0 ){ + 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=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; diff --git a/test/fuzzinvariants.c b/test/fuzzinvariants.c index f93722ced2..a601e7aa45 100644 --- a/test/fuzzinvariants.c +++ b/test/fuzzinvariants.c @@ -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=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 ) 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'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; ib 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 diff --git a/test/joinH.test b/test/joinH.test new file mode 100644 index 0000000000..9832861208 --- /dev/null +++ b/test/joinH.test @@ -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 diff --git a/test/select3.test b/test/select3.test index fec8ba4a51..690514b496 100644 --- a/test/select3.test +++ b/test/select3.test @@ -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 # diff --git a/test/window1.test b/test/window1.test index 84331d1152..fd71ed6bb9 100644 --- a/test/window1.test +++ b/test/window1.test @@ -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 diff --git a/tool/dbtotxt.c b/tool/dbtotxt.c index 8b0600fa51..a56416dcc4 100644 --- a/tool/dbtotxt.c +++ b/tool/dbtotxt.c @@ -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=0} { if {[regexp $BEGIN $line]} break + if {$N>0} { + write_one_file $all + set N 0 + set all {} + } puts $out1 $line } }