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

Remove the column-cache from the code generator. The column-cache has been

a persistent source of bugs for years and with recent improvements
in the performance of OP_Column, it no longer provides a benefit.  After
the column cache is removed, the binary is almost 2KB smaller and the
speed-check.sh performance test is over 3 million cycles faster.

FossilOrigin-Name: cdff3af7bedc5ebea04bd9b5e2112d3db451a475c18c9a9ebd45f6f3a89a43cb
This commit is contained in:
drh
2018-08-04 20:30:55 +00:00
19 changed files with 51 additions and 472 deletions

View File

@@ -1,5 +1,5 @@
C Add\stest\scases\sfor\sthe\sconstant\sexpression\sfix\sof\sthe\sprevious\scheck-in. C Remove\sthe\scolumn-cache\sfrom\sthe\scode\sgenerator.\s\sThe\scolumn-cache\shas\sbeen\na\spersistent\ssource\sof\sbugs\sfor\syears\sand\swith\srecent\simprovements\nin\sthe\sperformance\sof\sOP_Column,\sit\sno\slonger\sprovides\sa\sbenefit.\s\sAfter\nthe\scolumn\scache\sis\sremoved,\sthe\sbinary\sis\salmost\s2KB\ssmaller\sand\sthe\nspeed-check.sh\sperformance\stest\sis\sover\s3\smillion\scycles\sfaster.
D 2018-08-04T15:28:12.613 D 2018-08-04T20:30:55.322
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 Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6
@@ -442,15 +442,15 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173 F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173
F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2 F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
F src/build.c 7e82726057d67de1d77961f3a3f371353171099bb6b006adb172b6d3aebb1d4a F src/build.c fe407be13d1201bf386d2c629424e5c97a07bcfc6ef21cf6e888e50b792a6191
F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288 F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387 F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2
F src/expr.c 825198653fb655df3d758c556eb003f0a531a3661d0573cf445b4e9298daac07 F src/expr.c aac1c33ef8899d0cfe32e4269810e10372f8fdbce6554b38034973d5e8c285d9
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
@@ -459,7 +459,7 @@ F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 8613af9c5ba1503bc68f4e9432c6c024e0fdafdc791575c50f380f73ec91189f F src/insert.c 894594952bcda1dc6e1549871e4022517563545ffc7a3f4e9e5f3faa788893fd
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b
F src/main.c dc023f468eda20aed1fb7c300673cbb40617607b5771840e4229ec239dade250 F src/main.c dc023f468eda20aed1fb7c300673cbb40617607b5771840e4229ec239dade250
@@ -491,24 +491,24 @@ F src/parse.y 704c94624d41d7d46a5467574130e55aa8029a563f4df538f0121475eae46e34
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
F src/pragma.c 71c585f1d26e14b931fa4573f587933d6dfddecd9d9001b0f126f74f7306bf87 F src/pragma.c 873b767f233932e97cbffd094aa61928be90aca03f946a94bb29ce5695e4885b
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
F src/prepare.c e966ecc97c3671ff0e96227c8c877b83f2d33ea371ee190bbf1698b36b5605c0 F src/prepare.c e966ecc97c3671ff0e96227c8c877b83f2d33ea371ee190bbf1698b36b5605c0
F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365 F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 797088662ed61102485e3070ba3b3f7828bd5ef6a588223ba6865d77d52f6cea F src/resolve.c 797088662ed61102485e3070ba3b3f7828bd5ef6a588223ba6865d77d52f6cea
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 18636c49eeb9016bb429ac6892220aea51bc618d021cf16770146e1858cf6f1e F src/select.c ae7396a314cc1bb1d767947cd57094e3a9ffcbb155ebc1b1c391e028c44a9a04
F src/shell.c.in 5e4c139799f059a5231f0259111f51f6dffcb28154c535f6b4c2192619a40844 F src/shell.c.in 5e4c139799f059a5231f0259111f51f6dffcb28154c535f6b4c2192619a40844
F src/sqlite.h.in c6451bb876adced3aba5b1682c6317d215c5eceaba21a6ce979e71a0b8d0bf95 F src/sqlite.h.in c6451bb876adced3aba5b1682c6317d215c5eceaba21a6ce979e71a0b8d0bf95
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
F src/sqliteInt.h de37aae03c6a4e4f1e1eff15c04292153dbba015ad8e0dc0dffe82ea0fe76d5e F src/sqliteInt.h a5d212bb7ae5cfc0540af6fb09eee2092a45fe083fac4191ee64ff70e7d4d78a
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c e0bf71a6d24b8c23393c000abffab05979bbca2a72d0b0f79260e2cf1527fda5 F src/tclsqlite.c e0bf71a6d24b8c23393c000abffab05979bbca2a72d0b0f79260e2cf1527fda5
F src/test1.c 335740ddc632c0b54765b6fd373da7f76a397adde3ded3592390dd1e5fb0dd55 F src/test1.c 55424c026dd93c06ad84ff4e46cec64aa3e12e767d50c31886e6a69ee53fe81e
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6 F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
@@ -564,18 +564,18 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 01e96d1b639c3eb0b9ef90616e766d453935c554f1f7aa86b6db937b79554b97 F src/tokenize.c 01e96d1b639c3eb0b9ef90616e766d453935c554f1f7aa86b6db937b79554b97
F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f
F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995 F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995
F src/update.c 7b7c768dc415a8d2eb9fd2cea8b524cb29cf354f319700e22f94f262d3f507cb F src/update.c 345ce35eb1332eb4829857aa8b1f65a614b07dae91d0346c0dc2baacafbcc51b
F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88 F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855 F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
F src/vdbe.c 8fbefa50884f4803139bdc2d4795b973a1a892f023726fa72246fea2fe8e9925 F src/vdbe.c 8744e9e830262867a9730ca487a114abc7265b572b48f80b18124d1d347f7b1b
F src/vdbe.h d93abdc8bc9295e0a256e582c19f548c545dc498319d108bbc9dd29de31c48a2 F src/vdbe.h d93abdc8bc9295e0a256e582c19f548c545dc498319d108bbc9dd29de31c48a2
F src/vdbeInt.h 2a45270d7f44870ca5452f48cdf3c56387019ae03331c008d670a7d0a3e1ba3f F src/vdbeInt.h 8ea493d994c6697cf7bccc60583a80a0222560490410f60f1113e90d36643ce0
F src/vdbeapi.c af4a3de00d1851bcbc55b85dfbe52849aa2b1e17b4a5a1f3d9c257df7af361ff F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611
F src/vdbeaux.c 1265a36260c36eb55afb40d744ffc1a3f11252d5712274c6218efb087204a7e5 F src/vdbeaux.c b610cef3d8d381c9287d02c2e61590acc0a1b4de1cc0188d560f5ef345527a24
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c a699a1d7ccc3f94cdff69ddf35d5f7540dbf52ca44cf040eda3c87520e67858c F src/vdbemem.c 720df42ad8e5c7cb883573de40a185afef4a214903098a16f2bb14b62b2399b7
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392 F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
F src/vtab.c 678992ac8ec677a3f9b08126aaf891441083805e3b42574e3654d44538381c14 F src/vtab.c 678992ac8ec677a3f9b08126aaf891441083805e3b42574e3654d44538381c14
@@ -583,9 +583,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c d44a0811afd2155b1157c38b33141d4ac028fda6232485bed664015bb05819ca F src/wal.c d44a0811afd2155b1157c38b33141d4ac028fda6232485bed664015bb05819ca
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4 F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4
F src/where.c 52ab6d07a6ac6e2cb2a7da41217f0b7c13ce17a30d6a1d3459e86ac94b160e15 F src/where.c 155809967fbab889374dedf970ea6561b8fb519fcb165d6ba00776552ecc5cde
F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4 F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
F src/wherecode.c eb558ea9a482e179d27858113ca7012e508b904ff90b892367cc9ca4c0b9b246 F src/wherecode.c 2b6cd1b27736cc803060289e04ecf9849976106f4077aa67d1a2c0e3ec420159
F src/whereexpr.c dc34f0df69418dedb4619f7ad61b7d31f447971223540b957a1b836a62c0ce7b F src/whereexpr.c dc34f0df69418dedb4619f7ad61b7d31f447971223540b957a1b836a62c0ce7b
F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65 F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -676,7 +676,7 @@ F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45
F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983 F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983
F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99 F test/btree02.test a0f33669ba76632247c14718af32db939fa6de5cd13890798ad3f2a362cf7fe4
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3 F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727 F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
@@ -1754,7 +1754,8 @@ 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 8bc7f84c39f913b0b0f5e9f5fd9d7dd8bda8422248c069712b6992c32c759a83 P 95db5bd9fea86a10c9528dd24841e1370dfdc0bbb5c98b7cbd808a8bc59dd48f a500893b6f64aced197cd32b79d51a481629a39d45dbcf0f02d65e5451ac4706
R 6932e89db01172dd37443d3c6c0ba024 R a895202b2ab9d783fc535831c38c174c
T +closed a500893b6f64aced197cd32b79d51a481629a39d45dbcf0f02d65e5451ac4706
U drh U drh
Z 944fd02700c6746ca58d0f2d1bfa9fb6 Z 37d5cbe7046590064debd1c15a35aeb1

