mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-27 20:41:58 +03:00
Simplifications to the Expr object: Remove Expr.span completely and convert
Expr.token into a char* Expr.zToken. Also simplify the Token object by removing the Token.dyn and Token.quoted fields. (CVS 6681) FossilOrigin-Name: 7cb1c3ba0759539cb035978fdaff6316775986f3
This commit is contained in:
54
manifest
54
manifest
@ -1,5 +1,5 @@
|
|||||||
C Fix\sthe\srtree\stest\smodule\sso\sthat\sit\sworks\seven\sif\sthe\sext/\ssubfolder\sis\nomitted\sfrom\sthe\stree.\s(CVS\s6679)
|
C Simplifications\sto\sthe\sExpr\sobject:\s\sRemove\sExpr.span\scompletely\sand\sconvert\nExpr.token\sinto\sa\schar*\sExpr.zToken.\s\sAlso\ssimplify\sthe\sToken\sobject\sby\nremoving\sthe\sToken.dyn\sand\sToken.quoted\sfields.\s(CVS\s6681)
|
||||||
D 2009-05-25T14:17:35
|
D 2009-05-27T10:31:29
|
||||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||||
F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
|
F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@ -99,9 +99,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
|||||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||||
F src/alter.c f0430ee68d8d80711155ddf27876abf218903b03
|
F src/alter.c accb3c77ef20903e16ec44a04f5ee5ff1bfcf7e4
|
||||||
F src/analyze.c e239496cfb5394ac8867f1c112905ddab8d01cd9
|
F src/analyze.c e239496cfb5394ac8867f1c112905ddab8d01cd9
|
||||||
F src/attach.c 3b99611f04926fc69c35b1145603fc3ddb0ca967
|
F src/attach.c 92517f52fb53037c0584c0ecac922ec83e5d9d42
|
||||||
F src/auth.c 98db07c2088455797678eb1031f42d4d94d18a71
|
F src/auth.c 98db07c2088455797678eb1031f42d4d94d18a71
|
||||||
F src/backup.c 437efc2c3371b52bbb943b8c9dfabba774adcf86
|
F src/backup.c 437efc2c3371b52bbb943b8c9dfabba774adcf86
|
||||||
F src/bitvec.c ef370407e03440b0852d05024fb016b14a471d3d
|
F src/bitvec.c ef370407e03440b0852d05024fb016b14a471d3d
|
||||||
@ -109,14 +109,14 @@ F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c
|
|||||||
F src/btree.c 7c4b02afea7efb561361f20408414fec68df898c
|
F src/btree.c 7c4b02afea7efb561361f20408414fec68df898c
|
||||||
F src/btree.h 58d876d3ed944a8f4f1fd0e67024b385243fc9dd
|
F src/btree.h 58d876d3ed944a8f4f1fd0e67024b385243fc9dd
|
||||||
F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5
|
F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5
|
||||||
F src/build.c 2b4cef0dccea8d5ceb34d30b69121590ad2d5314
|
F src/build.c 028255aa488ee3941ee77e16ae078ad5e03fe6d8
|
||||||
F src/callback.c 57359fa93de47c341b6b8ee504a88ff276397686
|
F src/callback.c 57359fa93de47c341b6b8ee504a88ff276397686
|
||||||
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
|
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
|
||||||
F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
|
F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
|
||||||
F src/delete.c a0a0932eea77471ab243337026abbce444024c43
|
F src/delete.c 59da0e52380d7626e98d84082b72f431fafe2799
|
||||||
F src/expr.c af190966891a8418def1c47588bbb522cdb3a6c5
|
F src/expr.c cdddb81c68a0d222e03a4b92a7821d370c298a8e
|
||||||
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
||||||
F src/func.c f667fe886309707c7178542073bb0ced00a9fae7
|
F src/func.c be5067593d9c8971e1af803bb503b91ef1541e8d
|
||||||
F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c
|
F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c
|
||||||
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
|
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
|
||||||
F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
|
F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
|
||||||
@ -148,21 +148,21 @@ F src/os_unix.c e55d977c516ed880a2f83f0610b019efd9f8bc06
|
|||||||
F src/os_win.c 725c38a524d168ce280446ad8761d731bc516405
|
F src/os_win.c 725c38a524d168ce280446ad8761d731bc516405
|
||||||
F src/pager.c 8bf62fefc7afefc065d37611ebfd1fe0e1c2eb39
|
F src/pager.c 8bf62fefc7afefc065d37611ebfd1fe0e1c2eb39
|
||||||
F src/pager.h 73f481a308a873ccd626d97331c081db3b53e2e5
|
F src/pager.h 73f481a308a873ccd626d97331c081db3b53e2e5
|
||||||
F src/parse.y ba2fa210be4b17001e0a16d5e73a8141939b1987
|
F src/parse.y 6b55e52fb3362ad84130013f861c21f4b3ba5005
|
||||||
F src/pcache.c 395f752a13574120bd7513a400ba02a265aaa76d
|
F src/pcache.c 395f752a13574120bd7513a400ba02a265aaa76d
|
||||||
F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324
|
F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324
|
||||||
F src/pcache1.c bed75f157283e7c666f323df0c874c6a2515f76e
|
F src/pcache1.c bed75f157283e7c666f323df0c874c6a2515f76e
|
||||||
F src/pragma.c c26c16c49a80d03c8597f0e6c7daba53f283428f
|
F src/pragma.c cf9adc601f5d0e6de6f3a3ffb8fa5dfef8217d13
|
||||||
F src/prepare.c f46d1a029760edee5447e27164fb3ae10e2a6839
|
F src/prepare.c f46d1a029760edee5447e27164fb3ae10e2a6839
|
||||||
F src/printf.c 3f4dca207a88258d37af5a7a03e800a825fe6456
|
F src/printf.c 3f4dca207a88258d37af5a7a03e800a825fe6456
|
||||||
F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
|
F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
|
||||||
F src/resolve.c 2ce8f8bc8a0c913cbaec3fb3da2be113ea1fa5af
|
F src/resolve.c 0c9faa469e4e71ff84efd7fa60613036e88498d6
|
||||||
F src/rowset.c c64dafba1f9fd876836c8db8682966b9d197eb1f
|
F src/rowset.c c64dafba1f9fd876836c8db8682966b9d197eb1f
|
||||||
F src/select.c 88e654ab5b183e4fdb084680b66b5bfa6f214dc5
|
F src/select.c 18c296d45cc8cad8dc4b862d2df000a4681d7883
|
||||||
F src/shell.c 7eacd0bdaa887931f5ff205c9defc3e8df95a2dd
|
F src/shell.c 7eacd0bdaa887931f5ff205c9defc3e8df95a2dd
|
||||||
F src/sqlite.h.in 79210c4d8905cfb4b038486dde5f36fabb796a86
|
F src/sqlite.h.in 79210c4d8905cfb4b038486dde5f36fabb796a86
|
||||||
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
||||||
F src/sqliteInt.h b4cc76a99bc82894703528376067c743eb27184c
|
F src/sqliteInt.h 28a5b5c0bfb0efbb735dc0dedc3f076f7de95c57
|
||||||
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
|
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
|
||||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||||
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
|
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
|
||||||
@ -197,11 +197,11 @@ F src/test_server.c f0a403b5f699c09bd2b1236b6f69830fd6221f6b
|
|||||||
F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4
|
F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4
|
||||||
F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac
|
F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac
|
||||||
F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241
|
F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241
|
||||||
F src/tokenize.c 286ce8a4bffe5ec81ad893e6243684d8f8846ed9
|
F src/tokenize.c ef5e56bae212d08ff3a334ff059bc5292322251d
|
||||||
F src/trigger.c 853bb30f957c636a00b6437de755830213a9ee07
|
F src/trigger.c 6d233d6d737a229e31f810012f38ecac7dd89021
|
||||||
F src/update.c deb930324dd67b7ad98234e1258a0ebcdd1ca0f9
|
F src/update.c 3aec63a3a85754d16f7571ec80eb928e2fcf6c2e
|
||||||
F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff
|
F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff
|
||||||
F src/util.c 71c2d9d6befc0405377744585461246c30a4474b
|
F src/util.c f3ee188f05921d450ee2a2ff236e455d3131f9ce
|
||||||
F src/vacuum.c e8d178004377e97500c7ea87c8a3542976e3ea45
|
F src/vacuum.c e8d178004377e97500c7ea87c8a3542976e3ea45
|
||||||
F src/vdbe.c b859cb274024e5755aa03625251ff859e3e95158
|
F src/vdbe.c b859cb274024e5755aa03625251ff859e3e95158
|
||||||
F src/vdbe.h 35a648bc3279a120da24f34d9a25213ec15daf8a
|
F src/vdbe.h 35a648bc3279a120da24f34d9a25213ec15daf8a
|
||||||
@ -209,10 +209,10 @@ F src/vdbeInt.h 43183a2a18654fa570219ab65e53a608057c48ae
|
|||||||
F src/vdbeapi.c 86aa27a5f3493aaffb8ac051782aa3b22670d7ed
|
F src/vdbeapi.c 86aa27a5f3493aaffb8ac051782aa3b22670d7ed
|
||||||
F src/vdbeaux.c 1a07329bdf51cc3687f88d9f5b2bd3f1d47cc5a8
|
F src/vdbeaux.c 1a07329bdf51cc3687f88d9f5b2bd3f1d47cc5a8
|
||||||
F src/vdbeblob.c 5c5abe9af28316772e7829359f6f9cda2c737ebd
|
F src/vdbeblob.c 5c5abe9af28316772e7829359f6f9cda2c737ebd
|
||||||
F src/vdbemem.c d8b985eeb88214941380372466a30ca410043a93
|
F src/vdbemem.c 4d1a9b01ad47a8699b767bfc364168c61510b3d1
|
||||||
F src/vtab.c b0216337ae7d27708dedd56d220e6f4fecda92f1
|
F src/vtab.c b0216337ae7d27708dedd56d220e6f4fecda92f1
|
||||||
F src/walker.c 7cdf63223c953d4343c6833e940f110281a378ee
|
F src/walker.c b28cc618f5dc739bc5fb77389b6a42bc1be679ab
|
||||||
F src/where.c d11b8a8c49c518384292d410738bd21da5c00bf4
|
F src/where.c 145bb0d0590b36603a38f0fe17887fde06c3ed53
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||||
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
|
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
|
||||||
@ -226,7 +226,7 @@ F test/async.test c042ff6d2a29f65e05d498a52448229d25bb5d9d
|
|||||||
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
|
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
|
||||||
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
|
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
|
||||||
F test/async4.test bdb997924394a2034ff3df1d839ff95b2e602ed4
|
F test/async4.test bdb997924394a2034ff3df1d839ff95b2e602ed4
|
||||||
F test/attach.test 75a5d22f88e730967d68f2c9f95e786e3953d8e3
|
F test/attach.test 27635c34453504c2df8630730a5eab6e98c59eb9
|
||||||
F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
|
F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
|
||||||
F test/attach3.test 7b92dc8e40c1ebca9732ca6f2d3fefbd46f196df
|
F test/attach3.test 7b92dc8e40c1ebca9732ca6f2d3fefbd46f196df
|
||||||
F test/attachmalloc.test cf8cf17d183de357b1147a9baacbdfc85b940b61
|
F test/attachmalloc.test cf8cf17d183de357b1147a9baacbdfc85b940b61
|
||||||
@ -521,7 +521,7 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
|
|||||||
F test/savepoint6.test e28f7d8ab8a389d4e5bd1dc08bf2c3312754cc67
|
F test/savepoint6.test e28f7d8ab8a389d4e5bd1dc08bf2c3312754cc67
|
||||||
F test/schema.test deafe5472099ab5bc65748059dc5182fc8ebad74
|
F test/schema.test deafe5472099ab5bc65748059dc5182fc8ebad74
|
||||||
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
||||||
F test/select1.test 041fe01f2a8b7d77ffe77872f7b18ef531b31dfa
|
F test/select1.test 313078d5fca7a6fe1fb83e5f2e5b3e317beb8fac
|
||||||
F test/select2.test 9735da20ccd41e42bf2b4c19fd939141b591adae
|
F test/select2.test 9735da20ccd41e42bf2b4c19fd939141b591adae
|
||||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||||
F test/select4.test 44aa6e7110592e18110b0b9cf5c024d37d23be17
|
F test/select4.test 44aa6e7110592e18110b0b9cf5c024d37d23be17
|
||||||
@ -583,7 +583,7 @@ F test/tkt1449.test 93584a449752d52b07d2cfc280a69842b6e16ed5
|
|||||||
F test/tkt1473.test 9d000af3e11a4450d4c596f5e58b4b0d24eb0f8b
|
F test/tkt1473.test 9d000af3e11a4450d4c596f5e58b4b0d24eb0f8b
|
||||||
F test/tkt1501.test 2064f98e00871848af4b2f517e46c1a7fb2e32db
|
F test/tkt1501.test 2064f98e00871848af4b2f517e46c1a7fb2e32db
|
||||||
F test/tkt1512.test a1df1f66caf0b9122d6220c15dcee230298c2c2f
|
F test/tkt1512.test a1df1f66caf0b9122d6220c15dcee230298c2c2f
|
||||||
F test/tkt1514.test baa587a69fa2e8d575ebdaf1460f711281dcba49
|
F test/tkt1514.test ddef38e34fea72eb1ab935ded9f17a3fb71dd9df
|
||||||
F test/tkt1536.test 83ff7a7b6e248016f8d682d4f7a4ae114070d466
|
F test/tkt1536.test 83ff7a7b6e248016f8d682d4f7a4ae114070d466
|
||||||
F test/tkt1537.test e3a14332de9770be8ff14bd15c19a49cbec10808
|
F test/tkt1537.test e3a14332de9770be8ff14bd15c19a49cbec10808
|
||||||
F test/tkt1567.test 18023cc3626a365f0118e17b66decedec93b1a6f
|
F test/tkt1567.test 18023cc3626a365f0118e17b66decedec93b1a6f
|
||||||
@ -629,7 +629,7 @@ F test/tkt3457.test e9ca2b90f0eb1fb8be73a30d29aacb2e3abedeb9
|
|||||||
F test/tkt3461.test f79d027198b7e2bcf3d2d1a5501b6efef52096ee
|
F test/tkt3461.test f79d027198b7e2bcf3d2d1a5501b6efef52096ee
|
||||||
F test/tkt3472.test 98c7e54b8fef2b1266a552a66c8e5d88a6908d1d
|
F test/tkt3472.test 98c7e54b8fef2b1266a552a66c8e5d88a6908d1d
|
||||||
F test/tkt3493.test 8472b3464e49a27ff7271308eec46154209e667b
|
F test/tkt3493.test 8472b3464e49a27ff7271308eec46154209e667b
|
||||||
F test/tkt3508.test d9e285ff91731247d4673f9252fe5934639d7f0d
|
F test/tkt3508.test 26dbc10515145627fde6ad8905c842cec18e6f87
|
||||||
F test/tkt3522.test 22ce2ebbcb04a6be56c0977d405c207967318fd6
|
F test/tkt3522.test 22ce2ebbcb04a6be56c0977d405c207967318fd6
|
||||||
F test/tkt3527.test ee4af96183579565987e58873a7490bc04934ffb
|
F test/tkt3527.test ee4af96183579565987e58873a7490bc04934ffb
|
||||||
F test/tkt3541.test 5dc257bde9bc833ab9cc6844bf170b998dbb950a
|
F test/tkt3541.test 5dc257bde9bc833ab9cc6844bf170b998dbb950a
|
||||||
@ -731,7 +731,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
|||||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
P 5f358e63712e8de93bd6fecc5131badeef0292be
|
P 086206e1f51e22ce7b9f45865b370088db126cd2
|
||||||
R a6c27f16d174fa515fc2d13cfb08fb69
|
R 7a6811accc43c94a2230cdb121b78704
|
||||||
U drh
|
U drh
|
||||||
Z 246888a53f189c8881cdf3338527c2a3
|
Z 55c79ac1dc5e1ab2bd7febb8a2417351
|
||||||
|
@ -1 +1 @@
|
|||||||
086206e1f51e22ce7b9f45865b370088db126cd2
|
7cb1c3ba0759539cb035978fdaff6316775986f3
|
11
src/alter.c
11
src/alter.c
@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that used to generate VDBE code
|
** This file contains C code routines that used to generate VDBE code
|
||||||
** that implements the ALTER TABLE command.
|
** that implements the ALTER TABLE command.
|
||||||
**
|
**
|
||||||
** $Id: alter.c,v 1.58 2009/05/12 17:46:54 drh Exp $
|
** $Id: alter.c,v 1.59 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ static void renameTableFunc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Store the token that zCsr points to in tname. */
|
/* Store the token that zCsr points to in tname. */
|
||||||
tname.z = zCsr;
|
tname.z = (char*)zCsr;
|
||||||
tname.n = len;
|
tname.n = len;
|
||||||
|
|
||||||
/* Advance zCsr to the next token. Store that token type in 'token',
|
/* Advance zCsr to the next token. Store that token type in 'token',
|
||||||
@ -79,7 +79,7 @@ static void renameTableFunc(
|
|||||||
assert( len>0 );
|
assert( len>0 );
|
||||||
} while( token!=TK_LP && token!=TK_USING );
|
} while( token!=TK_LP && token!=TK_USING );
|
||||||
|
|
||||||
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql,
|
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
|
||||||
zTableName, tname.z+tname.n);
|
zTableName, tname.z+tname.n);
|
||||||
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
|
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ static void renameTriggerFunc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Store the token that zCsr points to in tname. */
|
/* Store the token that zCsr points to in tname. */
|
||||||
tname.z = zCsr;
|
tname.z = (char*)zCsr;
|
||||||
tname.n = len;
|
tname.n = len;
|
||||||
|
|
||||||
/* Advance zCsr to the next token. Store that token type in 'token',
|
/* Advance zCsr to the next token. Store that token type in 'token',
|
||||||
@ -155,7 +155,7 @@ static void renameTriggerFunc(
|
|||||||
/* Variable tname now contains the token that is the old table-name
|
/* Variable tname now contains the token that is the old table-name
|
||||||
** in the CREATE TRIGGER statement.
|
** in the CREATE TRIGGER statement.
|
||||||
*/
|
*/
|
||||||
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql,
|
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
|
||||||
zTableName, tname.z+tname.n);
|
zTableName, tname.z+tname.n);
|
||||||
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
|
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
|
||||||
}
|
}
|
||||||
@ -636,6 +636,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
|
|||||||
pCol->zColl = 0;
|
pCol->zColl = 0;
|
||||||
pCol->zType = 0;
|
pCol->zType = 0;
|
||||||
pCol->pDflt = 0;
|
pCol->pDflt = 0;
|
||||||
|
pCol->zDflt = 0;
|
||||||
}
|
}
|
||||||
pNew->pSchema = db->aDb[iDb].pSchema;
|
pNew->pSchema = db->aDb[iDb].pSchema;
|
||||||
pNew->addColOffset = pTab->addColOffset;
|
pNew->addColOffset = pTab->addColOffset;
|
||||||
|
35
src/attach.c
35
src/attach.c
@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** This file contains code used to implement the ATTACH and DETACH commands.
|
** This file contains code used to implement the ATTACH and DETACH commands.
|
||||||
**
|
**
|
||||||
** $Id: attach.c,v 1.90 2009/05/01 06:19:21 danielk1977 Exp $
|
** $Id: attach.c,v 1.91 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
|
|||||||
if( pExpr->op!=TK_ID ){
|
if( pExpr->op!=TK_ID ){
|
||||||
rc = sqlite3ResolveExprNames(pName, pExpr);
|
rc = sqlite3ResolveExprNames(pName, pExpr);
|
||||||
if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
|
if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
|
||||||
sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span);
|
sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->zToken);
|
||||||
return SQLITE_ERROR;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@ -298,21 +298,6 @@ static void codeAttach(
|
|||||||
sqlite3* db = pParse->db;
|
sqlite3* db = pParse->db;
|
||||||
int regArgs;
|
int regArgs;
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
||||||
assert( db->mallocFailed || pAuthArg );
|
|
||||||
if( pAuthArg ){
|
|
||||||
char *zAuthArg = sqlite3NameFromToken(db, &pAuthArg->span);
|
|
||||||
if( !zAuthArg ){
|
|
||||||
goto attach_end;
|
|
||||||
}
|
|
||||||
rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
|
|
||||||
sqlite3DbFree(db, zAuthArg);
|
|
||||||
if(rc!=SQLITE_OK ){
|
|
||||||
goto attach_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SQLITE_OMIT_AUTHORIZATION */
|
|
||||||
|
|
||||||
memset(&sName, 0, sizeof(NameContext));
|
memset(&sName, 0, sizeof(NameContext));
|
||||||
sName.pParse = pParse;
|
sName.pParse = pParse;
|
||||||
|
|
||||||
@ -325,6 +310,20 @@ static void codeAttach(
|
|||||||
goto attach_end;
|
goto attach_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||||
|
if( pAuthArg ){
|
||||||
|
char *zAuthArg = pAuthArg->zToken;
|
||||||
|
if( zAuthArg==0 ){
|
||||||
|
goto attach_end;
|
||||||
|
}
|
||||||
|
rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
|
||||||
|
if(rc!=SQLITE_OK ){
|
||||||
|
goto attach_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_AUTHORIZATION */
|
||||||
|
|
||||||
|
|
||||||
v = sqlite3GetVdbe(pParse);
|
v = sqlite3GetVdbe(pParse);
|
||||||
regArgs = sqlite3GetTempRange(pParse, 4);
|
regArgs = sqlite3GetTempRange(pParse, 4);
|
||||||
sqlite3ExprCode(pParse, pFilename, regArgs);
|
sqlite3ExprCode(pParse, pFilename, regArgs);
|
||||||
@ -487,7 +486,7 @@ int sqlite3FixExpr(
|
|||||||
Expr *pExpr /* The expression to be fixed to one database */
|
Expr *pExpr /* The expression to be fixed to one database */
|
||||||
){
|
){
|
||||||
while( pExpr ){
|
while( pExpr ){
|
||||||
if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanToken) ) break;
|
if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break;
|
||||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||||
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
|
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
|
||||||
}else{
|
}else{
|
||||||
|
51
src/build.c
51
src/build.c
@ -22,7 +22,7 @@
|
|||||||
** COMMIT
|
** COMMIT
|
||||||
** ROLLBACK
|
** ROLLBACK
|
||||||
**
|
**
|
||||||
** $Id: build.c,v 1.544 2009/05/13 22:58:29 drh Exp $
|
** $Id: build.c,v 1.545 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -470,6 +470,7 @@ static void sqliteResetColumnNames(Table *pTable){
|
|||||||
for(i=0; i<pTable->nCol; i++, pCol++){
|
for(i=0; i<pTable->nCol; i++, pCol++){
|
||||||
sqlite3DbFree(db, pCol->zName);
|
sqlite3DbFree(db, pCol->zName);
|
||||||
sqlite3ExprDelete(db, pCol->pDflt);
|
sqlite3ExprDelete(db, pCol->pDflt);
|
||||||
|
sqlite3DbFree(db, pCol->zDflt);
|
||||||
sqlite3DbFree(db, pCol->zType);
|
sqlite3DbFree(db, pCol->zType);
|
||||||
sqlite3DbFree(db, pCol->zColl);
|
sqlite3DbFree(db, pCol->zColl);
|
||||||
}
|
}
|
||||||
@ -568,7 +569,7 @@ char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
|
|||||||
char *zName;
|
char *zName;
|
||||||
if( pName ){
|
if( pName ){
|
||||||
zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n);
|
zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n);
|
||||||
if( pName->quoted ) sqlite3Dequote(zName);
|
sqlite3Dequote(zName);
|
||||||
}else{
|
}else{
|
||||||
zName = 0;
|
zName = 0;
|
||||||
}
|
}
|
||||||
@ -1002,14 +1003,12 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
|
|||||||
** If none of the substrings in the above table are found,
|
** If none of the substrings in the above table are found,
|
||||||
** SQLITE_AFF_NUMERIC is returned.
|
** SQLITE_AFF_NUMERIC is returned.
|
||||||
*/
|
*/
|
||||||
char sqlite3AffinityType(const Token *pType){
|
char sqlite3AffinityType(const char *zIn){
|
||||||
u32 h = 0;
|
u32 h = 0;
|
||||||
char aff = SQLITE_AFF_NUMERIC;
|
char aff = SQLITE_AFF_NUMERIC;
|
||||||
const unsigned char *zIn = pType->z;
|
|
||||||
const unsigned char *zEnd = &pType->z[pType->n];
|
|
||||||
|
|
||||||
while( zIn!=zEnd ){
|
if( zIn ) while( zIn[0] ){
|
||||||
h = (h<<8) + sqlite3UpperToLower[*zIn];
|
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
|
||||||
zIn++;
|
zIn++;
|
||||||
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
|
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
|
||||||
aff = SQLITE_AFF_TEXT;
|
aff = SQLITE_AFF_TEXT;
|
||||||
@ -1058,7 +1057,7 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){
|
|||||||
pCol = &p->aCol[p->nCol-1];
|
pCol = &p->aCol[p->nCol-1];
|
||||||
assert( pCol->zType==0 );
|
assert( pCol->zType==0 );
|
||||||
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
|
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
|
||||||
pCol->affinity = sqlite3AffinityType(pType);
|
pCol->affinity = sqlite3AffinityType(pCol->zType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1071,14 +1070,14 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){
|
|||||||
** This routine is called by the parser while in the middle of
|
** This routine is called by the parser while in the middle of
|
||||||
** parsing a CREATE TABLE statement.
|
** parsing a CREATE TABLE statement.
|
||||||
*/
|
*/
|
||||||
void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
|
void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
|
||||||
Table *p;
|
Table *p;
|
||||||
Column *pCol;
|
Column *pCol;
|
||||||
sqlite3 *db = pParse->db;
|
sqlite3 *db = pParse->db;
|
||||||
p = pParse->pNewTable;
|
p = pParse->pNewTable;
|
||||||
if( p!=0 ){
|
if( p!=0 ){
|
||||||
pCol = &(p->aCol[p->nCol-1]);
|
pCol = &(p->aCol[p->nCol-1]);
|
||||||
if( !sqlite3ExprIsConstantOrFunction(pExpr) ){
|
if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr) ){
|
||||||
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
|
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
|
||||||
pCol->zName);
|
pCol->zName);
|
||||||
}else{
|
}else{
|
||||||
@ -1087,10 +1086,13 @@ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
|
|||||||
** is required by pragma table_info.
|
** is required by pragma table_info.
|
||||||
*/
|
*/
|
||||||
sqlite3ExprDelete(db, pCol->pDflt);
|
sqlite3ExprDelete(db, pCol->pDflt);
|
||||||
pCol->pDflt = sqlite3ExprDup(db, pExpr, EXPRDUP_REDUCE|EXPRDUP_SPAN);
|
pCol->pDflt = sqlite3ExprDup(db, pSpan->pExpr, EXPRDUP_REDUCE);
|
||||||
|
sqlite3DbFree(db, pCol->zDflt);
|
||||||
|
pCol->zDflt = sqlite3DbStrNDup(db, (char*)pSpan->zStart,
|
||||||
|
pSpan->zEnd - pSpan->zStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3ExprDelete(db, pExpr);
|
sqlite3ExprDelete(db, pSpan->pExpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1399,14 +1401,8 @@ static char *createTableStmt(sqlite3 *db, Table *p){
|
|||||||
|
|
||||||
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
|
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
|
||||||
len = sqlite3Strlen30(zType);
|
len = sqlite3Strlen30(zType);
|
||||||
#ifndef NDEBUG
|
assert( pCol->affinity==SQLITE_AFF_NONE
|
||||||
if( pCol->affinity!=SQLITE_AFF_NONE ){
|
|| pCol->affinity==sqlite3AffinityType(zType) );
|
||||||
Token typeToken;
|
|
||||||
typeToken.z = (u8*)zType;
|
|
||||||
typeToken.n = len;
|
|
||||||
assert( pCol->affinity==sqlite3AffinityType(&typeToken) );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
memcpy(&zStmt[k], zType, len);
|
memcpy(&zStmt[k], zType, len);
|
||||||
k += len;
|
k += len;
|
||||||
assert( k<=n );
|
assert( k<=n );
|
||||||
@ -1652,7 +1648,7 @@ void sqlite3CreateView(
|
|||||||
){
|
){
|
||||||
Table *p;
|
Table *p;
|
||||||
int n;
|
int n;
|
||||||
const unsigned char *z;
|
const char *z;
|
||||||
Token sEnd;
|
Token sEnd;
|
||||||
DbFixer sFix;
|
DbFixer sFix;
|
||||||
Token *pName;
|
Token *pName;
|
||||||
@ -1704,7 +1700,7 @@ void sqlite3CreateView(
|
|||||||
}
|
}
|
||||||
sEnd.n = 0;
|
sEnd.n = 0;
|
||||||
n = (int)(sEnd.z - pBegin->z);
|
n = (int)(sEnd.z - pBegin->z);
|
||||||
z = (const unsigned char*)pBegin->z;
|
z = pBegin->z;
|
||||||
while( ALWAYS(n>0) && sqlite3Isspace(z[n-1]) ){ n--; }
|
while( ALWAYS(n>0) && sqlite3Isspace(z[n-1]) ){ n--; }
|
||||||
sEnd.z = &z[n-1];
|
sEnd.z = &z[n-1];
|
||||||
sEnd.n = 1;
|
sEnd.n = 1;
|
||||||
@ -2508,11 +2504,11 @@ void sqlite3CreateIndex(
|
|||||||
** So create a fake list to simulate this.
|
** So create a fake list to simulate this.
|
||||||
*/
|
*/
|
||||||
if( pList==0 ){
|
if( pList==0 ){
|
||||||
nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName;
|
nullId.z = pTab->aCol[pTab->nCol-1].zName;
|
||||||
nullId.n = sqlite3Strlen30((char*)nullId.z);
|
nullId.n = sqlite3Strlen30((char*)nullId.z);
|
||||||
nullId.quoted = 0;
|
pList = sqlite3ExprListAppend(pParse, 0, 0);
|
||||||
pList = sqlite3ExprListAppend(pParse, 0, 0, &nullId);
|
|
||||||
if( pList==0 ) goto exit_create_index;
|
if( pList==0 ) goto exit_create_index;
|
||||||
|
sqlite3ExprListSetName(pParse, pList, &nullId, 0);
|
||||||
pList->a[0].sortOrder = (u8)sortOrder;
|
pList->a[0].sortOrder = (u8)sortOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3081,7 +3077,7 @@ SrcList *sqlite3SrcListEnlarge(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Append a new table name to the given SrcList. Create a new SrcList if
|
** Append a new table name to the given SrcList. Create a new SrcList if
|
||||||
** need be. A new entry is created in the SrcList even if pToken is NULL.
|
** need be. A new entry is created in the SrcList even if pTable is NULL.
|
||||||
**
|
**
|
||||||
** A SrcList is returned, or NULL if there is an OOM error. The returned
|
** A SrcList is returned, or NULL if there is an OOM error. The returned
|
||||||
** SrcList might be the same as the SrcList that was input or it might be
|
** SrcList might be the same as the SrcList that was input or it might be
|
||||||
@ -3109,6 +3105,9 @@ SrcList *sqlite3SrcListEnlarge(
|
|||||||
** then so is B. In other words, we never have a case where:
|
** then so is B. In other words, we never have a case where:
|
||||||
**
|
**
|
||||||
** sqlite3SrcListAppend(D,A,0,C);
|
** sqlite3SrcListAppend(D,A,0,C);
|
||||||
|
**
|
||||||
|
** Both pTable and pDatabase are assumed to be quoted. They are dequoted
|
||||||
|
** before being added to the SrcList.
|
||||||
*/
|
*/
|
||||||
SrcList *sqlite3SrcListAppend(
|
SrcList *sqlite3SrcListAppend(
|
||||||
sqlite3 *db, /* Connection to notify of malloc failures */
|
sqlite3 *db, /* Connection to notify of malloc failures */
|
||||||
|
23
src/delete.c
23
src/delete.c
@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** in order to generate code for DELETE FROM statements.
|
** in order to generate code for DELETE FROM statements.
|
||||||
**
|
**
|
||||||
** $Id: delete.c,v 1.201 2009/05/01 21:13:37 drh Exp $
|
** $Id: delete.c,v 1.202 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -82,13 +82,18 @@ void sqlite3MaterializeView(
|
|||||||
pDup = sqlite3SelectDup(db, pView->pSelect, 0);
|
pDup = sqlite3SelectDup(db, pView->pSelect, 0);
|
||||||
if( pWhere ){
|
if( pWhere ){
|
||||||
SrcList *pFrom;
|
SrcList *pFrom;
|
||||||
Token viewName;
|
|
||||||
|
|
||||||
pWhere = sqlite3ExprDup(db, pWhere, 0);
|
pWhere = sqlite3ExprDup(db, pWhere, 0);
|
||||||
viewName.z = (u8*)pView->zName;
|
pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
|
||||||
viewName.n = (unsigned int)sqlite3Strlen30((const char*)viewName.z);
|
if( pFrom ){
|
||||||
viewName.quoted = 0;
|
assert( pFrom->nSrc==1 );
|
||||||
pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);
|
pFrom->a[0].zAlias = sqlite3DbStrDup(db, pView->zName);
|
||||||
|
pFrom->a[0].pSelect = pDup;
|
||||||
|
assert( pFrom->a[0].pOn==0 );
|
||||||
|
assert( pFrom->a[0].pUsing==0 );
|
||||||
|
}else{
|
||||||
|
sqlite3SelectDelete(db, pDup);
|
||||||
|
}
|
||||||
pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
|
pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
|
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
|
||||||
@ -148,9 +153,9 @@ Expr *sqlite3LimitWhere(
|
|||||||
** );
|
** );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
|
pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
|
||||||
if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
|
if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
|
||||||
pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0);
|
pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid);
|
||||||
if( pEList == 0 ) goto limit_where_cleanup_2;
|
if( pEList == 0 ) goto limit_where_cleanup_2;
|
||||||
|
|
||||||
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
|
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
|
||||||
@ -167,7 +172,7 @@ Expr *sqlite3LimitWhere(
|
|||||||
if( pSelect == 0 ) return 0;
|
if( pSelect == 0 ) return 0;
|
||||||
|
|
||||||
/* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
|
/* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
|
||||||
pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
|
pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
|
||||||
if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
|
if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
|
||||||
pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
|
pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
|
||||||
if( pInClause == 0 ) goto limit_where_cleanup_1;
|
if( pInClause == 0 ) goto limit_where_cleanup_1;
|
||||||
|
424
src/expr.c
424
src/expr.c
@ -12,7 +12,7 @@
|
|||||||
** This file contains routines used for analyzing expressions and
|
** This file contains routines used for analyzing expressions and
|
||||||
** for generating VDBE code that evaluates expressions in SQLite.
|
** for generating VDBE code that evaluates expressions in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: expr.c,v 1.436 2009/05/25 11:46:29 drh Exp $
|
** $Id: expr.c,v 1.437 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ char sqlite3ExprAffinity(Expr *pExpr){
|
|||||||
}
|
}
|
||||||
#ifndef SQLITE_OMIT_CAST
|
#ifndef SQLITE_OMIT_CAST
|
||||||
if( op==TK_CAST ){
|
if( op==TK_CAST ){
|
||||||
return sqlite3AffinityType(&pExpr->token);
|
return sqlite3AffinityType(pExpr->zToken);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
|
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
|
||||||
@ -376,70 +376,109 @@ int sqlite3SelectExprHeight(Select *p){
|
|||||||
#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
|
#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
** This routine is the core allocator for Expr nodes.
|
||||||
|
**
|
||||||
** Construct a new expression node and return a pointer to it. Memory
|
** Construct a new expression node and return a pointer to it. Memory
|
||||||
** for this node is obtained from sqlite3_malloc(). The calling function
|
** for this node and for the pToken argument is a single allocation
|
||||||
|
** obtained from sqlite3DbMalloc(). The calling function
|
||||||
** is responsible for making sure the node eventually gets freed.
|
** is responsible for making sure the node eventually gets freed.
|
||||||
|
**
|
||||||
|
** If dequote is true, then the token (if it exists) is dequoted.
|
||||||
|
** If dequote is false, no dequoting is performance. The deQuote
|
||||||
|
** parameter is ignored if pToken is NULL or if the token does not
|
||||||
|
** appear to be quoted. If the quotes were of the form "..." (double-quotes)
|
||||||
|
** then the EP_DblQuoted flag is set on the expression node.
|
||||||
*/
|
*/
|
||||||
Expr *sqlite3Expr(
|
Expr *sqlite3ExprAlloc(
|
||||||
sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
|
sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
|
||||||
int op, /* Expression opcode */
|
int op, /* Expression opcode */
|
||||||
Expr *pLeft, /* Left operand */
|
const Token *pToken, /* Token argument. Might be NULL */
|
||||||
Expr *pRight, /* Right operand */
|
int dequote /* True to dequote */
|
||||||
const Token *pToken /* Argument token */
|
|
||||||
){
|
){
|
||||||
Expr *pNew;
|
Expr *pNew;
|
||||||
pNew = sqlite3DbMallocZero(db, sizeof(Expr));
|
int nExtra;
|
||||||
if( pNew==0 ){
|
|
||||||
/* When malloc fails, delete pLeft and pRight. Expressions passed to
|
if( pToken ){
|
||||||
** this function must always be allocated with sqlite3Expr() for this
|
nExtra = pToken->n+1;
|
||||||
** reason.
|
}else{
|
||||||
*/
|
nExtra = 0;
|
||||||
sqlite3ExprDelete(db, pLeft);
|
|
||||||
sqlite3ExprDelete(db, pRight);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra);
|
||||||
|
if( pNew ){
|
||||||
pNew->op = (u8)op;
|
pNew->op = (u8)op;
|
||||||
pNew->pLeft = pLeft;
|
|
||||||
pNew->pRight = pRight;
|
|
||||||
pNew->iAgg = -1;
|
pNew->iAgg = -1;
|
||||||
pNew->span.z = (u8*)"";
|
|
||||||
if( pToken ){
|
if( pToken ){
|
||||||
int c;
|
int c;
|
||||||
assert( pToken->dyn==0 );
|
pNew->zToken = (char*)&pNew[1];
|
||||||
pNew->span = *pToken;
|
memcpy(pNew->zToken, pToken->z, pToken->n);
|
||||||
if( pToken->n>=2
|
pNew->zToken[pToken->n] = 0;
|
||||||
|
if( dequote && nExtra>=3
|
||||||
&& ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
|
&& ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
|
||||||
sqlite3TokenCopy(db, &pNew->token, pToken);
|
sqlite3Dequote(pNew->zToken);
|
||||||
if( pNew->token.z ){
|
|
||||||
pNew->token.n = sqlite3Dequote((char*)pNew->token.z);
|
|
||||||
assert( pNew->token.n==(unsigned)sqlite3Strlen30((char*)pNew->token.z));
|
|
||||||
}
|
|
||||||
if( c=='"' ) pNew->flags |= EP_DblQuoted;
|
if( c=='"' ) pNew->flags |= EP_DblQuoted;
|
||||||
}else{
|
|
||||||
pNew->token = *pToken;
|
|
||||||
}
|
|
||||||
pNew->token.quoted = 0;
|
|
||||||
}else if( pLeft ){
|
|
||||||
if( pRight ){
|
|
||||||
if( pRight->span.dyn==0 && pLeft->span.dyn==0 ){
|
|
||||||
sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span);
|
|
||||||
}
|
|
||||||
if( pRight->flags & EP_ExpCollate ){
|
|
||||||
pNew->flags |= EP_ExpCollate;
|
|
||||||
pNew->pColl = pRight->pColl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( pLeft->flags & EP_ExpCollate ){
|
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||||
pNew->flags |= EP_ExpCollate;
|
pNew->nHeight = 1;
|
||||||
pNew->pColl = pLeft->pColl;
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
exprSetHeight(pNew);
|
|
||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
** Allocate a new expression node from a zero-terminated token that has
|
||||||
|
** already been dequoted.
|
||||||
|
*/
|
||||||
|
Expr *sqlite3Expr(
|
||||||
|
sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
|
||||||
|
int op, /* Expression opcode */
|
||||||
|
const char *zToken /* Token argument. Might be NULL */
|
||||||
|
){
|
||||||
|
Token x;
|
||||||
|
x.z = zToken;
|
||||||
|
x.n = zToken ? sqlite3Strlen30(zToken) : 0;
|
||||||
|
return sqlite3ExprAlloc(db, op, &x, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Attach subtrees pLeft and pRight to the Expr node pRoot.
|
||||||
|
**
|
||||||
|
** If pRoot==NULL that means that a memory allocation error has occurred.
|
||||||
|
** In that case, delete the subtrees pLeft and pRight.
|
||||||
|
*/
|
||||||
|
void sqlite3ExprAttachSubtrees(
|
||||||
|
sqlite3 *db,
|
||||||
|
Expr *pRoot,
|
||||||
|
Expr *pLeft,
|
||||||
|
Expr *pRight
|
||||||
|
){
|
||||||
|
if( pRoot==0 ){
|
||||||
|
assert( db->mallocFailed );
|
||||||
|
sqlite3ExprDelete(db, pLeft);
|
||||||
|
sqlite3ExprDelete(db, pRight);
|
||||||
|
}else{
|
||||||
|
if( pRight ){
|
||||||
|
pRoot->pRight = pRight;
|
||||||
|
if( pRight->flags & EP_ExpCollate ){
|
||||||
|
pRoot->flags |= EP_ExpCollate;
|
||||||
|
pRoot->pColl = pRight->pColl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( pLeft ){
|
||||||
|
pRoot->pLeft = pLeft;
|
||||||
|
if( pLeft->flags & EP_ExpCollate ){
|
||||||
|
pRoot->flags |= EP_ExpCollate;
|
||||||
|
pRoot->pColl = pLeft->pColl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exprSetHeight(pRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Allocate a Expr node which joins up to two subtrees.
|
||||||
|
**
|
||||||
|
** The
|
||||||
** Works like sqlite3Expr() except that it takes an extra Parse*
|
** Works like sqlite3Expr() except that it takes an extra Parse*
|
||||||
** argument and notifies the associated connection object if malloc fails.
|
** argument and notifies the associated connection object if malloc fails.
|
||||||
*/
|
*/
|
||||||
@ -450,34 +489,8 @@ Expr *sqlite3PExpr(
|
|||||||
Expr *pRight, /* Right operand */
|
Expr *pRight, /* Right operand */
|
||||||
const Token *pToken /* Argument token */
|
const Token *pToken /* Argument token */
|
||||||
){
|
){
|
||||||
Expr *p = sqlite3Expr(pParse->db, op, pLeft, pRight, pToken);
|
Expr *p = sqlite3ExprAlloc(pParse->db, op, pToken, 1);
|
||||||
if( p ){
|
sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
|
||||||
sqlite3ExprCheckHeight(pParse, p->nHeight);
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** When doing a nested parse, you can include terms in an expression
|
|
||||||
** that look like this: #1 #2 ... These terms refer to registers
|
|
||||||
** in the virtual machine. #N is the N-th register.
|
|
||||||
**
|
|
||||||
** This routine is called by the parser to deal with on of those terms.
|
|
||||||
** It immediately generates code to store the value in a memory location.
|
|
||||||
** The returns an expression that will code to extract the value from
|
|
||||||
** that memory location as needed.
|
|
||||||
*/
|
|
||||||
Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
|
|
||||||
Expr *p;
|
|
||||||
if( pParse->nested==0 ){
|
|
||||||
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken);
|
|
||||||
return sqlite3PExpr(pParse, TK_NULL, 0, 0, 0);
|
|
||||||
}
|
|
||||||
p = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, pToken);
|
|
||||||
if( p==0 ){
|
|
||||||
return 0; /* Malloc failed */
|
|
||||||
}
|
|
||||||
p->iTable = atoi((char*)&pToken->z[1]);
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,24 +504,9 @@ Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
|
|||||||
}else if( pRight==0 ){
|
}else if( pRight==0 ){
|
||||||
return pLeft;
|
return pLeft;
|
||||||
}else{
|
}else{
|
||||||
return sqlite3Expr(db, TK_AND, pLeft, pRight, 0);
|
Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
|
||||||
}
|
sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
|
||||||
}
|
return pNew;
|
||||||
|
|
||||||
/*
|
|
||||||
** Set the Expr.span field of the given expression to span all
|
|
||||||
** text between the two given tokens. Both tokens must be pointing
|
|
||||||
** at the same string.
|
|
||||||
*/
|
|
||||||
void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
|
|
||||||
assert( pRight!=0 );
|
|
||||||
assert( pLeft!=0 );
|
|
||||||
if( pExpr ){
|
|
||||||
pExpr->span.z = pLeft->z;
|
|
||||||
/* The following assert() may fail when this is called
|
|
||||||
** via sqlite3PExpr()/sqlite3Expr() from addWhereTerm(). */
|
|
||||||
/* assert(pRight->z >= pLeft->z); */
|
|
||||||
pExpr->span.n = pRight->n + (unsigned)(pRight->z - pLeft->z);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,17 +518,13 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
|
|||||||
Expr *pNew;
|
Expr *pNew;
|
||||||
sqlite3 *db = pParse->db;
|
sqlite3 *db = pParse->db;
|
||||||
assert( pToken );
|
assert( pToken );
|
||||||
pNew = sqlite3DbMallocZero(db, sizeof(Expr) );
|
pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
|
||||||
if( pNew==0 ){
|
if( pNew==0 ){
|
||||||
sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
|
sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pNew->op = TK_FUNCTION;
|
|
||||||
pNew->x.pList = pList;
|
pNew->x.pList = pList;
|
||||||
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
|
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
|
||||||
assert( pToken->dyn==0 );
|
|
||||||
pNew->span = *pToken;
|
|
||||||
sqlite3TokenCopy(db, &pNew->token, pToken);
|
|
||||||
sqlite3ExprSetHeight(pParse, pNew);
|
sqlite3ExprSetHeight(pParse, pNew);
|
||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
@ -552,22 +546,22 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
|
|||||||
** assigned.
|
** assigned.
|
||||||
*/
|
*/
|
||||||
void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||||
Token *pToken;
|
|
||||||
sqlite3 *db = pParse->db;
|
sqlite3 *db = pParse->db;
|
||||||
|
const char *z;
|
||||||
|
|
||||||
if( pExpr==0 ) return;
|
if( pExpr==0 ) return;
|
||||||
pToken = &pExpr->token;
|
z = pExpr->zToken;
|
||||||
assert( pToken->n>=1 );
|
assert( z!=0 );
|
||||||
assert( pToken->z!=0 );
|
assert( z[0]!=0 );
|
||||||
assert( pToken->z[0]!=0 );
|
if( z[1]==0 ){
|
||||||
if( pToken->n==1 ){
|
|
||||||
/* Wildcard of the form "?". Assign the next variable number */
|
/* Wildcard of the form "?". Assign the next variable number */
|
||||||
|
assert( z[0]=='?' );
|
||||||
pExpr->iTable = ++pParse->nVar;
|
pExpr->iTable = ++pParse->nVar;
|
||||||
}else if( pToken->z[0]=='?' ){
|
}else if( z[0]=='?' ){
|
||||||
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
|
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
|
||||||
** use it as the variable number */
|
** use it as the variable number */
|
||||||
int i;
|
int i;
|
||||||
pExpr->iTable = i = atoi((char*)&pToken->z[1]);
|
pExpr->iTable = i = atoi((char*)&z[1]);
|
||||||
testcase( i==0 );
|
testcase( i==0 );
|
||||||
testcase( i==1 );
|
testcase( i==1 );
|
||||||
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
|
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
|
||||||
@ -586,11 +580,11 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
|||||||
*/
|
*/
|
||||||
int i;
|
int i;
|
||||||
u32 n;
|
u32 n;
|
||||||
n = pToken->n;
|
n = sqlite3Strlen30(z);
|
||||||
for(i=0; i<pParse->nVarExpr; i++){
|
for(i=0; i<pParse->nVarExpr; i++){
|
||||||
Expr *pE = pParse->apVarExpr[i];
|
Expr *pE = pParse->apVarExpr[i];
|
||||||
assert( pE!=0 );
|
assert( pE!=0 );
|
||||||
if( pE->token.n==n && memcmp(pE->token.z, pToken->z, n)==0 ){
|
if( memcmp(pE->zToken, z, n)==0 && pE->zToken[n]==0 ){
|
||||||
pExpr->iTable = pE->iTable;
|
pExpr->iTable = pE->iTable;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -622,9 +616,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
|||||||
** Substructure is deleted.
|
** Substructure is deleted.
|
||||||
*/
|
*/
|
||||||
void sqlite3ExprClear(sqlite3 *db, Expr *p){
|
void sqlite3ExprClear(sqlite3 *db, Expr *p){
|
||||||
if( p->token.dyn ) sqlite3DbFree(db, (char*)p->token.z);
|
if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
|
||||||
if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanToken) ){
|
|
||||||
if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z);
|
|
||||||
if( ExprHasProperty(p, EP_Reduced) ){
|
if( ExprHasProperty(p, EP_Reduced) ){
|
||||||
/* Subtrees are part of the same memory allocation when EP_Reduced set */
|
/* Subtrees are part of the same memory allocation when EP_Reduced set */
|
||||||
if( p->pLeft ) sqlite3ExprClear(db, p->pLeft);
|
if( p->pLeft ) sqlite3ExprClear(db, p->pLeft);
|
||||||
@ -633,6 +625,8 @@ void sqlite3ExprClear(sqlite3 *db, Expr *p){
|
|||||||
/* Subtrees are separate allocations when EP_Reduced is clear */
|
/* Subtrees are separate allocations when EP_Reduced is clear */
|
||||||
sqlite3ExprDelete(db, p->pLeft);
|
sqlite3ExprDelete(db, p->pLeft);
|
||||||
sqlite3ExprDelete(db, p->pRight);
|
sqlite3ExprDelete(db, p->pRight);
|
||||||
|
/* Sometimes the zToken is allocated separately */
|
||||||
|
if( p->flags2 & EP2_FreeToken ) sqlite3DbFree(db, p->zToken);
|
||||||
}
|
}
|
||||||
/* x.pSelect and x.pList are always separately allocated */
|
/* x.pSelect and x.pList are always separately allocated */
|
||||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||||
@ -659,7 +653,6 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
|
|||||||
*/
|
*/
|
||||||
static int exprStructSize(Expr *p){
|
static int exprStructSize(Expr *p){
|
||||||
if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
|
if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
|
||||||
if( ExprHasProperty(p, EP_SpanToken) ) return EXPR_SPANTOKENSIZE;
|
|
||||||
if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
|
if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
|
||||||
return EXPR_FULLSIZE;
|
return EXPR_FULLSIZE;
|
||||||
}
|
}
|
||||||
@ -676,8 +669,6 @@ static int dupedExprStructSize(Expr *p, int flags){
|
|||||||
nSize = EXPR_FULLSIZE;
|
nSize = EXPR_FULLSIZE;
|
||||||
}else if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
|
}else if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
|
||||||
nSize = EXPR_REDUCEDSIZE;
|
nSize = EXPR_REDUCEDSIZE;
|
||||||
}else if( flags&EXPRDUP_SPAN ){
|
|
||||||
nSize = EXPR_SPANTOKENSIZE;
|
|
||||||
}else{
|
}else{
|
||||||
nSize = EXPR_TOKENONLYSIZE;
|
nSize = EXPR_TOKENONLYSIZE;
|
||||||
}
|
}
|
||||||
@ -688,15 +679,13 @@ static int dupedExprStructSize(Expr *p, int flags){
|
|||||||
** sqlite3ExprDup() has been called to create a copy of expression p with
|
** sqlite3ExprDup() has been called to create a copy of expression p with
|
||||||
** the EXPRDUP_XXX passed as the second argument. This function returns
|
** the EXPRDUP_XXX passed as the second argument. This function returns
|
||||||
** the space in bytes required to store the copy of the Expr structure
|
** the space in bytes required to store the copy of the Expr structure
|
||||||
** and the copies of the Expr.token.z and Expr.span.z (if applicable)
|
** and the copies of the Expr.zToken (if applicable)
|
||||||
** string buffers.
|
** string buffers.
|
||||||
*/
|
*/
|
||||||
static int dupedExprNodeSize(Expr *p, int flags){
|
static int dupedExprNodeSize(Expr *p, int flags){
|
||||||
int nByte = dupedExprStructSize(p, flags) + (p->token.z ? p->token.n + 1 : 0);
|
int nByte = dupedExprStructSize(p, flags);
|
||||||
if( (flags&EXPRDUP_SPAN)!=0
|
if( p->zToken ){
|
||||||
&& (p->token.z!=p->span.z || p->token.n!=p->span.n)
|
nByte += sqlite3Strlen30(p->zToken)+1;
|
||||||
){
|
|
||||||
nByte += p->span.n;
|
|
||||||
}
|
}
|
||||||
return ROUND8(nByte);
|
return ROUND8(nByte);
|
||||||
}
|
}
|
||||||
@ -707,9 +696,7 @@ static int dupedExprNodeSize(Expr *p, int flags){
|
|||||||
** mask containing EXPRDUP_XXX flags.
|
** mask containing EXPRDUP_XXX flags.
|
||||||
**
|
**
|
||||||
** The value returned includes space to create a copy of the Expr struct
|
** The value returned includes space to create a copy of the Expr struct
|
||||||
** itself and the buffer referred to by Expr.token, if any. If the
|
** itself and the buffer referred to by Expr.zToken, if any.
|
||||||
** EXPRDUP_SPAN flag is set, then space to create a copy of the buffer
|
|
||||||
** refered to by Expr.span is also included.
|
|
||||||
**
|
**
|
||||||
** If the EXPRDUP_REDUCE flag is set, then the return value includes
|
** If the EXPRDUP_REDUCE flag is set, then the return value includes
|
||||||
** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
|
** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
|
||||||
@ -721,8 +708,7 @@ static int dupedExprSize(Expr *p, int flags){
|
|||||||
if( p ){
|
if( p ){
|
||||||
nByte = dupedExprNodeSize(p, flags);
|
nByte = dupedExprNodeSize(p, flags);
|
||||||
if( flags&EXPRDUP_REDUCE ){
|
if( flags&EXPRDUP_REDUCE ){
|
||||||
int f = flags&(~EXPRDUP_SPAN);
|
nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags);
|
||||||
nByte += dupedExprSize(p->pLeft, f) + dupedExprSize(p->pRight, f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nByte;
|
return nByte;
|
||||||
@ -731,7 +717,7 @@ static int dupedExprSize(Expr *p, int flags){
|
|||||||
/*
|
/*
|
||||||
** This function is similar to sqlite3ExprDup(), except that if pzBuffer
|
** This function is similar to sqlite3ExprDup(), except that if pzBuffer
|
||||||
** is not NULL then *pzBuffer is assumed to point to a buffer large enough
|
** is not NULL then *pzBuffer is assumed to point to a buffer large enough
|
||||||
** to store the copy of expression p, the copies of p->token and p->span
|
** to store the copy of expression p, the copies of p->zToken
|
||||||
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
|
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
|
||||||
** if any. Before returning, *pzBuffer is set to the first byte passed the
|
** if any. Before returning, *pzBuffer is set to the first byte passed the
|
||||||
** portion of the buffer copied into by this function.
|
** portion of the buffer copied into by this function.
|
||||||
@ -739,7 +725,6 @@ static int dupedExprSize(Expr *p, int flags){
|
|||||||
static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
||||||
Expr *pNew = 0; /* Value to return */
|
Expr *pNew = 0; /* Value to return */
|
||||||
if( p ){
|
if( p ){
|
||||||
const int isRequireSpan = (flags&EXPRDUP_SPAN);
|
|
||||||
const int isReduced = (flags&EXPRDUP_REDUCE);
|
const int isReduced = (flags&EXPRDUP_REDUCE);
|
||||||
u8 *zAlloc;
|
u8 *zAlloc;
|
||||||
|
|
||||||
@ -757,10 +742,10 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
|||||||
/* Set nNewSize to the size allocated for the structure pointed to
|
/* Set nNewSize to the size allocated for the structure pointed to
|
||||||
** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
|
** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
|
||||||
** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
|
** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
|
||||||
** by the copy of the p->token.z string (if any).
|
** by the copy of the p->zToken string (if any).
|
||||||
*/
|
*/
|
||||||
const int nNewSize = dupedExprStructSize(p, flags);
|
const int nNewSize = dupedExprStructSize(p, flags);
|
||||||
const int nToken = (p->token.z ? p->token.n + 1 : 0);
|
const int nToken = (p->zToken ? sqlite3Strlen30(p->zToken) + 1 : 0);
|
||||||
if( isReduced ){
|
if( isReduced ){
|
||||||
assert( ExprHasProperty(p, EP_Reduced)==0 );
|
assert( ExprHasProperty(p, EP_Reduced)==0 );
|
||||||
memcpy(zAlloc, p, nNewSize);
|
memcpy(zAlloc, p, nNewSize);
|
||||||
@ -771,40 +756,19 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set the EP_Reduced and EP_TokenOnly flags appropriately. */
|
/* Set the EP_Reduced and EP_TokenOnly flags appropriately. */
|
||||||
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_SpanToken);
|
pNew->flags &= ~(EP_Reduced|EP_TokenOnly);
|
||||||
switch( nNewSize ){
|
switch( nNewSize ){
|
||||||
case EXPR_REDUCEDSIZE: pNew->flags |= EP_Reduced; break;
|
case EXPR_REDUCEDSIZE: pNew->flags |= EP_Reduced; break;
|
||||||
case EXPR_TOKENONLYSIZE: pNew->flags |= EP_TokenOnly; break;
|
case EXPR_TOKENONLYSIZE: pNew->flags |= EP_TokenOnly; break;
|
||||||
case EXPR_SPANTOKENSIZE: pNew->flags |= EP_SpanToken; break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the p->token string, if any. */
|
/* Copy the p->zToken string, if any. */
|
||||||
if( nToken ){
|
if( nToken ){
|
||||||
unsigned char *zToken = &zAlloc[nNewSize];
|
char *zToken = pNew->zToken = (char*)&zAlloc[nNewSize];
|
||||||
memcpy(zToken, p->token.z, nToken-1);
|
memcpy(zToken, p->zToken, nToken);
|
||||||
zToken[nToken-1] = '\0';
|
|
||||||
pNew->token.dyn = 0;
|
|
||||||
pNew->token.z = zToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
|
if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
|
||||||
/* Fill in the pNew->span token, if required. */
|
|
||||||
if( isRequireSpan ){
|
|
||||||
if( p->token.z!=p->span.z || p->token.n!=p->span.n ){
|
|
||||||
pNew->span.z = &zAlloc[nNewSize+nToken];
|
|
||||||
memcpy((char *)pNew->span.z, p->span.z, p->span.n);
|
|
||||||
pNew->span.dyn = 0;
|
|
||||||
}else{
|
|
||||||
pNew->span.z = pNew->token.z;
|
|
||||||
pNew->span.n = pNew->token.n;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
pNew->span.z = 0;
|
|
||||||
pNew->span.n = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_SpanToken)) ){
|
|
||||||
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
|
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
|
||||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||||
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced);
|
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced);
|
||||||
@ -814,7 +778,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fill in pNew->pLeft and pNew->pRight. */
|
/* Fill in pNew->pLeft and pNew->pRight. */
|
||||||
if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly|EP_SpanToken) ){
|
if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){
|
||||||
zAlloc += dupedExprNodeSize(p, flags);
|
zAlloc += dupedExprNodeSize(p, flags);
|
||||||
if( ExprHasProperty(pNew, EP_Reduced) ){
|
if( ExprHasProperty(pNew, EP_Reduced) ){
|
||||||
pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
|
pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
|
||||||
@ -823,11 +787,15 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
|||||||
if( pzBuffer ){
|
if( pzBuffer ){
|
||||||
*pzBuffer = zAlloc;
|
*pzBuffer = zAlloc;
|
||||||
}
|
}
|
||||||
}else if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanToken) ){
|
}else{
|
||||||
|
pNew->flags2 = 0;
|
||||||
|
if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
|
||||||
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
|
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
|
||||||
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
|
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
@ -844,12 +812,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
|||||||
**
|
**
|
||||||
** Any tables that the SrcList might point to are not duplicated.
|
** Any tables that the SrcList might point to are not duplicated.
|
||||||
**
|
**
|
||||||
** The flags parameter contains a combination of the EXPRDUP_XXX flags. If
|
** The flags parameter contains a combination of the EXPRDUP_XXX flags.
|
||||||
** the EXPRDUP_SPAN flag is set in the argument parameter, then the
|
|
||||||
** Expr.span field of the input expression is copied. If EXPRDUP_SPAN is
|
|
||||||
** clear, then the Expr.span field of the returned expression structure
|
|
||||||
** is zeroed.
|
|
||||||
**
|
|
||||||
** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
|
** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
|
||||||
** truncated version of the usual Expr structure that will be stored as
|
** truncated version of the usual Expr structure that will be stored as
|
||||||
** part of the in-memory representation of the database schema.
|
** part of the in-memory representation of the database schema.
|
||||||
@ -857,17 +820,6 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
|||||||
Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){
|
Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){
|
||||||
return exprDup(db, p, flags, 0);
|
return exprDup(db, p, flags, 0);
|
||||||
}
|
}
|
||||||
void sqlite3TokenCopy(sqlite3 *db, Token *pTo, const Token *pFrom){
|
|
||||||
if( pTo->dyn ) sqlite3DbFree(db, (char*)pTo->z);
|
|
||||||
if( pFrom->z ){
|
|
||||||
pTo->n = pFrom->n;
|
|
||||||
pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n);
|
|
||||||
pTo->dyn = 1;
|
|
||||||
pTo->quoted = pFrom->quoted;
|
|
||||||
}else{
|
|
||||||
pTo->z = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
|
ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
|
||||||
ExprList *pNew;
|
ExprList *pNew;
|
||||||
struct ExprList_item *pItem, *pOldItem;
|
struct ExprList_item *pItem, *pOldItem;
|
||||||
@ -888,6 +840,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
|
|||||||
Expr *pOldExpr = pOldItem->pExpr;
|
Expr *pOldExpr = pOldItem->pExpr;
|
||||||
pItem->pExpr = pNewExpr = sqlite3ExprDup(db, pOldExpr, flags);
|
pItem->pExpr = pNewExpr = sqlite3ExprDup(db, pOldExpr, flags);
|
||||||
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
|
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
|
||||||
|
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
|
||||||
pItem->sortOrder = pOldItem->sortOrder;
|
pItem->sortOrder = pOldItem->sortOrder;
|
||||||
pItem->done = 0;
|
pItem->done = 0;
|
||||||
pItem->iCol = pOldItem->iCol;
|
pItem->iCol = pOldItem->iCol;
|
||||||
@ -962,10 +915,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
|
|||||||
if( p==0 ) return 0;
|
if( p==0 ) return 0;
|
||||||
pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
|
pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
|
||||||
if( pNew==0 ) return 0;
|
if( pNew==0 ) return 0;
|
||||||
/* Always make a copy of the span for top-level expressions in the
|
pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
|
||||||
** expression list. The logic in SELECT processing that determines
|
|
||||||
** the names of columns in the result set needs this information */
|
|
||||||
pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags|EXPRDUP_SPAN);
|
|
||||||
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
|
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
|
||||||
pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
|
pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
|
||||||
pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
|
pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
|
||||||
@ -995,12 +945,15 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
|
|||||||
/*
|
/*
|
||||||
** Add a new element to the end of an expression list. If pList is
|
** Add a new element to the end of an expression list. If pList is
|
||||||
** initially NULL, then create a new expression list.
|
** initially NULL, then create a new expression list.
|
||||||
|
**
|
||||||
|
** If a memory allocation error occurs, the entire list is freed and
|
||||||
|
** NULL is returned. If non-NULL is returned, then it is guaranteed
|
||||||
|
** that the new entry was successfully appended.
|
||||||
*/
|
*/
|
||||||
ExprList *sqlite3ExprListAppend(
|
ExprList *sqlite3ExprListAppend(
|
||||||
Parse *pParse, /* Parsing context */
|
Parse *pParse, /* Parsing context */
|
||||||
ExprList *pList, /* List to which to append. Might be NULL */
|
ExprList *pList, /* List to which to append. Might be NULL */
|
||||||
Expr *pExpr, /* Expression to be appended */
|
Expr *pExpr /* Expression to be appended. Might be NULL */
|
||||||
Token *pName /* AS keyword for the expression */
|
|
||||||
){
|
){
|
||||||
sqlite3 *db = pParse->db;
|
sqlite3 *db = pParse->db;
|
||||||
if( pList==0 ){
|
if( pList==0 ){
|
||||||
@ -1021,12 +974,10 @@ ExprList *sqlite3ExprListAppend(
|
|||||||
pList->nAlloc = sqlite3DbMallocSize(db, a)/sizeof(a[0]);
|
pList->nAlloc = sqlite3DbMallocSize(db, a)/sizeof(a[0]);
|
||||||
}
|
}
|
||||||
assert( pList->a!=0 );
|
assert( pList->a!=0 );
|
||||||
if( pExpr || pName ){
|
if( 1 ){
|
||||||
struct ExprList_item *pItem = &pList->a[pList->nExpr++];
|
struct ExprList_item *pItem = &pList->a[pList->nExpr++];
|
||||||
memset(pItem, 0, sizeof(*pItem));
|
memset(pItem, 0, sizeof(*pItem));
|
||||||
pItem->zName = sqlite3NameFromToken(db, pName);
|
|
||||||
pItem->pExpr = pExpr;
|
pItem->pExpr = pExpr;
|
||||||
pItem->iAlias = 0;
|
|
||||||
}
|
}
|
||||||
return pList;
|
return pList;
|
||||||
|
|
||||||
@ -1037,6 +988,56 @@ no_mem:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Set the ExprList.a[].zName element of the most recently added item
|
||||||
|
** on the expression list.
|
||||||
|
**
|
||||||
|
** pList might be NULL following an OOM error. But pName should never be
|
||||||
|
** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag
|
||||||
|
** is set.
|
||||||
|
*/
|
||||||
|
void sqlite3ExprListSetName(
|
||||||
|
Parse *pParse, /* Parsing context */
|
||||||
|
ExprList *pList, /* List to which to add the span. */
|
||||||
|
Token *pName, /* Name to be added */
|
||||||
|
int dequote /* True to cause the name to be dequoted */
|
||||||
|
){
|
||||||
|
assert( pList!=0 || pParse->db->mallocFailed!=0 );
|
||||||
|
if( pList ){
|
||||||
|
struct ExprList_item *pItem;
|
||||||
|
assert( pList->nExpr>0 );
|
||||||
|
pItem = &pList->a[pList->nExpr-1];
|
||||||
|
assert( pItem->zName==0 );
|
||||||
|
pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
|
||||||
|
if( dequote && pItem->zName ) sqlite3Dequote(pItem->zName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Set the ExprList.a[].zSpan element of the most recently added item
|
||||||
|
** on the expression list.
|
||||||
|
**
|
||||||
|
** pList might be NULL following an OOM error. But pSpan should never be
|
||||||
|
** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag
|
||||||
|
** is set.
|
||||||
|
*/
|
||||||
|
void sqlite3ExprListSetSpan(
|
||||||
|
Parse *pParse, /* Parsing context */
|
||||||
|
ExprList *pList, /* List to which to add the span. */
|
||||||
|
ExprSpan *pSpan /* The span to be added */
|
||||||
|
){
|
||||||
|
sqlite3 *db = pParse->db;
|
||||||
|
assert( pList!=0 || db->mallocFailed!=0 );
|
||||||
|
if( pList ){
|
||||||
|
struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
|
||||||
|
assert( pList->nExpr>0 );
|
||||||
|
assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr );
|
||||||
|
sqlite3DbFree(db, pItem->zSpan);
|
||||||
|
pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart,
|
||||||
|
pSpan->zEnd - pSpan->zStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** If the expression list pEList contains more than iLimit elements,
|
** If the expression list pEList contains more than iLimit elements,
|
||||||
** leave an error message in pParse.
|
** leave an error message in pParse.
|
||||||
@ -1066,6 +1067,7 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
|
|||||||
for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
|
for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
|
||||||
sqlite3ExprDelete(db, pItem->pExpr);
|
sqlite3ExprDelete(db, pItem->pExpr);
|
||||||
sqlite3DbFree(db, pItem->zName);
|
sqlite3DbFree(db, pItem->zName);
|
||||||
|
sqlite3DbFree(db, pItem->zSpan);
|
||||||
}
|
}
|
||||||
sqlite3DbFree(db, pList->a);
|
sqlite3DbFree(db, pList->a);
|
||||||
sqlite3DbFree(db, pList);
|
sqlite3DbFree(db, pList);
|
||||||
@ -1183,7 +1185,7 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
|
|||||||
}
|
}
|
||||||
switch( p->op ){
|
switch( p->op ){
|
||||||
case TK_INTEGER: {
|
case TK_INTEGER: {
|
||||||
rc = sqlite3GetInt32((char*)p->token.z, pValue);
|
rc = sqlite3GetInt32(p->zToken, pValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_UPLUS: {
|
case TK_UPLUS: {
|
||||||
@ -1578,7 +1580,7 @@ void sqlite3CodeSubselect(
|
|||||||
** value of this select in a memory cell and record the number
|
** value of this select in a memory cell and record the number
|
||||||
** of the memory cell in iColumn.
|
** of the memory cell in iColumn.
|
||||||
*/
|
*/
|
||||||
static const Token one = { (u8*)"1", 0, 0, 1 };
|
static const Token one = { "1", 1 };
|
||||||
Select *pSel;
|
Select *pSel;
|
||||||
SelectDest dest;
|
SelectDest dest;
|
||||||
|
|
||||||
@ -1632,10 +1634,8 @@ static char *dup8bytes(Vdbe *v, const char *in){
|
|||||||
** z[n] character is guaranteed to be something that does not look
|
** z[n] character is guaranteed to be something that does not look
|
||||||
** like the continuation of the number.
|
** like the continuation of the number.
|
||||||
*/
|
*/
|
||||||
static void codeReal(Vdbe *v, const char *z, int n, int negateFlag, int iMem){
|
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
|
||||||
assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed );
|
assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed );
|
||||||
assert( !z || !sqlite3Isdigit(z[n]) );
|
|
||||||
UNUSED_PARAMETER(n);
|
|
||||||
if( z ){
|
if( z ){
|
||||||
double value;
|
double value;
|
||||||
char *zV;
|
char *zV;
|
||||||
@ -1665,9 +1665,9 @@ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){
|
|||||||
int i = pExpr->iTable;
|
int i = pExpr->iTable;
|
||||||
if( negFlag ) i = -i;
|
if( negFlag ) i = -i;
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
|
sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
|
||||||
}else if( (z = (char*)pExpr->token.z)!=0 ){
|
}else if( (z = pExpr->zToken)!=0 ){
|
||||||
int i;
|
int i;
|
||||||
int n = pExpr->token.n;
|
int n = sqlite3Strlen30(pExpr->zToken);
|
||||||
assert( !sqlite3Isdigit(z[n]) );
|
assert( !sqlite3Isdigit(z[n]) );
|
||||||
if( sqlite3GetInt32(z, &i) ){
|
if( sqlite3GetInt32(z, &i) ){
|
||||||
if( negFlag ) i = -i;
|
if( negFlag ) i = -i;
|
||||||
@ -1680,7 +1680,7 @@ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){
|
|||||||
zV = dup8bytes(v, (char*)&value);
|
zV = dup8bytes(v, (char*)&value);
|
||||||
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
|
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
|
||||||
}else{
|
}else{
|
||||||
codeReal(v, z, n, negFlag, iMem);
|
codeReal(v, z, negFlag, iMem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2078,12 +2078,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_FLOAT: {
|
case TK_FLOAT: {
|
||||||
codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0, target);
|
codeReal(v, pExpr->zToken, 0, target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_STRING: {
|
case TK_STRING: {
|
||||||
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0,
|
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->zToken, 0);
|
||||||
(char*)pExpr->token.z, pExpr->token.n);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_NULL: {
|
case TK_NULL: {
|
||||||
@ -2095,12 +2094,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
int n;
|
int n;
|
||||||
const char *z;
|
const char *z;
|
||||||
char *zBlob;
|
char *zBlob;
|
||||||
assert( pExpr->token.n>=3 );
|
assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' );
|
||||||
assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' );
|
assert( pExpr->zToken[1]=='\'' );
|
||||||
assert( pExpr->token.z[1]=='\'' );
|
z = &pExpr->zToken[2];
|
||||||
assert( pExpr->token.z[pExpr->token.n-1]=='\'' );
|
n = sqlite3Strlen30(z) - 1;
|
||||||
n = pExpr->token.n - 3;
|
assert( z[n]=='\'' );
|
||||||
z = (char*)pExpr->token.z + 2;
|
|
||||||
zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);
|
zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);
|
||||||
sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);
|
sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);
|
||||||
break;
|
break;
|
||||||
@ -2109,7 +2107,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
case TK_VARIABLE: {
|
case TK_VARIABLE: {
|
||||||
int iPrior;
|
int iPrior;
|
||||||
VdbeOp *pOp;
|
VdbeOp *pOp;
|
||||||
if( pExpr->token.n<=1
|
assert( pExpr->zToken!=0 );
|
||||||
|
assert( pExpr->zToken[0]!=0 );
|
||||||
|
if( pExpr->zToken[1]==0
|
||||||
&& (iPrior = sqlite3VdbeCurrentAddr(v)-1)>=0
|
&& (iPrior = sqlite3VdbeCurrentAddr(v)-1)>=0
|
||||||
&& (pOp = sqlite3VdbeGetOp(v, iPrior))->opcode==OP_Variable
|
&& (pOp = sqlite3VdbeGetOp(v, iPrior))->opcode==OP_Variable
|
||||||
&& pOp->p1+pOp->p3==pExpr->iTable
|
&& pOp->p1+pOp->p3==pExpr->iTable
|
||||||
@ -2124,8 +2124,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
pOp->p3++;
|
pOp->p3++;
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeAddOp3(v, OP_Variable, pExpr->iTable, target, 1);
|
sqlite3VdbeAddOp3(v, OP_Variable, pExpr->iTable, target, 1);
|
||||||
if( pExpr->token.n>1 ){
|
if( pExpr->zToken[1]!=0 ){
|
||||||
sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n);
|
sqlite3VdbeChangeP4(v, -1, pExpr->zToken, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2143,7 +2143,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
/* Expressions of the form: CAST(pLeft AS token) */
|
/* Expressions of the form: CAST(pLeft AS token) */
|
||||||
int aff, to_op;
|
int aff, to_op;
|
||||||
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
||||||
aff = sqlite3AffinityType(&pExpr->token);
|
aff = sqlite3AffinityType(pExpr->zToken);
|
||||||
to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
|
to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
|
||||||
assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
|
assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
|
||||||
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
|
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
|
||||||
@ -2236,7 +2236,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
Expr *pLeft = pExpr->pLeft;
|
Expr *pLeft = pExpr->pLeft;
|
||||||
assert( pLeft );
|
assert( pLeft );
|
||||||
if( pLeft->op==TK_FLOAT ){
|
if( pLeft->op==TK_FLOAT ){
|
||||||
codeReal(v, (char*)pLeft->token.z, pLeft->token.n, 1, target);
|
codeReal(v, pLeft->zToken, 1, target);
|
||||||
}else if( pLeft->op==TK_INTEGER ){
|
}else if( pLeft->op==TK_INTEGER ){
|
||||||
codeInteger(v, pLeft, 1, target);
|
codeInteger(v, pLeft, 1, target);
|
||||||
}else{
|
}else{
|
||||||
@ -2279,8 +2279,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
case TK_AGG_FUNCTION: {
|
case TK_AGG_FUNCTION: {
|
||||||
AggInfo *pInfo = pExpr->pAggInfo;
|
AggInfo *pInfo = pExpr->pAggInfo;
|
||||||
if( pInfo==0 ){
|
if( pInfo==0 ){
|
||||||
sqlite3ErrorMsg(pParse, "misuse of aggregate: %T",
|
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->zToken);
|
||||||
&pExpr->span);
|
|
||||||
}else{
|
}else{
|
||||||
inReg = pInfo->aFunc[pExpr->iAgg].iMem;
|
inReg = pInfo->aFunc[pExpr->iAgg].iMem;
|
||||||
}
|
}
|
||||||
@ -2301,14 +2300,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||||
testcase( op==TK_CONST_FUNC );
|
testcase( op==TK_CONST_FUNC );
|
||||||
testcase( op==TK_FUNCTION );
|
testcase( op==TK_FUNCTION );
|
||||||
if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanToken) ){
|
if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
|
||||||
pFarg = 0;
|
pFarg = 0;
|
||||||
}else{
|
}else{
|
||||||
pFarg = pExpr->x.pList;
|
pFarg = pExpr->x.pList;
|
||||||
}
|
}
|
||||||
nFarg = pFarg ? pFarg->nExpr : 0;
|
nFarg = pFarg ? pFarg->nExpr : 0;
|
||||||
zId = (char*)pExpr->token.z;
|
zId = pExpr->zToken;
|
||||||
nId = pExpr->token.n;
|
nId = sqlite3Strlen30(zId);
|
||||||
pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
|
pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
|
||||||
assert( pDef!=0 );
|
assert( pDef!=0 );
|
||||||
if( pFarg ){
|
if( pFarg ){
|
||||||
@ -2591,7 +2590,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
pExpr->affinity == OE_Abort ||
|
pExpr->affinity == OE_Abort ||
|
||||||
pExpr->affinity == OE_Fail );
|
pExpr->affinity == OE_Fail );
|
||||||
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->affinity, 0,
|
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->affinity, 0,
|
||||||
(char*)pExpr->token.z, pExpr->token.n);
|
pExpr->zToken, 0);
|
||||||
} else {
|
} else {
|
||||||
assert( pExpr->affinity == OE_Ignore );
|
assert( pExpr->affinity == OE_Ignore );
|
||||||
sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0);
|
sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0);
|
||||||
@ -3136,10 +3135,9 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
|
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
|
||||||
if( pA->op!=TK_COLUMN && pA->token.z ){
|
if( pA->op!=TK_COLUMN && pA->zToken ){
|
||||||
if( pB->token.z==0 ) return 0;
|
if( pB->zToken==0 ) return 0;
|
||||||
if( pB->token.n!=pA->token.n ) return 0;
|
if( sqlite3StrICmp(pA->zToken,pB->zToken)!=0 ){
|
||||||
if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3287,7 +3285,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
|||||||
pItem->pExpr = pExpr;
|
pItem->pExpr = pExpr;
|
||||||
pItem->iMem = ++pParse->nMem;
|
pItem->iMem = ++pParse->nMem;
|
||||||
pItem->pFunc = sqlite3FindFunction(pParse->db,
|
pItem->pFunc = sqlite3FindFunction(pParse->db,
|
||||||
(char*)pExpr->token.z, pExpr->token.n,
|
pExpr->zToken, sqlite3Strlen30(pExpr->zToken),
|
||||||
pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
|
pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
|
||||||
if( pExpr->flags & EP_Distinct ){
|
if( pExpr->flags & EP_Distinct ){
|
||||||
pItem->iDistinct = pParse->nTab++;
|
pItem->iDistinct = pParse->nTab++;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||||
** All other code has file scope.
|
** All other code has file scope.
|
||||||
**
|
**
|
||||||
** $Id: func.c,v 1.234 2009/04/20 12:07:37 drh Exp $
|
** $Id: func.c,v 1.235 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -1368,8 +1368,8 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||||
pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2,
|
pDef = sqlite3FindFunction(db, pExpr->zToken, sqlite3Strlen30(pExpr->zToken),
|
||||||
SQLITE_UTF8, 0);
|
2, SQLITE_UTF8, 0);
|
||||||
if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
|
if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
445
src/parse.y
445
src/parse.y
@ -14,7 +14,7 @@
|
|||||||
** the parser. Lemon will also generate a header file containing
|
** the parser. Lemon will also generate a header file containing
|
||||||
** numeric codes for all of the tokens.
|
** numeric codes for all of the tokens.
|
||||||
**
|
**
|
||||||
** @(#) $Id: parse.y,v 1.276 2009/05/11 18:22:31 drh Exp $
|
** @(#) $Id: parse.y,v 1.277 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// All token codes are small integers with #defines that begin with "TK_"
|
// All token codes are small integers with #defines that begin with "TK_"
|
||||||
@ -166,8 +166,6 @@ columnlist ::= column.
|
|||||||
column(A) ::= columnid(X) type carglist. {
|
column(A) ::= columnid(X) type carglist. {
|
||||||
A.z = X.z;
|
A.z = X.z;
|
||||||
A.n = (int)(pParse->sLastToken.z-X.z) + pParse->sLastToken.n;
|
A.n = (int)(pParse->sLastToken.z-X.z) + pParse->sLastToken.n;
|
||||||
A.quoted = 0;
|
|
||||||
A.dyn = 0;
|
|
||||||
}
|
}
|
||||||
columnid(A) ::= nm(X). {
|
columnid(A) ::= nm(X). {
|
||||||
sqlite3AddColumn(pParse,&X);
|
sqlite3AddColumn(pParse,&X);
|
||||||
@ -264,17 +262,20 @@ carglist ::= carglist carg.
|
|||||||
carglist ::= .
|
carglist ::= .
|
||||||
carg ::= CONSTRAINT nm ccons.
|
carg ::= CONSTRAINT nm ccons.
|
||||||
carg ::= ccons.
|
carg ::= ccons.
|
||||||
ccons ::= DEFAULT term(X). {sqlite3AddDefaultValue(pParse,X);}
|
ccons ::= DEFAULT term(X). {sqlite3AddDefaultValue(pParse,&X);}
|
||||||
ccons ::= DEFAULT LP expr(X) RP. {sqlite3AddDefaultValue(pParse,X);}
|
ccons ::= DEFAULT LP expr(X) RP. {sqlite3AddDefaultValue(pParse,&X);}
|
||||||
ccons ::= DEFAULT PLUS term(X). {sqlite3AddDefaultValue(pParse,X);}
|
ccons ::= DEFAULT PLUS term(X). {sqlite3AddDefaultValue(pParse,&X);}
|
||||||
ccons ::= DEFAULT MINUS(A) term(X). {
|
ccons ::= DEFAULT MINUS(A) term(X). {
|
||||||
Expr *p = sqlite3PExpr(pParse, TK_UMINUS, X, 0, 0);
|
ExprSpan v;
|
||||||
sqlite3ExprSpan(p,&A,&X->span);
|
v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, X.pExpr, 0, 0);
|
||||||
sqlite3AddDefaultValue(pParse,p);
|
v.zStart = A.z;
|
||||||
|
v.zEnd = X.zEnd;
|
||||||
|
sqlite3AddDefaultValue(pParse,&v);
|
||||||
}
|
}
|
||||||
ccons ::= DEFAULT id(X). {
|
ccons ::= DEFAULT id(X). {
|
||||||
Expr *p = sqlite3PExpr(pParse, TK_STRING, 0, 0, &X);
|
ExprSpan v;
|
||||||
sqlite3AddDefaultValue(pParse,p);
|
spanExpr(&v, pParse, TK_STRING, &X);
|
||||||
|
sqlite3AddDefaultValue(pParse,&v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In addition to the type name, we also care about the primary key and
|
// In addition to the type name, we also care about the primary key and
|
||||||
@ -285,7 +286,7 @@ ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);}
|
|||||||
ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I).
|
ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I).
|
||||||
{sqlite3AddPrimaryKey(pParse,0,R,I,Z);}
|
{sqlite3AddPrimaryKey(pParse,0,R,I,Z);}
|
||||||
ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);}
|
ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);}
|
||||||
ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);}
|
ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X.pExpr);}
|
||||||
ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
|
ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
|
||||||
{sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
|
{sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
|
||||||
ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);}
|
ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);}
|
||||||
@ -335,7 +336,8 @@ tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R).
|
|||||||
{sqlite3AddPrimaryKey(pParse,X,R,I,0);}
|
{sqlite3AddPrimaryKey(pParse,X,R,I,0);}
|
||||||
tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
|
tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
|
||||||
{sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);}
|
{sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);}
|
||||||
tcons ::= CHECK LP expr(E) RP onconf. {sqlite3AddCheckConstraint(pParse,E);}
|
tcons ::= CHECK LP expr(E) RP onconf.
|
||||||
|
{sqlite3AddCheckConstraint(pParse,E.pExpr);}
|
||||||
tcons ::= FOREIGN KEY LP idxlist(FA) RP
|
tcons ::= FOREIGN KEY LP idxlist(FA) RP
|
||||||
REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). {
|
REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). {
|
||||||
sqlite3CreateForeignKey(pParse, FA, &T, TA, R);
|
sqlite3CreateForeignKey(pParse, FA, &T, TA, R);
|
||||||
@ -433,17 +435,19 @@ distinct(A) ::= . {A = 0;}
|
|||||||
sclp(A) ::= selcollist(X) COMMA. {A = X;}
|
sclp(A) ::= selcollist(X) COMMA. {A = X;}
|
||||||
sclp(A) ::= . {A = 0;}
|
sclp(A) ::= . {A = 0;}
|
||||||
selcollist(A) ::= sclp(P) expr(X) as(Y). {
|
selcollist(A) ::= sclp(P) expr(X) as(Y). {
|
||||||
A = sqlite3ExprListAppend(pParse,P,X,Y.n?&Y:0);
|
A = sqlite3ExprListAppend(pParse, P, X.pExpr);
|
||||||
|
if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1);
|
||||||
|
sqlite3ExprListSetSpan(pParse,A,&X);
|
||||||
}
|
}
|
||||||
selcollist(A) ::= sclp(P) STAR. {
|
selcollist(A) ::= sclp(P) STAR. {
|
||||||
Expr *p = sqlite3PExpr(pParse, TK_ALL, 0, 0, 0);
|
Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
|
||||||
A = sqlite3ExprListAppend(pParse, P, p, 0);
|
A = sqlite3ExprListAppend(pParse, P, p);
|
||||||
}
|
}
|
||||||
selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). {
|
selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). {
|
||||||
Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &Y);
|
Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &Y);
|
||||||
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
||||||
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
|
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
|
||||||
A = sqlite3ExprListAppend(pParse,P, pDot, 0);
|
A = sqlite3ExprListAppend(pParse,P, pDot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// An option "AS <id>" phrase that can follow one of the expressions that
|
// An option "AS <id>" phrase that can follow one of the expressions that
|
||||||
@ -530,7 +534,7 @@ joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN.
|
|||||||
|
|
||||||
%type on_opt {Expr*}
|
%type on_opt {Expr*}
|
||||||
%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
|
||||||
on_opt(N) ::= ON expr(E). {N = E;}
|
on_opt(N) ::= ON expr(E). {N = E.pExpr;}
|
||||||
on_opt(N) ::= . {N = 0;}
|
on_opt(N) ::= . {N = 0;}
|
||||||
|
|
||||||
// Note that this block abuses the Token type just a little. If there is
|
// Note that this block abuses the Token type just a little. If there is
|
||||||
@ -564,14 +568,14 @@ using_opt(U) ::= . {U = 0;}
|
|||||||
orderby_opt(A) ::= . {A = 0;}
|
orderby_opt(A) ::= . {A = 0;}
|
||||||
orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;}
|
orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;}
|
||||||
sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). {
|
sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). {
|
||||||
A = sqlite3ExprListAppend(pParse,X,Y,0);
|
A = sqlite3ExprListAppend(pParse,X,Y);
|
||||||
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
|
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
|
||||||
}
|
}
|
||||||
sortlist(A) ::= sortitem(Y) sortorder(Z). {
|
sortlist(A) ::= sortitem(Y) sortorder(Z). {
|
||||||
A = sqlite3ExprListAppend(pParse,0,Y,0);
|
A = sqlite3ExprListAppend(pParse,0,Y);
|
||||||
if( A && A->a ) A->a[0].sortOrder = (u8)Z;
|
if( A && A->a ) A->a[0].sortOrder = (u8)Z;
|
||||||
}
|
}
|
||||||
sortitem(A) ::= expr(X). {A = X;}
|
sortitem(A) ::= expr(X). {A = X.pExpr;}
|
||||||
|
|
||||||
%type sortorder {int}
|
%type sortorder {int}
|
||||||
|
|
||||||
@ -587,7 +591,7 @@ groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
|
|||||||
%type having_opt {Expr*}
|
%type having_opt {Expr*}
|
||||||
%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);}
|
||||||
having_opt(A) ::= . {A = 0;}
|
having_opt(A) ::= . {A = 0;}
|
||||||
having_opt(A) ::= HAVING expr(X). {A = X;}
|
having_opt(A) ::= HAVING expr(X). {A = X.pExpr;}
|
||||||
|
|
||||||
%type limit_opt {struct LimitVal}
|
%type limit_opt {struct LimitVal}
|
||||||
|
|
||||||
@ -603,11 +607,11 @@ having_opt(A) ::= HAVING expr(X). {A = X;}
|
|||||||
// sqlite3ExprDelete(pParse->db, $$.pOffset);
|
// sqlite3ExprDelete(pParse->db, $$.pOffset);
|
||||||
//}
|
//}
|
||||||
limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;}
|
limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;}
|
||||||
limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X; A.pOffset = 0;}
|
limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X.pExpr; A.pOffset = 0;}
|
||||||
limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y).
|
limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y).
|
||||||
{A.pLimit = X; A.pOffset = Y;}
|
{A.pLimit = X.pExpr; A.pOffset = Y.pExpr;}
|
||||||
limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
|
limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
|
||||||
{A.pOffset = X; A.pLimit = Y;}
|
{A.pOffset = X.pExpr; A.pLimit = Y.pExpr;}
|
||||||
|
|
||||||
/////////////////////////// The DELETE statement /////////////////////////////
|
/////////////////////////// The DELETE statement /////////////////////////////
|
||||||
//
|
//
|
||||||
@ -630,7 +634,7 @@ cmd ::= DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
|
|||||||
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
|
||||||
|
|
||||||
where_opt(A) ::= . {A = 0;}
|
where_opt(A) ::= . {A = 0;}
|
||||||
where_opt(A) ::= WHERE expr(X). {A = X;}
|
where_opt(A) ::= WHERE expr(X). {A = X.pExpr;}
|
||||||
|
|
||||||
////////////////////////// The UPDATE command ////////////////////////////////
|
////////////////////////// The UPDATE command ////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -653,10 +657,14 @@ cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W).
|
|||||||
%type setlist {ExprList*}
|
%type setlist {ExprList*}
|
||||||
%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);}
|
%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);}
|
||||||
|
|
||||||
setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y).
|
setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). {
|
||||||
{A = sqlite3ExprListAppend(pParse,Z,Y,&X);}
|
A = sqlite3ExprListAppend(pParse, Z, Y.pExpr);
|
||||||
setlist(A) ::= nm(X) EQ expr(Y).
|
sqlite3ExprListSetName(pParse, A, &X, 1);
|
||||||
{A = sqlite3ExprListAppend(pParse,0,Y,&X);}
|
}
|
||||||
|
setlist(A) ::= nm(X) EQ expr(Y). {
|
||||||
|
A = sqlite3ExprListAppend(pParse, 0, Y.pExpr);
|
||||||
|
sqlite3ExprListSetName(pParse, A, &X, 1);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////// The INSERT command /////////////////////////////////
|
////////////////////////// The INSERT command /////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -677,9 +685,9 @@ insert_cmd(A) ::= REPLACE. {A = OE_Replace;}
|
|||||||
%destructor itemlist {sqlite3ExprListDelete(pParse->db, $$);}
|
%destructor itemlist {sqlite3ExprListDelete(pParse->db, $$);}
|
||||||
|
|
||||||
itemlist(A) ::= itemlist(X) COMMA expr(Y).
|
itemlist(A) ::= itemlist(X) COMMA expr(Y).
|
||||||
{A = sqlite3ExprListAppend(pParse,X,Y,0);}
|
{A = sqlite3ExprListAppend(pParse,X,Y.pExpr);}
|
||||||
itemlist(A) ::= expr(X).
|
itemlist(A) ::= expr(X).
|
||||||
{A = sqlite3ExprListAppend(pParse,0,X,0);}
|
{A = sqlite3ExprListAppend(pParse,0,X.pExpr);}
|
||||||
|
|
||||||
%type inscollist_opt {IdList*}
|
%type inscollist_opt {IdList*}
|
||||||
%destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);}
|
%destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);}
|
||||||
@ -696,240 +704,319 @@ inscollist(A) ::= nm(Y).
|
|||||||
/////////////////////////// Expression Processing /////////////////////////////
|
/////////////////////////// Expression Processing /////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
||||||
%type expr {Expr*}
|
%type expr {ExprSpan}
|
||||||
%destructor expr {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor expr {sqlite3ExprDelete(pParse->db, $$.pExpr);}
|
||||||
%type term {Expr*}
|
%type term {ExprSpan}
|
||||||
%destructor term {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor term {sqlite3ExprDelete(pParse->db, $$.pExpr);}
|
||||||
|
|
||||||
|
%include {
|
||||||
|
/* This is a utility routine used to set the ExprSpan.zStart and
|
||||||
|
** ExprSpan.zEnd values of pOut so that the span covers the complete
|
||||||
|
** range of text beginning with pStart and going to the end of pEnd.
|
||||||
|
*/
|
||||||
|
static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){
|
||||||
|
pOut->zStart = pStart->z;
|
||||||
|
pOut->zEnd = &pEnd->z[pEnd->n];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct a new Expr object from a single identifier. Use the
|
||||||
|
** new Expr to populate pOut. Set the span of pOut to be the identifier
|
||||||
|
** that created the expression.
|
||||||
|
*/
|
||||||
|
static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token *pValue){
|
||||||
|
pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, pValue);
|
||||||
|
pOut->zStart = pValue->z;
|
||||||
|
pOut->zEnd = &pValue->z[pValue->n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
expr(A) ::= term(X). {A = X;}
|
expr(A) ::= term(X). {A = X;}
|
||||||
expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); }
|
expr(A) ::= LP(B) expr(X) RP(E). {A.pExpr = X.pExpr; spanSet(&A,&B,&E);}
|
||||||
term(A) ::= NULL(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);}
|
term(A) ::= NULL(X). {spanExpr(&A, pParse, @X, &X);}
|
||||||
expr(A) ::= id(X). {A = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);}
|
expr(A) ::= id(X). {spanExpr(&A, pParse, TK_ID, &X);}
|
||||||
expr(A) ::= JOIN_KW(X). {A = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);}
|
expr(A) ::= JOIN_KW(X). {spanExpr(&A, pParse, TK_ID, &X);}
|
||||||
expr(A) ::= nm(X) DOT nm(Y). {
|
expr(A) ::= nm(X) DOT nm(Y). {
|
||||||
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
||||||
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
|
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
|
||||||
A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
|
A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
|
||||||
|
spanSet(&A,&X,&Y);
|
||||||
}
|
}
|
||||||
expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
|
expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
|
||||||
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
||||||
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
|
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
|
||||||
Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z);
|
Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z);
|
||||||
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
|
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
|
||||||
A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
|
A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
|
||||||
|
spanSet(&A,&X,&Z);
|
||||||
|
}
|
||||||
|
term(A) ::= INTEGER|FLOAT|BLOB(X). {spanExpr(&A, pParse, @X, &X);}
|
||||||
|
term(A) ::= STRING(X). {spanExpr(&A, pParse, @X, &X);}
|
||||||
|
expr(A) ::= REGISTER(X). {
|
||||||
|
/* When doing a nested parse, one can include terms in an expression
|
||||||
|
** that look like this: #1 #2 ... These terms refer to registers
|
||||||
|
** in the virtual machine. #N is the N-th register. */
|
||||||
|
if( pParse->nested==0 ){
|
||||||
|
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &X);
|
||||||
|
A.pExpr = 0;
|
||||||
|
}else{
|
||||||
|
A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &X);
|
||||||
|
if( A.pExpr ) sqlite3GetInt32(&X.z[1], &A.pExpr->iTable);
|
||||||
|
}
|
||||||
|
spanSet(&A, &X, &X);
|
||||||
}
|
}
|
||||||
term(A) ::= INTEGER|FLOAT|BLOB(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);}
|
|
||||||
term(A) ::= STRING(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);}
|
|
||||||
expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);}
|
|
||||||
expr(A) ::= VARIABLE(X). {
|
expr(A) ::= VARIABLE(X). {
|
||||||
Token *pToken = &X;
|
spanExpr(&A, pParse, TK_VARIABLE, &X);
|
||||||
Expr *pExpr = A = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken);
|
sqlite3ExprAssignVarNumber(pParse, A.pExpr);
|
||||||
sqlite3ExprAssignVarNumber(pParse, pExpr);
|
spanSet(&A, &X, &X);
|
||||||
}
|
}
|
||||||
expr(A) ::= expr(E) COLLATE ids(C). {
|
expr(A) ::= expr(E) COLLATE ids(C). {
|
||||||
A = sqlite3ExprSetColl(pParse, E, &C);
|
A.pExpr = sqlite3ExprSetColl(pParse, E.pExpr, &C);
|
||||||
|
A.zStart = E.zStart;
|
||||||
|
A.zEnd = &C.z[C.n];
|
||||||
}
|
}
|
||||||
%ifndef SQLITE_OMIT_CAST
|
%ifndef SQLITE_OMIT_CAST
|
||||||
expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). {
|
expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). {
|
||||||
A = sqlite3PExpr(pParse, TK_CAST, E, 0, &T);
|
A.pExpr = sqlite3PExpr(pParse, TK_CAST, E.pExpr, 0, &T);
|
||||||
sqlite3ExprSpan(A,&X,&Y);
|
spanSet(&A,&X,&Y);
|
||||||
}
|
}
|
||||||
%endif SQLITE_OMIT_CAST
|
%endif SQLITE_OMIT_CAST
|
||||||
expr(A) ::= ID(X) LP distinct(D) exprlist(Y) RP(E). {
|
expr(A) ::= ID(X) LP distinct(D) exprlist(Y) RP(E). {
|
||||||
if( Y && Y->nExpr>SQLITE_MAX_FUNCTION_ARG ){
|
if( Y && Y->nExpr>SQLITE_MAX_FUNCTION_ARG ){
|
||||||
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
|
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
|
||||||
}
|
}
|
||||||
A = sqlite3ExprFunction(pParse, Y, &X);
|
A.pExpr = sqlite3ExprFunction(pParse, Y, &X);
|
||||||
sqlite3ExprSpan(A,&X,&E);
|
spanSet(&A,&X,&E);
|
||||||
if( D && A ){
|
if( D && A.pExpr ){
|
||||||
A->flags |= EP_Distinct;
|
A.pExpr->flags |= EP_Distinct;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr(A) ::= ID(X) LP STAR RP(E). {
|
expr(A) ::= ID(X) LP STAR RP(E). {
|
||||||
A = sqlite3ExprFunction(pParse, 0, &X);
|
A.pExpr = sqlite3ExprFunction(pParse, 0, &X);
|
||||||
sqlite3ExprSpan(A,&X,&E);
|
spanSet(&A,&X,&E);
|
||||||
}
|
}
|
||||||
term(A) ::= CTIME_KW(OP). {
|
term(A) ::= CTIME_KW(OP). {
|
||||||
/* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
|
/* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
|
||||||
** treated as functions that return constants */
|
** treated as functions that return constants */
|
||||||
A = sqlite3ExprFunction(pParse, 0,&OP);
|
A.pExpr = sqlite3ExprFunction(pParse, 0,&OP);
|
||||||
if( A ){
|
if( A.pExpr ){
|
||||||
A->op = TK_CONST_FUNC;
|
A.pExpr->op = TK_CONST_FUNC;
|
||||||
A->span = OP;
|
}
|
||||||
|
spanSet(&A, &OP, &OP);
|
||||||
|
}
|
||||||
|
|
||||||
|
%include {
|
||||||
|
/* This routine constructs a binary expression node out of two ExprSpan
|
||||||
|
** objects and uses the result to populate a new ExprSpan object.
|
||||||
|
*/
|
||||||
|
static void spanBinaryExpr(
|
||||||
|
ExprSpan *pOut, /* Write the result here */
|
||||||
|
Parse *pParse, /* The parsing context. Errors accumulate here */
|
||||||
|
int op, /* The binary operation */
|
||||||
|
ExprSpan *pLeft, /* The left operand */
|
||||||
|
ExprSpan *pRight /* The right operand */
|
||||||
|
){
|
||||||
|
pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0);
|
||||||
|
pOut->zStart = pLeft->zStart;
|
||||||
|
pOut->zEnd = pRight->zEnd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr(A) ::= expr(X) AND(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);}
|
|
||||||
expr(A) ::= expr(X) OR(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);}
|
expr(A) ::= expr(X) AND(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||||
|
expr(A) ::= expr(X) OR(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||||
expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y).
|
expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y).
|
||||||
{A = sqlite3PExpr(pParse,@OP,X,Y,0);}
|
{spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||||
expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);}
|
expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||||
expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
|
expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
|
||||||
{A = sqlite3PExpr(pParse,@OP,X,Y,0);}
|
{spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||||
expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y).{A = sqlite3PExpr(pParse,@OP,X,Y,0);}
|
expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y).
|
||||||
|
{spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||||
expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y).
|
expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y).
|
||||||
{A = sqlite3PExpr(pParse,@OP,X,Y,0);}
|
{spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||||
expr(A) ::= expr(X) CONCAT(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);}
|
expr(A) ::= expr(X) CONCAT(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||||
%type likeop {struct LikeOp}
|
%type likeop {struct LikeOp}
|
||||||
likeop(A) ::= LIKE_KW(X). {A.eOperator = X; A.not = 0;}
|
likeop(A) ::= LIKE_KW(X). {A.eOperator = X; A.not = 0;}
|
||||||
likeop(A) ::= NOT LIKE_KW(X). {A.eOperator = X; A.not = 1;}
|
likeop(A) ::= NOT LIKE_KW(X). {A.eOperator = X; A.not = 1;}
|
||||||
likeop(A) ::= MATCH(X). {A.eOperator = X; A.not = 0;}
|
likeop(A) ::= MATCH(X). {A.eOperator = X; A.not = 0;}
|
||||||
likeop(A) ::= NOT MATCH(X). {A.eOperator = X; A.not = 1;}
|
likeop(A) ::= NOT MATCH(X). {A.eOperator = X; A.not = 1;}
|
||||||
%type escape {Expr*}
|
%type escape {ExprSpan}
|
||||||
%destructor escape {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor escape {sqlite3ExprDelete(pParse->db, $$.pExpr);}
|
||||||
escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;}
|
escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;}
|
||||||
escape(X) ::= . [ESCAPE] {X = 0;}
|
escape(X) ::= . [ESCAPE] {memset(&X,0,sizeof(X));}
|
||||||
expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] {
|
expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] {
|
||||||
ExprList *pList;
|
ExprList *pList;
|
||||||
pList = sqlite3ExprListAppend(pParse,0, Y, 0);
|
pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
|
||||||
pList = sqlite3ExprListAppend(pParse,pList, X, 0);
|
pList = sqlite3ExprListAppend(pParse,pList, X.pExpr);
|
||||||
if( E ){
|
if( E.pExpr ){
|
||||||
pList = sqlite3ExprListAppend(pParse,pList, E, 0);
|
pList = sqlite3ExprListAppend(pParse,pList, E.pExpr);
|
||||||
}
|
}
|
||||||
A = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
|
A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
|
||||||
if( OP.not ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0);
|
if( OP.not ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||||
sqlite3ExprSpan(A, &X->span, &Y->span);
|
A.zStart = X.zStart;
|
||||||
if( A ) A->flags |= EP_InfixFunc;
|
A.zEnd = Y.zEnd;
|
||||||
|
if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr(A) ::= expr(X) ISNULL|NOTNULL(E). {
|
%include {
|
||||||
A = sqlite3PExpr(pParse, @E, X, 0, 0);
|
/* Construct an expression node for a unary postfix operator
|
||||||
sqlite3ExprSpan(A,&X->span,&E);
|
*/
|
||||||
|
static void spanUnaryPostfix(
|
||||||
|
ExprSpan *pOut, /* Write the new expression node here */
|
||||||
|
Parse *pParse, /* Parsing context to record errors */
|
||||||
|
int op, /* The operator */
|
||||||
|
ExprSpan *pOperand, /* The operand */
|
||||||
|
Token *pPostOp /* The operand token for setting the span */
|
||||||
|
){
|
||||||
|
pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
|
||||||
|
pOut->zStart = pOperand->zStart;
|
||||||
|
pOut->zEnd = &pPostOp->z[pPostOp->n];
|
||||||
}
|
}
|
||||||
expr(A) ::= expr(X) IS NULL(E). {
|
|
||||||
A = sqlite3PExpr(pParse, TK_ISNULL, X, 0, 0);
|
|
||||||
sqlite3ExprSpan(A,&X->span,&E);
|
|
||||||
}
|
}
|
||||||
expr(A) ::= expr(X) NOT NULL(E). {
|
|
||||||
A = sqlite3PExpr(pParse, TK_NOTNULL, X, 0, 0);
|
expr(A) ::= expr(X) ISNULL|NOTNULL(E). {spanUnaryPostfix(&A,pParse,@E,&X,&E);}
|
||||||
sqlite3ExprSpan(A,&X->span,&E);
|
expr(A) ::= expr(X) IS NULL(E). {spanUnaryPostfix(&A,pParse,TK_ISNULL,&X,&E);}
|
||||||
|
expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
|
||||||
|
expr(A) ::= expr(X) IS NOT NULL(E).
|
||||||
|
{spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
|
||||||
|
|
||||||
|
%include {
|
||||||
|
/* Construct an expression node for a unary prefix operator
|
||||||
|
*/
|
||||||
|
static void spanUnaryPrefix(
|
||||||
|
ExprSpan *pOut, /* Write the new expression node here */
|
||||||
|
Parse *pParse, /* Parsing context to record errors */
|
||||||
|
int op, /* The operator */
|
||||||
|
ExprSpan *pOperand, /* The operand */
|
||||||
|
Token *pPreOp /* The operand token for setting the span */
|
||||||
|
){
|
||||||
|
pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
|
||||||
|
pOut->zStart = pPreOp->z;
|
||||||
|
pOut->zEnd = pOperand->zEnd;
|
||||||
}
|
}
|
||||||
expr(A) ::= expr(X) IS NOT NULL(E). {
|
|
||||||
A = sqlite3PExpr(pParse, TK_NOTNULL, X, 0, 0);
|
|
||||||
sqlite3ExprSpan(A,&X->span,&E);
|
|
||||||
}
|
|
||||||
expr(A) ::= NOT(B) expr(X). {
|
|
||||||
A = sqlite3PExpr(pParse, @B, X, 0, 0);
|
|
||||||
sqlite3ExprSpan(A,&B,&X->span);
|
|
||||||
}
|
|
||||||
expr(A) ::= BITNOT(B) expr(X). {
|
|
||||||
A = sqlite3PExpr(pParse, @B, X, 0, 0);
|
|
||||||
sqlite3ExprSpan(A,&B,&X->span);
|
|
||||||
}
|
|
||||||
expr(A) ::= MINUS(B) expr(X). [UMINUS] {
|
|
||||||
A = sqlite3PExpr(pParse, TK_UMINUS, X, 0, 0);
|
|
||||||
sqlite3ExprSpan(A,&B,&X->span);
|
|
||||||
}
|
|
||||||
expr(A) ::= PLUS(B) expr(X). [UPLUS] {
|
|
||||||
A = sqlite3PExpr(pParse, TK_UPLUS, X, 0, 0);
|
|
||||||
sqlite3ExprSpan(A,&B,&X->span);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
expr(A) ::= NOT(B) expr(X). {spanUnaryPrefix(&A,pParse,@B,&X,&B);}
|
||||||
|
expr(A) ::= BITNOT(B) expr(X). {spanUnaryPrefix(&A,pParse,@B,&X,&B);}
|
||||||
|
expr(A) ::= MINUS(B) expr(X). [UMINUS]
|
||||||
|
{spanUnaryPrefix(&A,pParse,TK_UMINUS,&X,&B);}
|
||||||
|
expr(A) ::= PLUS(B) expr(X). [UPLUS]
|
||||||
|
{spanUnaryPrefix(&A,pParse,TK_UPLUS,&X,&B);}
|
||||||
|
|
||||||
%type between_op {int}
|
%type between_op {int}
|
||||||
between_op(A) ::= BETWEEN. {A = 0;}
|
between_op(A) ::= BETWEEN. {A = 0;}
|
||||||
between_op(A) ::= NOT BETWEEN. {A = 1;}
|
between_op(A) ::= NOT BETWEEN. {A = 1;}
|
||||||
expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||||
ExprList *pList = sqlite3ExprListAppend(pParse,0, X, 0);
|
ExprList *pList = sqlite3ExprListAppend(pParse,0, X.pExpr);
|
||||||
pList = sqlite3ExprListAppend(pParse,pList, Y, 0);
|
pList = sqlite3ExprListAppend(pParse,pList, Y.pExpr);
|
||||||
A = sqlite3PExpr(pParse, TK_BETWEEN, W, 0, 0);
|
A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, W.pExpr, 0, 0);
|
||||||
if( A ){
|
if( A.pExpr ){
|
||||||
A->x.pList = pList;
|
A.pExpr->x.pList = pList;
|
||||||
}else{
|
}else{
|
||||||
sqlite3ExprListDelete(pParse->db, pList);
|
sqlite3ExprListDelete(pParse->db, pList);
|
||||||
}
|
}
|
||||||
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0);
|
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||||
sqlite3ExprSpan(A,&W->span,&Y->span);
|
A.zStart = W.zStart;
|
||||||
|
A.zEnd = Y.zEnd;
|
||||||
}
|
}
|
||||||
%ifndef SQLITE_OMIT_SUBQUERY
|
%ifndef SQLITE_OMIT_SUBQUERY
|
||||||
%type in_op {int}
|
%type in_op {int}
|
||||||
in_op(A) ::= IN. {A = 0;}
|
in_op(A) ::= IN. {A = 0;}
|
||||||
in_op(A) ::= NOT IN. {A = 1;}
|
in_op(A) ::= NOT IN. {A = 1;}
|
||||||
expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
|
expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
|
||||||
A = sqlite3PExpr(pParse, TK_IN, X, 0, 0);
|
A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
|
||||||
if( A ){
|
if( A.pExpr ){
|
||||||
A->x.pList = Y;
|
A.pExpr->x.pList = Y;
|
||||||
sqlite3ExprSetHeight(pParse, A);
|
sqlite3ExprSetHeight(pParse, A.pExpr);
|
||||||
}else{
|
}else{
|
||||||
sqlite3ExprListDelete(pParse->db, Y);
|
sqlite3ExprListDelete(pParse->db, Y);
|
||||||
}
|
}
|
||||||
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0);
|
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||||
sqlite3ExprSpan(A,&X->span,&E);
|
A.zStart = X.zStart;
|
||||||
|
A.zEnd = &E.z[E.n];
|
||||||
}
|
}
|
||||||
expr(A) ::= LP(B) select(X) RP(E). {
|
expr(A) ::= LP(B) select(X) RP(E). {
|
||||||
A = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
|
A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
|
||||||
if( A ){
|
if( A.pExpr ){
|
||||||
A->x.pSelect = X;
|
A.pExpr->x.pSelect = X;
|
||||||
ExprSetProperty(A, EP_xIsSelect);
|
ExprSetProperty(A.pExpr, EP_xIsSelect);
|
||||||
sqlite3ExprSetHeight(pParse, A);
|
sqlite3ExprSetHeight(pParse, A.pExpr);
|
||||||
}else{
|
}else{
|
||||||
sqlite3SelectDelete(pParse->db, X);
|
sqlite3SelectDelete(pParse->db, X);
|
||||||
}
|
}
|
||||||
sqlite3ExprSpan(A,&B,&E);
|
A.zStart = B.z;
|
||||||
|
A.zEnd = &E.z[E.n];
|
||||||
}
|
}
|
||||||
expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] {
|
expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] {
|
||||||
A = sqlite3PExpr(pParse, TK_IN, X, 0, 0);
|
A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
|
||||||
if( A ){
|
if( A.pExpr ){
|
||||||
A->x.pSelect = Y;
|
A.pExpr->x.pSelect = Y;
|
||||||
ExprSetProperty(A, EP_xIsSelect);
|
ExprSetProperty(A.pExpr, EP_xIsSelect);
|
||||||
sqlite3ExprSetHeight(pParse, A);
|
sqlite3ExprSetHeight(pParse, A.pExpr);
|
||||||
}else{
|
}else{
|
||||||
sqlite3SelectDelete(pParse->db, Y);
|
sqlite3SelectDelete(pParse->db, Y);
|
||||||
}
|
}
|
||||||
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0);
|
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||||
sqlite3ExprSpan(A,&X->span,&E);
|
A.zStart = X.zStart;
|
||||||
|
A.zEnd = &E.z[E.n];
|
||||||
}
|
}
|
||||||
expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
|
expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
|
||||||
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
|
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
|
||||||
A = sqlite3PExpr(pParse, TK_IN, X, 0, 0);
|
A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
|
||||||
if( A ){
|
if( A.pExpr ){
|
||||||
A->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
|
A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
|
||||||
ExprSetProperty(A, EP_xIsSelect);
|
ExprSetProperty(A.pExpr, EP_xIsSelect);
|
||||||
sqlite3ExprSetHeight(pParse, A);
|
sqlite3ExprSetHeight(pParse, A.pExpr);
|
||||||
}else{
|
}else{
|
||||||
sqlite3SrcListDelete(pParse->db, pSrc);
|
sqlite3SrcListDelete(pParse->db, pSrc);
|
||||||
}
|
}
|
||||||
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0);
|
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||||
sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y);
|
A.zStart = X.zStart;
|
||||||
|
A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n];
|
||||||
}
|
}
|
||||||
expr(A) ::= EXISTS(B) LP select(Y) RP(E). {
|
expr(A) ::= EXISTS(B) LP select(Y) RP(E). {
|
||||||
Expr *p = A = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
|
Expr *p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
|
||||||
if( p ){
|
if( p ){
|
||||||
p->x.pSelect = Y;
|
p->x.pSelect = Y;
|
||||||
ExprSetProperty(A, EP_xIsSelect);
|
ExprSetProperty(p, EP_xIsSelect);
|
||||||
sqlite3ExprSpan(p,&B,&E);
|
sqlite3ExprSetHeight(pParse, p);
|
||||||
sqlite3ExprSetHeight(pParse, A);
|
|
||||||
}else{
|
}else{
|
||||||
sqlite3SelectDelete(pParse->db, Y);
|
sqlite3SelectDelete(pParse->db, Y);
|
||||||
}
|
}
|
||||||
|
A.zStart = B.z;
|
||||||
|
A.zEnd = &E.z[E.n];
|
||||||
}
|
}
|
||||||
%endif SQLITE_OMIT_SUBQUERY
|
%endif SQLITE_OMIT_SUBQUERY
|
||||||
|
|
||||||
/* CASE expressions */
|
/* CASE expressions */
|
||||||
expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
|
expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
|
||||||
A = sqlite3PExpr(pParse, TK_CASE, X, Z, 0);
|
A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, Z, 0);
|
||||||
if( A ){
|
if( A.pExpr ){
|
||||||
A->x.pList = Y;
|
A.pExpr->x.pList = Y;
|
||||||
sqlite3ExprSetHeight(pParse, A);
|
sqlite3ExprSetHeight(pParse, A.pExpr);
|
||||||
}else{
|
}else{
|
||||||
sqlite3ExprListDelete(pParse->db, Y);
|
sqlite3ExprListDelete(pParse->db, Y);
|
||||||
}
|
}
|
||||||
sqlite3ExprSpan(A, &C, &E);
|
A.zStart = C.z;
|
||||||
|
A.zEnd = &E.z[E.n];
|
||||||
}
|
}
|
||||||
%type case_exprlist {ExprList*}
|
%type case_exprlist {ExprList*}
|
||||||
%destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);}
|
%destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);}
|
||||||
case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
|
case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
|
||||||
A = sqlite3ExprListAppend(pParse,X, Y, 0);
|
A = sqlite3ExprListAppend(pParse,X, Y.pExpr);
|
||||||
A = sqlite3ExprListAppend(pParse,A, Z, 0);
|
A = sqlite3ExprListAppend(pParse,A, Z.pExpr);
|
||||||
}
|
}
|
||||||
case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
|
case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
|
||||||
A = sqlite3ExprListAppend(pParse,0, Y, 0);
|
A = sqlite3ExprListAppend(pParse,0, Y.pExpr);
|
||||||
A = sqlite3ExprListAppend(pParse,A, Z, 0);
|
A = sqlite3ExprListAppend(pParse,A, Z.pExpr);
|
||||||
}
|
}
|
||||||
%type case_else {Expr*}
|
%type case_else {Expr*}
|
||||||
%destructor case_else {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor case_else {sqlite3ExprDelete(pParse->db, $$);}
|
||||||
case_else(A) ::= ELSE expr(X). {A = X;}
|
case_else(A) ::= ELSE expr(X). {A = X.pExpr;}
|
||||||
case_else(A) ::= . {A = 0;}
|
case_else(A) ::= . {A = 0;}
|
||||||
%type case_operand {Expr*}
|
%type case_operand {Expr*}
|
||||||
%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);}
|
||||||
case_operand(A) ::= expr(X). {A = X;}
|
case_operand(A) ::= expr(X). {A = X.pExpr;}
|
||||||
case_operand(A) ::= . {A = 0;}
|
case_operand(A) ::= . {A = 0;}
|
||||||
|
|
||||||
%type exprlist {ExprList*}
|
%type exprlist {ExprList*}
|
||||||
@ -940,9 +1027,9 @@ case_operand(A) ::= . {A = 0;}
|
|||||||
exprlist(A) ::= nexprlist(X). {A = X;}
|
exprlist(A) ::= nexprlist(X). {A = X;}
|
||||||
exprlist(A) ::= . {A = 0;}
|
exprlist(A) ::= . {A = 0;}
|
||||||
nexprlist(A) ::= nexprlist(X) COMMA expr(Y).
|
nexprlist(A) ::= nexprlist(X) COMMA expr(Y).
|
||||||
{A = sqlite3ExprListAppend(pParse,X,Y,0);}
|
{A = sqlite3ExprListAppend(pParse,X,Y.pExpr);}
|
||||||
nexprlist(A) ::= expr(Y).
|
nexprlist(A) ::= expr(Y).
|
||||||
{A = sqlite3ExprListAppend(pParse,0,Y,0);}
|
{A = sqlite3ExprListAppend(pParse,0,Y.pExpr);}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////// The CREATE INDEX command ///////////////////////
|
///////////////////////////// The CREATE INDEX command ///////////////////////
|
||||||
@ -968,10 +1055,11 @@ idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;}
|
|||||||
idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). {
|
idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). {
|
||||||
Expr *p = 0;
|
Expr *p = 0;
|
||||||
if( C.n>0 ){
|
if( C.n>0 ){
|
||||||
p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
|
p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
|
||||||
sqlite3ExprSetColl(pParse, p, &C);
|
sqlite3ExprSetColl(pParse, p, &C);
|
||||||
}
|
}
|
||||||
A = sqlite3ExprListAppend(pParse,X, p, &Y);
|
A = sqlite3ExprListAppend(pParse,X, p);
|
||||||
|
sqlite3ExprListSetName(pParse,A,&Y,1);
|
||||||
sqlite3ExprListCheckLength(pParse, A, "index");
|
sqlite3ExprListCheckLength(pParse, A, "index");
|
||||||
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
|
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
|
||||||
}
|
}
|
||||||
@ -981,7 +1069,8 @@ idxlist(A) ::= nm(Y) collate(C) sortorder(Z). {
|
|||||||
p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
|
p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
|
||||||
sqlite3ExprSetColl(pParse, p, &C);
|
sqlite3ExprSetColl(pParse, p, &C);
|
||||||
}
|
}
|
||||||
A = sqlite3ExprListAppend(pParse,0, p, &Y);
|
A = sqlite3ExprListAppend(pParse,0, p);
|
||||||
|
sqlite3ExprListSetName(pParse, A, &Y, 1);
|
||||||
sqlite3ExprListCheckLength(pParse, A, "index");
|
sqlite3ExprListCheckLength(pParse, A, "index");
|
||||||
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
|
if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z;
|
||||||
}
|
}
|
||||||
@ -1065,25 +1154,17 @@ foreach_clause ::= FOR EACH ROW.
|
|||||||
%type when_clause {Expr*}
|
%type when_clause {Expr*}
|
||||||
%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);}
|
||||||
when_clause(A) ::= . { A = 0; }
|
when_clause(A) ::= . { A = 0; }
|
||||||
when_clause(A) ::= WHEN expr(X). { A = X; }
|
when_clause(A) ::= WHEN expr(X). { A = X.pExpr; }
|
||||||
|
|
||||||
%type trigger_cmd_list {TriggerStep*}
|
%type trigger_cmd_list {TriggerStep*}
|
||||||
%destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);}
|
%destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);}
|
||||||
trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. {
|
trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. {
|
||||||
/*
|
|
||||||
if( Y ){
|
|
||||||
Y->pLast->pNext = X;
|
|
||||||
}else{
|
|
||||||
Y = X;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
assert( Y!=0 );
|
assert( Y!=0 );
|
||||||
Y->pLast->pNext = X;
|
Y->pLast->pNext = X;
|
||||||
Y->pLast = X;
|
Y->pLast = X;
|
||||||
A = Y;
|
A = Y;
|
||||||
}
|
}
|
||||||
trigger_cmd_list(A) ::= trigger_cmd(X) SEMI. {
|
trigger_cmd_list(A) ::= trigger_cmd(X) SEMI. {
|
||||||
/* if( X ) */
|
|
||||||
assert( X!=0 );
|
assert( X!=0 );
|
||||||
X->pLast = X;
|
X->pLast = X;
|
||||||
A = X;
|
A = X;
|
||||||
@ -1112,18 +1193,20 @@ trigger_cmd(A) ::= select(X). {A = sqlite3TriggerSelectStep(pParse->db, X); }
|
|||||||
|
|
||||||
// The special RAISE expression that may occur in trigger programs
|
// The special RAISE expression that may occur in trigger programs
|
||||||
expr(A) ::= RAISE(X) LP IGNORE RP(Y). {
|
expr(A) ::= RAISE(X) LP IGNORE RP(Y). {
|
||||||
A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
|
A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
|
||||||
if( A ){
|
if( A.pExpr ){
|
||||||
A->affinity = OE_Ignore;
|
A.pExpr->affinity = OE_Ignore;
|
||||||
sqlite3ExprSpan(A, &X, &Y);
|
|
||||||
}
|
}
|
||||||
|
A.zStart = X.z;
|
||||||
|
A.zEnd = &Y.z[Y.n];
|
||||||
}
|
}
|
||||||
expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). {
|
expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). {
|
||||||
A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z);
|
A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z);
|
||||||
if( A ) {
|
if( A.pExpr ) {
|
||||||
A->affinity = (char)T;
|
A.pExpr->affinity = (char)T;
|
||||||
sqlite3ExprSpan(A, &X, &Y);
|
|
||||||
}
|
}
|
||||||
|
A.zStart = X.z;
|
||||||
|
A.zEnd = &Y.z[Y.n];
|
||||||
}
|
}
|
||||||
%endif !SQLITE_OMIT_TRIGGER
|
%endif !SQLITE_OMIT_TRIGGER
|
||||||
|
|
||||||
@ -1143,16 +1226,16 @@ cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). {
|
|||||||
//////////////////////// ATTACH DATABASE file AS name /////////////////////////
|
//////////////////////// ATTACH DATABASE file AS name /////////////////////////
|
||||||
%ifndef SQLITE_OMIT_ATTACH
|
%ifndef SQLITE_OMIT_ATTACH
|
||||||
cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). {
|
cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). {
|
||||||
sqlite3Attach(pParse, F, D, K);
|
sqlite3Attach(pParse, F.pExpr, D.pExpr, K);
|
||||||
}
|
}
|
||||||
cmd ::= DETACH database_kw_opt expr(D). {
|
cmd ::= DETACH database_kw_opt expr(D). {
|
||||||
sqlite3Detach(pParse, D);
|
sqlite3Detach(pParse, D.pExpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
%type key_opt {Expr*}
|
%type key_opt {Expr*}
|
||||||
%destructor key_opt {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor key_opt {sqlite3ExprDelete(pParse->db, $$);}
|
||||||
key_opt(A) ::= . { A = 0; }
|
key_opt(A) ::= . { A = 0; }
|
||||||
key_opt(A) ::= KEY expr(X). { A = X; }
|
key_opt(A) ::= KEY expr(X). { A = X.pExpr; }
|
||||||
|
|
||||||
database_kw_opt ::= DATABASE.
|
database_kw_opt ::= DATABASE.
|
||||||
database_kw_opt ::= .
|
database_kw_opt ::= .
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** This file contains code used to implement the PRAGMA command.
|
** This file contains code used to implement the PRAGMA command.
|
||||||
**
|
**
|
||||||
** $Id: pragma.c,v 1.209 2009/04/07 22:05:43 drh Exp $
|
** $Id: pragma.c,v 1.210 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -840,10 +840,8 @@ void sqlite3Pragma(
|
|||||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
|
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
|
||||||
pCol->zType ? pCol->zType : "", 0);
|
pCol->zType ? pCol->zType : "", 0);
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4);
|
sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4);
|
||||||
if( pCol->pDflt ){
|
if( pCol->zDflt ){
|
||||||
const Token *p = &pCol->pDflt->span;
|
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0);
|
||||||
assert( p->z );
|
|
||||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)p->z, p->n);
|
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
|
sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
** resolve all identifiers by associating them with a particular
|
** resolve all identifiers by associating them with a particular
|
||||||
** table and column.
|
** table and column.
|
||||||
**
|
**
|
||||||
** $Id: resolve.c,v 1.22 2009/05/05 15:46:43 drh Exp $
|
** $Id: resolve.c,v 1.23 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -63,16 +63,25 @@ static void resolveAlias(
|
|||||||
assert( pOrig!=0 );
|
assert( pOrig!=0 );
|
||||||
assert( pOrig->flags & EP_Resolved );
|
assert( pOrig->flags & EP_Resolved );
|
||||||
db = pParse->db;
|
db = pParse->db;
|
||||||
|
if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
|
||||||
pDup = sqlite3ExprDup(db, pOrig, 0);
|
pDup = sqlite3ExprDup(db, pOrig, 0);
|
||||||
if( pDup==0 ) return;
|
|
||||||
sqlite3TokenCopy(db, &pDup->token, &pOrig->token);
|
|
||||||
if( pDup->op!=TK_COLUMN && zType[0]!='G' ){
|
|
||||||
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
|
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
|
||||||
if( pDup==0 ) return;
|
if( pDup==0 ) return;
|
||||||
if( pEList->a[iCol].iAlias==0 ){
|
if( pEList->a[iCol].iAlias==0 ){
|
||||||
pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
|
pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
|
||||||
}
|
}
|
||||||
pDup->iTable = pEList->a[iCol].iAlias;
|
pDup->iTable = pEList->a[iCol].iAlias;
|
||||||
|
}else{
|
||||||
|
char *zToken = pOrig->zToken;
|
||||||
|
pOrig->zToken = 0;
|
||||||
|
pDup = sqlite3ExprDup(db, pOrig, 0);
|
||||||
|
pOrig->zToken = zToken;
|
||||||
|
if( pDup==0 ) return;
|
||||||
|
if( zToken ){
|
||||||
|
assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
|
||||||
|
pDup->flags2 |= EP2_FreeToken;
|
||||||
|
pDup->zToken = sqlite3DbStrDup(db, zToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( pExpr->flags & EP_ExpCollate ){
|
if( pExpr->flags & EP_ExpCollate ){
|
||||||
pDup->pColl = pExpr->pColl;
|
pDup->pColl = pExpr->pColl;
|
||||||
@ -100,10 +109,10 @@ static void resolveAlias(
|
|||||||
** pExpr->pLeft Any expression this points to is deleted
|
** pExpr->pLeft Any expression this points to is deleted
|
||||||
** pExpr->pRight Any expression this points to is deleted.
|
** pExpr->pRight Any expression this points to is deleted.
|
||||||
**
|
**
|
||||||
** The pDbToken is the name of the database (the "X"). This value may be
|
** The zDb variable is the name of the database (the "X"). This value may be
|
||||||
** NULL meaning that name is of the form Y.Z or Z. Any available database
|
** NULL meaning that name is of the form Y.Z or Z. Any available database
|
||||||
** can be used. The pTableToken is the name of the table (the "Y"). This
|
** can be used. The zTable variable is the name of the table (the "Y"). This
|
||||||
** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it
|
** value can be NULL if zDb is also NULL. If zTable is NULL it
|
||||||
** means that the form of the name is Z and that columns from any table
|
** means that the form of the name is Z and that columns from any table
|
||||||
** can be used.
|
** can be used.
|
||||||
**
|
**
|
||||||
@ -112,15 +121,12 @@ static void resolveAlias(
|
|||||||
*/
|
*/
|
||||||
static int lookupName(
|
static int lookupName(
|
||||||
Parse *pParse, /* The parsing context */
|
Parse *pParse, /* The parsing context */
|
||||||
Token *pDbToken, /* Name of the database containing table, or NULL */
|
const char *zDb, /* Name of the database containing table, or NULL */
|
||||||
Token *pTableToken, /* Name of table containing column, or NULL */
|
const char *zTab, /* Name of table containing column, or NULL */
|
||||||
Token *pColumnToken, /* Name of the column. */
|
const char *zCol, /* Name of the column. */
|
||||||
NameContext *pNC, /* The name context used to resolve the name */
|
NameContext *pNC, /* The name context used to resolve the name */
|
||||||
Expr *pExpr /* Make this EXPR node point to the selected column */
|
Expr *pExpr /* Make this EXPR node point to the selected column */
|
||||||
){
|
){
|
||||||
char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
|
|
||||||
char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */
|
|
||||||
char *zCol = 0; /* Name of the column. The "Z" */
|
|
||||||
int i, j; /* Loop counters */
|
int i, j; /* Loop counters */
|
||||||
int cnt = 0; /* Number of matching column names */
|
int cnt = 0; /* Number of matching column names */
|
||||||
int cntTab = 0; /* Number of matching table names */
|
int cntTab = 0; /* Number of matching table names */
|
||||||
@ -131,15 +137,7 @@ static int lookupName(
|
|||||||
Schema *pSchema = 0; /* Schema of the expression */
|
Schema *pSchema = 0; /* Schema of the expression */
|
||||||
|
|
||||||
assert( pNC ); /* the name context cannot be NULL. */
|
assert( pNC ); /* the name context cannot be NULL. */
|
||||||
assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
|
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
|
||||||
|
|
||||||
/* Dequote and zero-terminate the names */
|
|
||||||
zDb = sqlite3NameFromToken(db, pDbToken);
|
|
||||||
zTab = sqlite3NameFromToken(db, pTableToken);
|
|
||||||
zCol = sqlite3NameFromToken(db, pColumnToken);
|
|
||||||
if( db->mallocFailed ){
|
|
||||||
goto lookupname_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the node to no-match */
|
/* Initialize the node to no-match */
|
||||||
pExpr->iTable = -1;
|
pExpr->iTable = -1;
|
||||||
@ -293,14 +291,13 @@ static int lookupName(
|
|||||||
pOrig = pEList->a[j].pExpr;
|
pOrig = pEList->a[j].pExpr;
|
||||||
if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
|
if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
|
||||||
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
|
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
|
||||||
sqlite3DbFree(db, zCol);
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
resolveAlias(pParse, pEList, j, pExpr, "");
|
resolveAlias(pParse, pEList, j, pExpr, "");
|
||||||
cnt = 1;
|
cnt = 1;
|
||||||
pMatch = 0;
|
pMatch = 0;
|
||||||
assert( zTab==0 && zDb==0 );
|
assert( zTab==0 && zDb==0 );
|
||||||
goto lookupname_end_2;
|
goto lookupname_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,7 +321,6 @@ static int lookupName(
|
|||||||
** fields are not changed in any context.
|
** fields are not changed in any context.
|
||||||
*/
|
*/
|
||||||
if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){
|
if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){
|
||||||
sqlite3DbFree(db, zCol);
|
|
||||||
pExpr->op = TK_STRING;
|
pExpr->op = TK_STRING;
|
||||||
pExpr->pTab = 0;
|
pExpr->pTab = 0;
|
||||||
return 0;
|
return 0;
|
||||||
@ -363,18 +359,14 @@ static int lookupName(
|
|||||||
pMatch->colUsed |= ((Bitmask)1)<<n;
|
pMatch->colUsed |= ((Bitmask)1)<<n;
|
||||||
}
|
}
|
||||||
|
|
||||||
lookupname_end:
|
|
||||||
/* Clean up and return
|
/* Clean up and return
|
||||||
*/
|
*/
|
||||||
sqlite3DbFree(db, zDb);
|
|
||||||
sqlite3DbFree(db, zTab);
|
|
||||||
sqlite3ExprDelete(db, pExpr->pLeft);
|
sqlite3ExprDelete(db, pExpr->pLeft);
|
||||||
pExpr->pLeft = 0;
|
pExpr->pLeft = 0;
|
||||||
sqlite3ExprDelete(db, pExpr->pRight);
|
sqlite3ExprDelete(db, pExpr->pRight);
|
||||||
pExpr->pRight = 0;
|
pExpr->pRight = 0;
|
||||||
pExpr->op = TK_COLUMN;
|
pExpr->op = TK_COLUMN;
|
||||||
lookupname_end_2:
|
lookupname_end:
|
||||||
sqlite3DbFree(db, zCol);
|
|
||||||
if( cnt==1 ){
|
if( cnt==1 ){
|
||||||
assert( pNC!=0 );
|
assert( pNC!=0 );
|
||||||
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
||||||
@ -447,7 +439,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
|||||||
/* A lone identifier is the name of a column.
|
/* A lone identifier is the name of a column.
|
||||||
*/
|
*/
|
||||||
case TK_ID: {
|
case TK_ID: {
|
||||||
lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
|
lookupName(pParse, 0, 0, pExpr->zToken, pNC, pExpr);
|
||||||
return WRC_Prune;
|
return WRC_Prune;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,24 +447,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
|||||||
** Or a database, table and column: ID.ID.ID
|
** Or a database, table and column: ID.ID.ID
|
||||||
*/
|
*/
|
||||||
case TK_DOT: {
|
case TK_DOT: {
|
||||||
Token *pColumn;
|
const char *zColumn;
|
||||||
Token *pTable;
|
const char *zTable;
|
||||||
Token *pDb;
|
const char *zDb;
|
||||||
Expr *pRight;
|
Expr *pRight;
|
||||||
|
|
||||||
/* if( pSrcList==0 ) break; */
|
/* if( pSrcList==0 ) break; */
|
||||||
pRight = pExpr->pRight;
|
pRight = pExpr->pRight;
|
||||||
if( pRight->op==TK_ID ){
|
if( pRight->op==TK_ID ){
|
||||||
pDb = 0;
|
zDb = 0;
|
||||||
pTable = &pExpr->pLeft->token;
|
zTable = pExpr->pLeft->zToken;
|
||||||
pColumn = &pRight->token;
|
zColumn = pRight->zToken;
|
||||||
}else{
|
}else{
|
||||||
assert( pRight->op==TK_DOT );
|
assert( pRight->op==TK_DOT );
|
||||||
pDb = &pExpr->pLeft->token;
|
zDb = pExpr->pLeft->zToken;
|
||||||
pTable = &pRight->pLeft->token;
|
zTable = pRight->pLeft->zToken;
|
||||||
pColumn = &pRight->pRight->token;
|
zColumn = pRight->pRight->zToken;
|
||||||
}
|
}
|
||||||
lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
|
lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
|
||||||
return WRC_Prune;
|
return WRC_Prune;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,8 +484,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
|||||||
u8 enc = ENC(pParse->db); /* The database encoding */
|
u8 enc = ENC(pParse->db); /* The database encoding */
|
||||||
|
|
||||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||||
zId = (char*)pExpr->token.z;
|
zId = pExpr->zToken;
|
||||||
nId = pExpr->token.n;
|
nId = sqlite3Strlen30(zId);
|
||||||
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
|
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
|
||||||
if( pDef==0 ){
|
if( pDef==0 ){
|
||||||
pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
|
pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
|
||||||
@ -594,20 +586,14 @@ static int resolveAsName(
|
|||||||
){
|
){
|
||||||
int i; /* Loop counter */
|
int i; /* Loop counter */
|
||||||
|
|
||||||
if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
|
if( pE->op==TK_ID || (pE->op==TK_STRING && pE->zToken[0]!='\'') ){
|
||||||
sqlite3 *db = pParse->db;
|
char *zCol = pE->zToken;
|
||||||
char *zCol = sqlite3NameFromToken(db, &pE->token);
|
|
||||||
if( zCol==0 ){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
for(i=0; i<pEList->nExpr; i++){
|
for(i=0; i<pEList->nExpr; i++){
|
||||||
char *zAs = pEList->a[i].zName;
|
char *zAs = pEList->a[i].zName;
|
||||||
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
|
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
|
||||||
sqlite3DbFree(db, zCol);
|
|
||||||
return i+1;
|
return i+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3DbFree(db, zCol);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -758,7 +744,7 @@ static int resolveCompoundOrderBy(
|
|||||||
CollSeq *pColl = pE->pColl;
|
CollSeq *pColl = pE->pColl;
|
||||||
int flags = pE->flags & EP_ExpCollate;
|
int flags = pE->flags & EP_ExpCollate;
|
||||||
sqlite3ExprDelete(db, pE);
|
sqlite3ExprDelete(db, pE);
|
||||||
pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0, 0, 0);
|
pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0);
|
||||||
if( pE==0 ) return 1;
|
if( pE==0 ) return 1;
|
||||||
pE->pColl = pColl;
|
pE->pColl = pColl;
|
||||||
pE->flags |= EP_IntValue | flags;
|
pE->flags |= EP_IntValue | flags;
|
||||||
|
140
src/select.c
140
src/select.c
@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.518 2009/05/19 19:04:58 drh Exp $
|
** $Id: select.c,v 1.519 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ Select *sqlite3SelectNew(
|
|||||||
memset(pNew, 0, sizeof(*pNew));
|
memset(pNew, 0, sizeof(*pNew));
|
||||||
}
|
}
|
||||||
if( pEList==0 ){
|
if( pEList==0 ){
|
||||||
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0,0,0), 0);
|
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0));
|
||||||
}
|
}
|
||||||
pNew->pEList = pEList;
|
pNew->pEList = pEList;
|
||||||
pNew->pSrc = pSrc;
|
pNew->pSrc = pSrc;
|
||||||
@ -191,23 +191,11 @@ static int columnIndex(Table *pTab, const char *zCol){
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Set the value of a token to a '\000'-terminated string.
|
|
||||||
*/
|
|
||||||
static void setToken(Token *p, const char *z){
|
|
||||||
p->z = (u8*)z;
|
|
||||||
p->n = z ? sqlite3Strlen30(z) : 0;
|
|
||||||
p->dyn = 0;
|
|
||||||
p->quoted = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Create an expression node for an identifier with the name of zName
|
** Create an expression node for an identifier with the name of zName
|
||||||
*/
|
*/
|
||||||
Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){
|
Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){
|
||||||
Token dummy;
|
return sqlite3Expr(pParse->db, TK_ID, zName);
|
||||||
setToken(&dummy, zName);
|
|
||||||
return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1072,7 +1060,7 @@ static void generateColumnNames(
|
|||||||
}
|
}
|
||||||
if( !shortNames && !fullNames ){
|
if( !shortNames && !fullNames ){
|
||||||
sqlite3VdbeSetColName(v, i, COLNAME_NAME,
|
sqlite3VdbeSetColName(v, i, COLNAME_NAME,
|
||||||
sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC);
|
sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
|
||||||
}else if( fullNames ){
|
}else if( fullNames ){
|
||||||
char *zName = 0;
|
char *zName = 0;
|
||||||
zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
|
zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
|
||||||
@ -1082,7 +1070,7 @@ static void generateColumnNames(
|
|||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeSetColName(v, i, COLNAME_NAME,
|
sqlite3VdbeSetColName(v, i, COLNAME_NAME,
|
||||||
sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC);
|
sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
generateColumnTypes(pParse, pTabList, pEList);
|
generateColumnTypes(pParse, pTabList, pEList);
|
||||||
@ -1139,7 +1127,7 @@ static int selectColumnsFromExprList(
|
|||||||
/* Get an appropriate name for the column
|
/* Get an appropriate name for the column
|
||||||
*/
|
*/
|
||||||
p = pEList->a[i].pExpr;
|
p = pEList->a[i].pExpr;
|
||||||
assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );
|
assert( p->pRight==0 || p->pRight->zToken==0 || p->pRight->zToken[0]!=0 );
|
||||||
if( (zName = pEList->a[i].zName)!=0 ){
|
if( (zName = pEList->a[i].zName)!=0 ){
|
||||||
/* If the column contains an "AS <name>" phrase, use <name> as the name */
|
/* If the column contains an "AS <name>" phrase, use <name> as the name */
|
||||||
zName = sqlite3DbStrDup(db, zName);
|
zName = sqlite3DbStrDup(db, zName);
|
||||||
@ -1154,10 +1142,11 @@ static int selectColumnsFromExprList(
|
|||||||
if( iCol<0 ) iCol = pTab->iPKey;
|
if( iCol<0 ) iCol = pTab->iPKey;
|
||||||
zName = sqlite3MPrintf(db, "%s",
|
zName = sqlite3MPrintf(db, "%s",
|
||||||
iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
|
iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
|
||||||
|
}else if( pColExpr->op==TK_ID ){
|
||||||
|
zName = sqlite3MPrintf(db, "%s", pColExpr->zToken);
|
||||||
}else{
|
}else{
|
||||||
/* Use the original text of the column expression as its name */
|
/* Use the original text of the column expression as its name */
|
||||||
Token *pToken = (pColExpr->span.z?&pColExpr->span:&pColExpr->token);
|
zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan);
|
||||||
zName = sqlite3MPrintf(db, "%T", pToken);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( db->mallocFailed ){
|
if( db->mallocFailed ){
|
||||||
@ -2056,11 +2045,11 @@ static int multiSelectOrderBy(
|
|||||||
if( pItem->iCol==i ) break;
|
if( pItem->iCol==i ) break;
|
||||||
}
|
}
|
||||||
if( j==nOrderBy ){
|
if( j==nOrderBy ){
|
||||||
Expr *pNew = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0);
|
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
|
||||||
if( pNew==0 ) return SQLITE_NOMEM;
|
if( pNew==0 ) return SQLITE_NOMEM;
|
||||||
pNew->flags |= EP_IntValue;
|
pNew->flags |= EP_IntValue;
|
||||||
pNew->iTable = i;
|
pNew->iTable = i;
|
||||||
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0);
|
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
|
||||||
pOrderBy->a[nOrderBy++].iCol = (u16)i;
|
pOrderBy->a[nOrderBy++].iCol = (u16)i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2345,13 +2334,13 @@ static void substSelect(sqlite3*, Select *, int, ExprList *);
|
|||||||
** changes to pExpr so that it refers directly to the source table
|
** changes to pExpr so that it refers directly to the source table
|
||||||
** of the subquery rather the result set of the subquery.
|
** of the subquery rather the result set of the subquery.
|
||||||
*/
|
*/
|
||||||
static void substExpr(
|
static Expr *substExpr(
|
||||||
sqlite3 *db, /* Report malloc errors to this connection */
|
sqlite3 *db, /* Report malloc errors to this connection */
|
||||||
Expr *pExpr, /* Expr in which substitution occurs */
|
Expr *pExpr, /* Expr in which substitution occurs */
|
||||||
int iTable, /* Table to be substituted */
|
int iTable, /* Table to be substituted */
|
||||||
ExprList *pEList /* Substitute expressions */
|
ExprList *pEList /* Substitute expressions */
|
||||||
){
|
){
|
||||||
if( pExpr==0 ) return;
|
if( pExpr==0 ) return 0;
|
||||||
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
|
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
|
||||||
if( pExpr->iColumn<0 ){
|
if( pExpr->iColumn<0 ){
|
||||||
pExpr->op = TK_NULL;
|
pExpr->op = TK_NULL;
|
||||||
@ -2359,38 +2348,20 @@ static void substExpr(
|
|||||||
Expr *pNew;
|
Expr *pNew;
|
||||||
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
|
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
|
||||||
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
|
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
|
||||||
pNew = pEList->a[pExpr->iColumn].pExpr;
|
pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
|
||||||
assert( pNew!=0 );
|
sqlite3ExprDelete(db, pExpr);
|
||||||
pExpr->op = pNew->op;
|
pExpr = pNew;
|
||||||
assert( pExpr->pLeft==0 );
|
|
||||||
pExpr->pLeft = sqlite3ExprDup(db, pNew->pLeft, 0);
|
|
||||||
assert( pExpr->pRight==0 );
|
|
||||||
pExpr->pRight = sqlite3ExprDup(db, pNew->pRight, 0);
|
|
||||||
pExpr->iTable = pNew->iTable;
|
|
||||||
pExpr->pTab = pNew->pTab;
|
|
||||||
pExpr->iColumn = pNew->iColumn;
|
|
||||||
pExpr->iAgg = pNew->iAgg;
|
|
||||||
sqlite3TokenCopy(db, &pExpr->token, &pNew->token);
|
|
||||||
sqlite3TokenCopy(db, &pExpr->span, &pNew->span);
|
|
||||||
assert( pExpr->x.pList==0 && pExpr->x.pSelect==0 );
|
|
||||||
if( ExprHasProperty(pNew, EP_xIsSelect) ){
|
|
||||||
pExpr->x.pSelect = sqlite3SelectDup(db, pNew->x.pSelect, 0);
|
|
||||||
}else{
|
|
||||||
pExpr->x.pList = sqlite3ExprListDup(db, pNew->x.pList, 0);
|
|
||||||
}
|
|
||||||
pExpr->flags = pNew->flags;
|
|
||||||
pExpr->pAggInfo = pNew->pAggInfo;
|
|
||||||
pNew->pAggInfo = 0;
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
substExpr(db, pExpr->pLeft, iTable, pEList);
|
pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
|
||||||
substExpr(db, pExpr->pRight, iTable, pEList);
|
pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList);
|
||||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||||
substSelect(db, pExpr->x.pSelect, iTable, pEList);
|
substSelect(db, pExpr->x.pSelect, iTable, pEList);
|
||||||
}else{
|
}else{
|
||||||
substExprList(db, pExpr->x.pList, iTable, pEList);
|
substExprList(db, pExpr->x.pList, iTable, pEList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return pExpr;
|
||||||
}
|
}
|
||||||
static void substExprList(
|
static void substExprList(
|
||||||
sqlite3 *db, /* Report malloc errors here */
|
sqlite3 *db, /* Report malloc errors here */
|
||||||
@ -2401,7 +2372,7 @@ static void substExprList(
|
|||||||
int i;
|
int i;
|
||||||
if( pList==0 ) return;
|
if( pList==0 ) return;
|
||||||
for(i=0; i<pList->nExpr; i++){
|
for(i=0; i<pList->nExpr; i++){
|
||||||
substExpr(db, pList->a[i].pExpr, iTable, pEList);
|
pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void substSelect(
|
static void substSelect(
|
||||||
@ -2417,8 +2388,8 @@ static void substSelect(
|
|||||||
substExprList(db, p->pEList, iTable, pEList);
|
substExprList(db, p->pEList, iTable, pEList);
|
||||||
substExprList(db, p->pGroupBy, iTable, pEList);
|
substExprList(db, p->pGroupBy, iTable, pEList);
|
||||||
substExprList(db, p->pOrderBy, iTable, pEList);
|
substExprList(db, p->pOrderBy, iTable, pEList);
|
||||||
substExpr(db, p->pHaving, iTable, pEList);
|
p->pHaving = substExpr(db, p->pHaving, iTable, pEList);
|
||||||
substExpr(db, p->pWhere, iTable, pEList);
|
p->pWhere = substExpr(db, p->pWhere, iTable, pEList);
|
||||||
substSelect(db, p->pPrior, iTable, pEList);
|
substSelect(db, p->pPrior, iTable, pEList);
|
||||||
pSrc = p->pSrc;
|
pSrc = p->pSrc;
|
||||||
assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */
|
assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */
|
||||||
@ -2840,17 +2811,16 @@ static int flattenSubquery(
|
|||||||
pList = pParent->pEList;
|
pList = pParent->pEList;
|
||||||
for(i=0; i<pList->nExpr; i++){
|
for(i=0; i<pList->nExpr; i++){
|
||||||
if( pList->a[i].zName==0 ){
|
if( pList->a[i].zName==0 ){
|
||||||
Expr *pExpr = pList->a[i].pExpr;
|
const char *zSpan = pList->a[i].zSpan;
|
||||||
if( ALWAYS(pExpr->span.z!=0) ){
|
if( zSpan ){
|
||||||
pList->a[i].zName =
|
pList->a[i].zName = sqlite3DbStrDup(db, zSpan);
|
||||||
sqlite3DbStrNDup(db, (char*)pExpr->span.z, pExpr->span.n);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
substExprList(db, pParent->pEList, iParent, pSub->pEList);
|
substExprList(db, pParent->pEList, iParent, pSub->pEList);
|
||||||
if( isAgg ){
|
if( isAgg ){
|
||||||
substExprList(db, pParent->pGroupBy, iParent, pSub->pEList);
|
substExprList(db, pParent->pGroupBy, iParent, pSub->pEList);
|
||||||
substExpr(db, pParent->pHaving, iParent, pSub->pEList);
|
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
|
||||||
}
|
}
|
||||||
if( pSub->pOrderBy ){
|
if( pSub->pOrderBy ){
|
||||||
assert( pParent->pOrderBy==0 );
|
assert( pParent->pOrderBy==0 );
|
||||||
@ -2868,13 +2838,13 @@ static int flattenSubquery(
|
|||||||
assert( pParent->pHaving==0 );
|
assert( pParent->pHaving==0 );
|
||||||
pParent->pHaving = pParent->pWhere;
|
pParent->pHaving = pParent->pWhere;
|
||||||
pParent->pWhere = pWhere;
|
pParent->pWhere = pWhere;
|
||||||
substExpr(db, pParent->pHaving, iParent, pSub->pEList);
|
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
|
||||||
pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
|
pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
|
||||||
sqlite3ExprDup(db, pSub->pHaving, 0));
|
sqlite3ExprDup(db, pSub->pHaving, 0));
|
||||||
assert( pParent->pGroupBy==0 );
|
assert( pParent->pGroupBy==0 );
|
||||||
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
|
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
|
||||||
}else{
|
}else{
|
||||||
substExpr(db, pParent->pWhere, iParent, pSub->pEList);
|
pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList);
|
||||||
pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere);
|
pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2926,10 +2896,9 @@ static u8 minMaxQuery(Select *p){
|
|||||||
pEList = pExpr->x.pList;
|
pEList = pExpr->x.pList;
|
||||||
if( pEList==0 || pEList->nExpr!=1 ) return 0;
|
if( pEList==0 || pEList->nExpr!=1 ) return 0;
|
||||||
if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
|
if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
|
||||||
if( pExpr->token.n!=3 ) return WHERE_ORDERBY_NORMAL;
|
if( sqlite3StrICmp(pExpr->zToken,"min")==0 ){
|
||||||
if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){
|
|
||||||
return WHERE_ORDERBY_MIN;
|
return WHERE_ORDERBY_MIN;
|
||||||
}else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){
|
}else if( sqlite3StrICmp(pExpr->zToken,"max")==0 ){
|
||||||
return WHERE_ORDERBY_MAX;
|
return WHERE_ORDERBY_MAX;
|
||||||
}
|
}
|
||||||
return WHERE_ORDERBY_NORMAL;
|
return WHERE_ORDERBY_NORMAL;
|
||||||
@ -3135,12 +3104,14 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
|
if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
|
||||||
/* This particular expression does not need to be expanded.
|
/* This particular expression does not need to be expanded.
|
||||||
*/
|
*/
|
||||||
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
|
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
|
||||||
if( pNew ){
|
if( pNew ){
|
||||||
pNew->a[pNew->nExpr-1].zName = a[k].zName;
|
pNew->a[pNew->nExpr-1].zName = a[k].zName;
|
||||||
|
pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
|
||||||
|
a[k].zName = 0;
|
||||||
|
a[k].zSpan = 0;
|
||||||
}
|
}
|
||||||
a[k].pExpr = 0;
|
a[k].pExpr = 0;
|
||||||
a[k].zName = 0;
|
|
||||||
}else{
|
}else{
|
||||||
/* This expression is a "*" or a "TABLE.*" and needs to be
|
/* This expression is a "*" or a "TABLE.*" and needs to be
|
||||||
** expanded. */
|
** expanded. */
|
||||||
@ -3148,7 +3119,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
char *zTName; /* text of name of TABLE */
|
char *zTName; /* text of name of TABLE */
|
||||||
if( pE->op==TK_DOT ){
|
if( pE->op==TK_DOT ){
|
||||||
assert( pE->pLeft!=0 );
|
assert( pE->pLeft!=0 );
|
||||||
zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
|
zTName = pE->pLeft->zToken;
|
||||||
}else{
|
}else{
|
||||||
zTName = 0;
|
zTName = 0;
|
||||||
}
|
}
|
||||||
@ -3166,6 +3137,9 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
for(j=0; j<pTab->nCol; j++){
|
for(j=0; j<pTab->nCol; j++){
|
||||||
Expr *pExpr, *pRight;
|
Expr *pExpr, *pRight;
|
||||||
char *zName = pTab->aCol[j].zName;
|
char *zName = pTab->aCol[j].zName;
|
||||||
|
char *zColname; /* The computed column name */
|
||||||
|
char *zToFree; /* Malloced string that needs to be freed */
|
||||||
|
Token sColname; /* Computed column name as a token */
|
||||||
|
|
||||||
/* If a column is marked as 'hidden' (currently only possible
|
/* If a column is marked as 'hidden' (currently only possible
|
||||||
** for virtual tables), do not include it in the expanded
|
** for virtual tables), do not include it in the expanded
|
||||||
@ -3190,30 +3164,25 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
|
pRight = sqlite3Expr(db, TK_ID, zName);
|
||||||
if( pRight==0 ) break;
|
zColname = zName;
|
||||||
setToken(&pRight->token, zName);
|
zToFree = 0;
|
||||||
if( longNames || pTabList->nSrc>1 ){
|
if( longNames || pTabList->nSrc>1 ){
|
||||||
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
|
Expr *pLeft;
|
||||||
|
pLeft = sqlite3Expr(db, TK_ID, zTabName);
|
||||||
pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
|
pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
|
||||||
if( pExpr==0 ) break;
|
if( longNames ){
|
||||||
setToken(&pLeft->token, zTabName);
|
zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
|
||||||
setToken(&pExpr->span,
|
zToFree = zColname;
|
||||||
sqlite3MPrintf(db, "%s.%s", zTabName, zName));
|
}
|
||||||
pExpr->span.dyn = 1;
|
|
||||||
pExpr->token.z = 0;
|
|
||||||
pExpr->token.n = 0;
|
|
||||||
pExpr->token.dyn = 0;
|
|
||||||
}else{
|
}else{
|
||||||
pExpr = pRight;
|
pExpr = pRight;
|
||||||
pExpr->span = pExpr->token;
|
|
||||||
pExpr->span.dyn = 0;
|
|
||||||
}
|
|
||||||
if( longNames ){
|
|
||||||
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
|
|
||||||
}else{
|
|
||||||
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
|
|
||||||
}
|
}
|
||||||
|
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
|
||||||
|
sColname.z = zColname;
|
||||||
|
sColname.n = sqlite3Strlen30(zColname);
|
||||||
|
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
|
||||||
|
sqlite3DbFree(db, zToFree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( !tableSeen ){
|
if( !tableSeen ){
|
||||||
@ -3223,7 +3192,6 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
sqlite3ErrorMsg(pParse, "no tables specified");
|
sqlite3ErrorMsg(pParse, "no tables specified");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3DbFree(db, zTName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3ExprListDelete(db, pEList);
|
sqlite3ExprListDelete(db, pEList);
|
||||||
@ -4175,8 +4143,8 @@ select_end:
|
|||||||
** or from temporary "printf" statements inserted for debugging.
|
** or from temporary "printf" statements inserted for debugging.
|
||||||
*/
|
*/
|
||||||
void sqlite3PrintExpr(Expr *p){
|
void sqlite3PrintExpr(Expr *p){
|
||||||
if( p->token.z && p->token.n>0 ){
|
if( p->zToken ){
|
||||||
sqlite3DebugPrintf("(%.*s", p->token.n, p->token.z);
|
sqlite3DebugPrintf("(%s", p->zToken);
|
||||||
}else{
|
}else{
|
||||||
sqlite3DebugPrintf("(%d", p->op);
|
sqlite3DebugPrintf("(%d", p->op);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.875 2009/05/20 02:40:46 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.876 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@ -579,6 +579,7 @@ typedef struct Db Db;
|
|||||||
typedef struct Schema Schema;
|
typedef struct Schema Schema;
|
||||||
typedef struct Expr Expr;
|
typedef struct Expr Expr;
|
||||||
typedef struct ExprList ExprList;
|
typedef struct ExprList ExprList;
|
||||||
|
typedef struct ExprSpan ExprSpan;
|
||||||
typedef struct FKey FKey;
|
typedef struct FKey FKey;
|
||||||
typedef struct FuncDef FuncDef;
|
typedef struct FuncDef FuncDef;
|
||||||
typedef struct FuncDefHash FuncDefHash;
|
typedef struct FuncDefHash FuncDefHash;
|
||||||
@ -1015,6 +1016,7 @@ struct Module {
|
|||||||
struct Column {
|
struct Column {
|
||||||
char *zName; /* Name of this column */
|
char *zName; /* Name of this column */
|
||||||
Expr *pDflt; /* Default value of this column */
|
Expr *pDflt; /* Default value of this column */
|
||||||
|
char *zDflt; /* Original text of the default value */
|
||||||
char *zType; /* Data type for this column */
|
char *zType; /* Data type for this column */
|
||||||
char *zColl; /* Collating sequence. If NULL, use the default */
|
char *zColl; /* Collating sequence. If NULL, use the default */
|
||||||
u8 notNull; /* True if there is a NOT NULL constraint */
|
u8 notNull; /* True if there is a NOT NULL constraint */
|
||||||
@ -1360,10 +1362,8 @@ struct Index {
|
|||||||
** and Token.n when Token.z==0.
|
** and Token.n when Token.z==0.
|
||||||
*/
|
*/
|
||||||
struct Token {
|
struct Token {
|
||||||
const unsigned char *z; /* Text of the token. Not NULL-terminated! */
|
const char *z; /* Text of the token. Not NULL-terminated! */
|
||||||
unsigned dyn : 1; /* True for malloced memory, false for static */
|
unsigned int n; /* Number of characters in this token */
|
||||||
unsigned quoted : 1; /* True if token still has its quotes */
|
|
||||||
unsigned n : 30; /* Number of characters in this token */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1464,9 +1464,9 @@ struct AggInfo {
|
|||||||
** help reduce memory requirements, sometimes an Expr object will be
|
** help reduce memory requirements, sometimes an Expr object will be
|
||||||
** truncated. And to reduce the number of memory allocations, sometimes
|
** truncated. And to reduce the number of memory allocations, sometimes
|
||||||
** two or more Expr objects will be stored in a single memory allocation,
|
** two or more Expr objects will be stored in a single memory allocation,
|
||||||
** together with Expr.token and/or Expr.span strings.
|
** together with Expr.token strings.
|
||||||
**
|
**
|
||||||
** If the EP_Reduced, EP_SpanToken, and EP_TokenOnly flags are set when
|
** If the EP_Reduced and EP_TokenOnly flags are set when
|
||||||
** an Expr object is truncated. When EP_Reduced is set, then all
|
** an Expr object is truncated. When EP_Reduced is set, then all
|
||||||
** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees
|
** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees
|
||||||
** are contained within the same memory allocation. Note, however, that
|
** are contained within the same memory allocation. Note, however, that
|
||||||
@ -1476,22 +1476,14 @@ struct AggInfo {
|
|||||||
struct Expr {
|
struct Expr {
|
||||||
u8 op; /* Operation performed by this node */
|
u8 op; /* Operation performed by this node */
|
||||||
char affinity; /* The affinity of the column or 0 if not a column */
|
char affinity; /* The affinity of the column or 0 if not a column */
|
||||||
VVA_ONLY(u8 vvaFlags;) /* Flags used for VV&A only. EVVA_* below. */
|
|
||||||
u16 flags; /* Various flags. EP_* See below */
|
u16 flags; /* Various flags. EP_* See below */
|
||||||
Token token; /* An operand token */
|
char *zToken; /* Token value. Zero terminated and dequoted */
|
||||||
|
|
||||||
/* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
|
/* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
|
||||||
** space is allocated for the fields below this point. An attempt to
|
** space is allocated for the fields below this point. An attempt to
|
||||||
** access them will result in a segfault or malfunction.
|
** access them will result in a segfault or malfunction.
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
Token span; /* Complete text of the expression */
|
|
||||||
|
|
||||||
/* If the EP_SpanToken flag is set in the Expr.flags mask, then no
|
|
||||||
** space is allocated for the fields below this point. An attempt to
|
|
||||||
** access them will result in a segfault or malfunction.
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
Expr *pLeft; /* Left subnode */
|
Expr *pLeft; /* Left subnode */
|
||||||
Expr *pRight; /* Right subnode */
|
Expr *pRight; /* Right subnode */
|
||||||
union {
|
union {
|
||||||
@ -1505,11 +1497,14 @@ struct Expr {
|
|||||||
** access them will result in a segfault or malfunction.
|
** access them will result in a segfault or malfunction.
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the
|
int iTable; /* TK_COLUMN: cursor number of table holding column
|
||||||
** iColumn-th field of the iTable-th table. */
|
** TK_REGISTER: register number
|
||||||
|
** EP_IntValue: integer value */
|
||||||
|
i16 iColumn; /* TK_COLUMN: column index. -1 for rowid */
|
||||||
|
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
||||||
|
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
||||||
|
u16 flags2; /* Second set of flags. EP2_... */
|
||||||
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
||||||
int iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
|
||||||
int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
|
||||||
Table *pTab; /* Table for TK_COLUMN expressions. */
|
Table *pTab; /* Table for TK_COLUMN expressions. */
|
||||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||||
int nHeight; /* Height of the tree headed by this node */
|
int nHeight; /* Height of the tree headed by this node */
|
||||||
@ -1535,16 +1530,12 @@ struct Expr {
|
|||||||
|
|
||||||
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
|
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
|
||||||
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
|
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
|
||||||
#define EP_SpanToken 0x8000 /* Expr size is EXPR_SPANTOKENSIZE bytes */
|
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The following are the meanings of bits in the Expr.vvaFlags field.
|
** The following are the meanings of bits in the Expr.flags2 field.
|
||||||
** This information is only used when SQLite is compiled with
|
|
||||||
** SQLITE_DEBUG defined.
|
|
||||||
*/
|
*/
|
||||||
#ifndef NDEBUG
|
#define EP2_FreeToken 0x0001 /* Need to call sqlite3DbFree() on Expr.zToken */
|
||||||
#define EVVA_ReadOnlyToken 0x01 /* Expr.token.z is read-only */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** These macros can be used to test, set, or clear bits in the
|
** These macros can be used to test, set, or clear bits in the
|
||||||
@ -1562,15 +1553,13 @@ struct Expr {
|
|||||||
*/
|
*/
|
||||||
#define EXPR_FULLSIZE sizeof(Expr) /* Full size */
|
#define EXPR_FULLSIZE sizeof(Expr) /* Full size */
|
||||||
#define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */
|
#define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */
|
||||||
#define EXPR_SPANTOKENSIZE offsetof(Expr,pLeft) /* Fewer features */
|
#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */
|
||||||
#define EXPR_TOKENONLYSIZE offsetof(Expr,span) /* Smallest possible */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Flags passed to the sqlite3ExprDup() function. See the header comment
|
** Flags passed to the sqlite3ExprDup() function. See the header comment
|
||||||
** above sqlite3ExprDup() for details.
|
** above sqlite3ExprDup() for details.
|
||||||
*/
|
*/
|
||||||
#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
|
#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
|
||||||
#define EXPRDUP_SPAN 0x0002 /* Make a copy of Expr.span */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** A list of expressions. Each expression may optionally have a
|
** A list of expressions. Each expression may optionally have a
|
||||||
@ -1587,6 +1576,7 @@ struct ExprList {
|
|||||||
struct ExprList_item {
|
struct ExprList_item {
|
||||||
Expr *pExpr; /* The list of expressions */
|
Expr *pExpr; /* The list of expressions */
|
||||||
char *zName; /* Token associated with this expression */
|
char *zName; /* Token associated with this expression */
|
||||||
|
char *zSpan; /* Original text of the expression */
|
||||||
u8 sortOrder; /* 1 for DESC or 0 for ASC */
|
u8 sortOrder; /* 1 for DESC or 0 for ASC */
|
||||||
u8 done; /* A flag to indicate when processing is finished */
|
u8 done; /* A flag to indicate when processing is finished */
|
||||||
u16 iCol; /* For ORDER BY, column number in result set */
|
u16 iCol; /* For ORDER BY, column number in result set */
|
||||||
@ -1594,6 +1584,17 @@ struct ExprList {
|
|||||||
} *a; /* One entry for each expression */
|
} *a; /* One entry for each expression */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** An instance of this structure is used by the parser to record both
|
||||||
|
** the parse tree for an expression and the span of input text for an
|
||||||
|
** expression.
|
||||||
|
*/
|
||||||
|
struct ExprSpan {
|
||||||
|
Expr *pExpr; /* The expression parse tree */
|
||||||
|
const char *zStart; /* First character of input text */
|
||||||
|
const char *zEnd; /* One character past the end of input text */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** An instance of this structure can hold a simple list of identifiers,
|
** An instance of this structure can hold a simple list of identifiers,
|
||||||
** such as the list "a,b,c" in the following statements:
|
** such as the list "a,b,c" in the following statements:
|
||||||
@ -2044,7 +2045,6 @@ struct Trigger {
|
|||||||
Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
|
Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
|
||||||
IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
|
IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
|
||||||
the <column-list> is stored here */
|
the <column-list> is stored here */
|
||||||
Token nameToken; /* Token containing zName. Use during parsing only */
|
|
||||||
Schema *pSchema; /* Schema containing the trigger */
|
Schema *pSchema; /* Schema containing the trigger */
|
||||||
Schema *pTabSchema; /* Schema containing the table */
|
Schema *pTabSchema; /* Schema containing the table */
|
||||||
TriggerStep *step_list; /* Link list of trigger program steps */
|
TriggerStep *step_list; /* Link list of trigger program steps */
|
||||||
@ -2078,7 +2078,7 @@ struct Trigger {
|
|||||||
* orconf -> stores the ON CONFLICT algorithm
|
* orconf -> stores the ON CONFLICT algorithm
|
||||||
* pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
|
* pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
|
||||||
* this stores a pointer to the SELECT statement. Otherwise NULL.
|
* this stores a pointer to the SELECT statement. Otherwise NULL.
|
||||||
* target -> A token holding the name of the table to insert into.
|
* target -> A token holding the quoted name of the table to insert into.
|
||||||
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
|
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
|
||||||
* this stores values to be inserted. Otherwise NULL.
|
* this stores values to be inserted. Otherwise NULL.
|
||||||
* pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
|
* pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
|
||||||
@ -2086,12 +2086,12 @@ struct Trigger {
|
|||||||
* inserted into.
|
* inserted into.
|
||||||
*
|
*
|
||||||
* (op == TK_DELETE)
|
* (op == TK_DELETE)
|
||||||
* target -> A token holding the name of the table to delete from.
|
* target -> A token holding the quoted name of the table to delete from.
|
||||||
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
|
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
|
||||||
* Otherwise NULL.
|
* Otherwise NULL.
|
||||||
*
|
*
|
||||||
* (op == TK_UPDATE)
|
* (op == TK_UPDATE)
|
||||||
* target -> A token holding the name of the table to update rows of.
|
* target -> A token holding the quoted name of the table to update rows of.
|
||||||
* pWhere -> The WHERE clause of the UPDATE statement if one is specified.
|
* pWhere -> The WHERE clause of the UPDATE statement if one is specified.
|
||||||
* Otherwise NULL.
|
* Otherwise NULL.
|
||||||
* pExprList -> A list of the columns to update and the expressions to update
|
* pExprList -> A list of the columns to update and the expressions to update
|
||||||
@ -2106,7 +2106,7 @@ struct TriggerStep {
|
|||||||
|
|
||||||
Select *pSelect; /* Valid for SELECT and sometimes
|
Select *pSelect; /* Valid for SELECT and sometimes
|
||||||
INSERT steps (when pExprList == 0) */
|
INSERT steps (when pExprList == 0) */
|
||||||
Token target; /* Valid for DELETE, UPDATE, INSERT steps */
|
Token target; /* Target table for DELETE, UPDATE, INSERT. Quoted */
|
||||||
Expr *pWhere; /* Valid for DELETE, UPDATE steps */
|
Expr *pWhere; /* Valid for DELETE, UPDATE steps */
|
||||||
ExprList *pExprList; /* Valid for UPDATE statements and sometimes
|
ExprList *pExprList; /* Valid for UPDATE statements and sometimes
|
||||||
INSERT steps (when pSelect == 0) */
|
INSERT steps (when pSelect == 0) */
|
||||||
@ -2384,16 +2384,19 @@ int sqlite3GetTempReg(Parse*);
|
|||||||
void sqlite3ReleaseTempReg(Parse*,int);
|
void sqlite3ReleaseTempReg(Parse*,int);
|
||||||
int sqlite3GetTempRange(Parse*,int);
|
int sqlite3GetTempRange(Parse*,int);
|
||||||
void sqlite3ReleaseTempRange(Parse*,int,int);
|
void sqlite3ReleaseTempRange(Parse*,int,int);
|
||||||
Expr *sqlite3Expr(sqlite3*, int, Expr*, Expr*, const Token*);
|
Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
|
||||||
|
Expr *sqlite3Expr(sqlite3*,int,const char*);
|
||||||
|
void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
|
||||||
Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
|
Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
|
||||||
Expr *sqlite3RegisterExpr(Parse*,Token*);
|
Expr *sqlite3RegisterExpr(Parse*,Token*);
|
||||||
Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
|
Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
|
||||||
void sqlite3ExprSpan(Expr*,Token*,Token*);
|
|
||||||
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
|
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
|
||||||
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
|
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
|
||||||
void sqlite3ExprClear(sqlite3*, Expr*);
|
void sqlite3ExprClear(sqlite3*, Expr*);
|
||||||
void sqlite3ExprDelete(sqlite3*, Expr*);
|
void sqlite3ExprDelete(sqlite3*, Expr*);
|
||||||
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*,Token*);
|
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
|
||||||
|
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
|
||||||
|
void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
|
||||||
void sqlite3ExprListDelete(sqlite3*, ExprList*);
|
void sqlite3ExprListDelete(sqlite3*, ExprList*);
|
||||||
int sqlite3Init(sqlite3*, char**);
|
int sqlite3Init(sqlite3*, char**);
|
||||||
int sqlite3InitCallback(void*, int, char**, char**);
|
int sqlite3InitCallback(void*, int, char**, char**);
|
||||||
@ -2409,7 +2412,7 @@ void sqlite3AddNotNull(Parse*, int);
|
|||||||
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
|
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
|
||||||
void sqlite3AddCheckConstraint(Parse*, Expr*);
|
void sqlite3AddCheckConstraint(Parse*, Expr*);
|
||||||
void sqlite3AddColumnType(Parse*,Token*);
|
void sqlite3AddColumnType(Parse*,Token*);
|
||||||
void sqlite3AddDefaultValue(Parse*,Expr*);
|
void sqlite3AddDefaultValue(Parse*,ExprSpan*);
|
||||||
void sqlite3AddCollateType(Parse*, Token*);
|
void sqlite3AddCollateType(Parse*, Token*);
|
||||||
void sqlite3EndTable(Parse*,Token*,Token*,Select*);
|
void sqlite3EndTable(Parse*,Token*,Token*,Select*);
|
||||||
|
|
||||||
@ -2523,7 +2526,6 @@ void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int,int,int);
|
|||||||
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
|
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
|
||||||
void sqlite3BeginWriteOperation(Parse*, int, int);
|
void sqlite3BeginWriteOperation(Parse*, int, int);
|
||||||
Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
|
Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
|
||||||
void sqlite3TokenCopy(sqlite3*,Token*,const Token*);
|
|
||||||
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
|
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
|
||||||
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
|
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
|
||||||
IdList *sqlite3IdListDup(sqlite3*,IdList*);
|
IdList *sqlite3IdListDup(sqlite3*,IdList*);
|
||||||
@ -2694,7 +2696,7 @@ void sqlite3ColumnDefault(Vdbe *, Table *, int);
|
|||||||
void sqlite3AlterFinishAddColumn(Parse *, Token *);
|
void sqlite3AlterFinishAddColumn(Parse *, Token *);
|
||||||
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
|
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
|
||||||
CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char*);
|
CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char*);
|
||||||
char sqlite3AffinityType(const Token*);
|
char sqlite3AffinityType(const char*);
|
||||||
void sqlite3Analyze(Parse*, Token*, Token*);
|
void sqlite3Analyze(Parse*, Token*, Token*);
|
||||||
int sqlite3InvokeBusyHandler(BusyHandler*);
|
int sqlite3InvokeBusyHandler(BusyHandler*);
|
||||||
int sqlite3FindDb(sqlite3*, Token*);
|
int sqlite3FindDb(sqlite3*, Token*);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
** individual tokens and sends those tokens one-by-one over to the
|
** individual tokens and sends those tokens one-by-one over to the
|
||||||
** parser for analysis.
|
** parser for analysis.
|
||||||
**
|
**
|
||||||
** $Id: tokenize.c,v 1.156 2009/05/01 21:13:37 drh Exp $
|
** $Id: tokenize.c,v 1.157 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -404,7 +404,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
|||||||
db->mallocFailed = 1;
|
db->mallocFailed = 1;
|
||||||
return SQLITE_NOMEM;
|
return SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
assert( pParse->sLastToken.dyn==0 );
|
|
||||||
assert( pParse->pNewTable==0 );
|
assert( pParse->pNewTable==0 );
|
||||||
assert( pParse->pNewTrigger==0 );
|
assert( pParse->pNewTrigger==0 );
|
||||||
assert( pParse->nVar==0 );
|
assert( pParse->nVar==0 );
|
||||||
@ -413,12 +412,9 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
|||||||
assert( pParse->apVarExpr==0 );
|
assert( pParse->apVarExpr==0 );
|
||||||
enableLookaside = db->lookaside.bEnabled;
|
enableLookaside = db->lookaside.bEnabled;
|
||||||
if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
|
if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
|
||||||
pParse->sLastToken.quoted = 1;
|
|
||||||
while( !db->mallocFailed && zSql[i]!=0 ){
|
while( !db->mallocFailed && zSql[i]!=0 ){
|
||||||
assert( i>=0 );
|
assert( i>=0 );
|
||||||
pParse->sLastToken.z = (u8*)&zSql[i];
|
pParse->sLastToken.z = &zSql[i];
|
||||||
assert( pParse->sLastToken.dyn==0 );
|
|
||||||
assert( pParse->sLastToken.quoted );
|
|
||||||
pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
|
pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
|
||||||
i += pParse->sLastToken.n;
|
i += pParse->sLastToken.n;
|
||||||
if( i>mxSqlLen ){
|
if( i>mxSqlLen ){
|
||||||
|
108
src/trigger.c
108
src/trigger.c
@ -10,7 +10,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
**
|
**
|
||||||
**
|
**
|
||||||
** $Id: trigger.c,v 1.139 2009/05/09 00:18:38 drh Exp $
|
** $Id: trigger.c,v 1.140 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -23,7 +23,6 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
|
|||||||
TriggerStep * pTmp = pTriggerStep;
|
TriggerStep * pTmp = pTriggerStep;
|
||||||
pTriggerStep = pTriggerStep->pNext;
|
pTriggerStep = pTriggerStep->pNext;
|
||||||
|
|
||||||
if( pTmp->target.dyn ) sqlite3DbFree(db, (char*)pTmp->target.z);
|
|
||||||
sqlite3ExprDelete(db, pTmp->pWhere);
|
sqlite3ExprDelete(db, pTmp->pWhere);
|
||||||
sqlite3ExprListDelete(db, pTmp->pExprList);
|
sqlite3ExprListDelete(db, pTmp->pExprList);
|
||||||
sqlite3SelectDelete(db, pTmp->pSelect);
|
sqlite3SelectDelete(db, pTmp->pSelect);
|
||||||
@ -218,7 +217,6 @@ void sqlite3BeginTrigger(
|
|||||||
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
|
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
|
||||||
pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
|
pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
|
||||||
pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
|
pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
|
||||||
sqlite3TokenCopy(db, &pTrigger->nameToken, pName);
|
|
||||||
assert( pParse->pNewTrigger==0 );
|
assert( pParse->pNewTrigger==0 );
|
||||||
pParse->pNewTrigger = pTrigger;
|
pParse->pNewTrigger = pTrigger;
|
||||||
|
|
||||||
@ -248,6 +246,7 @@ void sqlite3FinishTrigger(
|
|||||||
sqlite3 *db = pParse->db; /* The database */
|
sqlite3 *db = pParse->db; /* The database */
|
||||||
DbFixer sFix;
|
DbFixer sFix;
|
||||||
int iDb; /* Database containing the trigger */
|
int iDb; /* Database containing the trigger */
|
||||||
|
Token nameToken; /* Trigger name for error reporting */
|
||||||
|
|
||||||
pTrig = pParse->pNewTrigger;
|
pTrig = pParse->pNewTrigger;
|
||||||
pParse->pNewTrigger = 0;
|
pParse->pNewTrigger = 0;
|
||||||
@ -259,7 +258,9 @@ void sqlite3FinishTrigger(
|
|||||||
pStepList->pTrig = pTrig;
|
pStepList->pTrig = pTrig;
|
||||||
pStepList = pStepList->pNext;
|
pStepList = pStepList->pNext;
|
||||||
}
|
}
|
||||||
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken)
|
nameToken.z = pTrig->name;
|
||||||
|
nameToken.n = sqlite3Strlen30(nameToken.z);
|
||||||
|
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
|
||||||
&& sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
|
&& sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
|
||||||
goto triggerfinish_cleanup;
|
goto triggerfinish_cleanup;
|
||||||
}
|
}
|
||||||
@ -309,43 +310,6 @@ triggerfinish_cleanup:
|
|||||||
sqlite3DeleteTriggerStep(db, pStepList);
|
sqlite3DeleteTriggerStep(db, pStepList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Make a copy of all components of the given trigger step. This has
|
|
||||||
** the effect of copying all Expr.token.z values into memory obtained
|
|
||||||
** from sqlite3_malloc(). As initially created, the Expr.token.z values
|
|
||||||
** all point to the input string that was fed to the parser. But that
|
|
||||||
** string is ephemeral - it will go away as soon as the sqlite3_exec()
|
|
||||||
** call that started the parser exits. This routine makes a persistent
|
|
||||||
** copy of all the Expr.token.z strings so that the TriggerStep structure
|
|
||||||
** will be valid even after the sqlite3_exec() call returns.
|
|
||||||
*/
|
|
||||||
static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){
|
|
||||||
if( p->target.z ){
|
|
||||||
p->target.z = (u8*)sqlite3DbStrNDup(db, (char*)p->target.z, p->target.n);
|
|
||||||
p->target.dyn = 1;
|
|
||||||
}
|
|
||||||
if( p->pSelect ){
|
|
||||||
Select *pNew = sqlite3SelectDup(db, p->pSelect, 1);
|
|
||||||
sqlite3SelectDelete(db, p->pSelect);
|
|
||||||
p->pSelect = pNew;
|
|
||||||
}
|
|
||||||
if( p->pWhere ){
|
|
||||||
Expr *pNew = sqlite3ExprDup(db, p->pWhere, EXPRDUP_REDUCE);
|
|
||||||
sqlite3ExprDelete(db, p->pWhere);
|
|
||||||
p->pWhere = pNew;
|
|
||||||
}
|
|
||||||
if( p->pExprList ){
|
|
||||||
ExprList *pNew = sqlite3ExprListDup(db, p->pExprList, 1);
|
|
||||||
sqlite3ExprListDelete(db, p->pExprList);
|
|
||||||
p->pExprList = pNew;
|
|
||||||
}
|
|
||||||
if( p->pIdList ){
|
|
||||||
IdList *pNew = sqlite3IdListDup(db, p->pIdList);
|
|
||||||
sqlite3IdListDelete(db, p->pIdList);
|
|
||||||
p->pIdList = pNew;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Turn a SELECT statement (that the pSelect parameter points to) into
|
** Turn a SELECT statement (that the pSelect parameter points to) into
|
||||||
** a trigger step. Return a pointer to a TriggerStep structure.
|
** a trigger step. Return a pointer to a TriggerStep structure.
|
||||||
@ -359,12 +323,33 @@ TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
|
|||||||
sqlite3SelectDelete(db, pSelect);
|
sqlite3SelectDelete(db, pSelect);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pTriggerStep->op = TK_SELECT;
|
pTriggerStep->op = TK_SELECT;
|
||||||
pTriggerStep->pSelect = pSelect;
|
pTriggerStep->pSelect = pSelect;
|
||||||
pTriggerStep->orconf = OE_Default;
|
pTriggerStep->orconf = OE_Default;
|
||||||
sqlitePersistTriggerStep(db, pTriggerStep);
|
return pTriggerStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Allocate space to hold a new trigger step. The allocated space
|
||||||
|
** holds both the TriggerStep object and the TriggerStep.target.z string.
|
||||||
|
**
|
||||||
|
** If an OOM error occurs, NULL is returned and db->mallocFailed is set.
|
||||||
|
*/
|
||||||
|
static TriggerStep *triggerStepAllocate(
|
||||||
|
sqlite3 *db, /* Database connection */
|
||||||
|
int op, /* Trigger opcode */
|
||||||
|
Token *pName /* The target name */
|
||||||
|
){
|
||||||
|
TriggerStep *pTriggerStep;
|
||||||
|
|
||||||
|
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n);
|
||||||
|
if( pTriggerStep ){
|
||||||
|
char *z = (char*)&pTriggerStep[1];
|
||||||
|
memcpy(z, pName->z, pName->n);
|
||||||
|
pTriggerStep->target.z = z;
|
||||||
|
pTriggerStep->target.n = pName->n;
|
||||||
|
pTriggerStep->op = op;
|
||||||
|
}
|
||||||
return pTriggerStep;
|
return pTriggerStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,15 +373,12 @@ TriggerStep *sqlite3TriggerInsertStep(
|
|||||||
assert(pEList == 0 || pSelect == 0);
|
assert(pEList == 0 || pSelect == 0);
|
||||||
assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
|
assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
|
||||||
|
|
||||||
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
|
pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
|
||||||
if( pTriggerStep ){
|
if( pTriggerStep ){
|
||||||
pTriggerStep->op = TK_INSERT;
|
|
||||||
pTriggerStep->pSelect = pSelect;
|
pTriggerStep->pSelect = pSelect;
|
||||||
pTriggerStep->target = *pTableName;
|
|
||||||
pTriggerStep->pIdList = pColumn;
|
pTriggerStep->pIdList = pColumn;
|
||||||
pTriggerStep->pExprList = pEList;
|
pTriggerStep->pExprList = pEList;
|
||||||
pTriggerStep->orconf = orconf;
|
pTriggerStep->orconf = orconf;
|
||||||
sqlitePersistTriggerStep(db, pTriggerStep);
|
|
||||||
}else{
|
}else{
|
||||||
sqlite3IdListDelete(db, pColumn);
|
sqlite3IdListDelete(db, pColumn);
|
||||||
sqlite3ExprListDelete(db, pEList);
|
sqlite3ExprListDelete(db, pEList);
|
||||||
@ -418,20 +400,17 @@ TriggerStep *sqlite3TriggerUpdateStep(
|
|||||||
Expr *pWhere, /* The WHERE clause */
|
Expr *pWhere, /* The WHERE clause */
|
||||||
int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
|
int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
|
||||||
){
|
){
|
||||||
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
|
TriggerStep *pTriggerStep;
|
||||||
|
|
||||||
|
pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName);
|
||||||
if( pTriggerStep==0 ){
|
if( pTriggerStep==0 ){
|
||||||
sqlite3ExprListDelete(db, pEList);
|
sqlite3ExprListDelete(db, pEList);
|
||||||
sqlite3ExprDelete(db, pWhere);
|
sqlite3ExprDelete(db, pWhere);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pTriggerStep->op = TK_UPDATE;
|
|
||||||
pTriggerStep->target = *pTableName;
|
|
||||||
pTriggerStep->pExprList = pEList;
|
pTriggerStep->pExprList = pEList;
|
||||||
pTriggerStep->pWhere = pWhere;
|
pTriggerStep->pWhere = pWhere;
|
||||||
pTriggerStep->orconf = orconf;
|
pTriggerStep->orconf = orconf;
|
||||||
sqlitePersistTriggerStep(db, pTriggerStep);
|
|
||||||
|
|
||||||
return pTriggerStep;
|
return pTriggerStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,17 +424,15 @@ TriggerStep *sqlite3TriggerDeleteStep(
|
|||||||
Token *pTableName, /* The table from which rows are deleted */
|
Token *pTableName, /* The table from which rows are deleted */
|
||||||
Expr *pWhere /* The WHERE clause */
|
Expr *pWhere /* The WHERE clause */
|
||||||
){
|
){
|
||||||
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
|
TriggerStep *pTriggerStep;
|
||||||
|
|
||||||
|
pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName);
|
||||||
if( pTriggerStep==0 ){
|
if( pTriggerStep==0 ){
|
||||||
sqlite3ExprDelete(db, pWhere);
|
sqlite3ExprDelete(db, pWhere);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pTriggerStep->op = TK_DELETE;
|
|
||||||
pTriggerStep->target = *pTableName;
|
|
||||||
pTriggerStep->pWhere = pWhere;
|
pTriggerStep->pWhere = pWhere;
|
||||||
pTriggerStep->orconf = OE_Default;
|
pTriggerStep->orconf = OE_Default;
|
||||||
sqlitePersistTriggerStep(db, pTriggerStep);
|
|
||||||
|
|
||||||
return pTriggerStep;
|
return pTriggerStep;
|
||||||
}
|
}
|
||||||
@ -470,8 +447,6 @@ void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
|
|||||||
sqlite3DbFree(db, pTrigger->table);
|
sqlite3DbFree(db, pTrigger->table);
|
||||||
sqlite3ExprDelete(db, pTrigger->pWhen);
|
sqlite3ExprDelete(db, pTrigger->pWhen);
|
||||||
sqlite3IdListDelete(db, pTrigger->pColumns);
|
sqlite3IdListDelete(db, pTrigger->pColumns);
|
||||||
assert( pTrigger->nameToken.dyn );
|
|
||||||
sqlite3DbFree(db, (char*)pTrigger->nameToken.z);
|
|
||||||
sqlite3DbFree(db, pTrigger);
|
sqlite3DbFree(db, pTrigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,15 +644,16 @@ static SrcList *targetSrcList(
|
|||||||
int iDb; /* Index of the database to use */
|
int iDb; /* Index of the database to use */
|
||||||
SrcList *pSrc; /* SrcList to be returned */
|
SrcList *pSrc; /* SrcList to be returned */
|
||||||
|
|
||||||
|
pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
|
||||||
|
if( pSrc ){
|
||||||
|
assert( pSrc->nSrc>0 );
|
||||||
|
assert( pSrc->a!=0 );
|
||||||
iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
|
iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
|
||||||
if( iDb==0 || iDb>=2 ){
|
if( iDb==0 || iDb>=2 ){
|
||||||
|
sqlite3 *db = pParse->db;
|
||||||
assert( iDb<pParse->db->nDb );
|
assert( iDb<pParse->db->nDb );
|
||||||
sDb.z = (u8*)pParse->db->aDb[iDb].zName;
|
pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
|
||||||
sDb.n = sqlite3Strlen30((char*)sDb.z);
|
}
|
||||||
sDb.quoted = 0;
|
|
||||||
pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target);
|
|
||||||
} else {
|
|
||||||
pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
|
|
||||||
}
|
}
|
||||||
return pSrc;
|
return pSrc;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle UPDATE statements.
|
** to handle UPDATE statements.
|
||||||
**
|
**
|
||||||
** $Id: update.c,v 1.200 2009/05/05 15:46:10 drh Exp $
|
** $Id: update.c,v 1.201 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -630,10 +630,10 @@ static void updateVirtualTable(
|
|||||||
** all updated rows.
|
** all updated rows.
|
||||||
*/
|
*/
|
||||||
pEList = sqlite3ExprListAppend(pParse, 0,
|
pEList = sqlite3ExprListAppend(pParse, 0,
|
||||||
sqlite3CreateIdExpr(pParse, "_rowid_"), 0);
|
sqlite3CreateIdExpr(pParse, "_rowid_"));
|
||||||
if( pRowid ){
|
if( pRowid ){
|
||||||
pEList = sqlite3ExprListAppend(pParse, pEList,
|
pEList = sqlite3ExprListAppend(pParse, pEList,
|
||||||
sqlite3ExprDup(db, pRowid, 0), 0);
|
sqlite3ExprDup(db, pRowid, 0));
|
||||||
}
|
}
|
||||||
assert( pTab->iPKey<0 );
|
assert( pTab->iPKey<0 );
|
||||||
for(i=0; i<pTab->nCol; i++){
|
for(i=0; i<pTab->nCol; i++){
|
||||||
@ -642,7 +642,7 @@ static void updateVirtualTable(
|
|||||||
}else{
|
}else{
|
||||||
pExpr = sqlite3CreateIdExpr(pParse, pTab->aCol[i].zName);
|
pExpr = sqlite3CreateIdExpr(pParse, pTab->aCol[i].zName);
|
||||||
}
|
}
|
||||||
pEList = sqlite3ExprListAppend(pParse, pEList, pExpr, 0);
|
pEList = sqlite3ExprListAppend(pParse, pEList, pExpr);
|
||||||
}
|
}
|
||||||
pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
|
pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
** This file contains functions for allocating memory, comparing
|
** This file contains functions for allocating memory, comparing
|
||||||
** strings, and stuff like that.
|
** strings, and stuff like that.
|
||||||
**
|
**
|
||||||
** $Id: util.c,v 1.254 2009/05/06 19:03:14 drh Exp $
|
** $Id: util.c,v 1.255 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -108,6 +108,7 @@ int sqlite3IsNaN(double x){
|
|||||||
*/
|
*/
|
||||||
int sqlite3Strlen30(const char *z){
|
int sqlite3Strlen30(const char *z){
|
||||||
const char *z2 = z;
|
const char *z2 = z;
|
||||||
|
if( z==0 ) return 0;
|
||||||
while( *z2 ){ z2++; }
|
while( *z2 ){ z2++; }
|
||||||
return 0x3fffffff & (int)(z2 - z);
|
return 0x3fffffff & (int)(z2 - z);
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
** only within the VDBE. Interface routines refer to a Mem using the
|
** only within the VDBE. Interface routines refer to a Mem using the
|
||||||
** name sqlite_value
|
** name sqlite_value
|
||||||
**
|
**
|
||||||
** $Id: vdbemem.c,v 1.144 2009/05/05 12:54:50 drh Exp $
|
** $Id: vdbemem.c,v 1.145 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "vdbeInt.h"
|
#include "vdbeInt.h"
|
||||||
@ -974,7 +974,7 @@ int sqlite3ValueFromExpr(
|
|||||||
op = pExpr->op;
|
op = pExpr->op;
|
||||||
|
|
||||||
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
|
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
|
||||||
zVal = sqlite3DbStrNDup(db, (char*)pExpr->token.z, pExpr->token.n);
|
zVal = sqlite3DbStrDup(db, pExpr->zToken);
|
||||||
pVal = sqlite3ValueNew(db);
|
pVal = sqlite3ValueNew(db);
|
||||||
if( !zVal || !pVal ) goto no_mem;
|
if( !zVal || !pVal ) goto no_mem;
|
||||||
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
|
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
|
||||||
@ -996,14 +996,13 @@ int sqlite3ValueFromExpr(
|
|||||||
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
||||||
else if( op==TK_BLOB ){
|
else if( op==TK_BLOB ){
|
||||||
int nVal;
|
int nVal;
|
||||||
assert( pExpr->token.n>=3 );
|
assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' );
|
||||||
assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' );
|
assert( pExpr->zToken[1]=='\'' );
|
||||||
assert( pExpr->token.z[1]=='\'' );
|
|
||||||
assert( pExpr->token.z[pExpr->token.n-1]=='\'' );
|
|
||||||
pVal = sqlite3ValueNew(db);
|
pVal = sqlite3ValueNew(db);
|
||||||
if( !pVal ) goto no_mem;
|
if( !pVal ) goto no_mem;
|
||||||
nVal = pExpr->token.n - 3;
|
zVal = &pExpr->zToken[2];
|
||||||
zVal = (char*)pExpr->token.z + 2;
|
nVal = sqlite3Strlen30(zVal)-1;
|
||||||
|
assert( zVal[nVal]=='\'' );
|
||||||
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
|
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
|
||||||
0, SQLITE_DYNAMIC);
|
0, SQLITE_DYNAMIC);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
** This file contains routines used for walking the parser tree for
|
** This file contains routines used for walking the parser tree for
|
||||||
** an SQL statement.
|
** an SQL statement.
|
||||||
**
|
**
|
||||||
** $Id: walker.c,v 1.4 2009/04/08 13:51:52 drh Exp $
|
** $Id: walker.c,v 1.5 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -42,11 +42,10 @@ int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
|
|||||||
int rc;
|
int rc;
|
||||||
if( pExpr==0 ) return WRC_Continue;
|
if( pExpr==0 ) return WRC_Continue;
|
||||||
testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
|
testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
|
||||||
testcase( ExprHasProperty(pExpr, EP_SpanToken) );
|
|
||||||
testcase( ExprHasProperty(pExpr, EP_Reduced) );
|
testcase( ExprHasProperty(pExpr, EP_Reduced) );
|
||||||
rc = pWalker->xExprCallback(pWalker, pExpr);
|
rc = pWalker->xExprCallback(pWalker, pExpr);
|
||||||
if( rc==WRC_Continue
|
if( rc==WRC_Continue
|
||||||
&& !ExprHasAnyProperty(pExpr,EP_TokenOnly|EP_SpanToken) ){
|
&& !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){
|
||||||
if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
|
if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
|
||||||
if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
|
if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
|
||||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||||
|
34
src/where.c
34
src/where.c
@ -16,7 +16,7 @@
|
|||||||
** so is applicable. Because this module is responsible for selecting
|
** so is applicable. Because this module is responsible for selecting
|
||||||
** indices, you might also think of this module as the "query optimizer".
|
** indices, you might also think of this module as the "query optimizer".
|
||||||
**
|
**
|
||||||
** $Id: where.c,v 1.397 2009/05/22 15:43:27 danielk1977 Exp $
|
** $Id: where.c,v 1.398 2009/05/27 10:31:29 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@ -628,7 +628,6 @@ static int isLikeOrGlob(
|
|||||||
Expr *pRight, *pLeft; /* Right and left size of LIKE operator */
|
Expr *pRight, *pLeft; /* Right and left size of LIKE operator */
|
||||||
ExprList *pList; /* List of operands to the LIKE operator */
|
ExprList *pList; /* List of operands to the LIKE operator */
|
||||||
int c; /* One character in z[] */
|
int c; /* One character in z[] */
|
||||||
int n; /* Length of string z[] */
|
|
||||||
int cnt; /* Number of non-wildcard prefix characters */
|
int cnt; /* Number of non-wildcard prefix characters */
|
||||||
char wc[3]; /* Wildcard characters */
|
char wc[3]; /* Wildcard characters */
|
||||||
CollSeq *pColl; /* Collating sequence for LHS */
|
CollSeq *pColl; /* Collating sequence for LHS */
|
||||||
@ -659,15 +658,14 @@ static int isLikeOrGlob(
|
|||||||
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
|
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
z = (const char*)pRight->token.z;
|
z = pRight->zToken;
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
if( z ){
|
if( z ){
|
||||||
n = pRight->token.n;
|
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
|
||||||
while( cnt<n && (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
|
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( cnt==0 || 255==(u8)z[cnt-1] ){
|
if( cnt==0 || c==0 || 255==(u8)z[cnt-1] ){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
|
*pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
|
||||||
@ -693,8 +691,7 @@ static int isMatchOfColumn(
|
|||||||
if( pExpr->op!=TK_FUNCTION ){
|
if( pExpr->op!=TK_FUNCTION ){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if( pExpr->token.n!=5 ||
|
if( sqlite3StrICmp(pExpr->zToken,"match")!=0 ){
|
||||||
sqlite3StrNICmp((const char*)pExpr->token.z,"match",5)!=0 ){
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pList = pExpr->x.pList;
|
pList = pExpr->x.pList;
|
||||||
@ -963,12 +960,12 @@ static void exprAnalyzeOrTerm(
|
|||||||
assert( pOrTerm->leftCursor==iCursor );
|
assert( pOrTerm->leftCursor==iCursor );
|
||||||
assert( pOrTerm->u.leftColumn==iColumn );
|
assert( pOrTerm->u.leftColumn==iColumn );
|
||||||
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
|
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
|
||||||
pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0);
|
pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
|
||||||
pLeft = pOrTerm->pExpr->pLeft;
|
pLeft = pOrTerm->pExpr->pLeft;
|
||||||
}
|
}
|
||||||
assert( pLeft!=0 );
|
assert( pLeft!=0 );
|
||||||
pDup = sqlite3ExprDup(db, pLeft, 0);
|
pDup = sqlite3ExprDup(db, pLeft, 0);
|
||||||
pNew = sqlite3Expr(db, TK_IN, pDup, 0, 0);
|
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0);
|
||||||
if( pNew ){
|
if( pNew ){
|
||||||
int idxNew;
|
int idxNew;
|
||||||
transferJoinMarkings(pNew, pExpr);
|
transferJoinMarkings(pNew, pExpr);
|
||||||
@ -1121,7 +1118,8 @@ static void exprAnalyze(
|
|||||||
for(i=0; i<2; i++){
|
for(i=0; i<2; i++){
|
||||||
Expr *pNewExpr;
|
Expr *pNewExpr;
|
||||||
int idxNew;
|
int idxNew;
|
||||||
pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft, 0),
|
pNewExpr = sqlite3PExpr(pParse, ops[i],
|
||||||
|
sqlite3ExprDup(db, pExpr->pLeft, 0),
|
||||||
sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
|
sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
|
||||||
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||||
testcase( idxNew==0 );
|
testcase( idxNew==0 );
|
||||||
@ -1163,16 +1161,12 @@ static void exprAnalyze(
|
|||||||
|
|
||||||
pLeft = pExpr->x.pList->a[1].pExpr;
|
pLeft = pExpr->x.pList->a[1].pExpr;
|
||||||
pRight = pExpr->x.pList->a[0].pExpr;
|
pRight = pExpr->x.pList->a[0].pExpr;
|
||||||
pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0);
|
pStr1 = sqlite3Expr(db, TK_STRING, pRight->zToken);
|
||||||
if( pStr1 ){
|
if( pStr1 ) pStr1->zToken[nPattern] = 0;
|
||||||
sqlite3TokenCopy(db, &pStr1->token, &pRight->token);
|
|
||||||
pStr1->token.n = nPattern;
|
|
||||||
}
|
|
||||||
pStr2 = sqlite3ExprDup(db, pStr1, 0);
|
pStr2 = sqlite3ExprDup(db, pStr1, 0);
|
||||||
if( !db->mallocFailed ){
|
if( !db->mallocFailed ){
|
||||||
u8 c, *pC;
|
u8 c, *pC;
|
||||||
/* assert( pStr2->token.dyn ); */
|
pC = (u8*)&pStr2->zToken[nPattern-1];
|
||||||
pC = (u8*)&pStr2->token.z[nPattern-1];
|
|
||||||
c = *pC;
|
c = *pC;
|
||||||
if( noCase ){
|
if( noCase ){
|
||||||
if( c=='@' ) isComplete = 0;
|
if( c=='@' ) isComplete = 0;
|
||||||
@ -1216,7 +1210,8 @@ static void exprAnalyze(
|
|||||||
prereqColumn = exprTableUsage(pMaskSet, pLeft);
|
prereqColumn = exprTableUsage(pMaskSet, pLeft);
|
||||||
if( (prereqExpr & prereqColumn)==0 ){
|
if( (prereqExpr & prereqColumn)==0 ){
|
||||||
Expr *pNewExpr;
|
Expr *pNewExpr;
|
||||||
pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight, 0), 0);
|
pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
|
||||||
|
0, sqlite3ExprDup(db, pRight, 0), 0);
|
||||||
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||||
testcase( idxNew==0 );
|
testcase( idxNew==0 );
|
||||||
pNewTerm = &pWC->a[idxNew];
|
pNewTerm = &pWC->a[idxNew];
|
||||||
@ -2296,7 +2291,6 @@ static int codeEqualityTerm(
|
|||||||
eType = sqlite3FindInIndex(pParse, pX, 0);
|
eType = sqlite3FindInIndex(pParse, pX, 0);
|
||||||
iTab = pX->iTable;
|
iTab = pX->iTable;
|
||||||
sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
|
sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
|
||||||
VdbeComment((v, "%.*s", pX->span.n, pX->span.z));
|
|
||||||
assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
|
assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
|
||||||
if( pLevel->u.in.nIn==0 ){
|
if( pLevel->u.in.nIn==0 ){
|
||||||
pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
|
pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# focus of this script is testing the ATTACH and DETACH commands
|
# focus of this script is testing the ATTACH and DETACH commands
|
||||||
# and related functionality.
|
# and related functionality.
|
||||||
#
|
#
|
||||||
# $Id: attach.test,v 1.49 2008/07/12 14:52:20 drh Exp $
|
# $Id: attach.test,v 1.50 2009/05/27 10:31:30 drh Exp $
|
||||||
#
|
#
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
@ -756,8 +756,7 @@ ifcapable subquery {
|
|||||||
DETACH RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY
|
DETACH RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY
|
||||||
REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL )
|
REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL )
|
||||||
}
|
}
|
||||||
} {1 {invalid name: "RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY
|
} {1 {invalid name: ""}}
|
||||||
REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL )"}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create a malformed file (a file that is not a valid database)
|
# Create a malformed file (a file that is not a valid database)
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing the SELECT statement.
|
# focus of this file is testing the SELECT statement.
|
||||||
#
|
#
|
||||||
# $Id: select1.test,v 1.68 2009/04/23 14:58:40 danielk1977 Exp $
|
# $Id: select1.test,v 1.69 2009/05/27 10:31:30 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@ -306,7 +306,7 @@ do_test select1-4.3 {
|
|||||||
do_test select1-4.4 {
|
do_test select1-4.4 {
|
||||||
set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg]
|
set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg]
|
||||||
lappend v $msg
|
lappend v $msg
|
||||||
} {1 {misuse of aggregate: min(f1)}}
|
} {1 {misuse of aggregate: min()}}
|
||||||
|
|
||||||
# The restriction not allowing constants in the ORDER BY clause
|
# The restriction not allowing constants in the ORDER BY clause
|
||||||
# has been removed. See ticket #1768
|
# has been removed. See ticket #1768
|
||||||
|
@ -22,6 +22,6 @@ do_test tkt1514-1.1 {
|
|||||||
CREATE TABLE t1(a,b);
|
CREATE TABLE t1(a,b);
|
||||||
SELECT a FROM t1 WHERE max(b)<10 GROUP BY a;
|
SELECT a FROM t1 WHERE max(b)<10 GROUP BY a;
|
||||||
}
|
}
|
||||||
} {1 {misuse of aggregate: max(b)}}
|
} {1 {misuse of aggregate: max()}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# This file implements regression tests for SQLite library.
|
# This file implements regression tests for SQLite library.
|
||||||
#
|
#
|
||||||
# $Id: tkt3508.test,v 1.3 2008/11/26 20:09:15 pweilbacher Exp $
|
# $Id: tkt3508.test,v 1.4 2009/05/27 10:31:30 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@ -33,6 +33,6 @@ do_test tkt3508-1.1 {
|
|||||||
select SUBSTRATE_HPRD_ID, count(substrate_refseq_id) as c
|
select SUBSTRATE_HPRD_ID, count(substrate_refseq_id) as c
|
||||||
from modificationsTmp where c > 1 group by SUBSTRATE_HPRD_ID;
|
from modificationsTmp where c > 1 group by SUBSTRATE_HPRD_ID;
|
||||||
}
|
}
|
||||||
} {1 {misuse of aggregate: }}
|
} {1 {misuse of aggregate: count()}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
Reference in New Issue
Block a user