1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Refactor the Table object to reduce its memory footprint.

FossilOrigin-Name: bbb6759bcf6e01d36dfc787a82a610d359f50aaeac8104b73883a84906d54e1f
This commit is contained in:
drh
2021-08-02 16:41:57 +00:00
parent 79cf2b7120
commit f38524d20d
17 changed files with 246 additions and 205 deletions

View File

@@ -1,5 +1,5 @@
C Refactor\sthe\sway\sthat\sDEFAULT\sexpressions\sare\sstored\son\scolumns,\sin\sorder\nto\ssave\smemory\sin\sthe\scommon\scase\swhere\sthe\scolumn\shas\sno\sDEFAULT\sclause. C Refactor\sthe\sTable\sobject\sto\sreduce\sits\smemory\sfootprint.
D 2021-07-31T20:30:41.189 D 2021-08-02T16:41:57.123
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -478,7 +478,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 87c9b91d15826cbb2d289f4cff3bc5671935ec3b238e307407087e615220788a F src/alter.c e73e2dad9338274b53c04ba5fdcb8653fef898e4709b65d7f6f3197573e4d992
F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
F src/attach.c a514e81758ba7b3a3a0501faf70af6cfc509de8810235db726cfc9f25165e929 F src/attach.c a514e81758ba7b3a3a0501faf70af6cfc509de8810235db726cfc9f25165e929
F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853 F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
@@ -488,27 +488,27 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c e204a9c8fb4fe5dbb910a863ba487f4af9b5c501254ec4ccbfcdd6b1f65b7fb4 F src/btree.c e204a9c8fb4fe5dbb910a863ba487f4af9b5c501254ec4ccbfcdd6b1f65b7fb4
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0 F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
F src/build.c 19d9283feae27045cfd5712ae4cabcac91a9b7bf619e651f1571e9637bd7f65d F src/build.c d13fc40575b08422ddb44286537b0d3d80b03f063e0c3b6577d4bf84258f1f5e
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1
F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
F src/delete.c 62451bba9fe641159e9c0b7d9d2bab1c48d0cff11e16de2d14000603d2af1fcf F src/delete.c b43f0f4db586acf0b4078e3982485c26fbec984674df513d5ade48a08a323c5a
F src/expr.c 84691a9d63baddcc6c735080a9b347e7f6feedb04c293730284999c92af95371 F src/expr.c 4e2878324f6be88a766f4e83bc3132106a9913f2bd029a4b92447626501996ce
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 1df6ad21908d84adb6d1297d7657ccd239c8ef0836e3a457d1fe15318393933b F src/fkey.c bcd5006ce061ef7b331154d176a0869440b1049c67c14c92f0233a14a701f2cc
F src/func.c c224240cbc97fa5e9c4fe9acb128716cb835ca045532bca6951b7c45b020c56c F src/func.c c224240cbc97fa5e9c4fe9acb128716cb835ca045532bca6951b7c45b020c56c
F src/global.c 5eba017ebbd887e2365e6e6e815e1619e41406b8946d17594e94116174787df5 F src/global.c 5eba017ebbd887e2365e6e6e815e1619e41406b8946d17594e94116174787df5
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 6f10127cc5c8bb3631f25bad89f6d2f9c53606df789449f6af7b8647d8f97b4f F src/insert.c 167b286e3e289dbd1dad8f5a90858e9a6221bd83902985adf110e9db9fc2db67
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 0aa9e7f08e168e3874cb54984408e3976dafdf5616d511952c425b5ac088ea3e F src/loadext.c 0aa9e7f08e168e3874cb54984408e3976dafdf5616d511952c425b5ac088ea3e
F src/main.c 5d024b9b96d9c6809e66b7f4864c3745bc8caf2a6af3b27dc0f05328f4439dfd F src/main.c 6921ce667627d0d38e67f8508d5903e074134386427688e6b4588bfe57ce06a4
F src/malloc.c cbc93cdd429c4594912017d92ab656e2579aca64dbd1c6888551275bed46f25b F src/malloc.c cbc93cdd429c4594912017d92ab656e2579aca64dbd1c6888551275bed46f25b
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -537,19 +537,19 @@ F src/parse.y 0ba0baec5de6921ec8ba8bbcf1018969144ef29d26112e17539d8fbb1662e3eb
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 388304fd2d91c39591080b5e0f3c62cfba87db20370e7e0554062bfb29740e9f F src/pcache1.c 388304fd2d91c39591080b5e0f3c62cfba87db20370e7e0554062bfb29740e9f
F src/pragma.c e8efa185aaaa4c4036fc40572b74ff9bb5317520c3a1886567093b5ac8b15381 F src/pragma.c 4a510b24e5b2321fd6bb509cd0dc8003514cb574b872dd535f49870b84ee54b1
F src/pragma.h a11b4798f9c49f156f130e1f7041a9fcc9d316a64f3501b6013acdd2e4c6f549 F src/pragma.h a11b4798f9c49f156f130e1f7041a9fcc9d316a64f3501b6013acdd2e4c6f549
F src/prepare.c 0d53d20532aada295c1690792a125adbd6435f5ce703ff0adf1b9b3605238b67 F src/prepare.c 0d53d20532aada295c1690792a125adbd6435f5ce703ff0adf1b9b3605238b67
F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c 047a822844cea769f6fdd8418a335dd4bcd8b75ab5e264f2506a0804f869b562 F src/resolve.c 047a822844cea769f6fdd8418a335dd4bcd8b75ab5e264f2506a0804f869b562
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c 99c36dd4e7c2207ebdfd8c30986ab5aaeae74d0cdbbc471420807d50c417c241 F src/select.c 2b25a79706c8a71e40f5fbc8705073c54f6a3d25f556dac9d6d91676026a0413
F src/shell.c.in 24b99dae8818d1a234732d73f4d5b49f12b510bc62735a41c04e314fafae09e3 F src/shell.c.in 24b99dae8818d1a234732d73f4d5b49f12b510bc62735a41c04e314fafae09e3
F src/sqlite.h.in 43fcf0fe2af04081f420a906fc020bde1243851ba44b0aa567a27f94bf8c3145 F src/sqlite.h.in 43fcf0fe2af04081f420a906fc020bde1243851ba44b0aa567a27f94bf8c3145
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510 F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
F src/sqliteInt.h ea94bc5f087522abe62550bb73ef1d7f78d28337fc3834cd676ef39d143ef2c2 F src/sqliteInt.h 8601c620280dcb514e6e9dfb1fa7ee005ccc56c244ac82cb48a1045ed2e7003c
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -610,8 +610,8 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c bae853ad129d1129c063de8630a3e99e306283bc40146f359b1bb91be2c08f1e F src/tokenize.c bae853ad129d1129c063de8630a3e99e306283bc40146f359b1bb91be2c08f1e
F src/treeview.c 43f88d0fd19976a60aee6867959213b438593276f1e8179048df85f416a1ab19 F src/treeview.c 43f88d0fd19976a60aee6867959213b438593276f1e8179048df85f416a1ab19
F src/trigger.c 7d16aa09e63226b6d8b3f0fc60b21cbfa596fc406288b2ebcf4266633d1ba222 F src/trigger.c 43d76cf913e65a5d06ed0768d8ded7259a5d6e284641a18acb355a302792cd05
F src/update.c d2648c47202cf54104c94b427209be0350e667fbf4b825a61cae54ef86aaf1d9 F src/update.c 985a8a45b4ff86a0231fedd584e2bd87fd6fac5168286935195ad006d032d555
F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235 F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 6ca9cf268dfaf2393866990788c0797240e20e7ba7e3a22cd076e6a3c7b1a132 F src/util.c 6ca9cf268dfaf2393866990788c0797240e20e7ba7e3a22cd076e6a3c7b1a132
@@ -621,17 +621,17 @@ F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b
F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5 F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5
F src/vdbeaux.c 202dbaf7d1570cd53678f6b0bcad7b0642e88bc5d77abc1d5b8b9a202a6a19fd F src/vdbeaux.c 202dbaf7d1570cd53678f6b0bcad7b0642e88bc5d77abc1d5b8b9a202a6a19fd
F src/vdbeblob.c c6b8db50b227f66fb404215732068df76485b5b433e5f9d4d9ac27410b218193 F src/vdbeblob.c 2f3c2ada0429045c54e5ebd48f45281c52addf4648e0d234a2718dbdeab01c80
F src/vdbemem.c 53881aa0a7845922a075b3f375695588618098871a7a4120af4c297b80fa3e64 F src/vdbemem.c 53881aa0a7845922a075b3f375695588618098871a7a4120af4c297b80fa3e64
F src/vdbesort.c cd5130f683706c1a43e165a74187745fb3351cb56052cf9dc91de820634bbde2 F src/vdbesort.c cd5130f683706c1a43e165a74187745fb3351cb56052cf9dc91de820634bbde2
F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb724 F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb724
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
F src/vtab.c 516cb50e2a57359155db7f71d98f1690dc9cae84d359a1c6801b2615dc3cf362 F src/vtab.c 75bdaec808be883b8bb69a1f0a479c3a359823c5a85a26497cd5d90d3c30b74b
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 2be08331d798237ad5d7ae0b252700ffb2b63189cb18d993496d009a93e2f81c F src/wal.c 2be08331d798237ad5d7ae0b252700ffb2b63189cb18d993496d009a93e2f81c
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac
F src/where.c 07c63dde6ab72477b964f4c81bee61ef78a246ca149bb9a560784f2e85cd78d7 F src/where.c 6e27c9f9438ddbb8aebbb83d24574a75398942b5e73b3f8cc572a39dc00f7482
F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b
F src/wherecode.c 9f1f65d11437b25cd0a1497a170514c785f19ce6ad9d3e6fc73719cb5a49012f F src/wherecode.c 9f1f65d11437b25cd0a1497a170514c785f19ce6ad9d3e6fc73719cb5a49012f
F src/whereexpr.c 3a9144a9d52e110efdc012a73b1574e7b2b4df4bf98949387cb620295eba0975 F src/whereexpr.c 3a9144a9d52e110efdc012a73b1574e7b2b4df4bf98949387cb620295eba0975
@@ -1920,7 +1920,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P d2da62a9df63036b02dadca3798de9e623c2680b3ef0c37d2b18bb88693afd7f P 8646547e54211d44c415663c33775c4268550f8332949c4731a4bb6ec9cc663a
R 2bd36d7d73ef054d58c2b5fa1473f7b9 R 8143bc84e57e339634d6338dda56d190
U drh U drh
Z d1f622cc8631b67a8482f1c93905c30a Z 0d31e4d81e774d8d4cc71b3c0a3d1311

