In the parse tree, combine LIMIT and OFFSET into a single expression rooted

on a TK_LIMIT node, for a small code size reduction and performance increase,
and a reduction in code complexity.

FossilOrigin-Name: 3925facd942c9df663f9b29b1e6f94f6be14af8c2b99eb691bfc836b4c220826
This commit is contained in:
drh 2017-11-14 23:48:23 +00:00
parent 65efeaca83
commit 8c0833fb21
15 changed files with 92 additions and 140 deletions

View File

@ -1,5 +1,5 @@
C Add\sthe\sability\sto\sread\sfrom\sread-only\sWAL-mode\sdatabase\sfiles\sas\slong\sas\nthe\s-wal\sand\s-shm\sfiles\sare\spresent\son\sdisk. C In\sthe\sparse\stree,\scombine\sLIMIT\sand\sOFFSET\sinto\sa\ssingle\sexpression\srooted\non\sa\sTK_LIMIT\snode,\sfor\sa\ssmall\scode\ssize\sreduction\sand\sperformance\sincrease,\nand\sa\sreduction\sin\scode\scomplexity.
D 2017-11-14T19:34:22.764 D 2017-11-14T23:48:23.099
F Makefile.in b142eb20482922153ebc77b261cdfd0a560ed05a81e9f6d9a2b0e8192922a1d2 F Makefile.in b142eb20482922153ebc77b261cdfd0a560ed05a81e9f6d9a2b0e8192922a1d2
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a55372a22454e742ba7c8f6edf05b83213ec01125166ad7dcee0567e2f7fc81b F Makefile.msc a55372a22454e742ba7c8f6edf05b83213ec01125166ad7dcee0567e2f7fc81b
@ -407,7 +407,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594 F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594
F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421 F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421
F src/attach.c 07b706e336fd3cedbd855e1f8266d10e82fecae07daf86717b5760cd7784c584 F src/attach.c 84c477e856b24c2b9a0983b438a707c0cf4d616cee7a425401d418e58afec24c
F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
@ -422,17 +422,17 @@ F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0
F src/date.c 48f743d88bbe88f848532d333cca84f26e52a4f217e86f86be7fc1b919c33d74 F src/date.c 48f743d88bbe88f848532d333cca84f26e52a4f217e86f86be7fc1b919c33d74
F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6
F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720
F src/delete.c f97cc2a9a30b4119ec5ed0da4e41335060cbb8510a5f1a756be48c065cb824f0 F src/delete.c e6a70fb58f6628f0ffc6d7221a6702c0d7b342c82520385b3996b364c22e0cb3
F src/expr.c 0016b95aed1df47ebc0eb7415bd621841d72dbffd3bfb62210e50e71d83b4691 F src/expr.c 5257a9157f22f048ddcce5cd494d39633e89c2a4769671311b3e7875d262f746
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 821f70b6c43ba4542ffb5fdf11d3ac5f79e4cbae4750ee3de379afbc5e1f7781 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331
F src/func.c 0fb9a2d678d3c8aba89b46468b309cd7e8fa9806a369a30aa89024660845bb13 F src/func.c 0fb9a2d678d3c8aba89b46468b309cd7e8fa9806a369a30aa89024660845bb13
F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c c7f333547211b8efbac8a72f71adad736b91e655d7bcdfacc737351ecf3c8df2 F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 20865b183bb8a3723d59cf1efffc3c50217eb452c1021d077b908c94da26b0b2 F src/loadext.c 20865b183bb8a3723d59cf1efffc3c50217eb452c1021d077b908c94da26b0b2
F src/main.c c1965ee8159cee5fba3f590cc4767515a690504455a03e4817b1accfe0ba95a5 F src/main.c c1965ee8159cee5fba3f590cc4767515a690504455a03e4817b1accfe0ba95a5
@ -459,7 +459,7 @@ F src/os_win.c 7f36120492e4a23c48d1dd685edf29ae459c6d555660c61f1323cea3e5a1191d
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903 F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903
F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a
F src/parse.y f5f02ef39444982af36545bd52ae2921fc4ba1bac24d9b11efd8ec1f52c5b4dc F src/parse.y d79001da275bfe344b409006b85e81e486a0f6afc3762fdf0944f000f4aa0111
F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201 F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
@ -468,14 +468,14 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
F src/prepare.c 7cf451f903ad92a14e22de415a13e7a7d30f1bd23b3d21eeb0dc7264723244c5 F src/prepare.c 7cf451f903ad92a14e22de415a13e7a7d30f1bd23b3d21eeb0dc7264723244c5
F src/printf.c 9506b4b96e59c0467047155f09015750cb2878aeda3d39e5610c1192ddc3c41c F src/printf.c 9506b4b96e59c0467047155f09015750cb2878aeda3d39e5610c1192ddc3c41c
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 5b1e89ba279f4a4ab2f0975a7100d75be71e1a43a2df75a9c909d45bdd18c6ed F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 660ef7977841fb462f24c8561e4212615bb6e5c9835fd3556257ce8316c50fee F src/select.c 17e220191860a64a18c084141e1a8b7309e166a6f2d42c02021af27ea080d157
F src/shell.c.in 08cbffc31900359fea85896342a46147e9772c370d8a5079b7be26e3a1f50e8a F src/shell.c.in 08cbffc31900359fea85896342a46147e9772c370d8a5079b7be26e3a1f50e8a
F src/sqlite.h.in 8fd97993d48b50b9bade38c52f12d175942c9497c960905610c7b03a3e4b5818 F src/sqlite.h.in 8fd97993d48b50b9bade38c52f12d175942c9497c960905610c7b03a3e4b5818
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
F src/sqliteInt.h abd4e64bc72906449d801d0e211265525239bc021bd9b7a72143c281fc24fa03 F src/sqliteInt.h fb297e4b891608057e857d583e30a261d905a3f41493f351fc91bae7d22008ff
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@ -533,9 +533,9 @@ F src/test_windirent.h 5d67483a55442e31e1bde0f4a230e6e932ad5906
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5 F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5
F src/treeview.c 2ee4a5dada213d5ab08a742af5c876cee6f1aaae65f10a61923f3fb63846afef F src/treeview.c 08a83195de8fad3f00542e3c8b3c1eb1222c999817c9e301ffb7f332882b96dd
F src/trigger.c 929b12bb5f9ab3b10c589f71fa176effe6ea8bddc9eb1bbd2439755fa0acdfdf F src/trigger.c fc6be2a6e103d9e38b161e07d7db0ffb1f2218bd2f27ccdc0a3d1cc89e9cea0f
F src/update.c 2e7ef3839eb620e9140a41bbfd05e29d7d216441c5d97221b75635dea4e49672 F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c d01fa6f45bfad3b65fb2490513aa2e0676412c61b4b094340b513cf72c3704a4 F src/util.c d01fa6f45bfad3b65fb2490513aa2e0676412c61b4b094340b513cf72c3704a4
F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739
@ -552,7 +552,7 @@ F src/vtab.c 0e4885495172e1bdf54b12cce23b395ac74ef5729031f15e1bc1e3e6b360ed1a
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c beeb71e4eab65dbf0d95f2717efc6ca3c0f5b3090ce67f3de63828f39a6ff053 F src/wal.c beeb71e4eab65dbf0d95f2717efc6ca3c0f5b3090ce67f3de63828f39a6ff053
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
F src/walker.c d591e8a9ccf60abb010966b354fcea4aa08eba4d83675c2b281a8764c76cc22f F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
F src/where.c 031a80bcafe93934fd7052f3031c9e7eb36b61754c6c84d6bf0833184abad3db F src/where.c 031a80bcafe93934fd7052f3031c9e7eb36b61754c6c84d6bf0833184abad3db
F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971 F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971
F src/wherecode.c 4a117dd5886616d074f7b6589c23bf742f5a9858d6ffdaf8b9d1f76ab06245d2 F src/wherecode.c 4a117dd5886616d074f7b6589c23bf742f5a9858d6ffdaf8b9d1f76ab06245d2
@ -1677,8 +1677,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P dae4a97a483bee1e6ac0271ddd28a0dffcebf7522edaf12eb5e0eba5fc62516a 486949fc03706e0056439b52ce60931ea4ce0a65e391da7f6287fe13862de251 P 00ec95fcd02bb415dabd7f25fee24856d45d6916c18b2728e97e9bb9b8322ba3
R 4dd08ae7170c8d270fe307a98bb5bfb2 R 9fe4e3d4453a36374c8a196662e2c5b0
T +closed 486949fc03706e0056439b52ce60931ea4ce0a65e391da7f6287fe13862de251
U drh U drh
Z 1fe131254421255cb83ffd7abf325441 Z 3ab594fe26a5b432ce6d9e25b1b1040f

