From: drh Date: Wed, 19 Sep 2018 14:54:38 +0000 (+0000) Subject: Reduce the size of Expr from 80 to 72 bytes moving the pRight field inside the X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d6bedf14f4ffac622c65cad08a129db90db204b;p=thirdparty%2Fsqlite.git Reduce the size of Expr from 80 to 72 bytes moving the pRight field inside the "x" union. This is an incremental check-in that still has issues. FossilOrigin-Name: 147c61a6d4b2a17d6c1da3584e3f29f2bc441e81fbea9d19110a9169c38fbd5f --- diff --git a/manifest b/manifest index 27f417bc57..d89726185e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\stemporary\sExpr\sobjects\sare\sfully\sinitialized\sprior\sto\ssending\sthem\ninto\ssqlite3ExprCodeTemp(). -D 2018-09-19T11:59:15.245 +C Reduce\sthe\ssize\sof\sExpr\sfrom\s80\sto\s72\sbytes\smoving\sthe\spRight\sfield\sinside\sthe\n"x"\sunion.\s\sThis\sis\san\sincremental\scheck-in\sthat\sstill\shas\sissues. +D 2018-09-19T14:54:38.166 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -438,7 +438,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 2269dd2f37ba963fde4c51e9e83542f126c86a8e10357c17f48137c6bee5299b F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9 -F src/attach.c 8b8e52590fca04bed868461aadc5d38de7542f005310ced863e032c83e1b1b6a +F src/attach.c d06bf7ab9efceb7c679ba8beaeeb3082ce3defde482f54de50ac175469f7c4ca F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 @@ -454,7 +454,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c 07a7ecf18a64478be7241cbb332bc26321586384c750e47fb566f678c5aee512 -F src/expr.c d48bca738efa75f4a8731c55db8425d275e6367163ca0149bed9b6117eab5e32 +F src/expr.c cc72d25fe9c2f3d6e8bdf9d519ab20135a45a8ade37c7712155af5d88693092e F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a F src/func.c 82aeef69505b67197a476836d44cc16c1a434ee53481f23cffb70a75a1bcbc7a @@ -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 15eeb0ead639555727ed81fc61bd8e28968e9379bc074ae9cb48b95c79b50f0d +F src/parse.y cea885dd89f7c2963aee930b93c8ba14a7a9eb2bb31ba146777a7bbbc5b8a121 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 301eadb8bf5afcd0b673d4db3c85c179334e19970af276187932e5b0a97b90ec +F src/resolve.c 1f8444d1155b4711cbe2fc1fcd40ecace3f71faa1cf593472581e17b9b39e6af F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c af9efbeea79c7eaa21f51c2640f9f8e21d1c9dbcea236d5af68bb8f0313d9b1e +F src/select.c f3070ba3c6a591799c62eed45cce83ec458e77f39567debf92e90b022bd2f05a 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 0aed6451d241a43814ac54d93f7d2b8645826ffa9e35e7289240dd38e967b813 +F src/sqliteInt.h b8a598f500ce81be682730b30b5d0dbdc4c1ec70a8ef640b7893d0edcadb5bdd 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 b6f459831c544d697e4b38471b98b972d9dd3b4611d0e8c6338632c7ad926d12 +F src/treeview.c 1bc9fc4ebd661bea19b4f39dd32f34b609faf2250112d83d7ffa40ab1c3b386b F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd F src/update.c 682f112c49247d2fe5950c9fe2226046c6bc497cf114f74d58766926914216ff F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 @@ -577,7 +577,7 @@ 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 @@ -586,11 +586,11 @@ F src/vtab.c 8665561f244c137a2d17b5c3e5910d7303054fe841c5d510e53f23beb0089594 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a -F src/walker.c b2d62136868f1f939a7778bdce8b372bb4e314862cd2b33bd1ec9614eef0b44c -F src/where.c c90c392c7c8c8ea3e36592dba9800cee35eeadd36c512ab904da8245c334b148 +F src/walker.c 4ba292cadd145b8b77e8b2128a363beff0bd87c7f9abfe090c0948eb0330d727 +F src/where.c 33a546a918b0439e3e174351ca00c9158f26d73c5a8bb54c6c3cf5bae20b7499 F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4 -F src/wherecode.c 75a3b20d28a5c9f88e6c6dd9037ffeacdd786feaba8013245f7d8576a093dcf4 -F src/whereexpr.c c08b5afce2e7b9046c65f5edc3302888d79e8c541907a97df089c135895b25f0 +F src/wherecode.c 4c3ec236bfeaf2229e5d862e3ff9a2ac22d7cc3ce69c56892d3d25582bece577 +F src/whereexpr.c ba56a077649e8b0f4453eabfe57f3077c85bc6c9b7b3884bf2223c04f57fbca5 F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -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 8849a463d67d79ec60c74a08835c176c08da651a82731558a1dceac2781cd75d -R db879ad69540fd8a785f584d64935c70 +P de02a1d97a860f780d9b75cddf008a8b1824cf0483f7891e6ed55b83e2d32d91 +R 48c3dc53a777e2b3895af501d46c8ac1 U drh -Z 1294c1f2dad466247d6550207298ec20 +Z 0905558528608b1236ee1840013b25d6 diff --git a/manifest.uuid b/manifest.uuid index 56e8b35607..18d7323951 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -de02a1d97a860f780d9b75cddf008a8b1824cf0483f7891e6ed55b83e2d32d91 \ No newline at end of file +147c61a6d4b2a17d6c1da3584e3f29f2bc441e81fbea9d19110a9169c38fbd5f \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 9d77d83c47..073d74c8b1 100644 --- a/src/attach.c +++ b/src/attach.c @@ -573,9 +573,10 @@ int sqlite3FixExpr( if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; break; } - } - if( sqlite3FixExpr(pFix, pExpr->pRight) ){ - return 1; + case EX_Right: { + if( sqlite3FixExpr(pFix, pExpr->x.pRight) ) return 1; + break; + } } pExpr = pExpr->pLeft; } diff --git a/src/expr.c b/src/expr.c index 82dd06d8e1..43f116aab8 100644 --- a/src/expr.c +++ b/src/expr.c @@ -166,7 +166,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ - Expr *pNext = p->pRight; + 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. */ @@ -178,6 +178,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ break; } } + }else if( p->eX==EX_Right ){ + pNext = p->x.pRight; } p = pNext; } @@ -256,8 +258,8 @@ 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); + 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 ){ @@ -305,8 +307,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 @@ -325,6 +331,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. @@ -342,7 +355,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); @@ -545,7 +558,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; @@ -679,12 +692,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( p->eX==EX_Select ){ - heightOfSelect(p->x.pSelect, &nHeight); - }else if( p->eX==EX_List ){ - 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; } @@ -823,7 +844,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 ){ @@ -1076,36 +1099,32 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ #ifdef SQLITE_DEBUG if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ assert( p->pLeft==0 ); - assert( p->pRight==0 ); assert( p->eX==EX_None ); } if( !ExprHasProperty(p, EP_TokenOnly) ){ assert( p->op!=TK_FUNCTION || p->pLeft==0 ); - assert( p->pRight==0 || p->x.pSelect==0 ); } if( !ExprHasProperty(p, (EP_TokenOnly|EP_Reduced)) ){ assert( p->pWin==0 || p->pLeft==0 ); assert( p->pWin==0 || p->pTab==0 ); assert( p->pWin==0 || p->op==TK_FUNCTION ); - assert( p->pTab==0 || (p->pRight==0 && p->eX==EX_None) ); + assert( p->pTab==0 || p->eX==EX_None ); } #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{ - switch( p->eX ){ - case EX_Select: { - sqlite3SelectDelete(db, p->x.pSelect); - break; - } - case EX_List: { - sqlite3ExprListDelete(db, p->x.pList); - break; - } + 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) ){ @@ -1182,10 +1201,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; } } @@ -1223,7 +1241,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; @@ -1233,7 +1252,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. */ @@ -1313,14 +1332,15 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ } } - /* 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; @@ -1336,12 +1356,14 @@ 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); + } } } } @@ -1418,8 +1440,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 ); @@ -1665,7 +1687,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 @@ -2477,7 +2501,7 @@ int sqlite3FindInIndex( for(i=0; ipLeft, 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 ); @@ -2759,7 +2783,7 @@ int sqlite3CodeSubselect( assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); for(i=0; iaColl[i] = sqlite3BinaryCompareCollSeq( + pKeyInfo->aColl[i] = sqlite3ComparisonCollSeq( pParse, p, pEList->a[i].pExpr ); } @@ -3543,8 +3567,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); @@ -3581,7 +3606,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 ); @@ -3625,7 +3651,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); @@ -4012,7 +4039,8 @@ expr_code_doover: for(i=0; ipLeft; 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); @@ -4388,14 +4419,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: { @@ -4408,7 +4441,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 ){ @@ -4436,8 +4470,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); @@ -4554,14 +4589,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; } @@ -4575,7 +4612,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 ){ @@ -4606,8 +4644,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); @@ -4786,7 +4825,9 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){ 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( 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; } @@ -4884,9 +4925,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; } @@ -4954,8 +4996,9 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); + assert( pExpr->eX==EX_Right ); if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab)) - || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab)) + || (pExpr->x.pRight->op==TK_COLUMN && IsVirtual(pExpr->x.pRight->pTab)) ){ return WRC_Prune; } diff --git a/src/parse.y b/src/parse.y index aaa2f91787..c489c7e393 100644 --- a/src/parse.y +++ b/src/parse.y @@ -939,7 +939,7 @@ idlist(A) ::= nm(Y). p->eX = EX_None; p->flags = EP_Leaf; p->iAgg = -1; - p->pLeft = p->pRight = 0; + p->pLeft = 0; p->pAggInfo = 0; p->pTab = 0; p->op2 = 0; @@ -1100,10 +1100,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; } } } diff --git a/src/resolve.c b/src/resolve.c index 6b2111af29..53bd8165a8 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -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 @@ -429,7 +429,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->pLeft==0 ); assert( pExpr->eX==EX_None ); pOrig = pEList->a[j].pExpr; if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ @@ -521,8 +521,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: @@ -676,14 +679,16 @@ 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; @@ -904,7 +909,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 ){ @@ -932,8 +938,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 ); diff --git a/src/select.c b/src/select.c index 17ba72c76d..864e5a6e7c 100644 --- a/src/select.c +++ b/src/select.c @@ -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; ix.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; ix.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; } } @@ -1957,7 +1957,8 @@ 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 ); @@ -2125,7 +2126,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 +2134,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 +2183,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 +3443,7 @@ static Expr *substExpr( Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr; Expr ifNullRow; assert( pSubst->pEList!=0 && pExpr->iColumnpEList->nExpr ); - assert( pExpr->pRight==0 ); + assert( pExpr->eX!=EX_Right ); if( sqlite3ExprIsVector(pCopy) ){ sqlite3VectorErrorMsg(pSubst->pParse, pCopy); }else{ @@ -3471,7 +3472,6 @@ static Expr *substExpr( pExpr->iTable = pSubst->iNewTable; } pExpr->pLeft = substExpr(pSubst, pExpr->pLeft); - pExpr->pRight = substExpr(pSubst, pExpr->pRight); switch( pExpr->eX ){ case EX_Select: { substSelect(pSubst, pExpr->x.pSelect, 1); @@ -3481,6 +3481,10 @@ static Expr *substExpr( substExprList(pSubst, pExpr->x.pList); break; } + case EX_Right: { + pExpr->x.pRight = substExpr(pSubst, pExpr->x.pRight); + break; + } } } return pExpr; @@ -3720,7 +3724,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) */ } @@ -4115,26 +4121,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); } @@ -4321,7 +4329,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; } @@ -4907,9 +4916,9 @@ static int selectExpander(Walker *pWalker, Select *p){ for(k=0; knExpr; 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( knExpr ){ @@ -4927,7 +4936,7 @@ static int selectExpander(Walker *pWalker, Select *p){ for(k=0; knExpr; 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) diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5779f4d3c3..0efbecf844 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2433,8 +2433,8 @@ 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 */ } x; @@ -4402,7 +4402,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 diff --git a/src/treeview.c b/src/treeview.c index 713fc13b5b..44fc5b595c 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -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; } @@ -601,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: { @@ -626,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); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 5ec3d131e0..aca5692e49 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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); } diff --git a/src/walker.c b/src/walker.c index 4c6701f1c7..f6c773b69d 100644 --- a/src/walker.c +++ b/src/walker.c @@ -45,20 +45,18 @@ 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{ - switch( pExpr->eX ){ - 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; - } + 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 diff --git a/src/where.c b/src/where.c index 2a195f8aff..ef78e5dec6 100644 --- a/src/where.c +++ b/src/where.c @@ -253,7 +253,9 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquivaiCur) - && (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; jnEquiv; 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,8 +2339,11 @@ 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; + 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; @@ -2354,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; } @@ -2630,12 +2644,13 @@ static int whereLoopAddBtreeIndex( && 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; @@ -2789,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; inTerm; i++, pTerm++){ @@ -3244,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); } diff --git a/src/wherecode.c b/src/wherecode.c index 84174ea595..f0f1287b08 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -504,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); @@ -744,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); @@ -1263,8 +1266,9 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( pTerm->eOperator & WO_IN ){ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); addrNotFound = pLevel->addrNxt; - }else{ - Expr *pRight = pTerm->pExpr->pRight; + }else if( pTerm->pExpr->eX==EX_Right ){ + Expr *pRight; + pRight = pTerm->pExpr->x.pRight; codeExprOrVector(pParse, pRight, iTarget, 1); } } @@ -1309,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); } @@ -1395,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 ); @@ -1408,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)]; } @@ -1428,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); } } @@ -1624,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 @@ -1676,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 diff --git a/src/whereexpr.c b/src/whereexpr.c index 16d441c52b..b609521f7d 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -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 ); @@ -426,7 +428,7 @@ 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; + Expr *pRight = pExpr->x.pRight; if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){ res++; } @@ -516,10 +518,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 +833,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,7 +860,8 @@ 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; } @@ -902,15 +910,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); } /* @@ -1055,7 +1064,7 @@ 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; switch( pExpr->eX ){ case EX_Select: { @@ -1067,10 +1076,13 @@ static void exprAnalyze( 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); @@ -1091,10 +1103,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 ); @@ -1335,16 +1353,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->eX!=EX_Select || pExpr->pRight->eX!=EX_Select ) + && 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; ipLeft, 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); @@ -1452,8 +1472,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); } } @@ -1512,20 +1533,19 @@ 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{ - switch( p->eX ){ - 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; - } + 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;