View File

@@ -1 +1 @@
95db5bd9fea86a10c9528dd24841e1370dfdc0bbb5c98b7cbd808a8bc59dd48f cdff3af7bedc5ebea04bd9b5e2112d3db451a475c18c9a9ebd45f6f3a89a43cb

View File

@@ -225,7 +225,6 @@ void sqlite3FinishCoding(Parse *pParse){
/* Get the VDBE program ready for execution /* Get the VDBE program ready for execution
*/ */
if( v && pParse->nErr==0 && !db->mallocFailed ){ if( v && pParse->nErr==0 && !db->mallocFailed ){
assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
/* A minimum of one cursor is required if autoincrement is used /* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */ * See ticket [a696379c1f08866] */
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1; if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;

View File

@@ -463,9 +463,8 @@ void sqlite3DeleteFrom(
} }
iKey = iPk; iKey = iPk;
}else{ }else{
iKey = pParse->nMem + 1; iKey = ++pParse->nMem;
iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0); sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, -1, iKey);
if( iKey>pParse->nMem ) pParse->nMem = iKey;
} }
if( eOnePass!=ONEPASS_OFF ){ if( eOnePass!=ONEPASS_OFF ){
@@ -898,7 +897,6 @@ int sqlite3GenerateIndexKey(
if( pIdx->pPartIdxWhere ){ if( pIdx->pPartIdxWhere ){
*piPartIdxLabel = sqlite3VdbeMakeLabel(v); *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
pParse->iSelfTab = iDataCur + 1; pParse->iSelfTab = iDataCur + 1;
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL); SQLITE_JUMPIFNULL);
pParse->iSelfTab = 0; pParse->iSelfTab = 0;
@@ -945,6 +943,5 @@ int sqlite3GenerateIndexKey(
void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
if( iLabel ){ if( iLabel ){
sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel);
sqlite3ExprCachePop(pParse);
} }
} }

View File

@@ -581,7 +581,6 @@ static void codeVectorCompare(
Expr *pL, *pR; Expr *pL, *pR;
int r1, r2; int r1, r2;
assert( i>=0 && i<nLeft ); assert( i>=0 && i<nLeft );
if( i>0 ) sqlite3ExprCachePush(pParse);
r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1); r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2); r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5); codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
@@ -593,7 +592,6 @@ static void codeVectorCompare(
testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
sqlite3ReleaseTempReg(pParse, regFree1); sqlite3ReleaseTempReg(pParse, regFree1);
sqlite3ReleaseTempReg(pParse, regFree2); sqlite3ReleaseTempReg(pParse, regFree2);
if( i>0 ) sqlite3ExprCachePop(pParse);
if( i==nLeft-1 ){ if( i==nLeft-1 ){
break; break;
} }
@@ -2627,7 +2625,6 @@ int sqlite3CodeSubselect(
int rReg = 0; /* Register storing resulting */ int rReg = 0; /* Register storing resulting */
Vdbe *v = sqlite3GetVdbe(pParse); Vdbe *v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return 0; if( NEVER(v==0) ) return 0;
sqlite3ExprCachePush(pParse);
/* The evaluation of the IN/EXISTS/SELECT must be repeated every time it /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it
** is encountered if any of the following is true: ** is encountered if any of the following is true:
@@ -2763,7 +2760,6 @@ int sqlite3CodeSubselect(
sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
}else{ }else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3ExprCacheAffinityChange(pParse, r3, 1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
} }
} }
@@ -2844,7 +2840,6 @@ int sqlite3CodeSubselect(
if( jmpIfDynamic>=0 ){ if( jmpIfDynamic>=0 ){
sqlite3VdbeJumpHere(v, jmpIfDynamic); sqlite3VdbeJumpHere(v, jmpIfDynamic);
} }
sqlite3ExprCachePop(pParse);
return rReg; return rReg;
} }
@@ -2963,7 +2958,6 @@ static void sqlite3ExprCodeIN(
** aiMap[] array contains a mapping from the original LHS field order to ** aiMap[] array contains a mapping from the original LHS field order to
** the field order that matches the RHS index. ** the field order that matches the RHS index.
*/ */
sqlite3ExprCachePush(pParse);
rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy);
for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */ for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */
if( i==nVector ){ if( i==nVector ){
@@ -3122,7 +3116,6 @@ static void sqlite3ExprCodeIN(
sqlite3ExprCodeIN_finished: sqlite3ExprCodeIN_finished:
if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs);
sqlite3ExprCachePop(pParse);
VdbeComment((v, "end IN expr")); VdbeComment((v, "end IN expr"));
sqlite3ExprCodeIN_oom_error: sqlite3ExprCodeIN_oom_error:
sqlite3DbFree(pParse->db, aiMap); sqlite3DbFree(pParse->db, aiMap);
@@ -3190,152 +3183,6 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
} }
} }
/*
** Erase column-cache entry number i
*/
static void cacheEntryClear(Parse *pParse, int i){
if( pParse->aColCache[i].tempReg ){
if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
}
}
pParse->nColCache--;
if( i<pParse->nColCache ){
pParse->aColCache[i] = pParse->aColCache[pParse->nColCache];
}
}
/*
** Record in the column cache that a particular column from a
** particular table is stored in a particular register.
*/
void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
int i;
int minLru;
int idxLru;
struct yColCache *p;
/* Unless an error has occurred, register numbers are always positive. */
assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed );
assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */
/* The SQLITE_ColumnCache flag disables the column cache. This is used
** for testing only - to verify that SQLite always gets the same answer
** with and without the column cache.
*/
if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return;
/* First replace any existing entry.
**
** Actually, the way the column cache is currently used, we are guaranteed
** that the object will never already be in cache. Verify this guarantee.
*/
#ifndef NDEBUG
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
assert( p->iTable!=iTab || p->iColumn!=iCol );
}
#endif
#ifdef SQLITE_DEBUG_COLUMNCACHE
/* Add a SetTabCol opcode for run-time verification that the column
** cache is working correctly.
*/
sqlite3VdbeAddOp3(pParse->pVdbe, OP_SetTabCol, iTab, iCol, iReg);
#endif
/* If the cache is already full, delete the least recently used entry */
if( pParse->nColCache>=SQLITE_N_COLCACHE ){
minLru = 0x7fffffff;
idxLru = -1;
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
if( p->lru<minLru ){
idxLru = i;
minLru = p->lru;
}
}
p = &pParse->aColCache[idxLru];
}else{
p = &pParse->aColCache[pParse->nColCache++];
}
/* Add the new entry to the end of the cache */
p->iLevel = pParse->iCacheLevel;
p->iTable = iTab;
p->iColumn = iCol;
p->iReg = iReg;
p->tempReg = 0;
p->lru = pParse->iCacheCnt++;
}
/*
** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
** Purge the range of registers from the column cache.
*/
void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
int i = 0;
while( i<pParse->nColCache ){
struct yColCache *p = &pParse->aColCache[i];
if( p->iReg >= iReg && p->iReg < iReg+nReg ){
cacheEntryClear(pParse, i);
}else{
i++;
}
}
}
/*
** Remember the current column cache context. Any new entries added
** added to the column cache after this call are removed when the
** corresponding pop occurs.
*/
void sqlite3ExprCachePush(Parse *pParse){
pParse->iCacheLevel++;
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("PUSH to %d\n", pParse->iCacheLevel);
}
#endif
}
/*
** Remove from the column cache any entries that were added since the
** the previous sqlite3ExprCachePush operation. In other words, restore
** the cache to the state it was in prior the most recent Push.
*/
void sqlite3ExprCachePop(Parse *pParse){
int i = 0;
assert( pParse->iCacheLevel>=1 );
pParse->iCacheLevel--;
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("POP to %d\n", pParse->iCacheLevel);
}
#endif
while( i<pParse->nColCache ){
if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){
cacheEntryClear(pParse, i);
}else{
i++;
}
}
}
/*
** When a cached column is reused, make sure that its register is
** no longer available as a temp register. ticket #3879: that same
** register might be in the cache in multiple places, so be sure to
** get them all.
*/
static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
int i;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
if( p->iReg==iReg ){
p->tempReg = 0;
}
}
}
/* Generate code that will load into register regOut a value that is /* Generate code that will load into register regOut a value that is
** appropriate for the iIdxCol-th column of index pIdx. ** appropriate for the iIdxCol-th column of index pIdx.
@@ -3391,12 +3238,7 @@ void sqlite3ExprCodeGetColumnOfTable(
/* /*
** Generate code that will extract the iColumn-th column from ** Generate code that will extract the iColumn-th column from
** table pTab and store the column value in a register. ** table pTab and store the column value in register iReg.
**
** An effort is made to store the column value in register iReg. This
** is not garanteeed for GetColumn() - the result can be stored in
** any register. But the result is guaranteed to land in register iReg
** for GetColumnToReg().
** **
** There must be an open cursor to pTab in iTable when this routine ** There must be an open cursor to pTab in iTable when this routine
** is called. If iColumn<0 then code is generated that extracts the rowid. ** is called. If iColumn<0 then code is generated that extracts the rowid.
@@ -3410,99 +3252,23 @@ int sqlite3ExprCodeGetColumn(
u8 p5 /* P5 value for OP_Column + FLAGS */ u8 p5 /* P5 value for OP_Column + FLAGS */
){ ){
Vdbe *v = pParse->pVdbe; Vdbe *v = pParse->pVdbe;
int i;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
if( p->iTable==iTable && p->iColumn==iColumn ){
p->lru = pParse->iCacheCnt++;
sqlite3ExprCachePinRegister(pParse, p->iReg);
#ifdef SQLITE_DEBUG_COLUMNCACHE
sqlite3VdbeAddOp3(v, OP_VerifyTabCol, iTable, iColumn, p->iReg);
#endif
return p->iReg;
}
}
assert( v!=0 ); assert( v!=0 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg); sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
if( p5 ){ if( p5 ){
sqlite3VdbeChangeP5(v, p5); sqlite3VdbeChangeP5(v, p5);
}else{
sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
} }
return iReg; return iReg;
} }
void sqlite3ExprCodeGetColumnToReg(
Parse *pParse, /* Parsing and code generating context */
Table *pTab, /* Description of the table we are reading from */
int iColumn, /* Index of the table column */
int iTable, /* The cursor pointing to the table */
int iReg /* Store results here */
){
int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0);
if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg);
}
/*
** Clear all column cache entries.
*/
void sqlite3ExprCacheClear(Parse *pParse){
int i;
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("CLEAR\n");
}
#endif
for(i=0; i<pParse->nColCache; i++){
if( pParse->aColCache[i].tempReg
&& pParse->nTempReg<ArraySize(pParse->aTempReg)
){
pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
}
}
pParse->nColCache = 0;
}
/*
** Record the fact that an affinity change has occurred on iCount
** registers starting with iStart.
*/
void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
sqlite3ExprCacheRemove(pParse, iStart, iCount);
}
/* /*
** Generate code to move content from registers iFrom...iFrom+nReg-1 ** Generate code to move content from registers iFrom...iFrom+nReg-1
** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. ** over to iTo..iTo+nReg-1.
*/ */
void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo ); assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
sqlite3ExprCacheRemove(pParse, iFrom, nReg);
} }
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
/*
** Return true if any register in the range iFrom..iTo (inclusive)
** is used as part of the column cache.
**
** This routine is used within assert() and testcase() macros only
** and does not appear in a normal build.
*/
static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
int i;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
int r = p->iReg;
if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
}
return 0;
}
#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
/* /*
** Convert a scalar expression node to a TK_REGISTER referencing ** Convert a scalar expression node to a TK_REGISTER referencing
** register iReg. The caller must ensure that iReg already contains ** register iReg. The caller must ensure that iReg already contains
@@ -3683,8 +3449,6 @@ expr_code_doover:
} }
sqlite3VdbeAddOp2(v, OP_Cast, target, sqlite3VdbeAddOp2(v, OP_Cast, target,
sqlite3AffinityType(pExpr->u.zToken, 0)); sqlite3AffinityType(pExpr->u.zToken, 0));
testcase( usedAsColumnCache(pParse, inReg, inReg) );
sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
return inReg; return inReg;
} }
#endif /* SQLITE_OMIT_CAST */ #endif /* SQLITE_OMIT_CAST */
@@ -3870,10 +3634,7 @@ expr_code_doover:
for(i=1; i<nFarg; i++){ for(i=1; i<nFarg; i++){
sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce); sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
VdbeCoverage(v); VdbeCoverage(v);
sqlite3ExprCacheRemove(pParse, target, 1);
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target); sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
sqlite3ExprCachePop(pParse);
} }
sqlite3VdbeResolveLabel(v, endCoalesce); sqlite3VdbeResolveLabel(v, endCoalesce);
break; break;
@@ -3939,10 +3700,8 @@ expr_code_doover:
} }
} }
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, sqlite3ExprCodeExprList(pParse, pFarg, r1, 0,
SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */
}else{ }else{
r1 = 0; r1 = 0;
} }
@@ -4115,9 +3874,7 @@ expr_code_doover:
case TK_IF_NULL_ROW: { case TK_IF_NULL_ROW: {
int addrINR; int addrINR;
addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
sqlite3ExprCachePush(pParse);
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
sqlite3ExprCachePop(pParse);
sqlite3VdbeJumpHere(v, addrINR); sqlite3VdbeJumpHere(v, addrINR);
sqlite3VdbeChangeP3(v, addrINR, inReg); sqlite3VdbeChangeP3(v, addrINR, inReg);
break; break;
@@ -4154,7 +3911,6 @@ expr_code_doover:
Expr opCompare; /* The X==Ei expression */ Expr opCompare; /* The X==Ei expression */
Expr *pX; /* The X expression */ Expr *pX; /* The X expression */
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
assert(pExpr->x.pList->nExpr > 0); assert(pExpr->x.pList->nExpr > 0);
@@ -4178,7 +3934,6 @@ expr_code_doover:
regFree1 = 0; regFree1 = 0;
} }
for(i=0; i<nExpr-1; i=i+2){ for(i=0; i<nExpr-1; i=i+2){
sqlite3ExprCachePush(pParse);
if( pX ){ if( pX ){
assert( pTest!=0 ); assert( pTest!=0 );
opCompare.pRight = aListelem[i].pExpr; opCompare.pRight = aListelem[i].pExpr;
@@ -4191,18 +3946,13 @@ expr_code_doover:
testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeGoto(v, endLabel); sqlite3VdbeGoto(v, endLabel);
sqlite3ExprCachePop(pParse);
sqlite3VdbeResolveLabel(v, nextCase); sqlite3VdbeResolveLabel(v, nextCase);
} }
if( (nExpr&1)!=0 ){ if( (nExpr&1)!=0 ){
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target); sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
sqlite3ExprCachePop(pParse);
}else{ }else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target); sqlite3VdbeAddOp2(v, OP_Null, 0, target);
} }
assert( pParse->db->mallocFailed || pParse->nErr>0
|| pParse->iCacheLevel==iCacheLevel );
sqlite3VdbeResolveLabel(v, endLabel); sqlite3VdbeResolveLabel(v, endLabel);
break; break;
} }
@@ -4562,18 +4312,14 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
int d2 = sqlite3VdbeMakeLabel(v); int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 ); testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2); sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse);
break; break;
} }
case TK_OR: { case TK_OR: {
testcase( jumpIfNull==0 ); testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse);
break; break;
} }
case TK_NOT: { case TK_NOT: {
@@ -4732,19 +4478,15 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_AND: { case TK_AND: {
testcase( jumpIfNull==0 ); testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse);
break; break;
} }
case TK_OR: { case TK_OR: {
int d2 = sqlite3VdbeMakeLabel(v); int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 ); testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2); sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse);
break; break;
} }
case TK_NOT: { case TK_NOT: {
@@ -5512,21 +5254,9 @@ int sqlite3GetTempReg(Parse *pParse){
/* /*
** Deallocate a register, making available for reuse for some other ** Deallocate a register, making available for reuse for some other
** purpose. ** purpose.
**
** If a register is currently being used by the column cache, then
** the deallocation is deferred until the column cache line that uses
** the register becomes stale.
*/ */
void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
int i;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
if( p->iReg==iReg ){
p->tempReg = 1;
return;
}
}
pParse->aTempReg[pParse->nTempReg++] = iReg; pParse->aTempReg[pParse->nTempReg++] = iReg;
} }
} }
@@ -5540,7 +5270,6 @@ int sqlite3GetTempRange(Parse *pParse, int nReg){
i = pParse->iRangeReg; i = pParse->iRangeReg;
n = pParse->nRangeReg; n = pParse->nRangeReg;
if( nReg<=n ){ if( nReg<=n ){
assert( !usedAsColumnCache(pParse, i, i+n-1) );
pParse->iRangeReg += nReg; pParse->iRangeReg += nReg;
pParse->nRangeReg -= nReg; pParse->nRangeReg -= nReg;
}else{ }else{
@@ -5554,7 +5283,6 @@ void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
sqlite3ReleaseTempReg(pParse, iReg); sqlite3ReleaseTempReg(pParse, iReg);
return; return;
} }
sqlite3ExprCacheRemove(pParse, iReg, nReg);
if( nReg>pParse->nRangeReg ){ if( nReg>pParse->nRangeReg ){
pParse->nRangeReg = nReg; pParse->nRangeReg = nReg;
pParse->iRangeReg = iReg; pParse->iRangeReg = iReg;

View File

@@ -1533,7 +1533,6 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeVerifyAbortable(v, onError); sqlite3VdbeVerifyAbortable(v, onError);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
VdbeCoverage(v); VdbeCoverage(v);
sqlite3ExprCachePush(pParse);
switch( onError ){ switch( onError ){
default: { default: {
@@ -1610,7 +1609,6 @@ void sqlite3GenerateConstraintChecks(
break; break;
} }
} }
sqlite3ExprCachePop(pParse);
sqlite3VdbeResolveLabel(v, addrRowidOk); sqlite3VdbeResolveLabel(v, addrRowidOk);
if( sAddr.ipkTop ){ if( sAddr.ipkTop ){
sAddr.ipkBtm = sqlite3VdbeAddOp0(v, OP_Goto); sAddr.ipkBtm = sqlite3VdbeAddOp0(v, OP_Goto);
@@ -1744,7 +1742,6 @@ void sqlite3GenerateConstraintChecks(
} }
/* Check to see if the new index entry will be unique */ /* Check to see if the new index entry will be unique */
sqlite3ExprCachePush(pParse);
sqlite3VdbeVerifyAbortable(v, onError); sqlite3VdbeVerifyAbortable(v, onError);
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v); regIdx, pIdx->nKeyCol); VdbeCoverage(v);
@@ -1850,7 +1847,6 @@ void sqlite3GenerateConstraintChecks(
}else{ }else{
sqlite3VdbeResolveLabel(v, addrUniqueOk); sqlite3VdbeResolveLabel(v, addrUniqueOk);
} }
sqlite3ExprCachePop(pParse);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
} }
@@ -1954,7 +1950,6 @@ void sqlite3CompleteInsertion(
sqlite3SetMakeRecordP5(v, pTab); sqlite3SetMakeRecordP5(v, pTab);
if( !bAffinityDone ){ if( !bAffinityDone ){
sqlite3TableAffinity(v, pTab, 0); sqlite3TableAffinity(v, pTab, 0);
sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
} }
if( pParse->nested ){ if( pParse->nested ){
pik_flags = 0; pik_flags = 0;

View File

@@ -1550,7 +1550,6 @@ void sqlite3Pragma(
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur); 1, 0, &iDataCur, &iIdxCur);
/* reg[7] counts the number of entries in the table. /* reg[7] counts the number of entries in the table.
@@ -1593,7 +1592,6 @@ void sqlite3Pragma(
char *zErr; char *zErr;
int k; int k;
pParse->iSelfTab = iDataCur + 1; pParse->iSelfTab = iDataCur + 1;
sqlite3ExprCachePush(pParse);
for(k=pCheck->nExpr-1; k>0; k--){ for(k=pCheck->nExpr-1; k>0; k--){
sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
} }
@@ -1606,7 +1604,6 @@ void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
integrityCheckResultRow(v); integrityCheckResultRow(v);
sqlite3VdbeResolveLabel(v, addrCkOk); sqlite3VdbeResolveLabel(v, addrCkOk);
sqlite3ExprCachePop(pParse);
} }
sqlite3ExprListDelete(db, pCheck); sqlite3ExprListDelete(db, pCheck);
} }

View File

@@ -1149,7 +1149,6 @@ static void selectInnerLoop(
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol); r1, pDest->zAffSdst, nResultCol);
sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r1);
} }
@@ -1193,7 +1192,6 @@ static void selectInnerLoop(
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
}else{ }else{
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
} }
break; break;
} }
@@ -1550,7 +1548,6 @@ static void generateSortTail(
assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) ); assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid,
pDest->zAffSdst, nColumn); pDest->zAffSdst, nColumn);
sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn);
break; break;
} }
@@ -1565,7 +1562,6 @@ static void generateSortTail(
testcase( eDest==SRT_Coroutine ); testcase( eDest==SRT_Coroutine );
if( eDest==SRT_Output ){ if( eDest==SRT_Output ){
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
}else{ }else{
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
} }
@@ -2166,7 +2162,6 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
** The current implementation interprets "LIMIT 0" to mean ** The current implementation interprets "LIMIT 0" to mean
** no rows. ** no rows.
*/ */
sqlite3ExprCacheClear(pParse);
if( pLimit ){ if( pLimit ){
assert( pLimit->op==TK_LIMIT ); assert( pLimit->op==TK_LIMIT );
assert( pLimit->pLeft!=0 ); assert( pLimit->pLeft!=0 );
@@ -2952,7 +2947,6 @@ static int generateOutputSubroutine(
r1 = sqlite3GetTempReg(pParse); r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
r1, pDest->zAffSdst, pIn->nSdst); r1, pDest->zAffSdst, pIn->nSdst);
sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst); pIn->iSdst, pIn->nSdst);
sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r1);
@@ -2995,7 +2989,6 @@ static int generateOutputSubroutine(
default: { default: {
assert( pDest->eDest==SRT_Output ); assert( pDest->eDest==SRT_Output );
sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst);
sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
break; break;
} }
} }
@@ -5336,36 +5329,21 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem); sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem);
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg); sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg); sqlite3ReleaseTempRange(pParse, regAgg, nArg);
if( addrNext ){ if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext); sqlite3VdbeResolveLabel(v, addrNext);
sqlite3ExprCacheClear(pParse);
} }
} }
/* Before populating the accumulator registers, clear the column cache.
** Otherwise, if any of the required column values are already present
** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value
** to pC->iMem. But by the time the value is used, the original register
** may have been used, invalidating the underlying buffer holding the
** text or blob value. See ticket [883034dcb5].
**
** Another solution would be to change the OP_SCopy used to copy cached
** values to an OP_Copy.
*/
if( regHit==0 && pAggInfo->nAccumulator ){ if( regHit==0 && pAggInfo->nAccumulator ){
regHit = regAcc; regHit = regAcc;
} }
if( regHit ){ if( regHit ){
addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v); addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
} }
sqlite3ExprCacheClear(pParse);
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
} }
pAggInfo->directMode = 0; pAggInfo->directMode = 0;
sqlite3ExprCacheClear(pParse);
if( addrHitTest ){ if( addrHitTest ){
sqlite3VdbeJumpHere(v, addrHitTest); sqlite3VdbeJumpHere(v, addrHitTest);
} }
@@ -6318,15 +6296,14 @@ int sqlite3Select(
} }
} }
regBase = sqlite3GetTempRange(pParse, nCol); regBase = sqlite3GetTempRange(pParse, nCol);
sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0);
j = nGroupBy; j = nGroupBy;
for(i=0; i<sAggInfo.nColumn; i++){ for(i=0; i<sAggInfo.nColumn; i++){
struct AggInfo_col *pCol = &sAggInfo.aCol[i]; struct AggInfo_col *pCol = &sAggInfo.aCol[i];
if( pCol->iSorterColumn>=j ){ if( pCol->iSorterColumn>=j ){
int r1 = j + regBase; int r1 = j + regBase;
sqlite3ExprCodeGetColumnToReg(pParse, sqlite3ExprCodeGetColumnOfTable(v,
pCol->pTab, pCol->iColumn, pCol->iTable, r1); pCol->pTab, pCol->iTable, pCol->iColumn, r1);
j++; j++;
} }
} }
@@ -6342,8 +6319,6 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
sAggInfo.useSortingIdx = 1; sAggInfo.useSortingIdx = 1;
sqlite3ExprCacheClear(pParse);
} }
/* If the index or temporary table used by the GROUP BY sort /* If the index or temporary table used by the GROUP BY sort
@@ -6366,7 +6341,6 @@ int sqlite3Select(
** from the previous row currently stored in a0, a1, a2... ** from the previous row currently stored in a0, a1, a2...
*/ */
addrTopOfLoop = sqlite3VdbeCurrentAddr(v); addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3ExprCacheClear(pParse);
if( groupBySort ){ if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
sortOut, sortPTab); sortOut, sortPTab);