View File

@ -1 +1 @@
00ec95fcd02bb415dabd7f25fee24856d45d6916c18b2728e97e9bb9b8322ba3 3925facd942c9df663f9b29b1e6f94f6be14af8c2b99eb691bfc836b4c220826

View File

@ -504,9 +504,6 @@ int sqlite3FixSelect(
if( sqlite3FixExpr(pFix, pSelect->pLimit) ){ if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
return 1; return 1;
} }
if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
return 1;
}
pSelect = pSelect->pPrior; pSelect = pSelect->pPrior;
} }
return 0; return 0;

View File

@ -92,7 +92,6 @@ void sqlite3MaterializeView(
Expr *pWhere, /* Optional WHERE clause to be added */ Expr *pWhere, /* Optional WHERE clause to be added */
ExprList *pOrderBy, /* Optional ORDER BY clause */ ExprList *pOrderBy, /* Optional ORDER BY clause */
Expr *pLimit, /* Optional LIMIT clause */ Expr *pLimit, /* Optional LIMIT clause */
Expr *pOffset, /* Optional OFFSET clause */
int iCur /* Cursor number for ephemeral table */ int iCur /* Cursor number for ephemeral table */
){ ){
SelectDest dest; SelectDest dest;
@ -110,7 +109,7 @@ void sqlite3MaterializeView(
assert( pFrom->a[0].pUsing==0 ); assert( pFrom->a[0].pUsing==0 );
} }
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy, pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy,
SF_IncludeHidden, pLimit, pOffset); SF_IncludeHidden, pLimit);
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
sqlite3Select(pParse, pSel, &dest); sqlite3Select(pParse, pSel, &dest);
sqlite3SelectDelete(db, pSel); sqlite3SelectDelete(db, pSel);
@ -132,7 +131,6 @@ Expr *sqlite3LimitWhere(
Expr *pWhere, /* The WHERE clause. May be null */ Expr *pWhere, /* The WHERE clause. May be null */
ExprList *pOrderBy, /* The ORDER BY clause. May be null */ ExprList *pOrderBy, /* The ORDER BY clause. May be null */
Expr *pLimit, /* The LIMIT clause. May be null */ Expr *pLimit, /* The LIMIT clause. May be null */
Expr *pOffset, /* The OFFSET clause. May be null */
char *zStmtType /* Either DELETE or UPDATE. For err msgs. */ char *zStmtType /* Either DELETE or UPDATE. For err msgs. */
){ ){
sqlite3 *db = pParse->db; sqlite3 *db = pParse->db;
@ -149,8 +147,6 @@ Expr *sqlite3LimitWhere(
sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
sqlite3ExprDelete(pParse->db, pWhere); sqlite3ExprDelete(pParse->db, pWhere);
sqlite3ExprListDelete(pParse->db, pOrderBy); sqlite3ExprListDelete(pParse->db, pOrderBy);
sqlite3ExprDelete(pParse->db, pLimit);
sqlite3ExprDelete(pParse->db, pOffset);
return 0; return 0;
} }
@ -158,8 +154,6 @@ Expr *sqlite3LimitWhere(
** is a limit/offset term to enforce. ** is a limit/offset term to enforce.
*/ */
if( pLimit == 0 ) { if( pLimit == 0 ) {
/* if pLimit is null, pOffset will always be null as well. */
assert( pOffset == 0 );
return pWhere; return pWhere;
} }
@ -206,7 +200,7 @@ Expr *sqlite3LimitWhere(
/* generate the SELECT expression tree. */ /* generate the SELECT expression tree. */
pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0, pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0,
pOrderBy,0,pLimit,pOffset pOrderBy,0,pLimit
); );
/* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
@ -229,8 +223,7 @@ void sqlite3DeleteFrom(
SrcList *pTabList, /* The table from which we should delete things */ SrcList *pTabList, /* The table from which we should delete things */
Expr *pWhere, /* The WHERE clause. May be null */ Expr *pWhere, /* The WHERE clause. May be null */
ExprList *pOrderBy, /* ORDER BY clause. May be null */ ExprList *pOrderBy, /* ORDER BY clause. May be null */
Expr *pLimit, /* LIMIT clause. May be null */ Expr *pLimit /* LIMIT clause. May be null */
Expr *pOffset /* OFFSET clause. May be null */
){ ){
Vdbe *v; /* The virtual database engine */ Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */ Table *pTab; /* The table from which records will be deleted */
@ -303,10 +296,10 @@ void sqlite3DeleteFrom(
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT #ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView ){ if( !isView ){
pWhere = sqlite3LimitWhere( pWhere = sqlite3LimitWhere(
pParse, pTabList, pWhere, pOrderBy, pLimit, pOffset, "DELETE" pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE"
); );
pOrderBy = 0; pOrderBy = 0;
pLimit = pOffset = 0; pLimit = 0;
} }
#endif #endif
@ -358,11 +351,11 @@ void sqlite3DeleteFrom(
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){ if( isView ){
sqlite3MaterializeView(pParse, pTab, sqlite3MaterializeView(pParse, pTab,
pWhere, pOrderBy, pLimit, pOffset, iTabCur pWhere, pOrderBy, pLimit, iTabCur
); );
iDataCur = iIdxCur = iTabCur; iDataCur = iIdxCur = iTabCur;
pOrderBy = 0; pOrderBy = 0;
pLimit = pOffset = 0; pLimit = 0;
} }
#endif #endif
@ -609,7 +602,6 @@ delete_from_cleanup:
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
sqlite3ExprListDelete(db, pOrderBy); sqlite3ExprListDelete(db, pOrderBy);
sqlite3ExprDelete(db, pLimit); sqlite3ExprDelete(db, pLimit);
sqlite3ExprDelete(db, pOffset);
#endif #endif
sqlite3DbFree(db, aToOpen); sqlite3DbFree(db, aToOpen);
return; return;

