Compare commits
8 Commits
patch
...
expr-simplify
| Author | SHA1 | Date | |
|---|---|---|---|
| 8477f7f79c | |||
| ee9d4d7fed | |||
| 53872e7259 | |||
| 3d6bedf14f | |||
| 12b0fabde2 | |||
| 3b3c86ade2 | |||
| 110e3afd11 | |||
| 35284b6c48 |
@@ -1,5 +1,5 @@
|
||||
C Avoid\sincrementing\sthe\sSQLITE_LOOKASIDE_MISS_SIZE\sstat\sbefore\ssqlite3_open()\nreturns.\sFix\stest\sscript\sproblem\sin\slookaside.test.
|
||||
D 2018-09-18T17:50:34.415
|
||||
C Reduce\sthe\ssize\sof\sExpr\sto\s64-bytes.\s\sThis\sworks\ssomewhat,\sbut\sthere\sare\ntest\sfailures.\s\sMore\simportantly,\sthe\ssize\sreduction\sfrom\s80-\sto\s64-bytes\shas\nnot\slowered\sthe\sschema\smemory\susage,\sbut\sit\shas\smade\sthe\scode\sa\slittle\sbigger\nand\sa\slittle\sslower.\s\sSo\sthe\sinitial\sevidence\sis\sthat\sthis\sExpr\srefactoring\nexperiment\sis\snot\sworking...
|
||||
D 2018-09-19T20:14:48.730
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334
|
||||
@@ -436,9 +436,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 2269dd2f37ba963fde4c51e9e83542f126c86a8e10357c17f48137c6bee5299b
|
||||
F src/alter.c 3a859149c15cc78a446e0d632a1a9d24786e230ed1de53d8b88ca2c96f90ace0
|
||||
F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
|
||||
F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a
|
||||
F src/attach.c d06bf7ab9efceb7c679ba8beaeeb3082ce3defde482f54de50ac175469f7c4ca
|
||||
F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114
|
||||
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
@@ -453,11 +453,11 @@ F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387
|
||||
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
|
||||
F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
|
||||
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
|
||||
F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2
|
||||
F src/expr.c 92dc4e104b06d06ffeacbd1a4dc0a520daf37f6156278fb6ece5e90e2ca6b610
|
||||
F src/delete.c 07a7ecf18a64478be7241cbb332bc26321586384c750e47fb566f678c5aee512
|
||||
F src/expr.c 5814b4b5d4b9e615faba427a554de5152c972cc0132f6968a13250c07b709372
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
|
||||
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
|
||||
F src/fkey.c 234d4e9fb2a35a11d6ee831dbc19e74fb8bfaf5e09b310ce3cffbf37d6eb57e0
|
||||
F src/func.c 82aeef69505b67197a476836d44cc16c1a434ee53481f23cffb70a75a1bcbc7a
|
||||
F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
|
||||
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
@@ -491,7 +491,7 @@ F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b
|
||||
F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963
|
||||
F src/parse.y 4118dbf9c37c410e5c4775c033b1aaf67ac8ff7965df7a4bb429dd5db2dbe374
|
||||
F src/parse.y 96a86b76766af46ac9e64afc1576ea7cb0f7219d2f3a7b6c03bb07043017bdf5
|
||||
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
|
||||
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
||||
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
||||
@@ -500,14 +500,14 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
|
||||
F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097
|
||||
F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b
|
||||
F src/resolve.c adfb08e3e31243433ed60613bd244ba0bef63c80ca0f2fee754db02a831b5811
|
||||
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
|
||||
F src/select.c 8afcc2b56a6ef76717bb59b6109cd3de0f6fae2803894d6f806640c0aa24dfac
|
||||
F src/select.c 6bacf10a3a65b692586e80ffda8114ce485d47b0bc1fe18a001f39c5c054db81
|
||||
F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f
|
||||
F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63
|
||||
F src/sqliteInt.h 83ee9b55db521b70294b2858872e69b96d0a4810d8221796def3e99cca5ee663
|
||||
F src/sqliteInt.h 5cf4c8f1687b8a2042da2259ee8a5a14bf8aa7914a124afa2010afd2c759ccb2
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
@@ -566,7 +566,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b
|
||||
F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f
|
||||
F src/treeview.c 1bc9fc4ebd661bea19b4f39dd32f34b609faf2250112d83d7ffa40ab1c3b386b
|
||||
F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
|
||||
F src/update.c 682f112c49247d2fe5950c9fe2226046c6bc497cf114f74d58766926914216ff
|
||||
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
|
||||
@@ -577,20 +577,20 @@ F src/vdbe.c 80603eb66708c2f27879912a4e9456900e66491c3409ca5e392109114e8f6337
|
||||
F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
|
||||
F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827
|
||||
F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611
|
||||
F src/vdbeaux.c c3c397274380f13db702baa3506ba87379446a4d71135a1177b624f73dd3c830
|
||||
F src/vdbeaux.c 43ee58196823e17093601388993bbea03456c6ffbbd83d516096af71346d93e3
|
||||
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
|
||||
F src/vdbemem.c 81329ab760e4ec0162119d9cd10193e0303c45c5935bb20c7ae9139d44dd6641
|
||||
F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
|
||||
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
|
||||
F src/vtab.c 8665561f244c137a2d17b5c3e5910d7303054fe841c5d510e53f23beb0089594
|
||||
F src/vtab.c 0d613164d56f43aca041de072ceba541f35fc29eeb7085e69f84829249d7fc46
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
|
||||
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
|
||||
F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4
|
||||
F src/where.c 2019126801437944c38cc62a99491e98591460b7cc07ab57eb66165f710a289b
|
||||
F src/walker.c 4ba292cadd145b8b77e8b2128a363beff0bd87c7f9abfe090c0948eb0330d727
|
||||
F src/where.c 33a546a918b0439e3e174351ca00c9158f26d73c5a8bb54c6c3cf5bae20b7499
|
||||
F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
|
||||
F src/wherecode.c 4f88f5b39ad4aeb5bdd47a546d74149bb902ef49ca9f02a45b2a5bd2dd70b6bd
|
||||
F src/whereexpr.c eb462ebe085f6cbb6bdda797a041fbd7e3724586203344043d1088a2117d8e44
|
||||
F src/wherecode.c ab5992174e31e30f4624fbd57ddffce63db69c861c09811871e0cbab739a2a91
|
||||
F src/whereexpr.c c88f2047c493c36a11116b524c0c9b621253f512930386e81ea96309d7740fd6
|
||||
F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
@@ -665,7 +665,7 @@ F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a
|
||||
F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
|
||||
F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e
|
||||
F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455
|
||||
F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b
|
||||
F test/bestindex5.test 0b61fc294997a6b5f869a9f7e111a64c0437b5cef2f6a3d1fb2bba4af6f7c1b0
|
||||
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
|
||||
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
@@ -1767,7 +1767,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P de2e3cbd08c00d235106c040fa472ec267ef8f1ec13c34ed7d16deac8d50b6cc
|
||||
R 87b8b2ee28b1a1a8366c364e4fdd6314
|
||||
U dan
|
||||
Z 971302d914167dfdeae1d53b5caa351e
|
||||
P 8487f84af00a8afde4ae24c4925e0f8ac9f38e86ea8b453dccedb3ee10f7f667
|
||||
R dc50e2519bfa1235f8e5a29ec2577516
|
||||
U drh
|
||||
Z a9cd90cadb1b1e1e79d944ecc746eecf
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
e461cb281959d8517296e3e4e934eba8206770b1a592cd7655b6567268da1634
|
||||
24b0f66ac611e26f55ffeaff459b0d7ab53e6fa8d72765bea77c3b50634357e8
|
||||
+7
-3
@@ -803,7 +803,8 @@ static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
|
||||
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
|
||||
}else if( pExpr->op==TK_COLUMN
|
||||
&& pExpr->iColumn==p->iCol
|
||||
&& p->pTab==pExpr->pTab
|
||||
&& ALWAYS(pExpr->eX==EX_Tab)
|
||||
&& p->pTab==pExpr->x.pTab
|
||||
){
|
||||
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
|
||||
}
|
||||
@@ -1341,8 +1342,11 @@ renameColumnFunc_done:
|
||||
*/
|
||||
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
|
||||
RenameCtx *p = pWalker->u.pRename;
|
||||
if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){
|
||||
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab);
|
||||
if( pExpr->op==TK_COLUMN
|
||||
&& ALWAYS(pExpr->eX==EX_Tab)
|
||||
&& p->pTab==pExpr->x.pTab
|
||||
){
|
||||
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->x.pTab);
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
+13
-7
@@ -564,13 +564,19 @@ int sqlite3FixExpr(
|
||||
}
|
||||
}
|
||||
if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
|
||||
}else{
|
||||
if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
|
||||
}
|
||||
if( sqlite3FixExpr(pFix, pExpr->pRight) ){
|
||||
return 1;
|
||||
switch( pExpr->eX ){
|
||||
case EX_Select: {
|
||||
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
|
||||
break;
|
||||
}
|
||||
case EX_Right: {
|
||||
if( sqlite3FixExpr(pFix, pExpr->x.pRight) ) return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pExpr = pExpr->pLeft;
|
||||
}
|
||||
|
||||
+1
-3
@@ -185,9 +185,7 @@ Expr *sqlite3LimitWhere(
|
||||
pEList = sqlite3ExprListAppend(pParse, pEList, p);
|
||||
}
|
||||
pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
|
||||
if( pLhs ){
|
||||
pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
|
||||
}
|
||||
sqlite3PExprAddExprList(pParse, pLhs, pEList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+241
-111
@@ -48,7 +48,7 @@ char sqlite3ExprAffinity(Expr *pExpr){
|
||||
if( pExpr->flags & EP_Generic ) return 0;
|
||||
op = pExpr->op;
|
||||
if( op==TK_SELECT ){
|
||||
assert( pExpr->flags&EP_xIsSelect );
|
||||
assert( pExpr->eX==EX_Select );
|
||||
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
|
||||
}
|
||||
if( op==TK_REGISTER ) op = pExpr->op2;
|
||||
@@ -58,11 +58,12 @@ char sqlite3ExprAffinity(Expr *pExpr){
|
||||
return sqlite3AffinityType(pExpr->u.zToken, 0);
|
||||
}
|
||||
#endif
|
||||
if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
|
||||
return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
|
||||
if( (op==TK_AGG_COLUMN || op==TK_COLUMN)
|
||||
&& ALWAYS(pExpr->eX==EX_Tab) && pExpr->x.pTab ){
|
||||
return sqlite3TableColumnAffinity(pExpr->x.pTab, pExpr->iColumn);
|
||||
}
|
||||
if( op==TK_SELECT_COLUMN ){
|
||||
assert( pExpr->pLeft->flags&EP_xIsSelect );
|
||||
assert( pExpr->pLeft->eX==EX_Select );
|
||||
return sqlite3ExprAffinity(
|
||||
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
|
||||
);
|
||||
@@ -108,7 +109,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
|
||||
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
|
||||
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
|
||||
if( ExprHasProperty(pExpr, EP_Unlikely) ){
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->eX==EX_List );
|
||||
assert( pExpr->x.pList->nExpr>0 );
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
pExpr = pExpr->x.pList->a[0].pExpr;
|
||||
@@ -143,13 +144,14 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
||||
if( p->flags & EP_Generic ) break;
|
||||
if( (op==TK_AGG_COLUMN || op==TK_COLUMN
|
||||
|| op==TK_REGISTER || op==TK_TRIGGER)
|
||||
&& p->pTab!=0
|
||||
&& p->eX==EX_Tab
|
||||
&& p->x.pTab!=0
|
||||
){
|
||||
/* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
|
||||
** a TK_COLUMN but was previously evaluated and cached in a register */
|
||||
int j = p->iColumn;
|
||||
if( j>=0 ){
|
||||
const char *zColl = p->pTab->aCol[j].zColl;
|
||||
const char *zColl = p->x.pTab->aCol[j].zColl;
|
||||
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
|
||||
}
|
||||
break;
|
||||
@@ -166,13 +168,11 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
||||
if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
|
||||
p = p->pLeft;
|
||||
}else{
|
||||
Expr *pNext = p->pRight;
|
||||
/* The Expr.x union is never used at the same time as Expr.pRight */
|
||||
assert( p->x.pList==0 || p->pRight==0 );
|
||||
Expr *pNext = 0;
|
||||
/* p->flags holds EP_Collate and p->pLeft->flags does not. And
|
||||
** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at
|
||||
** least one EP_Collate. Thus the following two ALWAYS. */
|
||||
if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
|
||||
if( p->eX==EX_List ){
|
||||
int i;
|
||||
for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
|
||||
if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
|
||||
@@ -180,6 +180,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else if( p->eX==EX_Right ){
|
||||
pNext = p->x.pRight;
|
||||
}
|
||||
p = pNext;
|
||||
}
|
||||
@@ -258,9 +260,9 @@ static char comparisonAffinity(Expr *pExpr){
|
||||
pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
|
||||
assert( pExpr->pLeft );
|
||||
aff = sqlite3ExprAffinity(pExpr->pLeft);
|
||||
if( pExpr->pRight ){
|
||||
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
|
||||
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( pExpr->eX==EX_Right ){
|
||||
aff = sqlite3CompareAffinity(pExpr->x.pRight, aff);
|
||||
}else if( pExpr->eX==EX_Select ){
|
||||
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
|
||||
}else if( aff==0 ){
|
||||
aff = SQLITE_AFF_BLOB;
|
||||
@@ -307,8 +309,12 @@ static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
|
||||
**
|
||||
** Argument pRight (but not pLeft) may be a null pointer. In this case,
|
||||
** it is not considered.
|
||||
**
|
||||
** The second form (sqlite3BinaryExprCollSeq()) uses the Expr.pLeft
|
||||
** and Expr.x.pRight pointer from the second argument instead of separate
|
||||
** pointers.
|
||||
*/
|
||||
CollSeq *sqlite3BinaryCompareCollSeq(
|
||||
CollSeq *sqlite3ComparisonCollSeq(
|
||||
Parse *pParse,
|
||||
Expr *pLeft,
|
||||
Expr *pRight
|
||||
@@ -327,6 +333,13 @@ CollSeq *sqlite3BinaryCompareCollSeq(
|
||||
}
|
||||
return pColl;
|
||||
}
|
||||
CollSeq *sqlite3ComparisonExprCollSeq(Parse *pParse, Expr *pExpr){
|
||||
if( pExpr->eX==EX_Right ){
|
||||
return sqlite3ComparisonCollSeq(pParse, pExpr->pLeft, pExpr->x.pRight);
|
||||
}else{
|
||||
return sqlite3ComparisonCollSeq(pParse, pExpr->pLeft, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for a comparison operator.
|
||||
@@ -344,7 +357,7 @@ static int codeCompare(
|
||||
int addr;
|
||||
CollSeq *p4;
|
||||
|
||||
p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
|
||||
p4 = sqlite3ComparisonCollSeq(pParse, pLeft, pRight);
|
||||
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
|
||||
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
|
||||
(void*)p4, P4_COLLSEQ);
|
||||
@@ -439,7 +452,7 @@ Expr *sqlite3ExprForVectorField(
|
||||
){
|
||||
Expr *pRet;
|
||||
if( pVector->op==TK_SELECT ){
|
||||
assert( pVector->flags & EP_xIsSelect );
|
||||
assert( pVector->eX==EX_Select );
|
||||
/* The TK_SELECT_COLUMN Expr node:
|
||||
**
|
||||
** pLeft: pVector containing TK_SELECT. Not deleted.
|
||||
@@ -547,7 +560,7 @@ static void codeVectorCompare(
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
Expr *pRight = pExpr->pRight;
|
||||
Expr *pRight = pExpr->x.pRight;
|
||||
int nLeft = sqlite3ExprVectorSize(pLeft);
|
||||
int i;
|
||||
int regLeft = 0;
|
||||
@@ -681,12 +694,20 @@ static void heightOfSelect(Select *pSelect, int *pnHeight){
|
||||
static void exprSetHeight(Expr *p){
|
||||
int nHeight = 0;
|
||||
heightOfExpr(p->pLeft, &nHeight);
|
||||
heightOfExpr(p->pRight, &nHeight);
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
heightOfSelect(p->x.pSelect, &nHeight);
|
||||
}else if( p->x.pList ){
|
||||
heightOfExprList(p->x.pList, &nHeight);
|
||||
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
|
||||
switch( p->eX ){
|
||||
case EX_Select: {
|
||||
heightOfSelect(p->x.pSelect, &nHeight);
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
heightOfExprList(p->x.pList, &nHeight);
|
||||
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
|
||||
break;
|
||||
}
|
||||
case EX_Right: {
|
||||
heightOfExpr(p->x.pRight, &nHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
p->nHeight = nHeight + 1;
|
||||
}
|
||||
@@ -700,7 +721,7 @@ static void exprSetHeight(Expr *p){
|
||||
** Expr.flags.
|
||||
*/
|
||||
void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
|
||||
if( pParse->nErr ) return;
|
||||
if( p==0 || pParse->nErr ) return;
|
||||
exprSetHeight(p);
|
||||
sqlite3ExprCheckHeight(pParse, p->nHeight);
|
||||
}
|
||||
@@ -720,7 +741,7 @@ int sqlite3SelectExprHeight(Select *p){
|
||||
** Expr.flags.
|
||||
*/
|
||||
void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
|
||||
if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
|
||||
if( p && p->eX==EX_List ){
|
||||
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
|
||||
}
|
||||
}
|
||||
@@ -825,7 +846,9 @@ void sqlite3ExprAttachSubtrees(
|
||||
sqlite3ExprDelete(db, pRight);
|
||||
}else{
|
||||
if( pRight ){
|
||||
pRoot->pRight = pRight;
|
||||
assert( pRoot->eX==EX_None );
|
||||
pRoot->x.pRight = pRight;
|
||||
pRoot->eX = EX_Right;
|
||||
pRoot->flags |= EP_Propagate & pRight->flags;
|
||||
}
|
||||
if( pLeft ){
|
||||
@@ -873,9 +896,11 @@ Expr *sqlite3PExpr(
|
||||
** do a memory allocation failure) then delete the pSelect object.
|
||||
*/
|
||||
void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
|
||||
if( pExpr ){
|
||||
if( pExpr && pSelect ){
|
||||
assert( pExpr->eX==EX_None );
|
||||
pExpr->eX = EX_Select;
|
||||
pExpr->x.pSelect = pSelect;
|
||||
ExprSetProperty(pExpr, EP_xIsSelect|EP_Subquery);
|
||||
ExprSetProperty(pExpr, EP_Subquery);
|
||||
sqlite3ExprSetHeightAndFlags(pParse, pExpr);
|
||||
}else{
|
||||
assert( pParse->db->mallocFailed );
|
||||
@@ -883,6 +908,22 @@ void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Add ExprList to the Expr.x.pList field. Or, if pExpr is NULL (due
|
||||
** do a memory allocation failure) then delete the pSelect object.
|
||||
*/
|
||||
void sqlite3PExprAddExprList(Parse *pParse, Expr *pExpr, ExprList *pList){
|
||||
if( pExpr && pList ){
|
||||
assert( pExpr->eX==EX_None );
|
||||
pExpr->eX = EX_List;
|
||||
pExpr->x.pList = pList;
|
||||
/* sqlite3ExprSetHeightAndFlags(pParse, pExpr); // done by caller */
|
||||
}else{
|
||||
assert( pParse->db->mallocFailed );
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** If the expression is always either TRUE or FALSE (respectively),
|
||||
@@ -956,9 +997,12 @@ Expr *sqlite3ExprFunction(
|
||||
if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
|
||||
sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
|
||||
}
|
||||
pNew->x.pList = pList;
|
||||
assert( pNew->eX==EX_None );
|
||||
if( pList ){
|
||||
pNew->eX = EX_List;
|
||||
pNew->x.pList = pList;
|
||||
}
|
||||
ExprSetProperty(pNew, EP_HasFunc);
|
||||
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
|
||||
sqlite3ExprSetHeightAndFlags(pParse, pNew);
|
||||
if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct);
|
||||
return pNew;
|
||||
@@ -1052,23 +1096,36 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
|
||||
assert( p!=0 );
|
||||
/* Sanity check: Assert that the IntValue is non-negative if it exists */
|
||||
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
|
||||
assert( p->eX!=EX_Select || p->x.pSelect!=0 );
|
||||
assert( p->eX!=EX_List || p->x.pList!=0 );
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
|
||||
assert( p->pLeft==0 );
|
||||
assert( p->pRight==0 );
|
||||
assert( p->x.pSelect==0 );
|
||||
assert( p->eX==EX_None || p->eX==EX_Tab );
|
||||
}
|
||||
if( !ExprHasProperty(p, EP_TokenOnly) ){
|
||||
assert( p->op!=TK_FUNCTION || p->pLeft==0 );
|
||||
}
|
||||
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Reduced)) ){
|
||||
assert( p->pWin==0 || p->pLeft==0 );
|
||||
assert( p->pWin==0 || p->op==TK_FUNCTION );
|
||||
}
|
||||
#endif
|
||||
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
|
||||
/* The Expr.x union is never used at the same time as Expr.pRight */
|
||||
assert( p->x.pList==0 || p->pRight==0 );
|
||||
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
|
||||
if( p->pRight ){
|
||||
sqlite3ExprDeleteNN(db, p->pRight);
|
||||
}else if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
sqlite3SelectDelete(db, p->x.pSelect);
|
||||
}else{
|
||||
sqlite3ExprListDelete(db, p->x.pList);
|
||||
switch( p->eX ){
|
||||
case EX_Select: {
|
||||
sqlite3SelectDelete(db, p->x.pSelect);
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
sqlite3ExprListDelete(db, p->x.pList);
|
||||
break;
|
||||
}
|
||||
case EX_Right: {
|
||||
sqlite3ExprDelete(db, p->x.pRight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !ExprHasProperty(p, EP_Reduced) ){
|
||||
sqlite3WindowDelete(db, p->pWin);
|
||||
@@ -1083,6 +1140,29 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
|
||||
if( p ) sqlite3ExprDeleteNN(db, p);
|
||||
}
|
||||
|
||||
void sqlite3ExprClearXUnion(sqlite3 *db, Expr *p){
|
||||
switch( p->eX ){
|
||||
case EX_Select: {
|
||||
sqlite3SelectDelete(db, p->x.pSelect);
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
sqlite3ExprListDelete(db, p->x.pList);
|
||||
break;
|
||||
}
|
||||
case EX_Right: {
|
||||
sqlite3ExprDelete(db, p->x.pRight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
p->eX = EX_None;
|
||||
}
|
||||
void sqlite3ExprAddTab(sqlite3 *db, Expr *pExpr, Table *pTab){
|
||||
sqlite3ExprClearXUnion(db, pExpr);
|
||||
pExpr->eX = EX_Tab;
|
||||
pExpr->x.pTab = pTab;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of bytes allocated for the expression structure
|
||||
** passed as the first argument. This is always one of EXPR_FULLSIZE,
|
||||
@@ -1144,10 +1224,9 @@ static int dupedExprStructSize(Expr *p, int flags){
|
||||
assert( !ExprHasProperty(p, EP_FromJoin) );
|
||||
assert( !ExprHasProperty(p, EP_MemToken) );
|
||||
assert( !ExprHasProperty(p, EP_NoReduce) );
|
||||
if( p->pLeft || p->x.pList ){
|
||||
if( p->pLeft || p->eX!=EX_None ){
|
||||
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
|
||||
}else{
|
||||
assert( p->pRight==0 );
|
||||
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
|
||||
}
|
||||
}
|
||||
@@ -1185,7 +1264,8 @@ static int dupedExprSize(Expr *p, int flags){
|
||||
if( p ){
|
||||
nByte = dupedExprNodeSize(p, flags);
|
||||
if( flags&EXPRDUP_REDUCE ){
|
||||
nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags);
|
||||
nByte += dupedExprSize(p->pLeft, flags);
|
||||
if( p->eX==EX_Right ) nByte += dupedExprSize(p->x.pRight, flags);
|
||||
}
|
||||
}
|
||||
return nByte;
|
||||
@@ -1195,7 +1275,7 @@ static int dupedExprSize(Expr *p, int flags){
|
||||
** This function is similar to sqlite3ExprDup(), except that if pzBuffer
|
||||
** 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->u.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->x.pRight expressions,
|
||||
** if any. Before returning, *pzBuffer is set to the first byte past the
|
||||
** portion of the buffer copied into by this function.
|
||||
*/
|
||||
@@ -1248,6 +1328,8 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
|
||||
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
|
||||
pNew->flags |= staticFlag;
|
||||
assert( pNew->eX==p->eX );
|
||||
assert( pNew->eV==p->eV );
|
||||
|
||||
/* Copy the p->u.zToken string, if any. */
|
||||
if( nToken ){
|
||||
@@ -1257,21 +1339,31 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
|
||||
if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){
|
||||
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
|
||||
}else{
|
||||
pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags);
|
||||
switch( p->eX ){
|
||||
case EX_Select: {
|
||||
assert( pNew->eX==EX_Select );
|
||||
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
|
||||
if( pNew->x.pSelect==0 ) pNew->eX = EX_None;
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
assert( pNew->eX==EX_List );
|
||||
pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags);
|
||||
if( pNew->x.pList==0 ) pNew->eX = EX_None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in pNew->pLeft and pNew->pRight. */
|
||||
/* Fill in pNew->pLeft and pNew->x.pRight. */
|
||||
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
|
||||
zAlloc += dupedExprNodeSize(p, dupFlags);
|
||||
if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
|
||||
pNew->pLeft = p->pLeft ?
|
||||
exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
|
||||
pNew->pRight = p->pRight ?
|
||||
exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
|
||||
if( p->eX==EX_Right ){
|
||||
pNew->x.pRight = exprDup(db, p->x.pRight, EXPRDUP_REDUCE, &zAlloc);
|
||||
}
|
||||
}
|
||||
if( pzBuffer ){
|
||||
*pzBuffer = zAlloc;
|
||||
@@ -1287,12 +1379,15 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
|
||||
if( pNew->op==TK_SELECT_COLUMN ){
|
||||
pNew->pLeft = p->pLeft;
|
||||
assert( p->iColumn==0 || p->pRight==0 );
|
||||
assert( p->pRight==0 || p->pRight==p->pLeft );
|
||||
assert( p->iColumn==0 || p->eX!=EX_Right );
|
||||
/* OLD: assert( p->pRight==0 || p->x.pRight==p->pLeft ); */
|
||||
}else{
|
||||
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
|
||||
}
|
||||
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
|
||||
if( p->eX==EX_Right ){
|
||||
pNew->x.pRight = sqlite3ExprDup(db, p->x.pRight, 0);
|
||||
if( pNew->x.pRight==0 ) pNew->eX = EX_None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1369,8 +1464,8 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
|
||||
){
|
||||
assert( pNewExpr->iColumn==0 || i>0 );
|
||||
if( pNewExpr->iColumn==0 ){
|
||||
assert( pOldExpr->pLeft==pOldExpr->pRight );
|
||||
pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
|
||||
assert( pOldExpr->pLeft==pOldExpr->x.pRight );
|
||||
pPriorSelectCol = pNewExpr->pLeft = pNewExpr->x.pRight;
|
||||
}else{
|
||||
assert( i>0 );
|
||||
assert( pItem[-1].pExpr!=0 );
|
||||
@@ -1616,7 +1711,9 @@ ExprList *sqlite3ExprListAppendVector(
|
||||
|
||||
/* Store the SELECT statement in pRight so it will be deleted when
|
||||
** sqlite3ExprListDelete() is called */
|
||||
pFirst->pRight = pExpr;
|
||||
assert( pFirst->eX==EX_None );
|
||||
pFirst->x.pRight = pExpr;
|
||||
pFirst->eX = EX_Right;
|
||||
pExpr = 0;
|
||||
|
||||
/* Remember the size of the LHS in iTable so that we can check that
|
||||
@@ -1954,7 +2051,7 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
|
||||
/* Check if pExpr is a sub-select. If so, consider it variable. */
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( pExpr->eX==EX_Select ){
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
@@ -2088,9 +2185,10 @@ int sqlite3ExprCanBeNull(const Expr *p){
|
||||
case TK_BLOB:
|
||||
return 0;
|
||||
case TK_COLUMN:
|
||||
assert( p->eX==EX_Tab );
|
||||
return ExprHasProperty(p, EP_CanBeNull) ||
|
||||
p->pTab==0 || /* Reference to column of index on expression */
|
||||
(p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
|
||||
p->x.pTab==0 || /* Reference to column of index on expression */
|
||||
(p->iColumn>=0 && p->x.pTab->aCol[p->iColumn].notNull==0);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -2160,8 +2258,10 @@ static Select *isCandidateForInOpt(Expr *pX){
|
||||
ExprList *pEList;
|
||||
Table *pTab;
|
||||
int i;
|
||||
if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */
|
||||
if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */
|
||||
if( pX->eX!=EX_Select ) return 0; /* Not a subquery */
|
||||
if( ExprHasProperty(pX, EP_VarSelect) ){
|
||||
return 0; /* Correlated subq */
|
||||
}
|
||||
p = pX->x.pSelect;
|
||||
if( p->pPrior ) return 0; /* Not a compound SELECT */
|
||||
if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
|
||||
@@ -2219,7 +2319,7 @@ static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
|
||||
static int sqlite3InRhsIsConstant(Expr *pIn){
|
||||
Expr *pLHS;
|
||||
int res;
|
||||
assert( !ExprHasProperty(pIn, EP_xIsSelect) );
|
||||
assert( pIn->eX!=EX_Select );
|
||||
pLHS = pIn->pLeft;
|
||||
pIn->pLeft = 0;
|
||||
res = sqlite3ExprIsConstant(pIn);
|
||||
@@ -2330,7 +2430,7 @@ int sqlite3FindInIndex(
|
||||
** or not NULL is actually possible (it may not be, for example, due
|
||||
** to NOT NULL constraints in the schema). If no NULL values are possible,
|
||||
** set prRhsHasNull to 0 before continuing. */
|
||||
if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){
|
||||
if( prRhsHasNull && pX->eX==EX_Select ){
|
||||
int i;
|
||||
ExprList *pEList = pX->x.pSelect->pEList;
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
@@ -2426,7 +2526,7 @@ int sqlite3FindInIndex(
|
||||
for(i=0; i<nExpr; i++){
|
||||
Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
|
||||
Expr *pRhs = pEList->a[i].pExpr;
|
||||
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
|
||||
CollSeq *pReq = sqlite3ComparisonCollSeq(pParse, pLhs, pRhs);
|
||||
int j;
|
||||
|
||||
assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr );
|
||||
@@ -2483,8 +2583,8 @@ int sqlite3FindInIndex(
|
||||
** the IN operator so return IN_INDEX_NOOP.
|
||||
*/
|
||||
if( eType==0
|
||||
&& (inFlags & IN_INDEX_NOOP_OK)
|
||||
&& !ExprHasProperty(pX, EP_xIsSelect)
|
||||
&& (inFlags & IN_INDEX_NOOP_OK)!=0
|
||||
&& pX->eX==EX_List
|
||||
&& (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
|
||||
){
|
||||
eType = IN_INDEX_NOOP;
|
||||
@@ -2499,7 +2599,7 @@ int sqlite3FindInIndex(
|
||||
eType = IN_INDEX_EPH;
|
||||
if( inFlags & IN_INDEX_LOOP ){
|
||||
pParse->nQueryLoop = 0;
|
||||
if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
|
||||
if( pX->pLeft->iColumn<0 && pX->eX==EX_List ){
|
||||
eType = IN_INDEX_ROWID;
|
||||
}
|
||||
}else if( prRhsHasNull ){
|
||||
@@ -2532,7 +2632,7 @@ int sqlite3FindInIndex(
|
||||
static char *exprINAffinity(Parse *pParse, Expr *pExpr){
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
int nVal = sqlite3ExprVectorSize(pLeft);
|
||||
Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0;
|
||||
Select *pSelect = (pExpr->eX==EX_Select) ? pExpr->x.pSelect : 0;
|
||||
char *zRet;
|
||||
|
||||
assert( pExpr->op==TK_IN );
|
||||
@@ -2580,7 +2680,7 @@ void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){
|
||||
*/
|
||||
void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
if( pExpr->flags & EP_xIsSelect ){
|
||||
if( pExpr->eX==EX_Select ){
|
||||
sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
|
||||
}else
|
||||
#endif
|
||||
@@ -2672,7 +2772,8 @@ int sqlite3CodeSubselect(
|
||||
pExpr->iTable, (isRowid?0:nVal));
|
||||
pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
|
||||
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
assert( pExpr->eX==EX_Select || pExpr->eX==EX_List );
|
||||
if( pExpr->eX==EX_Select ){
|
||||
/* Case 1: expr IN (SELECT ...)
|
||||
**
|
||||
** Generate code to write the results of the select into the temporary
|
||||
@@ -2707,7 +2808,7 @@ int sqlite3CodeSubselect(
|
||||
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
|
||||
for(i=0; i<nVal; i++){
|
||||
Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
|
||||
pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
|
||||
pKeyInfo->aColl[i] = sqlite3ComparisonCollSeq(
|
||||
pParse, p, pEList->a[i].pExpr
|
||||
);
|
||||
}
|
||||
@@ -2801,7 +2902,7 @@ int sqlite3CodeSubselect(
|
||||
testcase( pExpr->op==TK_EXISTS );
|
||||
testcase( pExpr->op==TK_SELECT );
|
||||
assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
|
||||
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->eX==EX_Select );
|
||||
|
||||
pSel = pExpr->x.pSelect;
|
||||
ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY",
|
||||
@@ -2858,7 +2959,7 @@ int sqlite3CodeSubselect(
|
||||
*/
|
||||
int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
|
||||
int nVector = sqlite3ExprVectorSize(pIn->pLeft);
|
||||
if( (pIn->flags & EP_xIsSelect) ){
|
||||
if( pIn->eX==EX_Select ){
|
||||
if( nVector!=pIn->x.pSelect->pEList->nExpr ){
|
||||
sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
|
||||
return 1;
|
||||
@@ -2988,7 +3089,7 @@ static void sqlite3ExprCodeIN(
|
||||
int r2, regToFree;
|
||||
int regCkNull = 0;
|
||||
int ii;
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->eX==EX_List );
|
||||
if( destIfNull!=destIfFalse ){
|
||||
regCkNull = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
|
||||
@@ -3377,8 +3478,10 @@ expr_code_doover:
|
||||
** datatype by applying the Affinity of the table column to the
|
||||
** constant.
|
||||
*/
|
||||
int aff;
|
||||
int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
|
||||
int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
|
||||
assert( pExpr->eX==EX_Tab );
|
||||
aff = sqlite3TableColumnAffinity(pExpr->x.pTab, pExpr->iColumn);
|
||||
if( aff!=SQLITE_AFF_BLOB ){
|
||||
static const char zAff[] = "B\000C\000D\000E";
|
||||
assert( SQLITE_AFF_BLOB=='A' );
|
||||
@@ -3402,7 +3505,8 @@ expr_code_doover:
|
||||
iTab = pParse->iSelfTab - 1;
|
||||
}
|
||||
}
|
||||
return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
|
||||
assert( pExpr->eX==EX_Tab );
|
||||
return sqlite3ExprCodeGetColumn(pParse, pExpr->x.pTab,
|
||||
pExpr->iColumn, iTab, target,
|
||||
pExpr->op2);
|
||||
}
|
||||
@@ -3491,8 +3595,9 @@ expr_code_doover:
|
||||
codeVectorCompare(pParse, pExpr, target, op, p5);
|
||||
}else{
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pLeft, pExpr->pRight, op,
|
||||
assert( pExpr->eX==EX_Right );
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2);
|
||||
codeCompare(pParse, pLeft, pExpr->x.pRight, op,
|
||||
r1, r2, inReg, SQLITE_STOREP2 | p5);
|
||||
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
@@ -3529,7 +3634,8 @@ expr_code_doover:
|
||||
assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
|
||||
assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2);
|
||||
sqlite3VdbeAddOp3(v, op, r2, r1, target);
|
||||
testcase( regFree1==0 );
|
||||
testcase( regFree2==0 );
|
||||
@@ -3548,6 +3654,7 @@ expr_code_doover:
|
||||
return target;
|
||||
#endif
|
||||
}else{
|
||||
memset(&tempX, 0, sizeof(tempX));
|
||||
tempX.op = TK_INTEGER;
|
||||
tempX.flags = EP_IntValue|EP_TokenOnly;
|
||||
tempX.u.iValue = 0;
|
||||
@@ -3572,7 +3679,8 @@ expr_code_doover:
|
||||
int bNormal; /* IS TRUE or IS FALSE */
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
testcase( regFree1==0 );
|
||||
isTrue = sqlite3ExprTruthValue(pExpr->pRight);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
isTrue = sqlite3ExprTruthValue(pExpr->x.pRight);
|
||||
bNormal = pExpr->op2==TK_IS;
|
||||
testcase( isTrue && bNormal);
|
||||
testcase( !isTrue && bNormal);
|
||||
@@ -3626,7 +3734,7 @@ expr_code_doover:
|
||||
** out of the inner loop, even if that means an extra OP_Copy. */
|
||||
return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->eX==EX_List || pExpr->eX==EX_None );
|
||||
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
|
||||
pFarg = 0;
|
||||
}else{
|
||||
@@ -3860,7 +3968,9 @@ expr_code_doover:
|
||||
** p1==1 -> old.a p1==4 -> new.a
|
||||
** p1==2 -> old.b p1==5 -> new.b
|
||||
*/
|
||||
Table *pTab = pExpr->pTab;
|
||||
Table *pTab;
|
||||
assert( pExpr->eX==EX_Tab );
|
||||
pTab = pExpr->x.pTab;
|
||||
int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
|
||||
|
||||
assert( pExpr->iTable==0 || pExpr->iTable==1 );
|
||||
@@ -3869,9 +3979,10 @@ expr_code_doover:
|
||||
assert( p1>=0 && p1<(pTab->nCol*2+2) );
|
||||
|
||||
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
|
||||
assert( pExpr->eX==EX_Tab );
|
||||
VdbeComment((v, "r[%d]=%s.%s", target,
|
||||
(pExpr->iTable ? "new" : "old"),
|
||||
(pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName)
|
||||
(pExpr->iColumn<0 ? "rowid" : pExpr->x.pTab->aCol[pExpr->iColumn].zName)
|
||||
));
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
@@ -3935,8 +4046,8 @@ expr_code_doover:
|
||||
Expr *pX; /* The X expression */
|
||||
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
|
||||
assert(pExpr->x.pList->nExpr > 0);
|
||||
assert( pExpr->eX==EX_List );
|
||||
assert( pExpr->x.pList->nExpr > 0);
|
||||
pEList = pExpr->x.pList;
|
||||
aListelem = pEList->a;
|
||||
nExpr = pEList->nExpr;
|
||||
@@ -3959,7 +4070,8 @@ expr_code_doover:
|
||||
for(i=0; i<nExpr-1; i=i+2){
|
||||
if( pX ){
|
||||
assert( pTest!=0 );
|
||||
opCompare.pRight = aListelem[i].pExpr;
|
||||
opCompare.x.pRight = aListelem[i].pExpr;
|
||||
opCompare.eX = EX_Right;
|
||||
}else{
|
||||
pTest = aListelem[i].pExpr;
|
||||
}
|
||||
@@ -4268,17 +4380,20 @@ static void exprCodeBetween(
|
||||
memset(&compRight, 0, sizeof(Expr));
|
||||
memset(&exprAnd, 0, sizeof(Expr));
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->eX==EX_List );
|
||||
exprX = *pExpr->pLeft;
|
||||
exprAnd.op = TK_AND;
|
||||
exprAnd.pLeft = &compLeft;
|
||||
exprAnd.pRight = &compRight;
|
||||
exprAnd.x.pRight = &compRight;
|
||||
exprAnd.eX = EX_Right;
|
||||
compLeft.op = TK_GE;
|
||||
compLeft.pLeft = &exprX;
|
||||
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
|
||||
compLeft.x.pRight = pExpr->x.pList->a[0].pExpr;
|
||||
compLeft.eX = EX_Right;
|
||||
compRight.op = TK_LE;
|
||||
compRight.pLeft = &exprX;
|
||||
compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
||||
compRight.x.pRight = pExpr->x.pList->a[1].pExpr;
|
||||
compRight.eX = EX_Right;
|
||||
exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1));
|
||||
if( xJump ){
|
||||
xJump(pParse, &exprAnd, dest, jumpIfNull);
|
||||
@@ -4335,14 +4450,16 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
int d2 = sqlite3VdbeMakeLabel(v);
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull);
|
||||
sqlite3VdbeResolveLabel(v, d2);
|
||||
break;
|
||||
}
|
||||
case TK_OR: {
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull);
|
||||
break;
|
||||
}
|
||||
case TK_NOT: {
|
||||
@@ -4355,7 +4472,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
int isTrue; /* IS TRUE or IS NOT TRUE */
|
||||
testcase( jumpIfNull==0 );
|
||||
isNot = pExpr->op2==TK_ISNOT;
|
||||
isTrue = sqlite3ExprTruthValue(pExpr->pRight);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
isTrue = sqlite3ExprTruthValue(pExpr->x.pRight);
|
||||
testcase( isTrue && isNot );
|
||||
testcase( !isTrue && isNot );
|
||||
if( isTrue ^ isNot ){
|
||||
@@ -4383,8 +4501,9 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
|
||||
testcase( jumpIfNull==0 );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
assert( pExpr->eX==EX_Right );
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
|
||||
r1, r2, dest, jumpIfNull);
|
||||
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
@@ -4501,14 +4620,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_AND: {
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull);
|
||||
break;
|
||||
}
|
||||
case TK_OR: {
|
||||
int d2 = sqlite3VdbeMakeLabel(v);
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull);
|
||||
sqlite3VdbeResolveLabel(v, d2);
|
||||
break;
|
||||
}
|
||||
@@ -4522,7 +4643,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
int isTrue; /* IS TRUE or IS NOT TRUE */
|
||||
testcase( jumpIfNull==0 );
|
||||
isNot = pExpr->op2==TK_ISNOT;
|
||||
isTrue = sqlite3ExprTruthValue(pExpr->pRight);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
isTrue = sqlite3ExprTruthValue(pExpr->x.pRight);
|
||||
testcase( isTrue && isNot );
|
||||
testcase( !isTrue && isNot );
|
||||
if( isTrue ^ isNot ){
|
||||
@@ -4553,8 +4675,9 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
|
||||
testcase( jumpIfNull==0 );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
assert( pExpr->eX==EX_Right );
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
|
||||
r1, r2, dest, jumpIfNull);
|
||||
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
@@ -4730,11 +4853,15 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
|
||||
}
|
||||
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
|
||||
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
|
||||
if( combinedFlags & EP_xIsSelect ) return 2;
|
||||
if( pA->eX==EX_Select || pA->eX!=pB->eX ) return 2;
|
||||
if( (combinedFlags & EP_FixedCol)==0
|
||||
&& sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
|
||||
if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
|
||||
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
|
||||
if( pA->eX==EX_Right ){
|
||||
if( sqlite3ExprCompare(pParse,pA->x.pRight,pB->x.pRight,iTab) ) return 2;
|
||||
}
|
||||
if( pA->eX==EX_List ){
|
||||
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
|
||||
}
|
||||
assert( (combinedFlags & EP_Reduced)==0 );
|
||||
if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
|
||||
if( pA->iColumn!=pB->iColumn ) return 2;
|
||||
@@ -4829,9 +4956,10 @@ int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
|
||||
if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
|
||||
return 1;
|
||||
}
|
||||
assert( pE2->op!=TK_OR || pE2->eX==EX_Right );
|
||||
if( pE2->op==TK_OR
|
||||
&& (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab)
|
||||
|| sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) )
|
||||
|| sqlite3ExprImpliesExpr(pParse, pE1, pE2->x.pRight, iTab) )
|
||||
){
|
||||
return 1;
|
||||
}
|
||||
@@ -4899,8 +5027,9 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pExpr->op==TK_LE );
|
||||
testcase( pExpr->op==TK_GT );
|
||||
testcase( pExpr->op==TK_GE );
|
||||
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
|
||||
|| (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
|
||||
assert( pExpr->eX==EX_Right );
|
||||
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->x.pTab))
|
||||
|| (pExpr->x.pRight->op==TK_COLUMN && IsVirtual(pExpr->x.pRight->x.pTab))
|
||||
){
|
||||
return WRC_Prune;
|
||||
}
|
||||
@@ -5131,7 +5260,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
|
||||
){
|
||||
pCol = &pAggInfo->aCol[k];
|
||||
pCol->pTab = pExpr->pTab;
|
||||
assert( pExpr->eX==EX_Tab );
|
||||
pCol->pTab = pExpr->x.pTab;
|
||||
pCol->iTable = pExpr->iTable;
|
||||
pCol->iColumn = pExpr->iColumn;
|
||||
pCol->iMem = ++pParse->nMem;
|
||||
@@ -5189,14 +5319,14 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
u8 enc = ENC(pParse->db);
|
||||
i = addAggInfoFunc(pParse->db, pAggInfo);
|
||||
if( i>=0 ){
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->eX==EX_List || pExpr->eX==EX_None );
|
||||
pItem = &pAggInfo->aFunc[i];
|
||||
pItem->pExpr = pExpr;
|
||||
pItem->iMem = ++pParse->nMem;
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
pItem->pFunc = sqlite3FindFunction(pParse->db,
|
||||
pExpr->u.zToken,
|
||||
pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
|
||||
pExpr->eX==EX_List ? pExpr->x.pList->nExpr : 0, enc, 0);
|
||||
if( pExpr->flags & EP_Distinct ){
|
||||
pItem->iDistinct = pParse->nTab++;
|
||||
}else{
|
||||
|
||||
+5
-1
@@ -502,7 +502,11 @@ static Expr *exprTableColumn(
|
||||
){
|
||||
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
|
||||
if( pExpr ){
|
||||
pExpr->pTab = pTab;
|
||||
assert( pExpr->eX==EX_None );
|
||||
if( pTab ){
|
||||
pExpr->x.pTab = pTab;
|
||||
pExpr->eX = EX_Tab;
|
||||
}
|
||||
pExpr->iTable = iCursor;
|
||||
pExpr->iColumn = iCol;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1848,7 +1848,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
||||
if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){
|
||||
return 0;
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->eX==EX_List );
|
||||
nExpr = pExpr->x.pList->nExpr;
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
|
||||
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
|
||||
|
||||
+12
-29
@@ -936,12 +936,11 @@ idlist(A) ::= nm(Y).
|
||||
/* memset(p, 0, sizeof(Expr)); */
|
||||
p->op = (u8)op;
|
||||
p->affinity = 0;
|
||||
p->eX = EX_None;
|
||||
p->flags = EP_Leaf;
|
||||
p->iAgg = -1;
|
||||
p->pLeft = p->pRight = 0;
|
||||
p->x.pList = 0;
|
||||
p->pLeft = 0;
|
||||
p->pAggInfo = 0;
|
||||
p->pTab = 0;
|
||||
p->op2 = 0;
|
||||
p->iTable = 0;
|
||||
p->iColumn = 0;
|
||||
@@ -1052,11 +1051,7 @@ term(A) ::= CTIME_KW(OP). {
|
||||
expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. {
|
||||
ExprList *pList = sqlite3ExprListAppend(pParse, X, Y);
|
||||
A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
|
||||
if( A ){
|
||||
A->x.pList = pList;
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
}
|
||||
sqlite3PExprAddExprList(pParse, A, pList);
|
||||
}
|
||||
|
||||
expr(A) ::= expr(A) AND(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);}
|
||||
@@ -1104,10 +1099,11 @@ expr(A) ::= expr(A) NOT NULL. {A = sqlite3PExpr(pParse,TK_NOTNULL,A,0);}
|
||||
** unary TK_ISNULL or TK_NOTNULL expression. */
|
||||
static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
|
||||
sqlite3 *db = pParse->db;
|
||||
if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){
|
||||
if( pA && pY && pY->op==TK_NULL && pA->eX==EX_Right && !IN_RENAME_OBJECT ){
|
||||
pA->op = (u8)op;
|
||||
sqlite3ExprDelete(db, pA->pRight);
|
||||
pA->pRight = 0;
|
||||
sqlite3ExprDelete(db, pA->x.pRight);
|
||||
pA->x.pRight = 0;
|
||||
pA->eX = EX_None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1143,11 +1139,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
ExprList *pList = sqlite3ExprListAppend(pParse,0, X);
|
||||
pList = sqlite3ExprListAppend(pParse,pList, Y);
|
||||
A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0);
|
||||
if( A ){
|
||||
A->x.pList = pList;
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
}
|
||||
sqlite3PExprAddExprList(pParse, A, pList);
|
||||
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
|
||||
}
|
||||
%ifndef SQLITE_OMIT_SUBQUERY
|
||||
@@ -1195,12 +1187,8 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
A = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A, pRHS);
|
||||
}else{
|
||||
A = sqlite3PExpr(pParse, TK_IN, A, 0);
|
||||
if( A ){
|
||||
A->x.pList = Y;
|
||||
sqlite3ExprSetHeightAndFlags(pParse, A);
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, Y);
|
||||
}
|
||||
sqlite3PExprAddExprList(pParse, A, Y);
|
||||
sqlite3ExprSetHeightAndFlags(pParse, A);
|
||||
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
|
||||
}
|
||||
}
|
||||
@@ -1231,13 +1219,8 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
/* CASE expressions */
|
||||
expr(A) ::= CASE case_operand(X) case_exprlist(Y) case_else(Z) END. {
|
||||
A = sqlite3PExpr(pParse, TK_CASE, X, 0);
|
||||
if( A ){
|
||||
A->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y;
|
||||
sqlite3ExprSetHeightAndFlags(pParse, A);
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, Y);
|
||||
sqlite3ExprDelete(pParse->db, Z);
|
||||
}
|
||||
sqlite3PExprAddExprList(pParse,A,Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y);
|
||||
sqlite3ExprSetHeightAndFlags(pParse, A);
|
||||
}
|
||||
%type case_exprlist {ExprList*}
|
||||
%destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);}
|
||||
|
||||
+36
-27
@@ -164,7 +164,7 @@ int sqlite3MatchSpanName(
|
||||
** pExpr->iColumn Set to the column number within the table.
|
||||
** pExpr->op Set to TK_COLUMN.
|
||||
** pExpr->pLeft Any expression this points to is deleted
|
||||
** pExpr->pRight Any expression this points to is deleted.
|
||||
** pExpr->x.pRight Any expression this points to is deleted.
|
||||
**
|
||||
** 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
|
||||
@@ -203,7 +203,6 @@ static int lookupName(
|
||||
|
||||
/* Initialize the node to no-match */
|
||||
pExpr->iTable = -1;
|
||||
pExpr->pTab = 0;
|
||||
ExprSetVVAProperty(pExpr, EP_NoReduce);
|
||||
|
||||
/* Translate the schema name in zDb into a pointer to the corresponding
|
||||
@@ -265,7 +264,7 @@ static int lookupName(
|
||||
continue;
|
||||
}
|
||||
if( IN_RENAME_OBJECT && pItem->zAlias ){
|
||||
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab);
|
||||
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->x.pTab);
|
||||
}
|
||||
}
|
||||
if( 0==(cntTab++) ){
|
||||
@@ -291,13 +290,13 @@ static int lookupName(
|
||||
}
|
||||
if( pMatch ){
|
||||
pExpr->iTable = pMatch->iCursor;
|
||||
pExpr->pTab = pMatch->pTab;
|
||||
sqlite3ExprAddTab(db, pExpr, pMatch->pTab);
|
||||
/* RIGHT JOIN not (yet) supported */
|
||||
assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
|
||||
if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
|
||||
ExprSetProperty(pExpr, EP_CanBeNull);
|
||||
}
|
||||
pSchema = pExpr->pTab->pSchema;
|
||||
pSchema = pExpr->x.pTab->pSchema;
|
||||
}
|
||||
} /* if( pSrcList ) */
|
||||
|
||||
@@ -354,7 +353,7 @@ static int lookupName(
|
||||
testcase( iCol==(-1) );
|
||||
if( IN_RENAME_OBJECT ){
|
||||
pExpr->iColumn = iCol;
|
||||
pExpr->pTab = pTab;
|
||||
sqlite3ExprAddTab(db, pExpr, pTab);
|
||||
eNewExprOp = TK_COLUMN;
|
||||
}else{
|
||||
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
|
||||
@@ -376,7 +375,7 @@ static int lookupName(
|
||||
testcase( iCol==32 );
|
||||
pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
|
||||
}
|
||||
pExpr->pTab = pTab;
|
||||
sqlite3ExprAddTab(db, pExpr, pTab);
|
||||
pExpr->iColumn = (i16)iCol;
|
||||
eNewExprOp = TK_TRIGGER;
|
||||
#endif /* SQLITE_OMIT_TRIGGER */
|
||||
@@ -429,9 +428,7 @@ static int lookupName(
|
||||
char *zAs = pEList->a[j].zName;
|
||||
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
|
||||
Expr *pOrig;
|
||||
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
|
||||
assert( pExpr->x.pList==0 );
|
||||
assert( pExpr->x.pSelect==0 );
|
||||
assert( pExpr->pLeft==0 );
|
||||
pOrig = pEList->a[j].pExpr;
|
||||
if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
|
||||
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
|
||||
@@ -476,7 +473,6 @@ static int lookupName(
|
||||
assert( pExpr->op==TK_ID );
|
||||
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
|
||||
pExpr->op = TK_STRING;
|
||||
pExpr->pTab = 0;
|
||||
return WRC_Prune;
|
||||
}
|
||||
if( sqlite3ExprIdToTrueFalse(pExpr) ){
|
||||
@@ -522,8 +518,11 @@ static int lookupName(
|
||||
*/
|
||||
sqlite3ExprDelete(db, pExpr->pLeft);
|
||||
pExpr->pLeft = 0;
|
||||
sqlite3ExprDelete(db, pExpr->pRight);
|
||||
pExpr->pRight = 0;
|
||||
if( pExpr->eX==EX_Right ){
|
||||
sqlite3ExprDelete(db, pExpr->x.pRight);
|
||||
pExpr->x.pRight = 0;
|
||||
pExpr->eX = EX_None;
|
||||
}
|
||||
pExpr->op = eNewExprOp;
|
||||
ExprSetProperty(pExpr, EP_Leaf);
|
||||
lookupname_end:
|
||||
@@ -554,9 +553,9 @@ Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
|
||||
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
|
||||
if( p ){
|
||||
struct SrcList_item *pItem = &pSrc->a[iSrc];
|
||||
p->pTab = pItem->pTab;
|
||||
sqlite3ExprAddTab(db, p, pItem->pTab);
|
||||
p->iTable = pItem->iCursor;
|
||||
if( p->pTab->iPKey==iCol ){
|
||||
if( p->x.pTab->iPKey==iCol ){
|
||||
p->iColumn = -1;
|
||||
}else{
|
||||
p->iColumn = (ynVar)iCol;
|
||||
@@ -677,22 +676,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
}else{
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
|
||||
pRight = pExpr->pRight;
|
||||
assert( pExpr->eX==EX_Right );
|
||||
pRight = pExpr->x.pRight;
|
||||
if( pRight->op==TK_ID ){
|
||||
zDb = 0;
|
||||
}else{
|
||||
assert( pRight->op==TK_DOT );
|
||||
assert( pRight->eX==EX_Right );
|
||||
zDb = pLeft->u.zToken;
|
||||
pLeft = pRight->pLeft;
|
||||
pRight = pRight->pRight;
|
||||
pRight = pRight->x.pRight;
|
||||
}
|
||||
zTable = pLeft->u.zToken;
|
||||
zColumn = pRight->u.zToken;
|
||||
if( IN_RENAME_OBJECT ){
|
||||
sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
|
||||
}
|
||||
if( IN_RENAME_OBJECT ){
|
||||
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft);
|
||||
if( pExpr->eX==EX_Tab ){
|
||||
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->x.pTab,(void*)pLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
|
||||
@@ -701,8 +702,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
/* Resolve function names
|
||||
*/
|
||||
case TK_FUNCTION: {
|
||||
ExprList *pList = pExpr->x.pList; /* The argument list */
|
||||
int n = pList ? pList->nExpr : 0; /* Number of arguments */
|
||||
ExprList *pList; /* The argument list */
|
||||
int n; /* Number of arguments */
|
||||
int no_such_func = 0; /* True if no such function exists */
|
||||
int wrong_num_args = 0; /* True if wrong number of arguments */
|
||||
int is_agg = 0; /* True if is an aggregate function */
|
||||
@@ -711,7 +712,14 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
FuncDef *pDef; /* Information about the function */
|
||||
u8 enc = ENC(pParse->db); /* The database encoding */
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->eX==EX_List || pExpr->eX==EX_None );
|
||||
if( pExpr->eX==EX_List ){
|
||||
pList = pExpr->x.pList;
|
||||
n = pList->nExpr;
|
||||
}else{
|
||||
pList = 0;
|
||||
n = 0;
|
||||
}
|
||||
zId = pExpr->u.zToken;
|
||||
nId = sqlite3Strlen30(zId);
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
|
||||
@@ -876,7 +884,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
#endif
|
||||
case TK_IN: {
|
||||
testcase( pExpr->op==TK_IN );
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( pExpr->eX==EX_Select ){
|
||||
int nRef = pNC->nRef;
|
||||
notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
|
||||
sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
|
||||
@@ -898,7 +906,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
assert( !ExprHasProperty(pExpr, EP_Reduced) );
|
||||
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
|
||||
** and "x IS NOT FALSE". */
|
||||
if( (pRight = pExpr->pRight)->op==TK_ID ){
|
||||
assert( pExpr->eX==EX_Right );
|
||||
if( (pRight = pExpr->x.pRight)->op==TK_ID ){
|
||||
int rc = resolveExprStep(pWalker, pRight);
|
||||
if( rc==WRC_Abort ) return WRC_Abort;
|
||||
if( pRight->op==TK_TRUEFALSE ){
|
||||
@@ -926,8 +935,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
|
||||
}
|
||||
}else{
|
||||
assert( pExpr->pRight!=0 );
|
||||
nRight = sqlite3ExprVectorSize(pExpr->pRight);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
nRight = sqlite3ExprVectorSize(pExpr->x.pRight);
|
||||
}
|
||||
if( nLeft!=nRight ){
|
||||
testcase( pExpr->op==TK_EQ );
|
||||
|
||||
+68
-41
@@ -390,14 +390,14 @@ static void setJoinExpr(Expr *p, int iTable){
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetVVAProperty(p, EP_NoReduce);
|
||||
p->iRightJoinTable = (i16)iTable;
|
||||
if( p->op==TK_FUNCTION && p->x.pList ){
|
||||
if( p->op==TK_FUNCTION && p->eX==EX_List ){
|
||||
int i;
|
||||
for(i=0; i<p->x.pList->nExpr; i++){
|
||||
setJoinExpr(p->x.pList->a[i].pExpr, iTable);
|
||||
}
|
||||
}
|
||||
setJoinExpr(p->pLeft, iTable);
|
||||
p = p->pRight;
|
||||
p = p->eX==EX_Right ? p->x.pRight : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,14 +413,14 @@ static void unsetJoinExpr(Expr *p, int iTable){
|
||||
&& (iTable<0 || p->iRightJoinTable==iTable) ){
|
||||
ExprClearProperty(p, EP_FromJoin);
|
||||
}
|
||||
if( p->op==TK_FUNCTION && p->x.pList ){
|
||||
if( p->op==TK_FUNCTION && p->eX==EX_List ){
|
||||
int i;
|
||||
for(i=0; i<p->x.pList->nExpr; i++){
|
||||
unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
|
||||
}
|
||||
}
|
||||
unsetJoinExpr(p->pLeft, iTable);
|
||||
p = p->pRight;
|
||||
p = p->eX==EX_Right ? p->x.pRight : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,8 +803,12 @@ static void selectExprDefer(
|
||||
struct ExprList_item *pItem = &pEList->a[i];
|
||||
if( pItem->u.x.iOrderByCol==0 ){
|
||||
Expr *pExpr = pItem->pExpr;
|
||||
Table *pTab = pExpr->pTab;
|
||||
if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
|
||||
Table *pTab;
|
||||
if( pExpr->op==TK_COLUMN
|
||||
&& pExpr->iColumn>=0
|
||||
&& ALWAYS(pExpr->eX==EX_Tab)
|
||||
&& (pTab = pExpr->x.pTab)!=0
|
||||
&& !IsVirtual(pTab)
|
||||
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
|
||||
){
|
||||
int j;
|
||||
@@ -822,16 +826,18 @@ static void selectExprDefer(
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
nKey = pPk->nKeyCol;
|
||||
}
|
||||
assert( pExpr->eX==EX_Tab );
|
||||
for(k=0; k<nKey; k++){
|
||||
Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
|
||||
if( pNew ){
|
||||
pNew->iTable = pExpr->iTable;
|
||||
pNew->pTab = pExpr->pTab;
|
||||
pNew->eX = EX_Tab;
|
||||
pNew->x.pTab = pExpr->x.pTab;
|
||||
pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
|
||||
pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
|
||||
}
|
||||
}
|
||||
pSort->aDefer[nDefer].pTab = pExpr->pTab;
|
||||
pSort->aDefer[nDefer].pTab = pExpr->x.pTab;
|
||||
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
|
||||
pSort->aDefer[nDefer].nKey = nKey;
|
||||
nDefer++;
|
||||
@@ -1680,7 +1686,7 @@ static const char *columnTypeImpl(
|
||||
break;
|
||||
}
|
||||
|
||||
assert( pTab && pExpr->pTab==pTab );
|
||||
assert( pTab && pExpr->eX==EX_Tab && pExpr->x.pTab==pTab );
|
||||
if( pS ){
|
||||
/* The "table" is actually a sub-select or a view in the FROM clause
|
||||
** of the SELECT statement. Return the declaration type and origin
|
||||
@@ -1736,7 +1742,7 @@ static const char *columnTypeImpl(
|
||||
NameContext sNC;
|
||||
Select *pS = pExpr->x.pSelect;
|
||||
Expr *p = pS->pEList->a[0].pExpr;
|
||||
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->eX==EX_Select );
|
||||
sNC.pSrcList = pS->pSrc;
|
||||
sNC.pNext = pNC;
|
||||
sNC.pParse = pNC->pParse;
|
||||
@@ -1865,7 +1871,8 @@ static void generateColumnNames(
|
||||
|
||||
assert( p!=0 );
|
||||
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
|
||||
assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
|
||||
/* Covering idx not yet coded: */
|
||||
assert( p->op!=TK_COLUMN || (p->eX==EX_Tab && p->x.pTab!=0) );
|
||||
if( pEList->a[i].zName ){
|
||||
/* An AS clause always takes first priority */
|
||||
char *zName = pEList->a[i].zName;
|
||||
@@ -1873,7 +1880,8 @@ static void generateColumnNames(
|
||||
}else if( srcName && p->op==TK_COLUMN ){
|
||||
char *zCol;
|
||||
int iCol = p->iColumn;
|
||||
pTab = p->pTab;
|
||||
assert( p->eX==EX_Tab );
|
||||
pTab = p->x.pTab;
|
||||
assert( pTab!=0 );
|
||||
if( iCol<0 ) iCol = pTab->iPKey;
|
||||
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
|
||||
@@ -1957,14 +1965,17 @@ int sqlite3ColumnsFromExprList(
|
||||
}else{
|
||||
Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
|
||||
while( pColExpr->op==TK_DOT ){
|
||||
pColExpr = pColExpr->pRight;
|
||||
assert( pColExpr->eX==EX_Right );
|
||||
pColExpr = pColExpr->x.pRight;
|
||||
assert( pColExpr!=0 );
|
||||
}
|
||||
assert( pColExpr->op!=TK_AGG_COLUMN );
|
||||
if( pColExpr->op==TK_COLUMN ){
|
||||
/* For columns use the column name name */
|
||||
int iCol = pColExpr->iColumn;
|
||||
Table *pTab = pColExpr->pTab;
|
||||
Table *pTab;
|
||||
assert( pColExpr->eX==EX_Tab );
|
||||
pTab = pColExpr->x.pTab;
|
||||
assert( pTab!=0 );
|
||||
if( iCol<0 ) iCol = pTab->iPKey;
|
||||
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
|
||||
@@ -2125,7 +2136,7 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
|
||||
|
||||
/*
|
||||
** Compute the iLimit and iOffset fields of the SELECT based on the
|
||||
** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions
|
||||
** pLimit expressions. pLimit->pLeft and pLimit->x,pRight hold the expressions
|
||||
** that appear in the original SQL statement after the LIMIT and OFFSET
|
||||
** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
|
||||
** are the integer memory register numbers for counters used to compute
|
||||
@@ -2133,7 +2144,7 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
|
||||
** iLimit and iOffset are negative.
|
||||
**
|
||||
** This routine changes the values of iLimit and iOffset only if
|
||||
** a limit or offset is defined by pLimit->pLeft and pLimit->pRight. iLimit
|
||||
** a limit or offset is defined by pLimit->pLeft and pLimit->x.pRight. iLimit
|
||||
** and iOffset should have been preset to appropriate default values (zero)
|
||||
** prior to calling this routine.
|
||||
**
|
||||
@@ -2182,10 +2193,10 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
VdbeComment((v, "LIMIT counter"));
|
||||
sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
|
||||
}
|
||||
if( pLimit->pRight ){
|
||||
if( pLimit->eX==EX_Right ){
|
||||
p->iOffset = iOffset = ++pParse->nMem;
|
||||
pParse->nMem++; /* Allocate an extra register for limit+offset */
|
||||
sqlite3ExprCode(pParse, pLimit->pRight, iOffset);
|
||||
sqlite3ExprCode(pParse, pLimit->x.pRight, iOffset);
|
||||
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
|
||||
VdbeComment((v, "OFFSET counter"));
|
||||
sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset);
|
||||
@@ -3442,7 +3453,7 @@ static Expr *substExpr(
|
||||
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
|
||||
Expr ifNullRow;
|
||||
assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
|
||||
assert( pExpr->pRight==0 );
|
||||
assert( pExpr->eX!=EX_Right );
|
||||
if( sqlite3ExprIsVector(pCopy) ){
|
||||
sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
|
||||
}else{
|
||||
@@ -3471,11 +3482,20 @@ static Expr *substExpr(
|
||||
pExpr->iTable = pSubst->iNewTable;
|
||||
}
|
||||
pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
|
||||
pExpr->pRight = substExpr(pSubst, pExpr->pRight);
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
substSelect(pSubst, pExpr->x.pSelect, 1);
|
||||
}else{
|
||||
substExprList(pSubst, pExpr->x.pList);
|
||||
switch( pExpr->eX ){
|
||||
case EX_Select: {
|
||||
substSelect(pSubst, pExpr->x.pSelect, 1);
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
substExprList(pSubst, pExpr->x.pList);
|
||||
break;
|
||||
}
|
||||
case EX_Right: {
|
||||
pExpr->x.pRight = substExpr(pSubst, pExpr->x.pRight);
|
||||
if( pExpr->x.pRight==0 ) pExpr->eX = EX_None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pExpr;
|
||||
@@ -3715,7 +3735,9 @@ static int flattenSubquery(
|
||||
** became arbitrary expressions, we were forced to add restrictions (13)
|
||||
** and (14). */
|
||||
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
|
||||
if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */
|
||||
if( pSub->pLimit && pSub->pLimit->eX==EX_Right ){
|
||||
return 0; /* Restriction (14) */
|
||||
}
|
||||
if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
|
||||
return 0; /* Restriction (15) */
|
||||
}
|
||||
@@ -4110,26 +4132,28 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
|
||||
if( pExpr==0 ) return;
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
|
||||
if( pExpr->op==TK_AND ){
|
||||
findConstInWhere(pConst, pExpr->pRight);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
findConstInWhere(pConst, pExpr->x.pRight);
|
||||
findConstInWhere(pConst, pExpr->pLeft);
|
||||
return;
|
||||
}
|
||||
if( pExpr->op!=TK_EQ ) return;
|
||||
pRight = pExpr->pRight;
|
||||
assert( pExpr->eX==EX_Right );
|
||||
pRight = pExpr->x.pRight;
|
||||
pLeft = pExpr->pLeft;
|
||||
assert( pRight!=0 );
|
||||
assert( pLeft!=0 );
|
||||
if( pRight->op==TK_COLUMN
|
||||
&& !ExprHasProperty(pRight, EP_FixedCol)
|
||||
&& sqlite3ExprIsConstant(pLeft)
|
||||
&& sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
|
||||
&& sqlite3IsBinary(sqlite3ComparisonCollSeq(pConst->pParse,pLeft,pRight))
|
||||
){
|
||||
constInsert(pConst, pRight, pLeft);
|
||||
}else
|
||||
if( pLeft->op==TK_COLUMN
|
||||
&& !ExprHasProperty(pLeft, EP_FixedCol)
|
||||
&& sqlite3ExprIsConstant(pRight)
|
||||
&& sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
|
||||
&& sqlite3IsBinary(sqlite3ComparisonCollSeq(pConst->pParse,pLeft,pRight))
|
||||
){
|
||||
constInsert(pConst, pLeft, pRight);
|
||||
}
|
||||
@@ -4316,7 +4340,8 @@ static int pushDownWhereTerms(
|
||||
return 0; /* restriction (3) */
|
||||
}
|
||||
while( pWhere->op==TK_AND ){
|
||||
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
|
||||
assert( pWhere->eX==EX_Right );
|
||||
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->x.pRight,
|
||||
iCursor, isLeftJoin);
|
||||
pWhere = pWhere->pLeft;
|
||||
}
|
||||
@@ -4902,9 +4927,9 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
for(k=0; k<pEList->nExpr; k++){
|
||||
pE = pEList->a[k].pExpr;
|
||||
if( pE->op==TK_ASTERISK ) break;
|
||||
assert( pE->op!=TK_DOT || pE->pRight!=0 );
|
||||
assert( pE->op!=TK_DOT || pE->eX==EX_Right );
|
||||
assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
|
||||
if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break;
|
||||
if( pE->op==TK_DOT && pE->x.pRight->op==TK_ASTERISK ) break;
|
||||
elistFlags |= pE->flags;
|
||||
}
|
||||
if( k<pEList->nExpr ){
|
||||
@@ -4922,7 +4947,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
for(k=0; k<pEList->nExpr; k++){
|
||||
pE = a[k].pExpr;
|
||||
elistFlags |= pE->flags;
|
||||
pRight = pE->pRight;
|
||||
pRight = pE->eX==EX_Right ? pE->x.pRight : 0;
|
||||
assert( pE->op!=TK_DOT || pRight!=0 );
|
||||
if( pE->op!=TK_ASTERISK
|
||||
&& (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK)
|
||||
@@ -5242,8 +5267,8 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
|
||||
if( pFunc->iDistinct>=0 ){
|
||||
Expr *pE = pFunc->pExpr;
|
||||
assert( !ExprHasProperty(pE, EP_xIsSelect) );
|
||||
if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
|
||||
assert( pE->eX==EX_List || pE->eX==EX_None );
|
||||
if( pE->eX==EX_None || pE->x.pList->nExpr!=1 ){
|
||||
sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
|
||||
"argument");
|
||||
pFunc->iDistinct = -1;
|
||||
@@ -5266,7 +5291,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
|
||||
struct AggInfo_func *pF;
|
||||
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
|
||||
ExprList *pList = pF->pExpr->x.pList;
|
||||
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
|
||||
assert( pF->pExpr->eX==EX_List || pF->pExpr->eX==EX_None );
|
||||
assert( pF->pExpr->eX==EX_List || pList==0 );
|
||||
sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
|
||||
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
|
||||
}
|
||||
@@ -5296,7 +5322,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
|
||||
int addrNext = 0;
|
||||
int regAgg;
|
||||
ExprList *pList = pF->pExpr->x.pList;
|
||||
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
|
||||
assert( pF->pExpr->eX==EX_List || pF->pExpr->eX==EX_None );
|
||||
if( pList ){
|
||||
nArg = pList->nExpr;
|
||||
regAgg = sqlite3GetTempRange(pParse, nArg);
|
||||
@@ -6186,10 +6212,11 @@ int sqlite3Select(
|
||||
minMaxFlag = WHERE_ORDERBY_NORMAL;
|
||||
}
|
||||
for(i=0; i<sAggInfo.nFunc; i++){
|
||||
assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
|
||||
sNC.ncFlags |= NC_InAggFunc;
|
||||
sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
|
||||
sNC.ncFlags &= ~NC_InAggFunc;
|
||||
if( sAggInfo.aFunc[i].pExpr->eX==EX_List ){
|
||||
sNC.ncFlags |= NC_InAggFunc;
|
||||
sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
|
||||
sNC.ncFlags &= ~NC_InAggFunc;
|
||||
}
|
||||
}
|
||||
sAggInfo.mxReg = pParse->nMem;
|
||||
if( db->mallocFailed ) goto select_end;
|
||||
|
||||
+25
-5
@@ -2419,6 +2419,8 @@ typedef int ynVar;
|
||||
struct Expr {
|
||||
u8 op; /* Operation performed by this node */
|
||||
char affinity; /* The affinity of the column or 0 if not a column */
|
||||
u8 eV; /* Which element of v-union is used */
|
||||
u8 eX; /* Which element of x-union is used */
|
||||
u32 flags; /* Various flags. EP_* See below */
|
||||
union {
|
||||
char *zToken; /* Token value. Zero terminated and dequoted */
|
||||
@@ -2431,10 +2433,12 @@ struct Expr {
|
||||
*********************************************************************/
|
||||
|
||||
Expr *pLeft; /* Left subnode */
|
||||
Expr *pRight; /* Right subnode */
|
||||
union {
|
||||
Expr *pRight; /* Right subnode */
|
||||
ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
|
||||
Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
|
||||
Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
|
||||
** for a column of an index on an expression */
|
||||
} x;
|
||||
|
||||
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
|
||||
@@ -2459,13 +2463,25 @@ struct Expr {
|
||||
** TK_COLUMN: the value of p5 for OP_Column
|
||||
** TK_AGG_FUNCTION: nesting depth */
|
||||
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
||||
Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
|
||||
** for a column of an index on an expression */
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
Window *pWin; /* Window definition for window functions */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** Allowed values for the Expr.eV and Expr.eX fields:
|
||||
*/
|
||||
#define EV_None 0 /* Expr.v is not used */
|
||||
#define EV_Left 1 /* Expr.v.pLeft */
|
||||
#define EV_Vector 2 /* Expr.v.pVector */
|
||||
#define EV_Win 3 /* Expr.v.pWin */
|
||||
|
||||
#define EX_None 0 /* Expr.x is not used */
|
||||
#define EX_Right 1 /* Expr.x.pRight */
|
||||
#define EX_List 2 /* Expr.x.pList */
|
||||
#define EX_Select 3 /* Expr.x.pSelect */
|
||||
#define EX_Tab 4 /* Expr.x.pTab */
|
||||
|
||||
/*
|
||||
** The following are the meanings of bits in the Expr.flags field.
|
||||
*/
|
||||
@@ -2480,7 +2496,7 @@ struct Expr {
|
||||
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
|
||||
#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */
|
||||
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
|
||||
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
|
||||
/* 0x000800 -- Available for reuse */
|
||||
#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
|
||||
#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
|
||||
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
|
||||
@@ -3794,10 +3810,13 @@ Expr *sqlite3Expr(sqlite3*,int,const char*);
|
||||
void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
|
||||
Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
|
||||
void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
|
||||
void sqlite3PExprAddExprList(Parse*, Expr*, ExprList*);
|
||||
void sqlite3ExprAddTab(sqlite3*, Expr*, Table*);
|
||||
Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
|
||||
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
|
||||
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
|
||||
void sqlite3ExprDelete(sqlite3*, Expr*);
|
||||
void sqlite3ExprClearXUnion(sqlite3*,Expr*);
|
||||
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
|
||||
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
|
||||
void sqlite3ExprListSetSortOrder(ExprList*,int);
|
||||
@@ -4385,7 +4404,8 @@ int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
|
||||
void sqlite3ParserReset(Parse*);
|
||||
int sqlite3Reprepare(Vdbe*);
|
||||
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
|
||||
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
|
||||
CollSeq *sqlite3ComparisonCollSeq(Parse*,Expr*,Expr*);
|
||||
CollSeq *sqlite3ComparisonExprCollSeq(Parse*,Expr*);
|
||||
int sqlite3TempInMemory(const sqlite3*);
|
||||
const char *sqlite3JournalModename(int);
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
|
||||
+19
-12
@@ -238,10 +238,10 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||
}
|
||||
if( p->pLimit ){
|
||||
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
|
||||
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
|
||||
if( p->pLimit->pRight ){
|
||||
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->eX==EX_Right);
|
||||
if( p->pLimit->eX==EX_Right ){
|
||||
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
|
||||
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
|
||||
sqlite3TreeViewExpr(pView, p->pLimit->x.pRight, 0);
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
sqlite3TreeViewPop(pView);
|
||||
@@ -468,9 +468,9 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
"IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
|
||||
};
|
||||
assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
|
||||
assert( pExpr->pRight );
|
||||
assert( pExpr->pRight->op==TK_TRUEFALSE );
|
||||
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
assert( pExpr->x.pRight->op==TK_TRUEFALSE );
|
||||
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->x.pRight);
|
||||
zUniOp = azOp[x];
|
||||
break;
|
||||
}
|
||||
@@ -532,10 +532,15 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
case TK_IN: {
|
||||
sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||
}else{
|
||||
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
||||
switch( pExpr->eX ){
|
||||
case EX_Select: {
|
||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -596,7 +601,8 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
case TK_MATCH: {
|
||||
sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
|
||||
pExpr->iTable, pExpr->iColumn, zFlgs);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
sqlite3TreeViewExpr(pView, pExpr->x.pRight, 0);
|
||||
break;
|
||||
}
|
||||
case TK_VECTOR: {
|
||||
@@ -621,7 +627,8 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
if( zBinOp ){
|
||||
sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
sqlite3TreeViewExpr(pView, pExpr->x.pRight, 0);
|
||||
}else if( zUniOp ){
|
||||
sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||
|
||||
+2
-2
@@ -1375,9 +1375,9 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
|
||||
if( zOp ){
|
||||
sqlite3_str_appendf(p, "%s(", zOp);
|
||||
displayP4Expr(p, pExpr->pLeft);
|
||||
if( pExpr->pRight ){
|
||||
if( pExpr->eX==EX_Right ){
|
||||
sqlite3_str_append(p, ",", 1);
|
||||
displayP4Expr(p, pExpr->pRight);
|
||||
displayP4Expr(p, pExpr->x.pRight);
|
||||
}
|
||||
sqlite3_str_append(p, ")", 1);
|
||||
}
|
||||
|
||||
+1
-2
@@ -1053,8 +1053,7 @@ FuncDef *sqlite3VtabOverloadFunction(
|
||||
/* Check to see the left operand is a column in a virtual table */
|
||||
if( NEVER(pExpr==0) ) return pDef;
|
||||
if( pExpr->op!=TK_COLUMN ) return pDef;
|
||||
pTab = pExpr->pTab;
|
||||
if( pTab==0 ) return pDef;
|
||||
if( pExpr->eX!=EX_Tab || (pTab = pExpr->x.pTab)==0 ) return pDef;
|
||||
if( !IsVirtual(pTab) ) return pDef;
|
||||
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
|
||||
assert( pVtab!=0 );
|
||||
|
||||
+13
-8
@@ -45,14 +45,19 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
|
||||
if( rc ) return rc & WRC_Abort;
|
||||
if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
|
||||
if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
|
||||
assert( pExpr->x.pList==0 || pExpr->pRight==0 );
|
||||
if( pExpr->pRight ){
|
||||
pExpr = pExpr->pRight;
|
||||
continue;
|
||||
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
|
||||
}else if( pExpr->x.pList ){
|
||||
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
|
||||
switch( pExpr->eX ){
|
||||
case EX_Right: {
|
||||
pExpr = pExpr->x.pRight;
|
||||
continue;
|
||||
}
|
||||
case EX_Select: {
|
||||
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){
|
||||
|
||||
+60
-38
@@ -253,7 +253,9 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
|
||||
){
|
||||
if( (pTerm->eOperator & WO_EQUIV)!=0
|
||||
&& pScan->nEquiv<ArraySize(pScan->aiCur)
|
||||
&& (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN
|
||||
&& ALWAYS(pTerm->pExpr->eX==EX_Right)
|
||||
&& (pX = sqlite3ExprSkipCollate(pTerm->pExpr->x.pRight))->op
|
||||
==TK_COLUMN
|
||||
){
|
||||
int j;
|
||||
for(j=0; j<pScan->nEquiv; j++){
|
||||
@@ -278,15 +280,15 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
|
||||
continue;
|
||||
}
|
||||
assert(pX->pLeft);
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse,
|
||||
pX->pLeft, pX->pRight);
|
||||
pColl = sqlite3ComparisonExprCollSeq(pParse, pX);
|
||||
if( pColl==0 ) pColl = pParse->db->pDfltColl;
|
||||
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
|
||||
&& (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
|
||||
&& ALWAYS(pTerm->pExpr->eX==EX_Right)
|
||||
&& (pX = pTerm->pExpr->x.pRight)->op==TK_COLUMN
|
||||
&& pX->iTable==pScan->aiCur[0]
|
||||
&& pX->iColumn==pScan->aiColumn[0]
|
||||
){
|
||||
@@ -789,7 +791,7 @@ static void constructAutomaticIndex(
|
||||
Expr *pX = pTerm->pExpr;
|
||||
idxCols |= cMask;
|
||||
pIdx->aiColumn[n] = pTerm->u.leftColumn;
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
|
||||
pColl = sqlite3ComparisonExprCollSeq(pParse, pX);
|
||||
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
|
||||
n++;
|
||||
}
|
||||
@@ -1006,7 +1008,8 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
|
||||
|
||||
if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
|
||||
&& sqlite3ExprIsVector(pTerm->pExpr->pRight)
|
||||
&& ALWAYS(pTerm->pExpr->eX==EX_Right)
|
||||
&& sqlite3ExprIsVector(pTerm->pExpr->x.pRight)
|
||||
){
|
||||
if( i<16 ) mNoOmit |= (1 << i);
|
||||
if( op==WO_LT ) pIdxCons[j].op = WO_LE;
|
||||
@@ -1366,11 +1369,13 @@ static int whereRangeSkipScanEst(
|
||||
|
||||
pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]);
|
||||
if( pLower ){
|
||||
rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight, aff, &p1);
|
||||
assert( pLower->pExpr->eX==EX_Right );
|
||||
rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->x.pRight, aff, &p1);
|
||||
nLower = 0;
|
||||
}
|
||||
if( pUpper && rc==SQLITE_OK ){
|
||||
rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->pRight, aff, &p2);
|
||||
assert( pUpper->pExpr->eX==EX_Right );
|
||||
rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->x.pRight, aff, &p2);
|
||||
nUpper = p2 ? 0 : p->nSample;
|
||||
}
|
||||
|
||||
@@ -1532,7 +1537,9 @@ static int whereRangeScanEst(
|
||||
/* If possible, improve on the iLower estimate using ($P:$L). */
|
||||
if( pLower ){
|
||||
int n; /* Values extracted from pExpr */
|
||||
Expr *pExpr = pLower->pExpr->pRight;
|
||||
Expr *pExpr;
|
||||
assert( pLower->pExpr->eX==EX_Right );
|
||||
pExpr = pLower->pExpr->x.pRight;
|
||||
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n);
|
||||
if( rc==SQLITE_OK && n ){
|
||||
tRowcnt iNew;
|
||||
@@ -1549,7 +1556,9 @@ static int whereRangeScanEst(
|
||||
/* If possible, improve on the iUpper estimate using ($P:$U). */
|
||||
if( pUpper ){
|
||||
int n; /* Values extracted from pExpr */
|
||||
Expr *pExpr = pUpper->pExpr->pRight;
|
||||
Expr *pExpr;
|
||||
assert( pUpper->pExpr->eX==EX_Right );
|
||||
pExpr = pUpper->pExpr->x.pRight;
|
||||
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n);
|
||||
if( rc==SQLITE_OK && n ){
|
||||
tRowcnt iNew;
|
||||
@@ -2279,7 +2288,9 @@ static void whereLoopOutputAdjust(
|
||||
** guess a reasonable truth probability. */
|
||||
pLoop->nOut--;
|
||||
if( pTerm->eOperator&(WO_EQ|WO_IS) ){
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
Expr *pRight;
|
||||
assert( pTerm->pExpr->eX==EX_Right );
|
||||
pRight = pTerm->pExpr->x.pRight;
|
||||
testcase( pTerm->pExpr->op==TK_IS );
|
||||
if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
|
||||
k = 10;
|
||||
@@ -2328,9 +2339,13 @@ static int whereRangeVectorLen(
|
||||
char aff; /* Comparison affinity */
|
||||
char idxaff = 0; /* Indexed columns affinity */
|
||||
CollSeq *pColl; /* Comparison collation sequence */
|
||||
Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
|
||||
Expr *pRhs = pTerm->pExpr->pRight;
|
||||
if( pRhs->flags & EP_xIsSelect ){
|
||||
Expr *pLhs;
|
||||
Expr *pRhs;
|
||||
pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
|
||||
assert( pTerm->pExpr->eX==EX_Right );
|
||||
pRhs = pTerm->pExpr->x.pRight;
|
||||
assert( pRhs->eX==EX_Select || pRhs->eX==EX_List );
|
||||
if( pRhs->eX==EX_Select ){
|
||||
pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
|
||||
}else{
|
||||
pRhs = pRhs->x.pList->a[i].pExpr;
|
||||
@@ -2353,7 +2368,7 @@ static int whereRangeVectorLen(
|
||||
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
|
||||
if( aff!=idxaff ) break;
|
||||
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
|
||||
pColl = sqlite3ComparisonCollSeq(pParse, pLhs, pRhs);
|
||||
if( pColl==0 ) break;
|
||||
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
|
||||
}
|
||||
@@ -2488,24 +2503,29 @@ static int whereLoopAddBtreeIndex(
|
||||
|
||||
if( eOp & WO_IN ){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
|
||||
int i;
|
||||
nIn = 46; assert( 46==sqlite3LogEst(25) );
|
||||
|
||||
/* The expression may actually be of the form (x, y) IN (SELECT...).
|
||||
** In this case there is a separate term for each of (x) and (y).
|
||||
** However, the nIn multiplier should only be applied once, not once
|
||||
** for each such term. The following loop checks that pTerm is the
|
||||
** first such term in use, and sets nIn back to 0 if it is not. */
|
||||
for(i=0; i<pNew->nLTerm-1; i++){
|
||||
if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
|
||||
switch( pExpr->eX ){
|
||||
case EX_Select: {
|
||||
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
|
||||
int i;
|
||||
nIn = 46; assert( 46==sqlite3LogEst(25) );
|
||||
|
||||
/* The expression may actually be of the form (x, y) IN (SELECT...).
|
||||
** In this case there is a separate term for each of (x) and (y).
|
||||
** However, the nIn multiplier should only be applied once, not once
|
||||
** for each such term. The following loop checks that pTerm is the
|
||||
** first such term in use, and sets nIn back to 0 if it is not. */
|
||||
for(i=0; i<pNew->nLTerm-1; i++){
|
||||
if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
/* "x IN (value, value, ...)" */
|
||||
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
|
||||
assert( nIn>0 ); /* RHS always has 2 or more terms... The parser
|
||||
** changes "x IN (?)" into "x=?". */
|
||||
break;
|
||||
}
|
||||
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
|
||||
/* "x IN (value, value, ...)" */
|
||||
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
|
||||
assert( nIn>0 ); /* RHS always has 2 or more terms... The parser
|
||||
** changes "x IN (?)" into "x=?". */
|
||||
}
|
||||
if( pProbe->hasStat1 ){
|
||||
LogEst M, logK, safetyMargin;
|
||||
@@ -2620,16 +2640,17 @@ static int whereLoopAddBtreeIndex(
|
||||
if( nInMul==0
|
||||
&& pProbe->nSample
|
||||
&& pNew->u.btree.nEq<=pProbe->nSampleCol
|
||||
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
|
||||
&& ((eOp & WO_IN)==0 || pTerm->pExpr->eX==EX_List)
|
||||
&& OptimizationEnabled(db, SQLITE_Stat34)
|
||||
){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
|
||||
if( (eOp & (WO_EQ|WO_IS))!=0 ){
|
||||
testcase( eOp & WO_EQ );
|
||||
testcase( eOp & WO_IS );
|
||||
testcase( eOp & WO_ISNULL );
|
||||
rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
|
||||
}else{
|
||||
assert( pExpr->eX==EX_Right );
|
||||
rc = whereEqualScanEst(pParse, pBuilder, pExpr->x.pRight, &nOut);
|
||||
}else if( pExpr->eX==EX_List ){
|
||||
rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
|
||||
}
|
||||
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
|
||||
@@ -2783,7 +2804,8 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
|
||||
Parse *pParse = pWC->pWInfo->pParse;
|
||||
while( pWhere->op==TK_AND ){
|
||||
if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0;
|
||||
pWhere = pWhere->pRight;
|
||||
assert( pWhere->eX==EX_Right );
|
||||
pWhere = pWhere->x.pRight;
|
||||
}
|
||||
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
|
||||
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
||||
@@ -3238,7 +3260,7 @@ const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){
|
||||
int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
|
||||
Expr *pX = pHidden->pWC->a[iTerm].pExpr;
|
||||
if( pX->pLeft ){
|
||||
pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight);
|
||||
pC = sqlite3ComparisonExprCollSeq(pHidden->pParse,pX);
|
||||
}
|
||||
zRet = (pC ? pC->zName : sqlite3StrBINARY);
|
||||
}
|
||||
|
||||
+32
-17
@@ -435,7 +435,9 @@ static Expr *removeUnindexableInClauseTerms(
|
||||
}
|
||||
sqlite3ExprListDelete(db, pOrigRhs);
|
||||
sqlite3ExprListDelete(db, pOrigLhs);
|
||||
assert( pNew->pLeft->eX==EX_List );
|
||||
pNew->pLeft->x.pList = pLhs;
|
||||
if( pLhs==0 ) pNew->pLeft->eX = EX_None;
|
||||
pNew->x.pSelect->pEList = pRhs;
|
||||
if( pLhs && pLhs->nExpr==1 ){
|
||||
/* Take care here not to generate a TK_VECTOR containing only a
|
||||
@@ -502,7 +504,8 @@ static int codeEqualityTerm(
|
||||
assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
|
||||
assert( iTarget>0 );
|
||||
if( pX->op==TK_EQ || pX->op==TK_IS ){
|
||||
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
|
||||
assert( pX->eX==EX_Right );
|
||||
iReg = sqlite3ExprCodeTarget(pParse, pX->x.pRight, iTarget);
|
||||
}else if( pX->op==TK_ISNULL ){
|
||||
iReg = iTarget;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
|
||||
@@ -538,7 +541,7 @@ static int codeEqualityTerm(
|
||||
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
|
||||
}
|
||||
|
||||
if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){
|
||||
if( pX->eX!=EX_Select || pX->x.pSelect->pEList->nExpr==1 ){
|
||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0);
|
||||
}else{
|
||||
sqlite3 *db = pParse->db;
|
||||
@@ -734,7 +737,7 @@ static int codeAllEqualityTerms(
|
||||
}
|
||||
}
|
||||
if( pTerm->eOperator & WO_IN ){
|
||||
if( pTerm->pExpr->flags & EP_xIsSelect ){
|
||||
if( pTerm->pExpr->eX==EX_Select ){
|
||||
/* No affinity ever needs to be (or should be) applied to a value
|
||||
** from the RHS of an "? IN (SELECT ...)" expression. The
|
||||
** sqlite3FindInIndex() routine has already ensured that the
|
||||
@@ -742,7 +745,9 @@ static int codeAllEqualityTerms(
|
||||
if( zAff ) zAff[j] = SQLITE_AFF_BLOB;
|
||||
}
|
||||
}else if( (pTerm->eOperator & WO_ISNULL)==0 ){
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
Expr *pRight;
|
||||
assert( pTerm->pExpr->eX==EX_Right );
|
||||
pRight = pTerm->pExpr->x.pRight;
|
||||
if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
|
||||
VdbeCoverage(v);
|
||||
@@ -1074,7 +1079,7 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
|
||||
assert( nReg>0 );
|
||||
if( p && sqlite3ExprIsVector(p) ){
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
if( (p->flags & EP_xIsSelect) ){
|
||||
if( p->eX==EX_Select ){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0);
|
||||
sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1);
|
||||
@@ -1117,7 +1122,7 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
|
||||
pExpr->op = TK_COLUMN;
|
||||
pExpr->iTable = pX->iIdxCur;
|
||||
pExpr->iColumn = pX->iIdxCol;
|
||||
pExpr->pTab = 0;
|
||||
/* pExpr->pTab = 0; */
|
||||
return WRC_Prune;
|
||||
}else{
|
||||
return WRC_Continue;
|
||||
@@ -1262,7 +1267,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
|
||||
addrNotFound = pLevel->addrNxt;
|
||||
}else{
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
Expr *pRight = pExpr->eX==EX_Right ? pExpr->x.pRight : 0;
|
||||
codeExprOrVector(pParse, pRight, iTarget, 1);
|
||||
}
|
||||
}
|
||||
@@ -1307,8 +1313,11 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
assert( pCompare!=0 || db->mallocFailed );
|
||||
if( pCompare ){
|
||||
pCompare->pLeft = pTerm->pExpr->pLeft;
|
||||
pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
|
||||
assert( pCompare->eX==EX_None );
|
||||
pRight = sqlite3Expr(db, TK_REGISTER, 0);
|
||||
if( pRight ){
|
||||
pCompare->x.pRight = pRight;
|
||||
pCompare->eX = EX_Right;
|
||||
pRight->iTable = iReg+j+2;
|
||||
sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0);
|
||||
}
|
||||
@@ -1393,9 +1402,10 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
pX = pStart->pExpr;
|
||||
assert( pX!=0 );
|
||||
testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
|
||||
if( sqlite3ExprIsVector(pX->pRight) ){
|
||||
assert( pX->eX==EX_Right );
|
||||
if( sqlite3ExprIsVector(pX->x.pRight) ){
|
||||
r1 = rTemp = sqlite3GetTempReg(pParse);
|
||||
codeExprOrVector(pParse, pX->pRight, r1, 1);
|
||||
codeExprOrVector(pParse, pX->x.pRight, r1, 1);
|
||||
testcase( pX->op==TK_GT );
|
||||
testcase( pX->op==TK_GE );
|
||||
testcase( pX->op==TK_LT );
|
||||
@@ -1406,7 +1416,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
assert( pX->op!=TK_LT || op==OP_SeekLE );
|
||||
assert( pX->op!=TK_LE || op==OP_SeekLE );
|
||||
}else{
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pX->x.pRight, &rTemp);
|
||||
disableTerm(pLevel, pStart);
|
||||
op = aMoveOp[(pX->op - TK_GT)];
|
||||
}
|
||||
@@ -1426,19 +1436,20 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
Expr *pX;
|
||||
pX = pEnd->pExpr;
|
||||
assert( pX!=0 );
|
||||
assert( pX->eX==EX_Right );
|
||||
assert( (pEnd->wtFlags & TERM_VNULL)==0 );
|
||||
testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */
|
||||
testcase( pEnd->wtFlags & TERM_VIRTUAL );
|
||||
memEndValue = ++pParse->nMem;
|
||||
codeExprOrVector(pParse, pX->pRight, memEndValue, 1);
|
||||
if( 0==sqlite3ExprIsVector(pX->pRight)
|
||||
codeExprOrVector(pParse, pX->x.pRight, memEndValue, 1);
|
||||
if( 0==sqlite3ExprIsVector(pX->x.pRight)
|
||||
&& (pX->op==TK_LT || pX->op==TK_GT)
|
||||
){
|
||||
testOp = bRev ? OP_Le : OP_Ge;
|
||||
}else{
|
||||
testOp = bRev ? OP_Lt : OP_Gt;
|
||||
}
|
||||
if( 0==sqlite3ExprIsVector(pX->pRight) ){
|
||||
if( 0==sqlite3ExprIsVector(pX->x.pRight) ){
|
||||
disableTerm(pLevel, pEnd);
|
||||
}
|
||||
}
|
||||
@@ -1622,7 +1633,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
/* Seek the index cursor to the start of the range. */
|
||||
nConstraint = nEq;
|
||||
if( pRangeStart ){
|
||||
Expr *pRight = pRangeStart->pExpr->pRight;
|
||||
Expr *pRight;
|
||||
assert( pRangeStart->pExpr->eX==EX_Right );
|
||||
pRight = pRangeStart->pExpr->x.pRight;
|
||||
codeExprOrVector(pParse, pRight, regBase+nEq, nBtm);
|
||||
whereLikeOptimizationStringFixup(v, pLevel, pRangeStart);
|
||||
if( (pRangeStart->wtFlags & TERM_VNULL)==0
|
||||
@@ -1674,7 +1687,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
*/
|
||||
nConstraint = nEq;
|
||||
if( pRangeEnd ){
|
||||
Expr *pRight = pRangeEnd->pExpr->pRight;
|
||||
Expr *pRight;
|
||||
assert( pRangeEnd->pExpr->eX==EX_Right );
|
||||
pRight = pRangeEnd->pExpr->x.pRight;
|
||||
codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
|
||||
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
|
||||
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
|
||||
@@ -2194,7 +2209,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( pAlt==0 ) continue;
|
||||
if( pAlt->wtFlags & (TERM_CODED) ) continue;
|
||||
if( (pAlt->eOperator & WO_IN)
|
||||
&& (pAlt->pExpr->flags & EP_xIsSelect)
|
||||
&& (pAlt->pExpr->eX==EX_Select)
|
||||
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
|
||||
){
|
||||
continue;
|
||||
|
||||
+87
-51
@@ -119,15 +119,17 @@ static int allowedOp(int op){
|
||||
** is not commuted.
|
||||
*/
|
||||
static void exprCommute(Parse *pParse, Expr *pExpr){
|
||||
u16 expRight = (pExpr->pRight->flags & EP_Collate);
|
||||
u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
|
||||
u16 expRight, expLeft;
|
||||
assert( pExpr->eX==EX_Right );
|
||||
expRight = (pExpr->x.pRight->flags & EP_Collate);
|
||||
expLeft = (pExpr->pLeft->flags & EP_Collate);
|
||||
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
|
||||
if( expRight==expLeft ){
|
||||
/* Either X and Y both have COLLATE operator or neither do */
|
||||
if( expRight ){
|
||||
/* Both X and Y have COLLATE operators. Make sure X is always
|
||||
** used by clearing the EP_Collate flag from Y. */
|
||||
pExpr->pRight->flags &= ~EP_Collate;
|
||||
pExpr->x.pRight->flags &= ~EP_Collate;
|
||||
}else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
|
||||
/* Neither X nor Y have COLLATE operators, but X has a non-default
|
||||
** collating sequence. So add the EP_Collate marker on X to cause
|
||||
@@ -135,7 +137,7 @@ static void exprCommute(Parse *pParse, Expr *pExpr){
|
||||
pExpr->pLeft->flags |= EP_Collate;
|
||||
}
|
||||
}
|
||||
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
|
||||
SWAP(Expr*,pExpr->x.pRight,pExpr->pLeft);
|
||||
if( pExpr->op>=TK_GT ){
|
||||
assert( TK_LT==TK_GT+2 );
|
||||
assert( TK_GE==TK_LE+2 );
|
||||
@@ -280,8 +282,9 @@ static int isLikeOrGlob(
|
||||
|| (zNew[0]+1=='0' && iTo==1)
|
||||
){
|
||||
if( pLeft->op!=TK_COLUMN
|
||||
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|
||||
|| IsVirtual(pLeft->pTab) /* Value might be numeric */
|
||||
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|
||||
|| NEVER(pLeft->eX!=EX_Tab)
|
||||
|| IsVirtual(pLeft->x.pTab) /* Value might be numeric */
|
||||
){
|
||||
sqlite3ExprDelete(db, pPrefix);
|
||||
sqlite3ValueFree(pVal);
|
||||
@@ -382,7 +385,7 @@ static int isAuxiliaryVtabOperator(
|
||||
** MATCH(expression,vtab_column)
|
||||
*/
|
||||
pCol = pList->a[1].pExpr;
|
||||
if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
|
||||
if( pCol->op==TK_COLUMN && pCol->eX==EX_Tab && IsVirtual(pCol->x.pTab) ){
|
||||
for(i=0; i<ArraySize(aOp); i++){
|
||||
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
|
||||
*peOp2 = aOp[i].eOp2;
|
||||
@@ -404,12 +407,12 @@ static int isAuxiliaryVtabOperator(
|
||||
** with function names in an arbitrary case.
|
||||
*/
|
||||
pCol = pList->a[0].pExpr;
|
||||
if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
|
||||
if( pCol->op==TK_COLUMN && pCol->eX==EX_Tab && IsVirtual(pCol->x.pTab) ){
|
||||
sqlite3_vtab *pVtab;
|
||||
sqlite3_module *pMod;
|
||||
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
|
||||
void *pNotUsed;
|
||||
pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab;
|
||||
pVtab = sqlite3GetVTable(db, pCol->x.pTab)->pVtab;
|
||||
assert( pVtab!=0 );
|
||||
assert( pVtab->pModule!=0 );
|
||||
pMod = (sqlite3_module *)pVtab->pModule;
|
||||
@@ -426,11 +429,12 @@ static int isAuxiliaryVtabOperator(
|
||||
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
|
||||
int res = 0;
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
Expr *pRight = pExpr->pRight;
|
||||
if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
|
||||
Expr *pRight = 0;
|
||||
if( pLeft->op==TK_COLUMN && pLeft->eX==EX_Tab && IsVirtual(pLeft->x.pTab) ){
|
||||
res++;
|
||||
}
|
||||
if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){
|
||||
if( pExpr->eX==EX_Right && (pRight = pExpr->x.pRight)->op==TK_COLUMN
|
||||
&& pRight->eX==EX_Tab && IsVirtual(pRight->x.pTab) ){
|
||||
res++;
|
||||
SWAP(Expr*, pLeft, pRight);
|
||||
}
|
||||
@@ -516,10 +520,14 @@ static void whereCombineDisjuncts(
|
||||
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
|
||||
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
|
||||
&& (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
|
||||
assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
|
||||
assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
|
||||
if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
|
||||
if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return;
|
||||
assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->eX==EX_Right );
|
||||
assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->eX==EX_Right );
|
||||
if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ){
|
||||
return;
|
||||
}
|
||||
if( sqlite3ExprCompare(0,pOne->pExpr->x.pRight, pTwo->pExpr->x.pRight,-1) ){
|
||||
return;
|
||||
}
|
||||
/* If we reach this point, it means the two subterms can be combined */
|
||||
if( (eOp & (eOp-1))!=0 ){
|
||||
if( eOp & (WO_LT|WO_LE) ){
|
||||
@@ -827,7 +835,8 @@ static void exprAnalyzeOrTerm(
|
||||
** of both right and left sides must be such that no type
|
||||
** conversions are required on the right. (Ticket #2249)
|
||||
*/
|
||||
affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight);
|
||||
assert( pOrTerm->pExpr->eX==EX_Right );
|
||||
affRight = sqlite3ExprAffinity(pOrTerm->pExpr->x.pRight);
|
||||
affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);
|
||||
if( affRight!=0 && affRight!=affLeft ){
|
||||
okToChngToIN = 0;
|
||||
@@ -853,25 +862,28 @@ static void exprAnalyzeOrTerm(
|
||||
assert( pOrTerm->eOperator & WO_EQ );
|
||||
assert( pOrTerm->leftCursor==iCursor );
|
||||
assert( pOrTerm->u.leftColumn==iColumn );
|
||||
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
|
||||
assert( pOrTerm->pExpr->eX==EX_Right );
|
||||
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->x.pRight, 0);
|
||||
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
|
||||
pLeft = pOrTerm->pExpr->pLeft;
|
||||
}
|
||||
assert( pLeft!=0 );
|
||||
pDup = sqlite3ExprDup(db, pLeft, 0);
|
||||
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
|
||||
if( pNew ){
|
||||
if( pNew && pList ){
|
||||
int idxNew;
|
||||
transferJoinMarkings(pNew, pExpr);
|
||||
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
|
||||
assert( pNew->eX==EX_None );
|
||||
pNew->eX = EX_List;
|
||||
pNew->x.pList = pList;
|
||||
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew==0 );
|
||||
exprAnalyze(pSrc, pWC, idxNew);
|
||||
/* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */
|
||||
/* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm used again */
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
}else{
|
||||
sqlite3ExprListDelete(db, pList);
|
||||
sqlite3ExprDelete(db, pNew);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -900,15 +912,16 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){
|
||||
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
|
||||
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
|
||||
aff2 = sqlite3ExprAffinity(pExpr->pRight);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
aff2 = sqlite3ExprAffinity(pExpr->x.pRight);
|
||||
if( aff1!=aff2
|
||||
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
|
||||
){
|
||||
return 0;
|
||||
}
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
|
||||
pColl = sqlite3ComparisonExprCollSeq(pParse, pExpr);
|
||||
if( sqlite3IsBinary(pColl) ) return 1;
|
||||
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
|
||||
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->x.pRight);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1053,17 +1066,25 @@ static void exprAnalyze(
|
||||
prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
|
||||
op = pExpr->op;
|
||||
if( op==TK_IN ){
|
||||
assert( pExpr->pRight==0 );
|
||||
assert( pExpr->eX!=EX_Right );
|
||||
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect);
|
||||
}else{
|
||||
pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList);
|
||||
switch( pExpr->eX ){
|
||||
case EX_Select: {
|
||||
pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect);
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet,pExpr->x.pList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else if( op==TK_ISNULL ){
|
||||
pTerm->prereqRight = 0;
|
||||
}else{
|
||||
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
|
||||
assert( op!=TK_ISNULL || pExpr->eX!=EX_Right );
|
||||
if( pExpr->eX==EX_Right ){
|
||||
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->x.pRight);
|
||||
}else{
|
||||
pTerm->prereqRight = 0;
|
||||
}
|
||||
}
|
||||
pMaskSet->bVarSelect = 0;
|
||||
prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
|
||||
@@ -1084,10 +1105,16 @@ static void exprAnalyze(
|
||||
pTerm->eOperator = 0;
|
||||
if( allowedOp(op) ){
|
||||
int aiCurCol[2];
|
||||
Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
|
||||
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
|
||||
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
|
||||
Expr *pLeft, *pRight;
|
||||
u16 opMask;
|
||||
|
||||
pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
|
||||
if( pExpr->eX==EX_Right ){
|
||||
pRight = sqlite3ExprSkipCollate(pExpr->x.pRight);
|
||||
}else{
|
||||
pRight = 0;
|
||||
}
|
||||
opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
|
||||
if( pTerm->iField>0 ){
|
||||
assert( op==TK_IN );
|
||||
assert( pLeft->op==TK_VECTOR );
|
||||
@@ -1328,17 +1355,18 @@ static void exprAnalyze(
|
||||
if( pWC->op==TK_AND
|
||||
&& (pExpr->op==TK_EQ || pExpr->op==TK_IS)
|
||||
&& (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
|
||||
&& sqlite3ExprVectorSize(pExpr->pRight)==nLeft
|
||||
&& ( (pExpr->pLeft->flags & EP_xIsSelect)==0
|
||||
|| (pExpr->pRight->flags & EP_xIsSelect)==0)
|
||||
&& ALWAYS(pExpr->eX==EX_Right)
|
||||
&& sqlite3ExprVectorSize(pExpr->x.pRight)==nLeft
|
||||
&& ( pExpr->pLeft->eX!=EX_Select || pExpr->x.pRight->eX!=EX_Select )
|
||||
){
|
||||
int i;
|
||||
for(i=0; i<nLeft; i++){
|
||||
int idxNew;
|
||||
Expr *pNew;
|
||||
Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
|
||||
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
|
||||
Expr *pNew, *pLeft, *pRight;
|
||||
|
||||
pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
|
||||
assert( pExpr->eX==EX_Right );
|
||||
pRight = sqlite3ExprForVectorField(pParse, pExpr->x.pRight, i);
|
||||
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
|
||||
transferJoinMarkings(pNew, pExpr);
|
||||
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
|
||||
@@ -1446,8 +1474,9 @@ void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
|
||||
if( pE2->op!=op ){
|
||||
whereClauseInsert(pWC, pExpr, 0);
|
||||
}else{
|
||||
assert( pE2->eX==EX_Right );
|
||||
sqlite3WhereSplit(pWC, pE2->pLeft, op);
|
||||
sqlite3WhereSplit(pWC, pE2->pRight, op);
|
||||
sqlite3WhereSplit(pWC, pE2->x.pRight, op);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1506,14 +1535,20 @@ Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
|
||||
}
|
||||
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
|
||||
if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
|
||||
if( p->pRight ){
|
||||
mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
|
||||
assert( p->x.pList==0 );
|
||||
}else if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
|
||||
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
|
||||
}else if( p->x.pList ){
|
||||
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
|
||||
switch( p->eX ){
|
||||
case EX_Right: {
|
||||
mask |= sqlite3WhereExprUsageNN(pMaskSet, p->x.pRight);
|
||||
break;
|
||||
}
|
||||
case EX_Select: {
|
||||
if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
|
||||
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
|
||||
break;
|
||||
}
|
||||
case EX_List: {
|
||||
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
@@ -1583,7 +1618,8 @@ void sqlite3WhereTabFuncArgs(
|
||||
if( pColRef==0 ) return;
|
||||
pColRef->iTable = pItem->iCursor;
|
||||
pColRef->iColumn = k++;
|
||||
pColRef->pTab = pTab;
|
||||
pColRef->x.pTab = pTab;
|
||||
pColRef->eX = EX_Tab;
|
||||
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
|
||||
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0));
|
||||
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix bestindex4
|
||||
set testprefix bestindex5
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
@@ -247,4 +247,3 @@ do_execsql_test 3.5 { SELECT rowid, * FROM t4 WHERE rowid!=1 OR x!='245'; } {}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
Reference in New Issue
Block a user