View File

@@ -1 +1 @@
8646547e54211d44c415663c33775c4268550f8332949c4731a4bb6ec9cc663a bbb6759bcf6e01d36dfc787a82a610d359f50aaeac8104b73883a84906d54e1f

View File

@@ -175,7 +175,7 @@ void sqlite3AlterRenameTable(
} }
#ifndef SQLITE_OMIT_VIEW #ifndef SQLITE_OMIT_VIEW
if( pTab->pSelect ){ if( IsView(pTab) ){
sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName); sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
goto exit_rename_table; goto exit_rename_table;
} }
@@ -371,7 +371,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
if( pDflt && pDflt->pLeft->op==TK_NULL ){ if( pDflt && pDflt->pLeft->op==TK_NULL ){
pDflt = 0; pDflt = 0;
} }
if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){ if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){
sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
"Cannot add a REFERENCES column with non-NULL default value"); "Cannot add a REFERENCES column with non-NULL default value");
} }
@@ -415,12 +415,13 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
db->mDbFlags |= DBFLAG_PreferBuiltin; db->mDbFlags |= DBFLAG_PreferBuiltin;
/* substr() operations on characters, but addColOffset is in bytes. So we /* substr() operations on characters, but addColOffset is in bytes. So we
** have to use printf() to translate between these units: */ ** have to use printf() to translate between these units: */
assert( !IsVirtual(pTab) );
sqlite3NestedParse(pParse, sqlite3NestedParse(pParse,
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET " "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
"sql = printf('%%.%ds, ',sql) || %Q" "sql = printf('%%.%ds, ',sql) || %Q"
" || substr(sql,1+length(printf('%%.%ds',sql))) " " || substr(sql,1+length(printf('%%.%ds',sql))) "
"WHERE type = 'table' AND name = %Q", "WHERE type = 'table' AND name = %Q",
zDb, pNew->addColOffset, zCol, pNew->addColOffset, zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset,
zTab zTab
); );
sqlite3DbFree(db, zCol); sqlite3DbFree(db, zCol);
@@ -500,7 +501,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
#endif #endif
/* Make sure this is not an attempt to ALTER a view. */ /* Make sure this is not an attempt to ALTER a view. */
if( pTab->pSelect ){ if( IsView(pTab) ){
sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
goto exit_begin_add_column; goto exit_begin_add_column;
} }
@@ -509,7 +510,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
} }
sqlite3MayAbort(pParse); sqlite3MayAbort(pParse);
assert( pTab->addColOffset>0 ); assert( pTab->u.tab.addColOffset>0 );
iDb = sqlite3SchemaToIndex(db, pTab->pSchema); iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
/* Put a copy of the Table struct in Parse.pNewTable for the /* Put a copy of the Table struct in Parse.pNewTable for the
@@ -540,9 +541,10 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
pCol->hName = sqlite3StrIHash(pCol->zName); pCol->hName = sqlite3StrIHash(pCol->zName);
pCol->zColl = 0; pCol->zColl = 0;
} }
pNew->pDfltList = sqlite3ExprListDup(db, pTab->pDfltList, 0); assert( !IsVirtual(pNew) );
pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0);
pNew->pSchema = db->aDb[iDb].pSchema; pNew->pSchema = db->aDb[iDb].pSchema;
pNew->addColOffset = pTab->addColOffset; pNew->u.tab.addColOffset = pTab->u.tab.addColOffset;
pNew->nTabRef = 1; pNew->nTabRef = 1;
exit_begin_add_column: exit_begin_add_column:
@@ -562,7 +564,7 @@ exit_begin_add_column:
static int isRealTable(Parse *pParse, Table *pTab, int bDrop){ static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
const char *zType = 0; const char *zType = 0;
#ifndef SQLITE_OMIT_VIEW #ifndef SQLITE_OMIT_VIEW
if( pTab->pSelect ){ if( IsView(pTab) ){
zType = "view"; zType = "view";
} }
#endif #endif
@@ -1494,8 +1496,8 @@ static void renameColumnFunc(
sCtx.pTab = pTab; sCtx.pTab = pTab;
if( rc!=SQLITE_OK ) goto renameColumnFunc_done; if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
if( sParse.pNewTable ){ if( sParse.pNewTable ){
Select *pSelect = sParse.pNewTable->pSelect; if( IsView(sParse.pNewTable) ){
if( pSelect ){ Select *pSelect = sParse.pNewTable->u.view.pSelect;
pSelect->selFlags &= ~SF_View; pSelect->selFlags &= ~SF_View;
sParse.rc = SQLITE_OK; sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, pSelect, 0); sqlite3SelectPrep(&sParse, pSelect, 0);
@@ -1504,11 +1506,10 @@ static void renameColumnFunc(
sqlite3WalkSelect(&sWalker, pSelect); sqlite3WalkSelect(&sWalker, pSelect);
} }
if( rc!=SQLITE_OK ) goto renameColumnFunc_done; if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
}else{ }else if( IsOrdinaryTable(sParse.pNewTable) ){
/* A regular table */ /* A regular table */
int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName); int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
FKey *pFKey; FKey *pFKey;
assert( sParse.pNewTable->pSelect==0 );
sCtx.pTab = sParse.pNewTable; sCtx.pTab = sParse.pNewTable;
if( bFKOnly==0 ){ if( bFKOnly==0 ){
if( iCol<sParse.pNewTable->nCol ){ if( iCol<sParse.pNewTable->nCol ){
@@ -1535,7 +1536,8 @@ static void renameColumnFunc(
#endif #endif
} }
for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){ assert( !IsVirtual(sParse.pNewTable) );
for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
for(i=0; i<pFKey->nCol; i++){ for(i=0; i<pFKey->nCol; i++){
if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){ if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){
renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]); renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
@@ -1701,28 +1703,31 @@ static void renameTableFunc(
if( sParse.pNewTable ){ if( sParse.pNewTable ){
Table *pTab = sParse.pNewTable; Table *pTab = sParse.pNewTable;
if( pTab->pSelect ){ if( IsView(pTab) ){
if( isLegacy==0 ){ if( isLegacy==0 ){
Select *pSelect = pTab->pSelect; Select *pSelect = pTab->u.view.pSelect;
NameContext sNC; NameContext sNC;
memset(&sNC, 0, sizeof(sNC)); memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse; sNC.pParse = &sParse;
assert( pSelect->selFlags & SF_View ); assert( pSelect->selFlags & SF_View );
pSelect->selFlags &= ~SF_View; pSelect->selFlags &= ~SF_View;
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC); sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC);
if( sParse.nErr ){ if( sParse.nErr ){
rc = sParse.rc; rc = sParse.rc;
}else{ }else{
sqlite3WalkSelect(&sWalker, pTab->pSelect); sqlite3WalkSelect(&sWalker, pTab->u.view.pSelect);
} }
} }
}else{ }else{
/* Modify any FK definitions to point to the new table. */ /* Modify any FK definitions to point to the new table. */
#ifndef SQLITE_OMIT_FOREIGN_KEY #ifndef SQLITE_OMIT_FOREIGN_KEY
if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){ if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys))
&& !IsVirtual(pTab)
){
FKey *pFKey; FKey *pFKey;
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ assert( !IsVirtual(pTab) );
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo); renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo);
} }
@@ -1862,8 +1867,8 @@ static void renameQuotefixFunc(
sWalker.u.pRename = &sCtx; sWalker.u.pRename = &sCtx;
if( sParse.pNewTable ){ if( sParse.pNewTable ){
Select *pSelect = sParse.pNewTable->pSelect; if( IsView(sParse.pNewTable) ){
if( pSelect ){ Select *pSelect = sParse.pNewTable->u.view.pSelect;
pSelect->selFlags &= ~SF_View; pSelect->selFlags &= ~SF_View;
sParse.rc = SQLITE_OK; sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, pSelect, 0); sqlite3SelectPrep(&sParse, pSelect, 0);
@@ -1961,11 +1966,11 @@ static void renameTableTest(
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL)); db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){ if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
NameContext sNC; NameContext sNC;
memset(&sNC, 0, sizeof(sNC)); memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse; sNC.pParse = &sParse;
sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC); sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc; if( sParse.nErr ) rc = sParse.rc;
} }
@@ -2042,7 +2047,8 @@ static void dropColumnFunc(
pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zName); pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zName);
zEnd = (const char*)pEnd->t.z; zEnd = (const char*)pEnd->t.z;
}else{ }else{
zEnd = (const char*)&zSql[pTab->addColOffset]; assert( !IsVirtual(pTab) );
zEnd = (const char*)&zSql[pTab->u.tab.addColOffset];
while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--; while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
} }