View File

@@ -367,17 +367,6 @@
# undef NDEBUG # undef NDEBUG
#endif #endif
/* SQLITE_DEBUG_COLUMNCACHE is synomous with SQLITE_DEBUG. The
** SQLITE_DEBUG_COLUMNCACHE symbol only exists to provide a convenient
** way to search for all code that deals with verifying correct behavior
** of the column cache.
*/
#ifdef SQLITE_DEBUG
# define SQLITE_DEBUG_COLUMNCACHE 1
#else
# undef SQLIT_DEBUG_COLUMNCACHE
#endif
/* /*
** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on. ** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on.
*/ */
@@ -1569,7 +1558,7 @@ struct sqlite3 {
** selectively disable various optimizations. ** selectively disable various optimizations.
*/ */
#define SQLITE_QueryFlattener 0x0001 /* Query flattening */ #define SQLITE_QueryFlattener 0x0001 /* Query flattening */
#define SQLITE_ColumnCache 0x0002 /* Column cache */ /* 0x0002 available for reuse */
#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */ #define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
@@ -2968,13 +2957,6 @@ struct AutoincInfo {
int regCtr; /* Memory register holding the rowid counter */ int regCtr; /* Memory register holding the rowid counter */
}; };
/*
** Size of the column cache
*/
#ifndef SQLITE_N_COLCACHE
# define SQLITE_N_COLCACHE 10
#endif
/* /*
** At least one instance of the following structure is created for each ** At least one instance of the following structure is created for each
** trigger that may be fired while parsing an INSERT, UPDATE or DELETE ** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
@@ -3050,7 +3032,6 @@ struct Parse {
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
u8 okConstFactor; /* OK to factor out constants */ u8 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 nColCache; /* Number of entries in aColCache[] */
int nRangeReg; /* Size of the temporary register block */ int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */ int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */ int nErr; /* Number of errors seen */
@@ -3060,8 +3041,6 @@ struct Parse {
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table associated with an index on expr, or negative int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */ ** of the base register during check-constraint eval */
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
int nLabel; /* Number of labels used */ int nLabel; /* Number of labels used */
int *aLabel; /* Space to hold the labels */ int *aLabel; /* Space to hold the labels */
ExprList *pConstExpr;/* Constant expressions */ ExprList *pConstExpr;/* Constant expressions */
@@ -3091,17 +3070,9 @@ struct Parse {
** Fields above must be initialized to zero. The fields that follow, ** Fields above must be initialized to zero. The fields that follow,
** down to the beginning of the recursive section, do not need to be ** down to the beginning of the recursive section, do not need to be
** initialized as they will be set before being used. The boundary is ** initialized as they will be set before being used. The boundary is
** determined by offsetof(Parse,aColCache). ** determined by offsetof(Parse,aTempReg).
**************************************************************************/ **************************************************************************/
struct yColCache {
int iTable; /* Table cursor number */
i16 iColumn; /* Table column number */
u8 tempReg; /* iReg is a temp register that needs to be freed */
int iLevel; /* Nesting level */
int iReg; /* Reg with value of this column. 0 means none. */
int lru; /* Least recently used entry has the smallest value */
} aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
int aTempReg[8]; /* Holding area for temporary registers */ int aTempReg[8]; /* Holding area for temporary registers */
Token sNameToken; /* Token with unqualified schema object name */ Token sNameToken; /* Token with unqualified schema object name */
@@ -3143,7 +3114,7 @@ struct Parse {
/* /*
** Sizes and pointers of various parts of the Parse object. ** Sizes and pointers of various parts of the Parse object.
*/ */
#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ #define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
@@ -3927,15 +3898,8 @@ int sqlite3WhereOkOnePass(WhereInfo*, int*);
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ #define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int);
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int, int);
void sqlite3ExprCacheStore(Parse*, int, int, int);
void sqlite3ExprCachePush(Parse*);
void sqlite3ExprCachePop(Parse*);
void sqlite3ExprCacheRemove(Parse*, int, int);
void sqlite3ExprCacheClear(Parse*);
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
void sqlite3ExprCode(Parse*, Expr*, int); void sqlite3ExprCode(Parse*, Expr*, int);
void sqlite3ExprCodeCopy(Parse*, Expr*, int); void sqlite3ExprCodeCopy(Parse*, Expr*, int);
void sqlite3ExprCodeFactorable(Parse*, Expr*, int); void sqlite3ExprCodeFactorable(Parse*, Expr*, int);

View File

@@ -6982,7 +6982,6 @@ static int SQLITE_TCLAPI optimization_control(
{ "all", SQLITE_AllOpts }, { "all", SQLITE_AllOpts },
{ "none", 0 }, { "none", 0 },
{ "query-flattener", SQLITE_QueryFlattener }, { "query-flattener", SQLITE_QueryFlattener },
{ "column-cache", SQLITE_ColumnCache },
{ "groupby-order", SQLITE_GroupByOrder }, { "groupby-order", SQLITE_GroupByOrder },
{ "factor-constants", SQLITE_FactorOutConst }, { "factor-constants", SQLITE_FactorOutConst },
{ "distinct-opt", SQLITE_DistinctOpt }, { "distinct-opt", SQLITE_DistinctOpt },

View File

@@ -610,13 +610,7 @@ void sqlite3Update(
*/ */
testcase( i==31 ); testcase( i==31 );
testcase( i==32 ); testcase( i==32 );
sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
if( tmask & TRIGGER_BEFORE ){
/* This value will be recomputed in After-BEFORE-trigger-reload-loop
** below, so make sure that it is not cached and reused.
** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28. */
sqlite3ExprCacheRemove(pParse, regNew+i, 1);
}
}else{ }else{
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
} }

View File

@@ -36,18 +36,6 @@
# define memAboutToChange(P,M) # define memAboutToChange(P,M)
#endif #endif
/*
** Given a cursor number and a column for a table or index, compute a
** hash value for use in the Mem.iTabColHash value. The iTabColHash
** column is only used for verification - it is omitted from production
** builds. Collisions are harmless in the sense that the correct answer
** still results. The only harm of collisions is that they can potential
** reduce column-cache error detection during SQLITE_DEBUG builds.
**
** No valid hash should be 0.
*/
#define TableColumnHash(T,C) (((u32)(T)<<16)^(u32)(C+2))
/* /*
** The following global variable is incremented every time a cursor ** The following global variable is incremented every time a cursor
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test ** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test
@@ -1308,7 +1296,6 @@ case OP_Copy: {
Deephemeralize(pOut); Deephemeralize(pOut);
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
pOut->pScopyFrom = 0; pOut->pScopyFrom = 0;
pOut->iTabColHash = 0;
#endif #endif
REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut); REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut);
if( (n--)==0 ) break; if( (n--)==0 ) break;
@@ -1925,6 +1912,11 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
u16 flags1; /* Copy of initial value of pIn1->flags */ u16 flags1; /* Copy of initial value of pIn1->flags */
u16 flags3; /* Copy of initial value of pIn3->flags */ u16 flags3; /* Copy of initial value of pIn3->flags */
/* The only way for P1 and P3 to be the same is when comparing constants.
** But in that case, the affinities will always be SQLITE_AFF_BLOB or none */
assert( pOp->p1!=pOp->p3 || (pOp->p5 & SQLITE_AFF_MASK)<=SQLITE_AFF_BLOB );
testcase( pOp->p1==pOp->p3 );
pIn1 = &aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3]; pIn3 = &aMem[pOp->p3];
flags1 = pIn1->flags; flags1 = pIn1->flags;
@@ -1972,7 +1964,11 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
if( (flags1 | flags3)&MEM_Str ){ if( (flags1 | flags3)&MEM_Str ){
if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn1,0); applyNumericAffinity(pIn1,0);
testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */ /* testcase( flags3!=pIn3->flags );
** this used to be possible with pIn1==pIn3, but not since
** the column cache was removed. The following assignment
** is essentially a no-op. But, it prevents defense-in-depth
** in case our analysis is incorrect, so it is left in. */
flags3 = pIn3->flags; flags3 = pIn3->flags;
} }
if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
@@ -7446,34 +7442,6 @@ case OP_Abortable: {
} }
#endif #endif
#ifdef SQLITE_DEBUG_COLUMNCACHE
/* Opcode: SetTabCol P1 P2 P3 * *
**
** Set a flag in register REG[P3] indicating that it holds the value
** of column P2 from the table on cursor P1. This flag is checked
** by a subsequent VerifyTabCol opcode.
**
** This opcode only appears SQLITE_DEBUG builds. It is used to verify
** that the expression table column cache is working correctly.
*/
case OP_SetTabCol: {
aMem[pOp->p3].iTabColHash = TableColumnHash(pOp->p1,pOp->p2);
break;
}
/* Opcode: VerifyTabCol P1 P2 P3 * *
**
** Verify that register REG[P3] contains the value of column P2 from
** cursor P1. Assert() if this is not the case.
**
** This opcode only appears SQLITE_DEBUG builds. It is used to verify
** that the expression table column cache is working correctly.
*/
case OP_VerifyTabCol: {
assert( aMem[pOp->p3].iTabColHash == TableColumnHash(pOp->p1,pOp->p2) );
break;
}
#endif
/* Opcode: Noop * * * * * /* Opcode: Noop * * * * *
** **
** Do nothing. This instruction is often useful as a jump ** Do nothing. This instruction is often useful as a jump

View File

@@ -211,10 +211,6 @@ struct sqlite3_value {
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
u16 mScopyFlags; /* flags value immediately after the shallow copy */ u16 mScopyFlags; /* flags value immediately after the shallow copy */
#endif #endif
#ifdef SQLITE_DEBUG_COLUMNCACHE
u32 iTabColHash; /* Hash of table.column that is origin of this value */
u32 iPadding; /* sqlite3_value objects must be 8-byte aligned */
#endif
}; };
/* /*

View File

@@ -971,9 +971,6 @@ static const Mem *columnNullValue(void){
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
/* .pScopyFrom = */ (Mem*)0, /* .pScopyFrom = */ (Mem*)0,
/* .mScopyFlags= */ 0, /* .mScopyFlags= */ 0,
#endif
#ifdef SQLITE_DEBUG_COLUMNCACHE
/* .iTabColHash= */ 0,
#endif #endif
}; };
return &nullMem; return &nullMem;