View File

@ -663,7 +663,6 @@ static void heightOfSelect(Select *p, int *pnHeight){
heightOfExpr(p->pWhere, pnHeight); heightOfExpr(p->pWhere, pnHeight);
heightOfExpr(p->pHaving, pnHeight); heightOfExpr(p->pHaving, pnHeight);
heightOfExpr(p->pLimit, pnHeight); heightOfExpr(p->pLimit, pnHeight);
heightOfExpr(p->pOffset, pnHeight);
heightOfExprList(p->pEList, pnHeight); heightOfExprList(p->pEList, pnHeight);
heightOfExprList(p->pGroupBy, pnHeight); heightOfExprList(p->pGroupBy, pnHeight);
heightOfExprList(p->pOrderBy, pnHeight); heightOfExprList(p->pOrderBy, pnHeight);
@ -1462,7 +1461,6 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
pNew->pNext = pNext; pNew->pNext = pNext;
pNew->pPrior = 0; pNew->pPrior = 0;
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
pNew->iLimit = 0; pNew->iLimit = 0;
pNew->iOffset = 0; pNew->iOffset = 0;
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
@ -2099,7 +2097,6 @@ static Select *isCandidateForInOpt(Expr *pX){
} }
assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */ assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */
if( p->pLimit ) return 0; /* Has no LIMIT clause */ if( p->pLimit ) return 0; /* Has no LIMIT clause */
assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */
if( p->pWhere ) return 0; /* Has no WHERE clause */ if( p->pWhere ) return 0; /* Has no WHERE clause */
pSrc = p->pSrc; pSrc = p->pSrc;
assert( pSrc!=0 ); assert( pSrc!=0 );
@ -2739,6 +2736,7 @@ int sqlite3CodeSubselect(
Select *pSel; /* SELECT statement to encode */ Select *pSel; /* SELECT statement to encode */
SelectDest dest; /* How to deal with SELECT result */ SelectDest dest; /* How to deal with SELECT result */
int nReg; /* Registers to allocate */ int nReg; /* Registers to allocate */
Expr *pLimit; /* New limit expression */
testcase( pExpr->op==TK_EXISTS ); testcase( pExpr->op==TK_EXISTS );
testcase( pExpr->op==TK_SELECT ); testcase( pExpr->op==TK_SELECT );
@ -2760,9 +2758,13 @@ int sqlite3CodeSubselect(
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
VdbeComment((v, "Init EXISTS result")); VdbeComment((v, "Init EXISTS result"));
} }
sqlite3ExprDelete(pParse->db, pSel->pLimit); pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER, if( pSel->pLimit ){
&sqlite3IntTokens[1], 0); sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
pSel->pLimit->pLeft = pLimit;
}else{
pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
}
pSel->iLimit = 0; pSel->iLimit = 0;
pSel->selFlags &= ~SF_MultiValue; pSel->selFlags &= ~SF_MultiValue;
if( sqlite3Select(pParse, pSel, &dest) ){ if( sqlite3Select(pParse, pSel, &dest) ){

View File

@ -725,7 +725,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
} }
pParse->disableTriggers = 1; pParse->disableTriggers = 1;
sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0, 0); sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0);
pParse->disableTriggers = 0; pParse->disableTriggers = 0;
/* If the DELETE has generated immediate foreign key constraint /* If the DELETE has generated immediate foreign key constraint
@ -1283,7 +1283,7 @@ static Trigger *fkActionTrigger(
sqlite3ExprListAppend(pParse, 0, pRaise), sqlite3ExprListAppend(pParse, 0, pRaise),
sqlite3SrcListAppend(db, 0, &tFrom, 0), sqlite3SrcListAppend(db, 0, &tFrom, 0),
pWhere, pWhere,
0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0
); );
pWhere = 0; pWhere = 0;
} }

View File

@ -2007,7 +2007,6 @@ static int xferOptimization(
if( pSelect->pLimit ){ if( pSelect->pLimit ){
return 0; /* SELECT may not have a LIMIT clause */ return 0; /* SELECT may not have a LIMIT clause */
} }
assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */
if( pSelect->pPrior ){ if( pSelect->pPrior ){
return 0; /* SELECT may not be a compound query */ return 0; /* SELECT may not be a compound query */
} }