View File

@@ -678,13 +678,15 @@ void sqlite3ColumnSetExpr(
Column *pCol, /* The column to receive the new DEFAULT expression */ Column *pCol, /* The column to receive the new DEFAULT expression */
Expr *pExpr /* The new default expression */ Expr *pExpr /* The new default expression */
){ ){
ExprList *pList = pTab->pDfltList; ExprList *pList;
assert( !IsVirtual(pTab) );
pList = pTab->u.tab.pDfltList;
if( pCol->iDflt==0 if( pCol->iDflt==0
|| pList==0 || pList==0
|| pList->nExpr<pCol->iDflt || pList->nExpr<pCol->iDflt
){ ){
pCol->iDflt = pList==0 ? 1 : pList->nExpr+1; pCol->iDflt = pList==0 ? 1 : pList->nExpr+1;
pTab->pDfltList = sqlite3ExprListAppend(pParse, pList, pExpr); pTab->u.tab.pDfltList = sqlite3ExprListAppend(pParse, pList, pExpr);
}else{ }else{
sqlite3ExprDelete(pParse->db, pList->a[pCol->iDflt-1].pExpr); sqlite3ExprDelete(pParse->db, pList->a[pCol->iDflt-1].pExpr);
pList->a[pCol->iDflt-1].pExpr = pExpr; pList->a[pCol->iDflt-1].pExpr = pExpr;
@@ -698,9 +700,10 @@ void sqlite3ColumnSetExpr(
*/ */
Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){ Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
if( pCol->iDflt==0 ) return 0; if( pCol->iDflt==0 ) return 0;
if( pTab->pDfltList==0 ) return 0; if( IsVirtual(pTab) ) return 0;
if( pTab->pDfltList->nExpr<pCol->iDflt ) return 0; if( pTab->u.tab.pDfltList==0 ) return 0;
return pTab->pDfltList->a[pCol->iDflt-1].pExpr; if( pTab->u.tab.pDfltList->nExpr<pCol->iDflt ) return 0;
return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
} }
/* /*
@@ -718,11 +721,15 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
sqlite3DbFree(db, pCol->zColl); sqlite3DbFree(db, pCol->zColl);
} }
sqlite3DbFree(db, pTable->aCol); sqlite3DbFree(db, pTable->aCol);
sqlite3ExprListDelete(db, pTable->pDfltList); if( !IsVirtual(pTable) ){
sqlite3ExprListDelete(db, pTable->u.tab.pDfltList);
}
if( db==0 || db->pnBytesFreed==0 ){ if( db==0 || db->pnBytesFreed==0 ){
pTable->aCol = 0; pTable->aCol = 0;
pTable->nCol = 0; pTable->nCol = 0;
pTable->pDfltList = 0; if( !IsVirtual(pTable) ){
pTable->u.tab.pDfltList = 0;
}
} }
} }
} }
@@ -775,19 +782,25 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
sqlite3FreeIndex(db, pIndex); sqlite3FreeIndex(db, pIndex);
} }
/* Delete any foreign keys attached to this table. */ if( IsOrdinaryTable(pTable) ){
sqlite3FkDelete(db, pTable); sqlite3FkDelete(db, pTable);
}
#ifndef SQLITE_OMIT_VIRTUAL_TABLE
else if( IsVirtual(pTable) ){
sqlite3VtabClear(db, pTable);
}
#endif
else{
assert( IsView(pTable) );
sqlite3SelectDelete(db, pTable->u.view.pSelect);
}
/* Delete the Table structure itself. /* Delete the Table structure itself.
*/ */
sqlite3DeleteColumnNames(db, pTable); sqlite3DeleteColumnNames(db, pTable);
sqlite3DbFree(db, pTable->zName); sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff); sqlite3DbFree(db, pTable->zColAff);
sqlite3SelectDelete(db, pTable->pSelect);
sqlite3ExprListDelete(db, pTable->pCheck); sqlite3ExprListDelete(db, pTable->pCheck);
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3VtabClear(db, pTable);
#endif
sqlite3DbFree(db, pTable); sqlite3DbFree(db, pTable);
/* Verify that no lookaside memory was used by schema tables */ /* Verify that no lookaside memory was used by schema tables */
@@ -2420,7 +2433,7 @@ int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
nName = sqlite3Strlen30(pTab->zName); nName = sqlite3Strlen30(pTab->zName);
if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0; if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
if( zName[nName]!='_' ) return 0; if( zName[nName]!='_' ) return 0;
pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]); pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
if( pMod==0 ) return 0; if( pMod==0 ) return 0;
if( pMod->pModule->iVersion<3 ) return 0; if( pMod->pModule->iVersion<3 ) return 0;
if( pMod->pModule->xShadowName==0 ) return 0; if( pMod->pModule->xShadowName==0 ) return 0;
@@ -2632,7 +2645,7 @@ void sqlite3EndTable(
/* /*
** Initialize zType for the new view or table. ** Initialize zType for the new view or table.
*/ */
if( p->pSelect==0 ){ if( IsOrdinaryTable(p) ){
/* A regular table */ /* A regular table */
zType = "table"; zType = "table";
zType2 = "TABLE"; zType2 = "TABLE";
@@ -2782,12 +2795,12 @@ void sqlite3EndTable(
} }
#ifndef SQLITE_OMIT_ALTERTABLE #ifndef SQLITE_OMIT_ALTERTABLE
if( !pSelect && !p->pSelect ){ if( !pSelect && IsOrdinaryTable(p) ){
assert( pCons && pEnd ); assert( pCons && pEnd );
if( pCons->z==0 ){ if( pCons->z==0 ){
pCons = pEnd; pCons = pEnd;
} }
p->addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z); p->u.tab.addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
} }
#endif #endif
} }
@@ -2844,12 +2857,13 @@ void sqlite3CreateView(
*/ */
pSelect->selFlags |= SF_View; pSelect->selFlags |= SF_View;
if( IN_RENAME_OBJECT ){ if( IN_RENAME_OBJECT ){
p->pSelect = pSelect; p->u.view.pSelect = pSelect;
pSelect = 0; pSelect = 0;
}else{ }else{
p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); p->u.view.pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
} }
p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE); p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
p->eTabType = TABTYP_VIEW;
if( db->mallocFailed ) goto create_view_fail; if( db->mallocFailed ) goto create_view_fail;
/* Locate the end of the CREATE VIEW statement. Make sEnd point to /* Locate the end of the CREATE VIEW statement. Make sEnd point to
@@ -2946,8 +2960,8 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** to be permanent. So the computation is done on a copy of the SELECT ** to be permanent. So the computation is done on a copy of the SELECT
** statement that defines the view. ** statement that defines the view.
*/ */
assert( pTable->pSelect ); assert( IsView(pTable) );
pSel = sqlite3SelectDup(db, pTable->pSelect, 0); pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0);
if( pSel ){ if( pSel ){
u8 eParseMode = pParse->eParseMode; u8 eParseMode = pParse->eParseMode;
pParse->eParseMode = PARSE_MODE_NORMAL; pParse->eParseMode = PARSE_MODE_NORMAL;
@@ -3022,7 +3036,7 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i); Table *pTab = sqliteHashData(i);
if( pTab->pSelect ){ if( IsView(pTab) ){
sqlite3DeleteColumnNames(db, pTab); sqlite3DeleteColumnNames(db, pTab);
} }
} }
@@ -3364,11 +3378,11 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
/* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
** on a table. ** on a table.
*/ */
if( isView && pTab->pSelect==0 ){ if( isView && !IsView(pTab) ){
sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName); sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
goto exit_drop_table; goto exit_drop_table;
} }
if( !isView && pTab->pSelect ){ if( !isView && IsView(pTab) ){
sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName); sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
goto exit_drop_table; goto exit_drop_table;
} }
@@ -3455,7 +3469,7 @@ void sqlite3CreateForeignKey(
goto fk_end; goto fk_end;
} }
pFKey->pFrom = p; pFKey->pFrom = p;
pFKey->pNextFrom = p->pFKey; pFKey->pNextFrom = p->u.tab.pFKey;
z = (char*)&pFKey->aCol[nCol]; z = (char*)&pFKey->aCol[nCol];
pFKey->zTo = z; pFKey->zTo = z;
if( IN_RENAME_OBJECT ){ if( IN_RENAME_OBJECT ){
@@ -3520,7 +3534,8 @@ void sqlite3CreateForeignKey(
/* Link the foreign key to the table as the last step. /* Link the foreign key to the table as the last step.
*/ */
p->pFKey = pFKey; assert( !IsVirtual(p) );
p->u.tab.pFKey = pFKey;
pFKey = 0; pFKey = 0;
fk_end: fk_end:
@@ -3541,7 +3556,9 @@ void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
#ifndef SQLITE_OMIT_FOREIGN_KEY #ifndef SQLITE_OMIT_FOREIGN_KEY
Table *pTab; Table *pTab;
FKey *pFKey; FKey *pFKey;
if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; if( (pTab = pParse->pNewTable)==0 ) return;
if( IsVirtual(pTab) ) return;
if( (pFKey = pTab->u.tab.pFKey)==0 ) return;
assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */ assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
pFKey->isDeferred = (u8)isDeferred; pFKey->isDeferred = (u8)isDeferred;
#endif #endif
@@ -3833,7 +3850,7 @@ void sqlite3CreateIndex(
goto exit_create_index; goto exit_create_index;
} }
#ifndef SQLITE_OMIT_VIEW #ifndef SQLITE_OMIT_VIEW
if( pTab->pSelect ){ if( IsView(pTab) ){
sqlite3ErrorMsg(pParse, "views may not be indexed"); sqlite3ErrorMsg(pParse, "views may not be indexed");
goto exit_create_index; goto exit_create_index;
} }

View File

@@ -84,7 +84,7 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
return 1; return 1;
} }
#ifndef SQLITE_OMIT_VIEW #ifndef SQLITE_OMIT_VIEW
if( !viewOk && pTab->pSelect ){ if( !viewOk && IsView(pTab) ){
sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
return 1; return 1;
} }
@@ -301,7 +301,7 @@ void sqlite3DeleteFrom(
*/ */
#ifndef SQLITE_OMIT_TRIGGER #ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
isView = pTab->pSelect!=0; isView = IsView(pTab);
#else #else
# define pTrigger 0 # define pTrigger 0
# define isView 0 # define isView 0
@@ -551,7 +551,7 @@ void sqlite3DeleteFrom(
if( eOnePass!=ONEPASS_OFF ){ if( eOnePass!=ONEPASS_OFF ){
assert( nKey==nPk ); /* OP_Found will use an unpacked key */ assert( nKey==nPk ); /* OP_Found will use an unpacked key */
if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
assert( pPk!=0 || pTab->pSelect!=0 ); assert( pPk!=0 || IsView(pTab) );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
VdbeCoverage(v); VdbeCoverage(v);
} }
@@ -785,7 +785,7 @@ void sqlite3GenerateRowDelete(
** the update-hook is not invoked for rows removed by REPLACE, but the ** the update-hook is not invoked for rows removed by REPLACE, but the
** pre-update-hook is. ** pre-update-hook is.
*/ */
if( pTab->pSelect==0 ){ if( !IsView(pTab) ){
u8 p5 = 0; u8 p5 = 0;
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));

View File

@@ -2513,7 +2513,7 @@ static Select *isCandidateForInOpt(Expr *pX){
if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */ if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
pTab = pSrc->a[0].pTab; pTab = pSrc->a[0].pTab;
assert( pTab!=0 ); assert( pTab!=0 );
assert( pTab->pSelect==0 ); /* FROM clause is not a view */ assert( !IsView(pTab) ); /* FROM clause is not a view */
if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
pEList = p->pEList; pEList = p->pEList;
assert( pEList!=0 ); assert( pEList!=0 );

View File

@@ -723,7 +723,8 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
Vdbe *v = sqlite3GetVdbe(pParse); Vdbe *v = sqlite3GetVdbe(pParse);
assert( v ); /* VDBE has already been allocated */ assert( v ); /* VDBE has already been allocated */
assert( pTab->pSelect==0 ); /* Not a view */ assert( !IsView(pTab) ); /* Not a view */
assert( !IsVirtual(pTab) );
if( sqlite3FkReferences(pTab)==0 ){ if( sqlite3FkReferences(pTab)==0 ){
/* Search for a deferred foreign key constraint for which this table /* Search for a deferred foreign key constraint for which this table
** is the child table. If one cannot be found, return without ** is the child table. If one cannot be found, return without
@@ -731,7 +732,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
** the entire DELETE if there are no outstanding deferred constraints ** the entire DELETE if there are no outstanding deferred constraints
** when this statement is run. */ ** when this statement is run. */
FKey *p; FKey *p;
for(p=pTab->pFKey; p; p=p->pNextFrom){ for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break; if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
} }
if( !p ) return; if( !p ) return;
@@ -893,7 +894,8 @@ void sqlite3FkCheck(
/* Loop through all the foreign key constraints for which pTab is the /* Loop through all the foreign key constraints for which pTab is the
** child table (the table that the foreign key definition is part of). */ ** child table (the table that the foreign key definition is part of). */
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ assert( !IsVirtual(pTab) );
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
Table *pTo; /* Parent table of foreign key pFKey */ Table *pTo; /* Parent table of foreign key pFKey */
Index *pIdx = 0; /* Index on key columns in pTo */ Index *pIdx = 0; /* Index on key columns in pTo */
int *aiFree = 0; int *aiFree = 0;
@@ -1078,7 +1080,8 @@ u32 sqlite3FkOldmask(
if( pParse->db->flags&SQLITE_ForeignKeys ){ if( pParse->db->flags&SQLITE_ForeignKeys ){
FKey *p; FKey *p;
int i; int i;
for(p=pTab->pFKey; p; p=p->pNextFrom){ assert( !IsVirtual(pTab) );
for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
} }
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
@@ -1128,19 +1131,19 @@ int sqlite3FkRequired(
){ ){
int eRet = 1; /* Value to return if bHaveFK is true */ int eRet = 1; /* Value to return if bHaveFK is true */
int bHaveFK = 0; /* If FK processing is required */ int bHaveFK = 0; /* If FK processing is required */
if( pParse->db->flags&SQLITE_ForeignKeys ){ if( pParse->db->flags&SQLITE_ForeignKeys && !IsVirtual(pTab) ){
if( !aChange ){ if( !aChange ){
/* A DELETE operation. Foreign key processing is required if the /* A DELETE operation. Foreign key processing is required if the
** table in question is either the child or parent table for any ** table in question is either the child or parent table for any
** foreign key constraint. */ ** foreign key constraint. */
bHaveFK = (sqlite3FkReferences(pTab) || pTab->pFKey); bHaveFK = (sqlite3FkReferences(pTab) || pTab->u.tab.pFKey);
}else{ }else{
/* This is an UPDATE. Foreign key processing is only required if the /* This is an UPDATE. Foreign key processing is only required if the
** operation modifies one or more child or parent key columns. */ ** operation modifies one or more child or parent key columns. */
FKey *p; FKey *p;
/* Check if any child key columns are being modified. */ /* Check if any child key columns are being modified. */
for(p=pTab->pFKey; p; p=p->pNextFrom){ for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
if( fkChildIsModified(pTab, p, aChange, chngRowid) ){ if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2; if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2;
bHaveFK = 1; bHaveFK = 1;
@@ -1416,9 +1419,9 @@ void sqlite3FkDelete(sqlite3 *db, Table *pTab){
FKey *pFKey; /* Iterator variable */ FKey *pFKey; /* Iterator variable */
FKey *pNext; /* Copy of pFKey->pNextFrom */ FKey *pNext; /* Copy of pFKey->pNextFrom */
assert( db==0 || IsVirtual(pTab) assert( !IsVirtual(pTab) );
|| sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){
/* Remove the FK from the fkeyHash hash table. */ /* Remove the FK from the fkeyHash hash table. */
if( !db || db->pnBytesFreed==0 ){ if( !db || db->pnBytesFreed==0 ){

View File

@@ -703,7 +703,7 @@ void sqlite3Insert(
*/ */
#ifndef SQLITE_OMIT_TRIGGER #ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask); pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
isView = pTab->pSelect!=0; isView = IsView(pTab);
#else #else
# define pTrigger 0 # define pTrigger 0
# define tmask 0 # define tmask 0
@@ -989,7 +989,7 @@ void sqlite3Insert(
pTab->zName); pTab->zName);
goto insert_cleanup; goto insert_cleanup;
} }
if( pTab->pSelect ){ if( IsView(pTab) ){
sqlite3ErrorMsg(pParse, "cannot UPSERT a view"); sqlite3ErrorMsg(pParse, "cannot UPSERT a view");
goto insert_cleanup; goto insert_cleanup;
} }
@@ -1624,7 +1624,7 @@ void sqlite3GenerateConstraintChecks(
db = pParse->db; db = pParse->db;
v = pParse->pVdbe; v = pParse->pVdbe;
assert( v!=0 ); assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */ assert( !IsView(pTab) ); /* This table is not a VIEW */
nCol = pTab->nCol; nCol = pTab->nCol;
/* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
@@ -2185,7 +2185,7 @@ void sqlite3GenerateConstraintChecks(
&& ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */ && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0)) 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
&& ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */ && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
(0==pTab->pFKey && 0==sqlite3FkReferences(pTab))) (0==pTab->u.tab.pFKey && 0==sqlite3FkReferences(pTab)))
){ ){
sqlite3VdbeResolveLabel(v, addrUniqueOk); sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue; continue;
@@ -2484,7 +2484,7 @@ void sqlite3CompleteInsertion(
v = pParse->pVdbe; v = pParse->pVdbe;
assert( v!=0 ); assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */ assert( !IsView(pTab) ); /* This table is not a VIEW */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
/* All REPLACE indexes are at the end of the list */ /* All REPLACE indexes are at the end of the list */
assert( pIdx->onError!=OE_Replace assert( pIdx->onError!=OE_Replace
@@ -2786,13 +2786,8 @@ static int xferOptimization(
if( HasRowid(pDest)!=HasRowid(pSrc) ){ if( HasRowid(pDest)!=HasRowid(pSrc) ){
return 0; /* source and destination must both be WITHOUT ROWID or not */ return 0; /* source and destination must both be WITHOUT ROWID or not */
} }
#ifndef SQLITE_OMIT_VIRTUALTABLE if( !IsOrdinaryTable(pSrc) ){
if( IsVirtual(pSrc) ){ return 0; /* tab2 may not be a view or virtual table */
return 0; /* tab2 must not be a virtual table */
}
#endif
if( pSrc->pSelect ){
return 0; /* tab2 may not be a view */
} }
if( pDest->nCol!=pSrc->nCol ){ if( pDest->nCol!=pSrc->nCol ){
return 0; /* Number of columns must be the same in tab1 and tab2 */ return 0; /* Number of columns must be the same in tab1 and tab2 */
@@ -2899,7 +2894,7 @@ static int xferOptimization(
** the extra complication to make this rule less restrictive is probably ** the extra complication to make this rule less restrictive is probably
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
*/ */
if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){
return 0; return 0;
} }
#endif #endif

View File

@@ -3731,7 +3731,7 @@ int sqlite3_table_column_metadata(
/* Locate the table in question */ /* Locate the table in question */
pTab = sqlite3FindTable(db, zTableName, zDbName); pTab = sqlite3FindTable(db, zTableName, zDbName);
if( !pTab || pTab->pSelect ){ if( !pTab || IsView(pTab) ){
pTab = 0; pTab = 0;
goto error_out; goto error_out;
} }

View File

@@ -1360,8 +1360,8 @@ void sqlite3Pragma(
FKey *pFK; FKey *pFK;
Table *pTab; Table *pTab;
pTab = sqlite3FindTable(db, zRight, zDb); pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){ if( pTab && !IsVirtual(pTab) ){
pFK = pTab->pFKey; pFK = pTab->u.tab.pFKey;
if( pFK ){ if( pFK ){
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int i = 0; int i = 0;
@@ -1420,7 +1420,7 @@ void sqlite3Pragma(
pTab = (Table*)sqliteHashData(k); pTab = (Table*)sqliteHashData(k);
k = sqliteHashNext(k); k = sqliteHashNext(k);
} }
if( pTab==0 || pTab->pFKey==0 ) continue; if( pTab==0 || IsVirtual(pTab) || pTab->u.tab.pFKey==0 ) continue;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema); iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
zDb = db->aDb[iDb].zDbSName; zDb = db->aDb[iDb].zDbSName;
sqlite3CodeVerifySchema(pParse, iDb); sqlite3CodeVerifySchema(pParse, iDb);
@@ -1428,7 +1428,8 @@ void sqlite3Pragma(
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
sqlite3VdbeLoadString(v, regResult, pTab->zName); sqlite3VdbeLoadString(v, regResult, pTab->zName);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ assert( !IsVirtual(pTab) );
for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3FindTable(db, pFK->zTo, zDb); pParent = sqlite3FindTable(db, pFK->zTo, zDb);
if( pParent==0 ) continue; if( pParent==0 ) continue;
pIdx = 0; pIdx = 0;
@@ -1450,7 +1451,8 @@ void sqlite3Pragma(
if( pFK ) break; if( pFK ) break;
if( pParse->nTab<i ) pParse->nTab = i; if( pParse->nTab<i ) pParse->nTab = i;
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ assert( !IsVirtual(pTab) );
for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3FindTable(db, pFK->zTo, zDb); pParent = sqlite3FindTable(db, pFK->zTo, zDb);
pIdx = 0; pIdx = 0;
aiCols = 0; aiCols = 0;

View File

@@ -4933,7 +4933,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
} }
pTab = p->pSrc->a[0].pTab; pTab = p->pSrc->a[0].pTab;
pExpr = p->pEList->a[0].pExpr; pExpr = p->pEList->a[0].pExpr;
assert( pTab && !pTab->pSelect && pExpr ); assert( pTab && !IsView(pTab) && pExpr );
if( IsVirtual(pTab) ) return 0; if( IsVirtual(pTab) ) return 0;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
@@ -5478,30 +5478,31 @@ static int selectExpander(Walker *pWalker, Select *p){
return WRC_Abort; return WRC_Abort;
} }
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
if( IsVirtual(pTab) || pTab->pSelect ){ if( !IsOrdinaryTable(pTab) ){
i16 nCol; i16 nCol;
u8 eCodeOrig = pWalker->eCode; u8 eCodeOrig = pWalker->eCode;
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 ); assert( pFrom->pSelect==0 );
if( pTab->pSelect if( IsView(pTab) ){
&& (db->flags & SQLITE_EnableView)==0 if( (db->flags & SQLITE_EnableView)==0
&& pTab->pSchema!=db->aDb[1].pSchema && pTab->pSchema!=db->aDb[1].pSchema
){ ){
sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited", sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
pTab->zName); pTab->zName);
} }
pFrom->pSelect = sqlite3SelectDup(db, pTab->u.view.pSelect, 0);
}else
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 ); if( ALWAYS(IsVirtual(pTab))
if( IsVirtual(pTab)
&& pFrom->fg.fromDDL && pFrom->fg.fromDDL
&& ALWAYS(pTab->pVTable!=0) && ALWAYS(pTab->u.vtab.p!=0)
&& pTab->pVTable->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0) && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
){ ){
sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"", sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
pTab->zName); pTab->zName);
} }
assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 );
#endif #endif
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
nCol = pTab->nCol; nCol = pTab->nCol;
pTab->nCol = -1; pTab->nCol = -1;
pWalker->eCode = 1; /* Turn on Select.selId renumbering */ pWalker->eCode = 1; /* Turn on Select.selId renumbering */

View File

@@ -2201,19 +2201,16 @@ struct VTable {
#define SQLITE_VTABRISK_High 2 #define SQLITE_VTABRISK_High 2
/* /*
** The schema for each SQL table and view is represented in memory ** The schema for each SQL table, virtual table, and view is represented
** by an instance of the following structure. ** in memory by an instance of the following structure.
*/ */
struct Table { struct Table {
char *zName; /* Name of the table or view */ char *zName; /* Name of the table or view */
Column *aCol; /* Information about each column */ Column *aCol; /* Information about each column */
Index *pIndex; /* List of SQL indexes on this table. */ Index *pIndex; /* List of SQL indexes on this table. */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */ char *zColAff; /* String defining the affinity of each column */
ExprList *pCheck; /* All CHECK constraints */ ExprList *pCheck; /* All CHECK constraints */
/* ... also used as column name list in a VIEW */ /* ... also used as column name list in a VIEW */
ExprList *pDfltList; /* DEFAULT clauses on various columns */
Pgno tnum; /* Root BTree page for this table */ Pgno tnum; /* Root BTree page for this table */
u32 nTabRef; /* Number of pointers to this Table */ u32 nTabRef; /* Number of pointers to this Table */
u32 tabFlags; /* Mask of TF_* values */ u32 tabFlags; /* Mask of TF_* values */
@@ -2226,15 +2223,24 @@ struct Table {
LogEst costMult; /* Cost multiplier for using this table */ LogEst costMult; /* Cost multiplier for using this table */
#endif #endif
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
#ifndef SQLITE_OMIT_ALTERTABLE u8 eTabType; /* 0: normal, 1: virtual, 2: view */
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ union {
#endif struct { /* Used by ordinary tables: */
#ifndef SQLITE_OMIT_VIRTUALTABLE int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
int nModuleArg; /* Number of arguments to the module */ FKey *pFKey; /* Linked list of all foreign keys in this table */
char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */ ExprList *pDfltList; /* DEFAULT clauses on various columns.
VTable *pVTable; /* List of VTable objects. */ ** Or the AS clause for generated columns. */
#endif } tab;
Trigger *pTrigger; /* List of triggers stored in pSchema */ struct { /* Used by views: */
Select *pSelect; /* View definition */
} view;
struct { /* Used by virtual tables only: */
int nArg; /* Number of arguments to the module */
char **azArg; /* 0: module 1: schema 2: vtab name 3...: args */
VTable *p; /* List of VTable objects. */
} vtab;
} u;
Trigger *pTrigger; /* List of triggers on this object */
Schema *pSchema; /* Schema that contains this table */ Schema *pSchema; /* Schema that contains this table */
}; };
@@ -2253,24 +2259,34 @@ struct Table {
** TF_HasStored == COLFLAG_STORED ** TF_HasStored == COLFLAG_STORED
** TF_HasHidden == COLFLAG_HIDDEN ** TF_HasHidden == COLFLAG_HIDDEN
*/ */
#define TF_Readonly 0x0001 /* Read-only system table */ #define TF_Readonly 0x00000001 /* Read-only system table */
#define TF_HasHidden 0x0002 /* Has one or more hidden columns */ #define TF_HasHidden 0x00000002 /* Has one or more hidden columns */
#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */ #define TF_HasPrimaryKey 0x00000004 /* Table has a primary key */
#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */ #define TF_Autoincrement 0x00000008 /* Integer primary key is autoincrement */
#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */ #define TF_HasStat1 0x00000010 /* nRowLogEst set from sqlite_stat1 */
#define TF_HasVirtual 0x0020 /* Has one or more VIRTUAL columns */ #define TF_HasVirtual 0x00000020 /* Has one or more VIRTUAL columns */
#define TF_HasStored 0x0040 /* Has one or more STORED columns */ #define TF_HasStored 0x00000040 /* Has one or more STORED columns */
#define TF_HasGenerated 0x0060 /* Combo: HasVirtual + HasStored */ #define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */
#define TF_WithoutRowid 0x0080 /* No rowid. PRIMARY KEY is the key */ #define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */
#define TF_StatsUsed 0x0100 /* Query planner decisions affected by #define TF_StatsUsed 0x00000100 /* Query planner decisions affected by
** Index.aiRowLogEst[] values */ ** Index.aiRowLogEst[] values */
#define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */ #define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */ #define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */
#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */ #define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */
#define TF_Shadow 0x1000 /* True for a shadow table */ #define TF_Shadow 0x00001000 /* True for a shadow table */
#define TF_HasStat4 0x2000 /* STAT4 info available for this table */ #define TF_HasStat4 0x00002000 /* STAT4 info available for this table */
#define TF_Ephemeral 0x4000 /* An ephemeral table */ #define TF_Ephemeral 0x00004000 /* An ephemeral table */
#define TF_Eponymous 0x8000 /* An eponymous virtual table */ #define TF_Eponymous 0x00008000 /* An eponymous virtual table */
/*
** Allowed values for Table.eTabType
*/
#define TABTYP_NORM 0 /* Ordinary table */
#define TABTYP_VTAB 1 /* Virtual table */
#define TABTYP_VIEW 2 /* A view */
#define IsView(X) ((X)->eTabType==TABTYP_VIEW)
#define IsOrdinaryTable(X) ((X)->eTabType==TABTYP_NORM)
/* /*
** Test to see whether or not a table is a virtual table. This is ** Test to see whether or not a table is a virtual table. This is
@@ -2278,9 +2294,9 @@ struct Table {
** table support is omitted from the build. ** table support is omitted from the build.
*/ */
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
# define IsVirtual(X) ((X)->nModuleArg) # define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB)
# define ExprIsVtab(X) \ # define ExprIsVtab(X) \
((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg) ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->eTabType==TABTYP_VTAB)
#else #else
# define IsVirtual(X) 0 # define IsVirtual(X) 0
# define ExprIsVtab(X) 0 # define ExprIsVtab(X) 0

View File

@@ -219,12 +219,12 @@ void sqlite3BeginTrigger(
/* INSTEAD of triggers are only for views and views only support INSTEAD /* INSTEAD of triggers are only for views and views only support INSTEAD
** of triggers. ** of triggers.
*/ */
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ if( IsView(pTab) && tr_tm!=TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a); (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
goto trigger_orphan_error; goto trigger_orphan_error;
} }
if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ if( !IsView(pTab) && tr_tm==TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
" trigger on table: %S", pTableName->a); " trigger on table: %S", pTableName->a);
goto trigger_orphan_error; goto trigger_orphan_error;

View File

@@ -60,7 +60,7 @@ static void updateVirtualTable(
*/ */
void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
assert( pTab!=0 ); assert( pTab!=0 );
if( !pTab->pSelect ){ if( !IsView(pTab) ){
sqlite3_value *pValue = 0; sqlite3_value *pValue = 0;
u8 enc = ENC(sqlite3VdbeDb(v)); u8 enc = ENC(sqlite3VdbeDb(v));
Column *pCol = &pTab->aCol[i]; Column *pCol = &pTab->aCol[i];
@@ -237,7 +237,7 @@ static void updateFromSelect(
pList = sqlite3ExprListAppend(pParse, pList, pNew); pList = sqlite3ExprListAppend(pParse, pList, pNew);
} }
eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom; eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
}else if( pTab->pSelect ){ }else if( IsView(pTab) ){
for(i=0; i<pTab->nCol; i++){ for(i=0; i<pTab->nCol; i++){
pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i)); pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
} }
@@ -362,7 +362,7 @@ void sqlite3Update(
*/ */
#ifndef SQLITE_OMIT_TRIGGER #ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
isView = pTab->pSelect!=0; isView = IsView(pTab);
assert( pTrigger || tmask==0 ); assert( pTrigger || tmask==0 );
#else #else
# define pTrigger 0 # define pTrigger 0

View File

@@ -167,7 +167,7 @@ int sqlite3_blob_open(
sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable); sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
} }
#ifndef SQLITE_OMIT_VIEW #ifndef SQLITE_OMIT_VIEW
if( pTab && pTab->pSelect ){ if( pTab && IsView(pTab) ){
pTab = 0; pTab = 0;
sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
} }
@@ -212,7 +212,8 @@ int sqlite3_blob_open(
** key columns must be indexed. The check below will pick up this ** key columns must be indexed. The check below will pick up this
** case. */ ** case. */
FKey *pFKey; FKey *pFKey;
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ assert( !IsVirtual(pTab) );
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
int j; int j;
for(j=0; j<pFKey->nCol; j++){ for(j=0; j<pFKey->nCol; j++){
if( pFKey->aCol[j].iFrom==iCol ){ if( pFKey->aCol[j].iFrom==iCol ){

View File

@@ -192,7 +192,7 @@ void sqlite3VtabLock(VTable *pVTab){
VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){ VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
VTable *pVtab; VTable *pVtab;
assert( IsVirtual(pTab) ); assert( IsVirtual(pTab) );
for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext); for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
return pVtab; return pVtab;
} }
@@ -220,21 +220,21 @@ void sqlite3VtabUnlock(VTable *pVTab){
/* /*
** Table p is a virtual table. This function moves all elements in the ** Table p is a virtual table. This function moves all elements in the
** p->pVTable list to the sqlite3.pDisconnect lists of their associated ** p->u.vtab.p list to the sqlite3.pDisconnect lists of their associated
** database connections to be disconnected at the next opportunity. ** database connections to be disconnected at the next opportunity.
** Except, if argument db is not NULL, then the entry associated with ** Except, if argument db is not NULL, then the entry associated with
** connection db is left in the p->pVTable list. ** connection db is left in the p->u.vtab.p list.
*/ */
static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
VTable *pRet = 0; VTable *pRet = 0;
VTable *pVTable = p->pVTable; VTable *pVTable = p->u.vtab.p;
p->pVTable = 0; p->u.vtab.p = 0;
/* Assert that the mutex (if any) associated with the BtShared database /* Assert that the mutex (if any) associated with the BtShared database
** that contains table p is held by the caller. See header comments ** that contains table p is held by the caller. See header comments
** above function sqlite3VtabUnlockList() for an explanation of why ** above function sqlite3VtabUnlockList() for an explanation of why
** this makes it safe to access the sqlite3.pDisconnect list of any ** this makes it safe to access the sqlite3.pDisconnect list of any
** database connection that may have an entry in the p->pVTable list. ** database connection that may have an entry in the p->u.vtab.p list.
*/ */
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
@@ -244,7 +244,7 @@ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
assert( db2 ); assert( db2 );
if( db2==db ){ if( db2==db ){
pRet = pVTable; pRet = pVTable;
p->pVTable = pRet; p->u.vtab.p = pRet;
pRet->pNext = 0; pRet->pNext = 0;
}else{ }else{
pVTable->pNext = db2->pDisconnect; pVTable->pNext = db2->pDisconnect;
@@ -272,7 +272,7 @@ void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3BtreeHoldsAllMutexes(db) );
assert( sqlite3_mutex_held(db->mutex) ); assert( sqlite3_mutex_held(db->mutex) );
for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){ for(ppVTab=&p->u.vtab.p; *ppVTab; ppVTab=&(*ppVTab)->pNext){
if( (*ppVTab)->db==db ){ if( (*ppVTab)->db==db ){
VTable *pVTab = *ppVTab; VTable *pVTab = *ppVTab;
*ppVTab = pVTab->pNext; *ppVTab = pVTab->pNext;
@@ -336,36 +336,36 @@ void sqlite3VtabUnlockList(sqlite3 *db){
*/ */
void sqlite3VtabClear(sqlite3 *db, Table *p){ void sqlite3VtabClear(sqlite3 *db, Table *p){
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
if( p->azModuleArg ){ if( p->u.vtab.azArg ){
int i; int i;
for(i=0; i<p->nModuleArg; i++){ for(i=0; i<p->u.vtab.nArg; i++){
if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]); if( i!=1 ) sqlite3DbFree(db, p->u.vtab.azArg[i]);
} }
sqlite3DbFree(db, p->azModuleArg); sqlite3DbFree(db, p->u.vtab.azArg);
} }
} }
/* /*
** Add a new module argument to pTable->azModuleArg[]. ** Add a new module argument to pTable->u.vtab.azArg[].
** The string is not copied - the pointer is stored. The ** The string is not copied - the pointer is stored. The
** string will be freed automatically when the table is ** string will be freed automatically when the table is
** deleted. ** deleted.
*/ */
static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){ static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){
sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->nModuleArg); sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->u.vtab.nArg);
char **azModuleArg; char **azModuleArg;
sqlite3 *db = pParse->db; sqlite3 *db = pParse->db;
if( pTable->nModuleArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){ if( pTable->u.vtab.nArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName); sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName);
} }
azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes); azModuleArg = sqlite3DbRealloc(db, pTable->u.vtab.azArg, nBytes);
if( azModuleArg==0 ){ if( azModuleArg==0 ){
sqlite3DbFree(db, zArg); sqlite3DbFree(db, zArg);
}else{ }else{
int i = pTable->nModuleArg++; int i = pTable->u.vtab.nArg++;
azModuleArg[i] = zArg; azModuleArg[i] = zArg;
azModuleArg[i+1] = 0; azModuleArg[i+1] = 0;
pTable->azModuleArg = azModuleArg; pTable->u.vtab.azArg = azModuleArg;
} }
} }
@@ -388,10 +388,11 @@ void sqlite3VtabBeginParse(
pTable = pParse->pNewTable; pTable = pParse->pNewTable;
if( pTable==0 ) return; if( pTable==0 ) return;
assert( 0==pTable->pIndex ); assert( 0==pTable->pIndex );
pTable->eTabType = TABTYP_VTAB;
db = pParse->db; db = pParse->db;
assert( pTable->nModuleArg==0 ); assert( pTable->u.vtab.nArg==0 );
addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName)); addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName));
addModuleArgument(pParse, pTable, 0); addModuleArgument(pParse, pTable, 0);
addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName)); addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName));
@@ -408,11 +409,11 @@ void sqlite3VtabBeginParse(
** sqlite_schema table, has already been made by sqlite3StartTable(). ** sqlite_schema table, has already been made by sqlite3StartTable().
** The second call, to obtain permission to create the table, is made now. ** The second call, to obtain permission to create the table, is made now.
*/ */
if( pTable->azModuleArg ){ if( pTable->u.vtab.azArg ){
int iDb = sqlite3SchemaToIndex(db, pTable->pSchema); int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
assert( iDb>=0 ); /* The database the table is being created in */ assert( iDb>=0 ); /* The database the table is being created in */
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); pTable->u.vtab.azArg[0], pParse->db->aDb[iDb].zDbSName);
} }
#endif #endif
} }
@@ -442,7 +443,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
if( pTab==0 ) return; if( pTab==0 ) return;
addArgumentToVtab(pParse); addArgumentToVtab(pParse);
pParse->sArg.z = 0; pParse->sArg.z = 0;
if( pTab->nModuleArg<1 ) return; if( pTab->u.vtab.nArg<1 ) return;
/* If the CREATE VIRTUAL TABLE statement is being entered for the /* If the CREATE VIRTUAL TABLE statement is being entered for the
** first time (in other words if the virtual table is actually being ** first time (in other words if the virtual table is actually being
@@ -557,8 +558,8 @@ static int vtabCallConstructor(
VtabCtx sCtx; VtabCtx sCtx;
VTable *pVTable; VTable *pVTable;
int rc; int rc;
const char *const*azArg = (const char *const*)pTab->azModuleArg; const char *const*azArg = (const char *const*)pTab->u.vtab.azArg;
int nArg = pTab->nModuleArg; int nArg = pTab->u.vtab.nArg;
char *zErr = 0; char *zErr = 0;
char *zModuleName; char *zModuleName;
int iDb; int iDb;
@@ -590,7 +591,7 @@ static int vtabCallConstructor(
pVTable->eVtabRisk = SQLITE_VTABRISK_Normal; pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema); iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
pTab->azModuleArg[1] = db->aDb[iDb].zDbSName; pTab->u.vtab.azArg[1] = db->aDb[iDb].zDbSName;
/* Invoke the virtual table constructor */ /* Invoke the virtual table constructor */
assert( &db->pVtabCtx ); assert( &db->pVtabCtx );
@@ -629,12 +630,12 @@ static int vtabCallConstructor(
int iCol; int iCol;
u16 oooHidden = 0; u16 oooHidden = 0;
/* If everything went according to plan, link the new VTable structure /* If everything went according to plan, link the new VTable structure
** into the linked list headed by pTab->pVTable. Then loop through the ** into the linked list headed by pTab->u.vtab.p. Then loop through the
** columns of the table to see if any of them contain the token "hidden". ** columns of the table to see if any of them contain the token "hidden".
** If so, set the Column COLFLAG_HIDDEN flag and remove the token from ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
** the type string. */ ** the type string. */
pVTable->pNext = pTab->pVTable; pVTable->pNext = pTab->u.vtab.p;
pTab->pVTable = pVTable; pTab->u.vtab.p = pVTable;
for(iCol=0; iCol<pTab->nCol; iCol++){ for(iCol=0; iCol<pTab->nCol; iCol++){
char *zType = sqlite3ColumnType(&pTab->aCol[iCol], ""); char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
@@ -692,11 +693,11 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
} }
/* Locate the required virtual table module */ /* Locate the required virtual table module */
zMod = pTab->azModuleArg[0]; zMod = pTab->u.vtab.azArg[0];
pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
if( !pMod ){ if( !pMod ){
const char *zModule = pTab->azModuleArg[0]; const char *zModule = pTab->u.vtab.azArg[0];
sqlite3ErrorMsg(pParse, "no such module: %s", zModule); sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
}else{ }else{
@@ -759,10 +760,10 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
const char *zMod; const char *zMod;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
assert( pTab && IsVirtual(pTab) && !pTab->pVTable ); assert( pTab && IsVirtual(pTab) && !pTab->u.vtab.p );
/* Locate the required virtual table module */ /* Locate the required virtual table module */
zMod = pTab->azModuleArg[0]; zMod = pTab->u.vtab.azArg[0];
pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
/* If the module has been registered and includes a Create method, /* If the module has been registered and includes a Create method,
@@ -822,19 +823,17 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr)
&& sParse.pNewTable && sParse.pNewTable
&& !db->mallocFailed && !db->mallocFailed
&& !sParse.pNewTable->pSelect && IsOrdinaryTable(sParse.pNewTable)
&& !IsVirtual(sParse.pNewTable)
){ ){
if( !pTab->aCol ){ if( !pTab->aCol ){
Table *pNew = sParse.pNewTable; Table *pNew = sParse.pNewTable;
Index *pIdx; Index *pIdx;
pTab->aCol = pNew->aCol; pTab->aCol = pNew->aCol;
pTab->pDfltList = pNew->pDfltList; sqlite3ExprListDelete(db, pNew->u.tab.pDfltList);
pTab->nNVCol = pTab->nCol = pNew->nCol; pTab->nNVCol = pTab->nCol = pNew->nCol;
pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
pNew->nCol = 0; pNew->nCol = 0;
pNew->aCol = 0; pNew->aCol = 0;
pNew->pDfltList = 0;
assert( pTab->pIndex==0 ); assert( pTab->pIndex==0 );
assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 ); assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 );
if( !HasRowid(pNew) if( !HasRowid(pNew)
@@ -885,10 +884,10 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
Table *pTab; Table *pTab;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){ if( pTab!=0 && ALWAYS(pTab->u.vtab.p!=0) ){
VTable *p; VTable *p;
int (*xDestroy)(sqlite3_vtab *); int (*xDestroy)(sqlite3_vtab *);
for(p=pTab->pVTable; p; p=p->pNext){ for(p=pTab->u.vtab.p; p; p=p->pNext){
assert( p->pVtab ); assert( p->pVtab );
if( p->pVtab->nRef>0 ){ if( p->pVtab->nRef>0 ){
return SQLITE_LOCKED; return SQLITE_LOCKED;
@@ -902,9 +901,9 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
rc = xDestroy(p->pVtab); rc = xDestroy(p->pVtab);
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
assert( pTab->pVTable==p && p->pNext==0 ); assert( pTab->u.vtab.p==p && p->pNext==0 );
p->pVtab = 0; p->pVtab = 0;
pTab->pVTable = 0; pTab->u.vtab.p = 0;
sqlite3VtabUnlock(p); sqlite3VtabUnlock(p);
} }
sqlite3DeleteTable(db, pTab); sqlite3DeleteTable(db, pTab);
@@ -1221,8 +1220,9 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
} }
pMod->pEpoTab = pTab; pMod->pEpoTab = pTab;
pTab->nTabRef = 1; pTab->nTabRef = 1;
pTab->eTabType = TABTYP_VTAB;
pTab->pSchema = db->aDb[0].pSchema; pTab->pSchema = db->aDb[0].pSchema;
assert( pTab->nModuleArg==0 ); assert( pTab->u.vtab.nArg==0 );
pTab->iPKey = -1; pTab->iPKey = -1;
pTab->tabFlags |= TF_Eponymous; pTab->tabFlags |= TF_Eponymous;
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));

View File

@@ -3060,7 +3060,7 @@ static int whereLoopAddBtree(
** those objects, since there is no opportunity to add schema ** those objects, since there is no opportunity to add schema
** indexes on subqueries and views. */ ** indexes on subqueries and views. */
pNew->rSetup = rLogSize + rSize; pNew->rSetup = rLogSize + rSize;
if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){ if( !IsView(pTab) && (pTab->tabFlags & TF_Ephemeral)==0 ){
pNew->rSetup += 28; pNew->rSetup += 28;
}else{ }else{
pNew->rSetup -= 10; pNew->rSetup -= 10;
@@ -5211,7 +5211,7 @@ WhereInfo *sqlite3WhereBegin(
pTab = pTabItem->pTab; pTab = pTabItem->pTab;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema); iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
pLoop = pLevel->pWLoop; pLoop = pLevel->pWLoop;
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){
/* Do nothing */ /* Do nothing */
}else }else
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -5580,7 +5580,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
** created for the ONEPASS optimization. ** created for the ONEPASS optimization.
*/ */
if( (pTab->tabFlags & TF_Ephemeral)==0 if( (pTab->tabFlags & TF_Ephemeral)==0
&& pTab->pSelect==0 && !IsView(pTab)
&& (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
){ ){
int ws = pLoop->wsFlags; int ws = pLoop->wsFlags;