View File

@@ -193,14 +193,6 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
#endif #endif
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){ if( p->db->flags & SQLITE_VdbeAddopTrace ){
int jj, kk;
Parse *pParse = p->pParse;
for(jj=kk=0; jj<pParse->nColCache; jj++){
struct yColCache *x = pParse->aColCache + jj;
printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
kk++;
}
if( kk ) printf("\n");
sqlite3VdbePrintOp(0, i, &p->aOp[i]); sqlite3VdbePrintOp(0, i, &p->aOp[i]);
test_addop_breakpoint(); test_addop_breakpoint();
} }
@@ -1646,9 +1638,6 @@ static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
p->szMalloc = 0; p->szMalloc = 0;
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
p->pScopyFrom = 0; p->pScopyFrom = 0;
#endif
#ifdef SQLITE_DEBUG_COLUMNCACHE
p->iTabColHash = 0;
#endif #endif
p++; p++;
} }

View File

@@ -934,9 +934,6 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
} }
} }
pMem->pScopyFrom = 0; pMem->pScopyFrom = 0;
#ifdef SQLITE_DEBUG_COLUMN_CACHE
pMem->iTabColHash = 0;
#endif
} }
#endif /* SQLITE_DEBUG */ #endif /* SQLITE_DEBUG */
@@ -957,9 +954,6 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
assert( pTo->db==pFrom->db ); assert( pTo->db==pFrom->db );
if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; } if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; }
memcpy(pTo, pFrom, MEMCELLSIZE); memcpy(pTo, pFrom, MEMCELLSIZE);
#ifdef SQLITE_DEBUG_COLUMNCACHE
pTo->iTabColHash = pFrom->iTabColHash;
#endif
if( (pFrom->flags&MEM_Static)==0 ){ if( (pFrom->flags&MEM_Static)==0 ){
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
assert( srcType==MEM_Ephem || srcType==MEM_Static ); assert( srcType==MEM_Ephem || srcType==MEM_Static );
@@ -977,9 +971,6 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
assert( (pFrom->flags & MEM_RowSet)==0 ); assert( (pFrom->flags & MEM_RowSet)==0 );
if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE); memcpy(pTo, pFrom, MEMCELLSIZE);
#ifdef SQLITE_DEBUG_COLUMNCACHE
pTo->iTabColHash = pFrom->iTabColHash;
#endif
pTo->flags &= ~MEM_Dyn; pTo->flags &= ~MEM_Dyn;
if( pTo->flags&(MEM_Str|MEM_Blob) ){ if( pTo->flags&(MEM_Str|MEM_Blob) ){
if( 0==(pFrom->flags&MEM_Static) ){ if( 0==(pFrom->flags&MEM_Static) ){

View File

@@ -802,7 +802,6 @@ static void constructAutomaticIndex(
VdbeComment((v, "for %s", pTable->zName)); VdbeComment((v, "for %s", pTable->zName));
/* Fill the automatic index with content */ /* Fill the automatic index with content */
sqlite3ExprCachePush(pParse);
pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
if( pTabItem->fg.viaCoroutine ){ if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn; int regYield = pTabItem->regReturn;
@@ -839,7 +838,6 @@ static void constructAutomaticIndex(
sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
sqlite3VdbeJumpHere(v, addrTop); sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ExprCachePop(pParse);
/* Jump here when skipping the initialization */ /* Jump here when skipping the initialization */
sqlite3VdbeJumpHere(v, addrInit); sqlite3VdbeJumpHere(v, addrInit);
@@ -5077,7 +5075,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Generate loop termination code. /* Generate loop termination code.
*/ */
VdbeModuleComment((v, "End WHERE-core")); VdbeModuleComment((v, "End WHERE-core"));
sqlite3ExprCacheClear(pParse);
for(i=pWInfo->nLevel-1; i>=0; i--){ for(i=pWInfo->nLevel-1; i>=0; i--){
int addr; int addr;
pLevel = &pWInfo->a[i]; pLevel = &pWInfo->a[i];

View File

@@ -347,7 +347,6 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
/* Code the OP_Affinity opcode if there is anything left to do. */ /* Code the OP_Affinity opcode if there is anything left to do. */
if( n>0 ){ if( n>0 ){
sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n); sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n);
sqlite3ExprCacheAffinityChange(pParse, base, n);
} }
} }
@@ -1256,7 +1255,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
int nConstraint = pLoop->nLTerm; int nConstraint = pLoop->nLTerm;
int iIn; /* Counter for IN constraints */ int iIn; /* Counter for IN constraints */
sqlite3ExprCachePush(pParse);
iReg = sqlite3GetTempRange(pParse, nConstraint+2); iReg = sqlite3GetTempRange(pParse, nConstraint+2);
addrNotFound = pLevel->addrBrk; addrNotFound = pLevel->addrBrk;
for(j=0; j<nConstraint; j++){ for(j=0; j<nConstraint; j++){
@@ -1329,7 +1327,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** **
** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
*/ */
sqlite3ExprCachePop(pParse);
}else }else
#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -1422,7 +1419,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
VdbeCoverageIf(v, pX->op==TK_LE); VdbeCoverageIf(v, pX->op==TK_LE);
VdbeCoverageIf(v, pX->op==TK_LT); VdbeCoverageIf(v, pX->op==TK_LT);
VdbeCoverageIf(v, pX->op==TK_GE); VdbeCoverageIf(v, pX->op==TK_GE);
sqlite3ExprCacheAffinityChange(pParse, r1, 1);
sqlite3ReleaseTempReg(pParse, rTemp); sqlite3ReleaseTempReg(pParse, rTemp);
}else{ }else{
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
@@ -1457,7 +1453,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( testOp!=OP_Noop ){ if( testOp!=OP_Noop ){
iRowidReg = ++pParse->nMem; iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
VdbeCoverageIf(v, testOp==OP_Le); VdbeCoverageIf(v, testOp==OP_Le);
VdbeCoverageIf(v, testOp==OP_Lt); VdbeCoverageIf(v, testOp==OP_Lt);
@@ -1683,7 +1678,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
nConstraint = nEq; nConstraint = nEq;
if( pRangeEnd ){ if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight; Expr *pRight = pRangeEnd->pExpr->pRight;
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
codeExprOrVector(pParse, pRight, regBase+nEq, nTop); codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0 if( (pRangeEnd->wtFlags & TERM_VNULL)==0
@@ -1708,7 +1702,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
} }
}else if( bStopAtNull ){ }else if( bStopAtNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
endEq = 0; endEq = 0;
nConstraint++; nConstraint++;
} }
@@ -1742,7 +1735,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
)){ )){
iRowidReg = ++pParse->nMem; iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
VdbeCoverage(v); VdbeCoverage(v);
}else{ }else{
@@ -1977,23 +1969,23 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** row will be skipped in subsequent sub-WHERE clauses. ** row will be skipped in subsequent sub-WHERE clauses.
*/ */
if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
int r;
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
if( HasRowid(pTab) ){ if( HasRowid(pTab) ){
r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0); sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, regRowid);
jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0,
r,iSet); regRowid, iSet);
VdbeCoverage(v); VdbeCoverage(v);
}else{ }else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab); Index *pPk = sqlite3PrimaryKeyIndex(pTab);
int nPk = pPk->nKeyCol; int nPk = pPk->nKeyCol;
int iPk; int iPk;
int r;
/* Read the PK into an array of temp registers. */ /* Read the PK into an array of temp registers. */
r = sqlite3GetTempRange(pParse, nPk); r = sqlite3GetTempRange(pParse, nPk);
for(iPk=0; iPk<nPk; iPk++){ for(iPk=0; iPk<nPk; iPk++){
int iCol = pPk->aiColumn[iPk]; int iCol = pPk->aiColumn[iPk];
sqlite3ExprCodeGetColumnToReg(pParse, pTab, iCol, iCur, r+iPk); sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk);
} }
/* Check if the temp table already contains this key. If so, /* Check if the temp table already contains this key. If so,
@@ -2226,7 +2218,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit")); VdbeComment((v, "record LEFT JOIN hit"));
sqlite3ExprCacheClear(pParse);
for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){ for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED ); testcase( pTerm->wtFlags & TERM_CODED );

View File

@@ -33,6 +33,8 @@ do_test btree02-110 {
db eval BEGIN db eval BEGIN
set i 0 set i 0
db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} { db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} {
if {$a==""} {set a 0}
if {$b==""} {set b 0}
db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)} db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)}
# puts "a,b,cnt = ($a,$b,$cnt)" # puts "a,b,cnt = ($a,$b,$cnt)"
incr i incr i
@@ -47,6 +49,6 @@ do_test btree02-110 {
db eval {COMMIT; BEGIN} db eval {COMMIT; BEGIN}
} }
db one {COMMIT; SELECT count(*) FROM t1;} db one {COMMIT; SELECT count(*) FROM t1;}
} {20} } {27}
finish_test finish_test