View File

@ -84,15 +84,6 @@
*/ */
#define YYMALLOCARGTYPE u64 #define YYMALLOCARGTYPE u64
/*
** An instance of this structure holds information about the
** LIMIT clause of a SELECT statement.
*/
struct LimitVal {
Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */
Expr *pOffset; /* The OFFSET expression. NULL if there is none */
};
/* /*
** An instance of the following structure describes the event of a ** An instance of the following structure describes the event of a
** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
@ -470,7 +461,7 @@ selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z). {
x.n = 0; x.n = 0;
parserDoubleLinkSelect(pParse, pRhs); parserDoubleLinkSelect(pParse, pRhs);
pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
} }
if( pRhs ){ if( pRhs ){
pRhs->op = (u8)Y; pRhs->op = (u8)Y;
@ -493,7 +484,7 @@ oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
#if SELECTTRACE_ENABLED #if SELECTTRACE_ENABLED
Token s = S; /*A-overwrites-S*/ Token s = S; /*A-overwrites-S*/
#endif #endif
A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset); A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L);
#if SELECTTRACE_ENABLED #if SELECTTRACE_ENABLED
/* Populate the Select.zSelName[] string that is used to help with /* Populate the Select.zSelName[] string that is used to help with
** query planner debugging, to differentiate between multiple Select ** query planner debugging, to differentiate between multiple Select
@ -524,11 +515,11 @@ oneselect(A) ::= values(A).
%type values {Select*} %type values {Select*}
%destructor values {sqlite3SelectDelete(pParse->db, $$);} %destructor values {sqlite3SelectDelete(pParse->db, $$);}
values(A) ::= VALUES LP nexprlist(X) RP. { values(A) ::= VALUES LP nexprlist(X) RP. {
A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0); A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0);
} }
values(A) ::= values(A) COMMA LP exprlist(Y) RP. { values(A) ::= values(A) COMMA LP exprlist(Y) RP. {
Select *pRight, *pLeft = A; Select *pRight, *pLeft = A;
pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0);
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
if( pRight ){ if( pRight ){
pRight->op = TK_ALL; pRight->op = TK_ALL;
@ -639,7 +630,7 @@ seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
}else{ }else{
Select *pSubquery; Select *pSubquery;
sqlite3SrcListShiftJoinType(F); sqlite3SrcListShiftJoinType(F);
pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0,0); pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0);
A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,N,U); A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,N,U);
} }
} }
@ -726,7 +717,7 @@ groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
having_opt(A) ::= . {A = 0;} having_opt(A) ::= . {A = 0;}
having_opt(A) ::= HAVING expr(X). {A = X.pExpr;} having_opt(A) ::= HAVING expr(X). {A = X.pExpr;}
%type limit_opt {struct LimitVal} %type limit_opt {Expr*}
// The destructor for limit_opt will never fire in the current grammar. // The destructor for limit_opt will never fire in the current grammar.
// The limit_opt non-terminal only occurs at the end of a single production // The limit_opt non-terminal only occurs at the end of a single production
@ -735,16 +726,14 @@ having_opt(A) ::= HAVING expr(X). {A = X.pExpr;}
// reduce. So there is never a limit_opt non-terminal on the stack // reduce. So there is never a limit_opt non-terminal on the stack
// except as a transient. So there is never anything to destroy. // except as a transient. So there is never anything to destroy.
// //
//%destructor limit_opt { //%destructor limit_opt {sqlite3ExprDelete(pParse->db, $$);}
// sqlite3ExprDelete(pParse->db, $$.pLimit); limit_opt(A) ::= . {A = 0;}
// sqlite3ExprDelete(pParse->db, $$.pOffset); limit_opt(A) ::= LIMIT expr(X).
//} {A = sqlite3PExpr(pParse,TK_LIMIT,X.pExpr,0);}
limit_opt(A) ::= . {A.pLimit = 0; 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.pExpr; A.pOffset = Y.pExpr;} {A = sqlite3PExpr(pParse,TK_LIMIT,X.pExpr,Y.pExpr);}
limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
{A.pOffset = X.pExpr; A.pLimit = Y.pExpr;} {A = sqlite3PExpr(pParse,TK_LIMIT,Y.pExpr,X.pExpr);}
/////////////////////////// The DELETE statement ///////////////////////////// /////////////////////////// The DELETE statement /////////////////////////////
// //
@ -753,14 +742,14 @@ cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W)
orderby_opt(O) limit_opt(L). { orderby_opt(O) limit_opt(L). {
sqlite3WithPush(pParse, C, 1); sqlite3WithPush(pParse, C, 1);
sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3DeleteFrom(pParse,X,W,O,L.pLimit,L.pOffset); sqlite3DeleteFrom(pParse,X,W,O,L);
} }
%endif %endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT %ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). { cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
sqlite3WithPush(pParse, C, 1); sqlite3WithPush(pParse, C, 1);
sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3DeleteFrom(pParse,X,W,0,0,0); sqlite3DeleteFrom(pParse,X,W,0,0);
} }
%endif %endif
@ -778,7 +767,7 @@ cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
sqlite3WithPush(pParse, C, 1); sqlite3WithPush(pParse, C, 1);
sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3ExprListCheckLength(pParse,Y,"set list"); sqlite3ExprListCheckLength(pParse,Y,"set list");
sqlite3Update(pParse,X,Y,W,R,O,L.pLimit,L.pOffset); sqlite3Update(pParse,X,Y,W,R,O,L);
} }
%endif %endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT %ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
@ -787,7 +776,7 @@ cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
sqlite3WithPush(pParse, C, 1); sqlite3WithPush(pParse, C, 1);
sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3ExprListCheckLength(pParse,Y,"set list"); sqlite3ExprListCheckLength(pParse,Y,"set list");
sqlite3Update(pParse,X,Y,W,R,0,0,0); sqlite3Update(pParse,X,Y,W,R,0,0);
} }
%endif %endif
@ -1189,7 +1178,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
} }
expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z) paren_exprlist(E). [IN] { expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z) paren_exprlist(E). [IN] {
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z); SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
if( E ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, E); if( E ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, E);
A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0); A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0);
sqlite3PExprAddSelect(pParse, A.pExpr, pSelect); sqlite3PExprAddSelect(pParse, A.pExpr, pSelect);

View File

@ -1196,8 +1196,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
*/ */
memset(&sNC, 0, sizeof(sNC)); memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse; sNC.pParse = pParse;
if( sqlite3ResolveExprNames(&sNC, p->pLimit) || if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){
sqlite3ResolveExprNames(&sNC, p->pOffset) ){
return WRC_Abort; return WRC_Abort;
} }

View File

@ -74,7 +74,6 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprDelete(db, p->pHaving); sqlite3ExprDelete(db, p->pHaving);
sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit); sqlite3ExprDelete(db, p->pLimit);
sqlite3ExprDelete(db, p->pOffset);
if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFreeNN(db, p); if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior; p = pPrior;
@ -107,8 +106,7 @@ Select *sqlite3SelectNew(
Expr *pHaving, /* the HAVING clause */ Expr *pHaving, /* the HAVING clause */
ExprList *pOrderBy, /* the ORDER BY clause */ ExprList *pOrderBy, /* the ORDER BY clause */
u32 selFlags, /* Flag parameters, such as SF_Distinct */ u32 selFlags, /* Flag parameters, such as SF_Distinct */
Expr *pLimit, /* LIMIT value. NULL means not used */ Expr *pLimit /* LIMIT value. NULL means not used */
Expr *pOffset /* OFFSET value. NULL means no offset */
){ ){
Select *pNew; Select *pNew;
Select standin; Select standin;
@ -141,10 +139,7 @@ Select *sqlite3SelectNew(
pNew->pPrior = 0; pNew->pPrior = 0;
pNew->pNext = 0; pNew->pNext = 0;
pNew->pLimit = pLimit; pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
pNew->pWith = 0; pNew->pWith = 0;
assert( pOffset==0 || pLimit!=0 || pParse->nErr>0
|| pParse->db->mallocFailed!=0 );
if( pParse->db->mallocFailed ) { if( pParse->db->mallocFailed ) {
clearSelect(pParse->db, pNew, pNew!=&standin); clearSelect(pParse->db, pNew, pNew!=&standin);
pNew = 0; pNew = 0;
@ -1874,7 +1869,7 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
/* /*
** Compute the iLimit and iOffset fields of the SELECT based on the ** Compute the iLimit and iOffset fields of the SELECT based on the
** pLimit and pOffset expressions. pLimit and pOffset hold the expressions ** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions
** that appear in the original SQL statement after the LIMIT and OFFSET ** that appear in the original SQL statement after the LIMIT and OFFSET
** keywords. Or NULL if those keywords are omitted. iLimit and iOffset ** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
** are the integer memory register numbers for counters used to compute ** are the integer memory register numbers for counters used to compute
@ -1882,15 +1877,15 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
** iLimit and iOffset are negative. ** iLimit and iOffset are negative.
** **
** This routine changes the values of iLimit and iOffset only if ** This routine changes the values of iLimit and iOffset only if
** a limit or offset is defined by pLimit and pOffset. iLimit and ** a limit or offset is defined by pLimit->pLeft and pLimit->pRight. iLimit
** iOffset should have been preset to appropriate default values (zero) ** and iOffset should have been preset to appropriate default values (zero)
** prior to calling this routine. ** prior to calling this routine.
** **
** The iOffset register (if it exists) is initialized to the value ** The iOffset register (if it exists) is initialized to the value
** of the OFFSET. The iLimit register is initialized to LIMIT. Register ** of the OFFSET. The iLimit register is initialized to LIMIT. Register
** iOffset+1 is initialized to LIMIT+OFFSET. ** iOffset+1 is initialized to LIMIT+OFFSET.
** **
** Only if pLimit!=0 or pOffset!=0 do the limit registers get ** Only if pLimit->pLeft!=0 do the limit registers get
** redefined. The UNION ALL operator uses this property to force ** redefined. The UNION ALL operator uses this property to force
** the reuse of the same limit and offset registers across multiple ** the reuse of the same limit and offset registers across multiple
** SELECT statements. ** SELECT statements.
@ -1900,6 +1895,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
int iLimit = 0; int iLimit = 0;
int iOffset; int iOffset;
int n; int n;
Expr *pLimit = p->pLimit;
if( p->iLimit ) return; if( p->iLimit ) return;
/* /*
@ -1909,12 +1906,13 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
** no rows. ** no rows.
*/ */
sqlite3ExprCacheClear(pParse); sqlite3ExprCacheClear(pParse);
assert( p->pOffset==0 || p->pLimit!=0 ); if( pLimit ){
if( p->pLimit ){ assert( pLimit->op==TK_LIMIT );
assert( pLimit->pLeft!=0 );
p->iLimit = iLimit = ++pParse->nMem; p->iLimit = iLimit = ++pParse->nMem;
v = sqlite3GetVdbe(pParse); v = sqlite3GetVdbe(pParse);
assert( v!=0 ); assert( v!=0 );
if( sqlite3ExprIsInteger(p->pLimit, &n) ){ if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
VdbeComment((v, "LIMIT counter")); VdbeComment((v, "LIMIT counter"));
if( n==0 ){ if( n==0 ){
@ -1924,15 +1922,15 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
p->selFlags |= SF_FixedLimit; p->selFlags |= SF_FixedLimit;
} }
}else{ }else{
sqlite3ExprCode(pParse, p->pLimit, iLimit); sqlite3ExprCode(pParse, pLimit->pLeft, iLimit);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
VdbeComment((v, "LIMIT counter")); VdbeComment((v, "LIMIT counter"));
sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
} }
if( p->pOffset ){ if( pLimit->pRight ){
p->iOffset = iOffset = ++pParse->nMem; p->iOffset = iOffset = ++pParse->nMem;
pParse->nMem++; /* Allocate an extra register for limit+offset */ pParse->nMem++; /* Allocate an extra register for limit+offset */
sqlite3ExprCode(pParse, p->pOffset, iOffset); sqlite3ExprCode(pParse, pLimit->pRight, iOffset);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
VdbeComment((v, "OFFSET counter")); VdbeComment((v, "OFFSET counter"));
sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset);
@ -2062,7 +2060,7 @@ static void generateWithRecursiveQuery(
int i; /* Loop counter */ int i; /* Loop counter */
int rc; /* Result code */ int rc; /* Result code */
ExprList *pOrderBy; /* The ORDER BY clause */ ExprList *pOrderBy; /* The ORDER BY clause */
Expr *pLimit, *pOffset; /* Saved LIMIT and OFFSET */ Expr *pLimit; /* Saved LIMIT and OFFSET */
int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */ int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */
/* Obtain authorization to do a recursive query */ /* Obtain authorization to do a recursive query */
@ -2073,10 +2071,9 @@ static void generateWithRecursiveQuery(
p->nSelectRow = 320; /* 4 billion rows */ p->nSelectRow = 320; /* 4 billion rows */
computeLimitRegisters(pParse, p, addrBreak); computeLimitRegisters(pParse, p, addrBreak);
pLimit = p->pLimit; pLimit = p->pLimit;
pOffset = p->pOffset;
regLimit = p->iLimit; regLimit = p->iLimit;
regOffset = p->iOffset; regOffset = p->iOffset;
p->pLimit = p->pOffset = 0; p->pLimit = 0;
p->iLimit = p->iOffset = 0; p->iLimit = p->iOffset = 0;
pOrderBy = p->pOrderBy; pOrderBy = p->pOrderBy;
@ -2169,7 +2166,6 @@ end_of_recursive_query:
sqlite3ExprListDelete(pParse->db, p->pOrderBy); sqlite3ExprListDelete(pParse->db, p->pOrderBy);
p->pOrderBy = pOrderBy; p->pOrderBy = pOrderBy;
p->pLimit = pLimit; p->pLimit = pLimit;
p->pOffset = pOffset;
return; return;
} }
#endif /* SQLITE_OMIT_CTE */ #endif /* SQLITE_OMIT_CTE */
@ -2205,7 +2201,6 @@ static int multiSelectValues(
assert( p->selFlags & SF_Values ); assert( p->selFlags & SF_Values );
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
assert( p->pLimit==0 ); assert( p->pLimit==0 );
assert( p->pOffset==0 );
assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr ); assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
if( p->pPrior==0 ) break; if( p->pPrior==0 ) break;
assert( p->pPrior->pNext==p ); assert( p->pPrior->pNext==p );
@ -2332,11 +2327,9 @@ static int multiSelect(
pPrior->iLimit = p->iLimit; pPrior->iLimit = p->iLimit;
pPrior->iOffset = p->iOffset; pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit; pPrior->pLimit = p->pLimit;
pPrior->pOffset = p->pOffset;
explainSetInteger(iSub1, pParse->iNextSelectId); explainSetInteger(iSub1, pParse->iNextSelectId);
rc = sqlite3Select(pParse, pPrior, &dest); rc = sqlite3Select(pParse, pPrior, &dest);
p->pLimit = 0; p->pLimit = 0;
p->pOffset = 0;
if( rc ){ if( rc ){
goto multi_select_end; goto multi_select_end;
} }
@ -2358,7 +2351,7 @@ static int multiSelect(
p->pPrior = pPrior; p->pPrior = pPrior;
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
if( pPrior->pLimit if( pPrior->pLimit
&& sqlite3ExprIsInteger(pPrior->pLimit, &nLimit) && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
){ ){
p->nSelectRow = sqlite3LogEst((u64)nLimit); p->nSelectRow = sqlite3LogEst((u64)nLimit);
@ -2373,7 +2366,7 @@ static int multiSelect(
int unionTab; /* Cursor number of the temporary table holding result */ int unionTab; /* Cursor number of the temporary table holding result */
u8 op = 0; /* One of the SRT_ operations to apply to self */ u8 op = 0; /* One of the SRT_ operations to apply to self */
int priorOp; /* The SRT_ operation to apply to prior selects */ int priorOp; /* The SRT_ operation to apply to prior selects */
Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ Expr *pLimit; /* Saved values of p->nLimit */
int addr; int addr;
SelectDest uniondest; SelectDest uniondest;
@ -2385,7 +2378,6 @@ static int multiSelect(
** right. ** right.
*/ */
assert( p->pLimit==0 ); /* Not allowed on leftward elements */ assert( p->pLimit==0 ); /* Not allowed on leftward elements */
assert( p->pOffset==0 ); /* Not allowed on leftward elements */
unionTab = dest.iSDParm; unionTab = dest.iSDParm;
}else{ }else{
/* We will need to create our own temporary table to hold the /* We will need to create our own temporary table to hold the
@ -2421,8 +2413,6 @@ static int multiSelect(
p->pPrior = 0; p->pPrior = 0;
pLimit = p->pLimit; pLimit = p->pLimit;
p->pLimit = 0; p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
uniondest.eDest = op; uniondest.eDest = op;
explainSetInteger(iSub2, pParse->iNextSelectId); explainSetInteger(iSub2, pParse->iNextSelectId);
rc = sqlite3Select(pParse, p, &uniondest); rc = sqlite3Select(pParse, p, &uniondest);
@ -2438,7 +2428,6 @@ static int multiSelect(
} }
sqlite3ExprDelete(db, p->pLimit); sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit; p->pLimit = pLimit;
p->pOffset = pOffset;
p->iLimit = 0; p->iLimit = 0;
p->iOffset = 0; p->iOffset = 0;
@ -2466,7 +2455,7 @@ static int multiSelect(
default: assert( p->op==TK_INTERSECT ); { default: assert( p->op==TK_INTERSECT ); {
int tab1, tab2; int tab1, tab2;
int iCont, iBreak, iStart; int iCont, iBreak, iStart;
Expr *pLimit, *pOffset; Expr *pLimit;
int addr; int addr;
SelectDest intersectdest; SelectDest intersectdest;
int r1; int r1;
@ -2502,8 +2491,6 @@ static int multiSelect(
p->pPrior = 0; p->pPrior = 0;
pLimit = p->pLimit; pLimit = p->pLimit;
p->pLimit = 0; p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
intersectdest.iSDParm = tab2; intersectdest.iSDParm = tab2;
explainSetInteger(iSub2, pParse->iNextSelectId); explainSetInteger(iSub2, pParse->iNextSelectId);
rc = sqlite3Select(pParse, p, &intersectdest); rc = sqlite3Select(pParse, p, &intersectdest);
@ -2513,7 +2500,6 @@ static int multiSelect(
if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
sqlite3ExprDelete(db, p->pLimit); sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit; p->pLimit = pLimit;
p->pOffset = pOffset;
/* Generate code to take the intersection of the two temporary /* Generate code to take the intersection of the two temporary
** tables. ** tables.
@ -2992,8 +2978,6 @@ static int multiSelectOrderBy(
} }
sqlite3ExprDelete(db, p->pLimit); sqlite3ExprDelete(db, p->pLimit);
p->pLimit = 0; p->pLimit = 0;
sqlite3ExprDelete(db, p->pOffset);
p->pOffset = 0;
regAddrA = ++pParse->nMem; regAddrA = ++pParse->nMem;
regAddrB = ++pParse->nMem; regAddrB = ++pParse->nMem;
@ -3457,7 +3441,7 @@ static int flattenSubquery(
** became arbitrary expressions, we were forced to add restrictions (13) ** became arbitrary expressions, we were forced to add restrictions (13)
** and (14). */ ** and (14). */
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
if( pSub->pOffset ) return 0; /* Restriction (14) */ if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */
if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){ if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
return 0; /* Restriction (15) */ return 0; /* Restriction (15) */
} }
@ -3605,16 +3589,13 @@ static int flattenSubquery(
Select *pNew; Select *pNew;
ExprList *pOrderBy = p->pOrderBy; ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit; Expr *pLimit = p->pLimit;
Expr *pOffset = p->pOffset;
Select *pPrior = p->pPrior; Select *pPrior = p->pPrior;
p->pOrderBy = 0; p->pOrderBy = 0;
p->pSrc = 0; p->pSrc = 0;
p->pPrior = 0; p->pPrior = 0;
p->pLimit = 0; p->pLimit = 0;
p->pOffset = 0;
pNew = sqlite3SelectDup(db, p, 0); pNew = sqlite3SelectDup(db, p, 0);
sqlite3SelectSetName(pNew, pSub->zSelName); sqlite3SelectSetName(pNew, pSub->zSelName);
p->pOffset = pOffset;
p->pLimit = pLimit; p->pLimit = pLimit;
p->pOrderBy = pOrderBy; p->pOrderBy = pOrderBy;
p->pSrc = pSrc; p->pSrc = pSrc;
@ -4080,7 +4061,6 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
assert( pNew->pPrior!=0 ); assert( pNew->pPrior!=0 );
pNew->pPrior->pNext = pNew; pNew->pPrior->pNext = pNew;
pNew->pLimit = 0; pNew->pLimit = 0;
pNew->pOffset = 0;
return WRC_Continue; return WRC_Continue;
} }

View File

@ -2749,7 +2749,6 @@ struct Select {
Select *pPrior; /* Prior select in a compound select statement */ Select *pPrior; /* Prior select in a compound select statement */
Select *pNext; /* Next select to the left in a compound */ Select *pNext; /* Next select to the left in a compound */
Expr *pLimit; /* LIMIT expression. NULL means not used. */ Expr *pLimit; /* LIMIT expression. NULL means not used. */
Expr *pOffset; /* OFFSET expression. NULL means not used. */
With *pWith; /* WITH clause attached to this select. Or NULL. */ With *pWith; /* WITH clause attached to this select. Or NULL. */
}; };
@ -3756,16 +3755,16 @@ void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
void sqlite3DropIndex(Parse*, SrcList*, int); void sqlite3DropIndex(Parse*, SrcList*, int);
int sqlite3Select(Parse*, Select*, SelectDest*); int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*,Expr*); Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*); void sqlite3SelectDelete(sqlite3*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*); Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int); int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif #endif
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*, Expr*); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*);
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
void sqlite3WhereEnd(WhereInfo*); void sqlite3WhereEnd(WhereInfo*);
LogEst sqlite3WhereOutputRowCount(WhereInfo*); LogEst sqlite3WhereOutputRowCount(WhereInfo*);
@ -3889,7 +3888,7 @@ int sqlite3SafetyCheckSickOrOk(sqlite3*);
void sqlite3ChangeCookie(Parse*, int); void sqlite3ChangeCookie(Parse*, int);
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,Expr*,int); void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
#endif #endif
#ifndef SQLITE_OMIT_TRIGGER #ifndef SQLITE_OMIT_TRIGGER

View File

@ -153,7 +153,6 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
if( p->pHaving ) n++; if( p->pHaving ) n++;
if( p->pOrderBy ) n++; if( p->pOrderBy ) n++;
if( p->pLimit ) n++; if( p->pLimit ) n++;
if( p->pOffset ) n++;
} }
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){ if( p->pSrc && p->pSrc->nSrc ){
@ -210,12 +209,12 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
} }
if( p->pLimit ){ if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit, 0); sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
if( p->pLimit->pRight ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
sqlite3TreeViewPop(pView); sqlite3TreeViewPop(pView);
} }
if( p->pOffset ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pOffset, 0);
sqlite3TreeViewPop(pView); sqlite3TreeViewPop(pView);
} }
if( p->pPrior ){ if( p->pPrior ){

View File

@ -711,7 +711,7 @@ static int codeTriggerProgram(
targetSrcList(pParse, pStep), targetSrcList(pParse, pStep),
sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprListDup(db, pStep->pExprList, 0),
sqlite3ExprDup(db, pStep->pWhere, 0), sqlite3ExprDup(db, pStep->pWhere, 0),
pParse->eOrconf, 0, 0, 0 pParse->eOrconf, 0, 0
); );
break; break;
} }
@ -727,7 +727,7 @@ static int codeTriggerProgram(
case TK_DELETE: { case TK_DELETE: {
sqlite3DeleteFrom(pParse, sqlite3DeleteFrom(pParse,
targetSrcList(pParse, pStep), targetSrcList(pParse, pStep),
sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0, 0 sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
); );
break; break;
} }

View File

@ -93,8 +93,7 @@ void sqlite3Update(
Expr *pWhere, /* The WHERE clause. May be null */ Expr *pWhere, /* The WHERE clause. May be null */
int onError, /* How to handle constraint errors */ int onError, /* How to handle constraint errors */
ExprList *pOrderBy, /* ORDER BY clause. May be null */ ExprList *pOrderBy, /* ORDER BY clause. May be null */
Expr *pLimit, /* LIMIT clause. May be null */ Expr *pLimit /* LIMIT clause. May be null */
Expr *pOffset /* OFFSET clause. May be null */
){ ){
int i, j; /* Loop counters */ int i, j; /* Loop counters */
Table *pTab; /* The table to be updated */ Table *pTab; /* The table to be updated */
@ -182,10 +181,10 @@ void sqlite3Update(
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT #ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView ){ if( !isView ){
pWhere = sqlite3LimitWhere( pWhere = sqlite3LimitWhere(
pParse, pTabList, pWhere, pOrderBy, pLimit, pOffset, "UPDATE" pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE"
); );
pOrderBy = 0; pOrderBy = 0;
pLimit = pOffset = 0; pLimit = 0;
} }
#endif #endif
@ -358,10 +357,10 @@ void sqlite3Update(
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){ if( isView ){
sqlite3MaterializeView(pParse, pTab, sqlite3MaterializeView(pParse, pTab,
pWhere, pOrderBy, pLimit, pOffset, iDataCur pWhere, pOrderBy, pLimit, iDataCur
); );
pOrderBy = 0; pOrderBy = 0;
pLimit = pOffset = 0; pLimit = 0;
} }
#endif #endif
@ -748,7 +747,6 @@ update_cleanup:
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
sqlite3ExprListDelete(db, pOrderBy); sqlite3ExprListDelete(db, pOrderBy);
sqlite3ExprDelete(db, pLimit); sqlite3ExprDelete(db, pLimit);
sqlite3ExprDelete(db, pOffset);
#endif #endif
return; return;
} }

View File

@ -91,7 +91,6 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort; if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort; if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort; if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
return WRC_Continue; return WRC_Continue;
} }