From: drh <> Date: Thu, 7 Oct 2021 17:43:30 +0000 (+0000) Subject: Protect all accesses to the Expr.x union using nearby assert()s and branches. X-Git-Tag: version-3.37.0~150 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a4eeccdfdf9a9b4a5a007d17ac51f124656272d9;p=thirdparty%2Fsqlite.git Protect all accesses to the Expr.x union using nearby assert()s and branches. FossilOrigin-Name: 8eaa1d4a98b24adf245bbd2fe9212aa6a924a0f09c445906d7f87574f36a7423 --- diff --git a/manifest b/manifest index de179051f3..4be9248ca9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sincorrect\sassert()\son\sPRAGMA\stable_xinfo\sadded\sby\sthe\sprevious\scheck-in. -D 2021-10-07T14:19:32.259 +C Protect\sall\saccesses\sto\sthe\sExpr.x\sunion\susing\snearby\sassert()s\sand\sbranches. +D 2021-10-07T17:43:30.167 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -501,10 +501,10 @@ F src/date.c fa928630fecf1d436cdc7a7a5c950c781709023ca782c21b7a43cc7361a9451e F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 3ce6af6b64c8b476de51ccc32da0cb3142d42e65754e1d8118addf65b8bcba15 -F src/expr.c a2ceac9ee826c43d0943d1412bd8ef668db24fca57d2829453d13c6eb1dccb1c +F src/expr.c 19c0b5c7afaf6a305274b7de312f319bd86e802383f08ef6633f0752f51d96a8 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 0c57a9cd2a0ecd04dde0c06e41df46959526f52a68c4409591e0f8c41a577042 -F src/func.c 315c63812b5ad965158fccdb3c15b155f62d123d064efeda87d35b23fd5d529d +F src/func.c 9577175a1459f65c9e3c4bbe7ed0bdf97ee928f693c81ee9f61e2642414c917c F src/global.c 612ea60c9acbcb45754c2ed659b4a56936a06814718e969636fedc7e3b889808 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 @@ -547,14 +547,14 @@ F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad F src/prepare.c 8f07616db04337057b8498b72d051ee90f73c54615c2e908c05404cef1e060b7 F src/printf.c 5901672228f305f7d493cbc4e7d76a61a5caecdbc1cd06b1f9ec42ea4265cf8d F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c -F src/resolve.c efbb58ab3bf5ce041a8529f08866811148fca2ee079d5b919c7681319b5e5ebc +F src/resolve.c 7f8954f49ddf18d16a13866593eb4f51a6deba8b30b2d877e27ef1b385cd94db F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 6b33d8197dad64015aca2031ee7ae67968c1532e812662fbce2406b39f46c278 +F src/select.c 6164779bdafadf23f506e87224095b73f27be519b242579bd9d24a6d6a53d9fb F src/shell.c.in ac685e63c506fb2e39375c83347c88bff84dc48fa5d6a59f508d7d67951693a0 F src/sqlite.h.in 4e977a5e2ed1a9e8987ff65a2cab5f99a4298ebf040ea5ff636e1753339ff45a F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510 -F src/sqliteInt.h 398111a3db45b92158b81d1fb9d7add8907704e83d4190a3560ebcf2bae6a151 +F src/sqliteInt.h e62e6eab356e01a8cf1c88d0a2ec7e403e5d3b141b4816ec0b5ea23acd1fcd14 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -614,7 +614,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c bae853ad129d1129c063de8630a3e99e306283bc40146f359b1bb91be2c08f1e -F src/treeview.c f8eaf6e9a237e7666ae18b47d7ff5a9091afdc5c2d2a08a493d41be24ce70c46 +F src/treeview.c e80a6126f82c0cd0a939aa617c428329c6e2c3351b7d4dabb8b8a83c9b4e7696 F src/trigger.c 3f612ce5f0858b6c23460a3c799d01f408b49b0b29d931d8b8e6fc224a8667de F src/update.c 69c4c10bc6873a80c0a77cb578f9fc60ee90003d03f9530bc3370fa24615772d F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 @@ -627,7 +627,7 @@ F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5 F src/vdbeaux.c 897912feb91ec3cd8dedc3fce21d192fd6d37d299538a13d9d93100b22e4d4a0 F src/vdbeblob.c 292e96c01c4219fca71d74e1002906d43eb232af4bd83f7552a3faec741f3eb8 -F src/vdbemem.c 51cb5d507a0f62cbf2ab6dd1f2042873807146d05920c6943955ecf4cec6529f +F src/vdbemem.c 8be0af1060012520381d3296fcb1718e80cd5b99ce04f51f7e1c4dba4072caac F src/vdbesort.c cd5130f683706c1a43e165a74187745fb3351cb56052cf9dc91de820634bbde2 F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c @@ -635,12 +635,12 @@ F src/vtab.c 3a6640d86d5dfae8f69715a1ee7405bb96d8982b39655b91c1f3648baae476a8 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 2be08331d798237ad5d7ae0b252700ffb2b63189cb18d993496d009a93e2f81c F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a -F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac -F src/where.c f71086505c5db78209574eaffdb01c4e7beb745873ccba2cfcd4822232ef4e39 +F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b +F src/where.c 56e1902e9b91fb1fe159181a21c34abd59a01e2cb8f5ef4c3e478d32c5d838df F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b -F src/wherecode.c af9bc0608f07f6582affb0e4f30f95815cca080feb5359c2acc4558b48500604 -F src/whereexpr.c 108a89887ea4943c2573f43c0b37342e4a23afa215d88f5d137d205c7fd2f66a -F src/window.c 7bb95e7e6e1c7279ccaf1784c06ccf55c33303c1c2dc37aa4b13fab312b7bd50 +F src/wherecode.c 6721f5de1d74d952b473c3f2473ea36b4a3aafed2c0ae0edb02c7e8a6b908d43 +F src/whereexpr.c 01d87dc0d5fb0a18100a65ba5466e399f2b8d96b3ec8a6056cf2aac10436afa5 +F src/window.c 0dff6fedf61493490d21ced5d7a7b4321d4c0db6c8123f0179c46080a860850a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7 @@ -1929,7 +1929,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 9af863f065e0bef491c2ab7525194505f9516f4e6dfc789d2e3a9d2c2438533a -R eeba287e3c7adfad939bd3178ae64a7a +P f85cb287c52baa729aeb223038e979a3b74a1eb3d97bf59c01f5417998204f84 +R d1a38de85ec9395d66459f512bc9b39f U drh -Z ead3dbf79919d143e014b4c2002fbeb0 +Z a07d4736a8e9c697e3914dd4948a3735 diff --git a/manifest.uuid b/manifest.uuid index 8d5c73ec26..2451d9c2a4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f85cb287c52baa729aeb223038e979a3b74a1eb3d97bf59c01f5417998204f84 \ No newline at end of file +8eaa1d4a98b24adf245bbd2fe9212aa6a924a0f09c445906d7f87574f36a7423 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 7d2558d2a5..01f6ae4199 100644 --- a/src/expr.c +++ b/src/expr.c @@ -57,7 +57,7 @@ char sqlite3ExprAffinity(const Expr *pExpr){ return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); } if( op==TK_SELECT ){ - assert( pExpr->flags&EP_xIsSelect ); + assert( ExprUseXSelect(pExpr) ); assert( pExpr->x.pSelect!=0 ); assert( pExpr->x.pSelect->pEList!=0 ); assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 ); @@ -70,7 +70,7 @@ char sqlite3ExprAffinity(const Expr *pExpr){ } #endif if( op==TK_SELECT_COLUMN ){ - assert( pExpr->pLeft->flags&EP_xIsSelect ); + assert( pExpr->pLeft!=0 && ExprUseXSelect(pExpr->pLeft) ); assert( pExpr->iColumn < pExpr->iTable ); assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr ); return sqlite3ExprAffinity( @@ -78,6 +78,7 @@ char sqlite3ExprAffinity(const Expr *pExpr){ ); } if( op==TK_VECTOR ){ + assert( ExprUseXList(pExpr) ); return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr); } return pExpr->affExpr; @@ -137,7 +138,7 @@ Expr *sqlite3ExprSkipCollate(Expr *pExpr){ Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){ while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){ if( ExprHasProperty(pExpr, EP_Unlikely) ){ - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( ExprUseXList(pExpr) ); assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; @@ -187,6 +188,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ continue; } if( op==TK_VECTOR ){ + assert( ExprUseXList(p) ); p = p->x.pList->a[0].pExpr; continue; } @@ -201,11 +203,9 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ }else{ Expr *pNext = p->pRight; /* The Expr.x union is never used at the same time as Expr.pRight */ + assert( ExprUseXList(p) ); assert( p->x.pList==0 || p->pRight==0 ); - if( p->x.pList!=0 - && !db->mallocFailed - && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) - ){ + if( p->x.pList!=0 && !db->mallocFailed ){ int i; for(i=0; ALWAYS(ix.pList->nExpr); i++){ if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ @@ -288,7 +288,7 @@ static char comparisonAffinity(const Expr *pExpr){ aff = sqlite3ExprAffinity(pExpr->pLeft); if( pExpr->pRight ){ aff = sqlite3CompareAffinity(pExpr->pRight, aff); - }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + }else if( ExprUseXSelect(pExpr) ){ aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); }else if( aff==0 ){ aff = SQLITE_AFF_BLOB; @@ -428,8 +428,10 @@ int sqlite3ExprVectorSize(const Expr *pExpr){ u8 op = pExpr->op; if( op==TK_REGISTER ) op = pExpr->op2; if( op==TK_VECTOR ){ + assert( ExprUseXList(pExpr) ); return pExpr->x.pList->nExpr; }else if( op==TK_SELECT ){ + assert( ExprUseXSelect(pExpr) ); return pExpr->x.pSelect->pEList->nExpr; }else{ return 1; @@ -456,8 +458,10 @@ Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){ if( sqlite3ExprIsVector(pVector) ){ assert( pVector->op2==0 || pVector->op==TK_REGISTER ); if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){ + assert( ExprUseXSelect(pVector) ); return pVector->x.pSelect->pEList->a[i].pExpr; }else{ + assert( ExprUseXList(pVector) ); return pVector->x.pList->a[i].pExpr; } } @@ -493,7 +497,7 @@ Expr *sqlite3ExprForVectorField( ){ Expr *pRet; if( pVector->op==TK_SELECT ){ - assert( pVector->flags & EP_xIsSelect ); + assert( ExprUseXSelect(pVector) ); /* The TK_SELECT_COLUMN Expr node: ** ** pLeft: pVector containing TK_SELECT. Not deleted. @@ -518,7 +522,9 @@ Expr *sqlite3ExprForVectorField( } }else{ if( pVector->op==TK_VECTOR ){ - Expr **ppVector = &pVector->x.pList->a[iField].pExpr; + Expr **ppVector; + assert( ExprUseXList(pVector) ); + ppVector = &pVector->x.pList->a[iField].pExpr; pVector = *ppVector; if( IN_RENAME_OBJECT ){ /* This must be a vector UPDATE inside a trigger */ @@ -582,10 +588,12 @@ static int exprVectorRegister( return pVector->iTable+iField; } if( op==TK_SELECT ){ + assert( ExprUseXSelect(pVector) ); *ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr; return regSelect+iField; } if( op==TK_VECTOR ){ + assert( ExprUseXList(pVector) ); *ppExpr = pVector->x.pList->a[iField].pExpr; return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree); } @@ -760,7 +768,7 @@ static void exprSetHeight(Expr *p){ int nHeight = 0; heightOfExpr(p->pLeft, &nHeight); heightOfExpr(p->pRight, &nHeight); - if( ExprHasProperty(p, EP_xIsSelect) ){ + if( ExprUseXSelect(p) ){ heightOfSelect(p->x.pSelect, &nHeight); }else if( p->x.pList ){ heightOfExprList(p->x.pList, &nHeight); @@ -799,7 +807,7 @@ int sqlite3SelectExprHeight(const Select *p){ */ void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ if( pParse->nErr ) return; - if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ + if( p && ExprUseXList(p) && p->x.pList ){ p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); } } @@ -983,13 +991,20 @@ Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){ for(ii=0; iinExpr; ii++){ Select *pSel; Expr *pExpr = pEList->a[ii].pExpr; - int nExprElem = (pExpr->op==TK_VECTOR ? pExpr->x.pList->nExpr : 1); + int nExprElem; + if( pExpr->op==TK_VECTOR ){ + assert( ExprUseXList(pExpr) ); + nExprElem = pExpr->x.pList->nExpr; + }else{ + nExprElem = 1; + } if( nExprElem!=nElem ){ sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d", nExprElem, nExprElem>1?"s":"", nElem ); break; } + assert( ExprUseXList(pExpr) ); pSel = sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0); pExpr->x.pList = 0; if( pSel ){ @@ -1059,7 +1074,7 @@ Expr *sqlite3ExprFunction( } pNew->x.pList = pList; ExprSetProperty(pNew, EP_HasFunc); - assert( !ExprHasProperty(pNew, EP_xIsSelect) ); + assert( ExprUseXList(pNew) ); sqlite3ExprSetHeightAndFlags(pParse, pNew); if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct); return pNew; @@ -1195,17 +1210,18 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ assert( p->pLeft==0 ); assert( p->pRight==0 ); - assert( p->x.pSelect==0 ); + assert( !ExprUseXSelect(p) || p->x.pSelect==0 ); + assert( !ExprUseXList(p) || p->x.pList==0 ); } #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 ); + assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 ); if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); if( p->pRight ){ assert( !ExprHasProperty(p, EP_WinFunc) ); sqlite3ExprDeleteNN(db, p->pRight); - }else if( ExprHasProperty(p, EP_xIsSelect) ){ + }else if( ExprUseXSelect(p) ){ assert( !ExprHasProperty(p, EP_WinFunc) ); sqlite3SelectDelete(db, p->x.pSelect); }else{ @@ -1436,7 +1452,7 @@ static Expr *exprDup(sqlite3 *db, const 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) ){ + if( ExprUseXSelect(p) ){ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); }else{ pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); @@ -2285,7 +2301,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( ExprUseXSelect(pExpr) ){ pWalker->eCode = 0; return WRC_Abort; } @@ -2512,7 +2528,7 @@ static Select *isCandidateForInOpt(const Expr *pX){ ExprList *pEList; Table *pTab; int i; - if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */ + if( !ExprUseXSelect(pX) ) 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 */ @@ -2683,7 +2699,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 && ExprUseXSelect(pX) ){ int i; ExprList *pEList = pX->x.pSelect->pEList; for(i=0; inExpr; i++){ @@ -2839,7 +2855,7 @@ int sqlite3FindInIndex( */ if( eType==0 && (inFlags & IN_INDEX_NOOP_OK) - && !ExprHasProperty(pX, EP_xIsSelect) + && ExprUseXList(pX) && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) ){ eType = IN_INDEX_NOOP; @@ -2887,7 +2903,7 @@ int sqlite3FindInIndex( static char *exprINAffinity(Parse *pParse, const Expr *pExpr){ Expr *pLeft = pExpr->pLeft; int nVal = sqlite3ExprVectorSize(pLeft); - Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0; + Select *pSelect = ExprUseXSelect(pExpr) ? pExpr->x.pSelect : 0; char *zRet; assert( pExpr->op==TK_IN ); @@ -2937,7 +2953,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( ExprUseXSelect(pExpr) ){ sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1); }else #endif @@ -3001,7 +3017,7 @@ void sqlite3CodeRhsOfIN( */ if( ExprHasProperty(pExpr, EP_Subrtn) ){ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUseXSelect(pExpr) ){ ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d", pExpr->x.pSelect->selId)); } @@ -3033,7 +3049,7 @@ void sqlite3CodeRhsOfIN( pExpr->iTable = iTab; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, nVal); #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUseXSelect(pExpr) ){ VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId)); }else{ VdbeComment((v, "RHS of IN operator")); @@ -3041,7 +3057,7 @@ void sqlite3CodeRhsOfIN( #endif pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUseXSelect(pExpr) ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary @@ -3175,7 +3191,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ 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( ExprUseXSelect(pExpr) ); pSel = pExpr->x.pSelect; /* If this routine has already been coded, then invoke it as a @@ -3283,7 +3299,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ */ int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){ int nVector = sqlite3ExprVectorSize(pIn->pLeft); - if( (pIn->flags & EP_xIsSelect)!=0 && !pParse->db->mallocFailed ){ + if( ExprUseXSelect(pIn) && !pParse->db->mallocFailed ){ if( nVector!=pIn->x.pSelect->pEList->nExpr ){ sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector); return 1; @@ -3417,13 +3433,15 @@ static void sqlite3ExprCodeIN( ** This is step (1) in the in-operator.md optimized algorithm. */ if( eType==IN_INDEX_NOOP ){ - ExprList *pList = pExpr->x.pList; - CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); + ExprList *pList; + CollSeq *pColl; int labelOk = sqlite3VdbeMakeLabel(pParse); int r2, regToFree; int regCkNull = 0; int ii; - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( ExprUseXList(pExpr) ); + pList = pExpr->x.pList; + pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); if( destIfNull!=destIfFalse ){ regCkNull = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull); @@ -3809,6 +3827,7 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){ int i; iResult = pParse->nMem+1; pParse->nMem += nResult; + assert( ExprUseXList(p) ); for(i=0; ix.pList->a[i].pExpr, i+iResult); } @@ -4315,8 +4334,8 @@ expr_code_doover: ** multiple times if we know they always give the same result */ return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); } - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); assert( !ExprHasProperty(pExpr, EP_TokenOnly) ); + assert( ExprUseXList(pExpr) ); pFarg = pExpr->x.pList; nFarg = pFarg ? pFarg->nExpr : 0; assert( !ExprHasProperty(pExpr, EP_IntValue) ); @@ -4435,7 +4454,10 @@ expr_code_doover: testcase( op==TK_SELECT ); if( pParse->db->mallocFailed ){ return 0; - }else if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){ + }else if( op==TK_SELECT + && ALWAYS( ExprUseXSelect(pExpr) ) + && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 + ){ sqlite3SubselectError(pParse, nCol, 1); }else{ return sqlite3CodeSubselect(pParse, pExpr); @@ -4607,7 +4629,7 @@ expr_code_doover: Expr *pDel = 0; sqlite3 *db = pParse->db; - assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); + assert( ExprUseXList(pExpr) && pExpr->x.pList!=0 ); assert(pExpr->x.pList->nExpr > 0); pEList = pExpr->x.pList; aListelem = pEList->a; @@ -4952,7 +4974,7 @@ static void exprCodeBetween( memset(&compRight, 0, sizeof(Expr)); memset(&exprAnd, 0, sizeof(Expr)); - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( ExprUseXList(pExpr) ); pDel = sqlite3ExprDup(db, pExpr->pLeft, 0); if( db->mallocFailed==0 ){ exprAnd.op = TK_AND; @@ -5539,12 +5561,13 @@ static int exprImpliesNotNull( switch( p->op ){ case TK_IN: { if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0; - assert( ExprHasProperty(p,EP_xIsSelect) - || (p->x.pList!=0 && p->x.pList->nExpr>0) ); + assert( ExprUseXSelect(p) || (p->x.pList!=0 && p->x.pList->nExpr>0) ); return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); } case TK_BETWEEN: { - ExprList *pList = p->x.pList; + ExprList *pList; + assert( ExprUseXList(p) ); + pList = p->x.pList; assert( pList!=0 ); assert( pList->nExpr==2 ); if( seenNot ) return 0; @@ -5908,6 +5931,7 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ cnt.iSrcInner = (pSrcList&&pSrcList->nSrc)?pSrcList->a[0].iCursor:0x7FFFFFFF; cnt.nThis = 0; cnt.nOther = 0; + assert( ExprUseXList(pExpr) ); sqlite3WalkExprList(&w, pExpr->x.pList); #ifndef SQLITE_OMIT_WINDOWFUNC if( ExprHasProperty(pExpr, EP_WinFunc) ){ @@ -6112,7 +6136,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ pItem = &pAggInfo->aFunc[i]; pItem->pFExpr = pExpr; pItem->iMem = ++pParse->nMem; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( ExprUseUToken(pExpr) ); pItem->pFunc = sqlite3FindFunction(pParse->db, pExpr->u.zToken, pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); diff --git a/src/func.c b/src/func.c index 3e1bd86c47..208da48e27 100644 --- a/src/func.c +++ b/src/func.c @@ -1935,10 +1935,10 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ int nExpr; assert( pExpr!=0 ); assert( pExpr->op==TK_FUNCTION ); + assert( ExprUseXList(pExpr) ); if( !pExpr->x.pList ){ return 0; } - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); nExpr = pExpr->x.pList->nExpr; assert( !ExprHasProperty(pExpr, EP_IntValue) ); pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0); diff --git a/src/resolve.c b/src/resolve.c index 24c9509658..a29b483db7 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -518,8 +518,8 @@ static int lookupName( ){ Expr *pOrig; assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - assert( pExpr->x.pList==0 ); - assert( pExpr->x.pSelect==0 ); + assert( ExprUseXList(pExpr)==0 || pExpr->x.pList==0 ); + assert( ExprUseXSelect(pExpr)==0 || pExpr->x.pSelect==0 ); pOrig = pEList->a[j].pExpr; if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); @@ -1120,7 +1120,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ #endif case TK_IN: { testcase( pExpr->op==TK_IN ); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUseXSelect(pExpr) ){ int nRef = pNC->nRef; testcase( pNC->ncFlags & NC_IsCheck ); testcase( pNC->ncFlags & NC_PartIdx ); @@ -1177,6 +1177,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ assert( pExpr->pLeft!=0 ); nLeft = sqlite3ExprVectorSize(pExpr->pLeft); if( pExpr->op==TK_BETWEEN ){ + assert( ExprUseXList(pExpr) ); nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr); if( nRight==nLeft ){ nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr); diff --git a/src/select.c b/src/select.c index d8047835ba..39bdc49686 100644 --- a/src/select.c +++ b/src/select.c @@ -391,10 +391,13 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(p, EP_NoReduce); p->iRightJoinTable = iTable; - if( p->op==TK_FUNCTION && p->x.pList ){ - int i; - for(i=0; ix.pList->nExpr; i++){ - sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable); + if( p->op==TK_FUNCTION ){ + assert( ExprUseXList(p) ); + if( p->x.pList ){ + int i; + for(i=0; ix.pList->nExpr; i++){ + sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable); + } } } sqlite3SetJoinExpr(p->pLeft, iTable); @@ -417,10 +420,13 @@ static void unsetJoinExpr(Expr *p, int iTable){ if( p->op==TK_COLUMN && p->iTable==iTable ){ ExprClearProperty(p, EP_CanBeNull); } - if( p->op==TK_FUNCTION && p->x.pList ){ - int i; - for(i=0; ix.pList->nExpr; i++){ - unsetJoinExpr(p->x.pList->a[i].pExpr, iTable); + if( p->op==TK_FUNCTION ){ + assert( ExprUseXList(p) ); + if( p->x.pList ){ + int i; + for(i=0; ix.pList->nExpr; i++){ + unsetJoinExpr(p->x.pList->a[i].pExpr, iTable); + } } } unsetJoinExpr(p->pLeft, iTable); @@ -1866,9 +1872,11 @@ static const char *columnTypeImpl( ** statement. */ NameContext sNC; - Select *pS = pExpr->x.pSelect; - Expr *p = pS->pEList->a[0].pExpr; - assert( ExprHasProperty(pExpr, EP_xIsSelect) ); + Select *pS; + Expr *p; + assert( ExprUseXSelect(pExpr) ); + pS = pExpr->x.pSelect; + p = pS->pEList->a[0].pExpr; sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; sNC.pParse = pNC->pParse; @@ -3675,7 +3683,7 @@ static Expr *substExpr( } pExpr->pLeft = substExpr(pSubst, pExpr->pLeft); pExpr->pRight = substExpr(pSubst, pExpr->pRight); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUseXSelect(pExpr) ){ substSelect(pSubst, pExpr->x.pSelect, 1); }else{ substExprList(pSubst, pExpr->x.pList); @@ -4886,7 +4894,7 @@ static int pushDownWhereTerms( */ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ - ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */ + ExprList *pEList; /* Arguments to agg function */ const char *zFunc; /* Name of aggregate function pFunc */ ExprList *pOrderBy; u8 sortFlags = 0; @@ -4894,6 +4902,8 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ assert( *ppMinMax==0 ); assert( pFunc->op==TK_AGG_FUNCTION ); assert( !IsWindowFunc(pFunc) ); + assert( ExprUseXList(pFunc) ); + pEList = pFunc->x.pList; if( pEList==0 || pEList->nExpr!=1 || ExprHasProperty(pFunc, EP_WinFunc) @@ -5870,7 +5880,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ for(pFunc=pAggInfo->aFunc, i=0; inFunc; i++, pFunc++){ if( pFunc->iDistinct>=0 ){ Expr *pE = pFunc->pFExpr; - assert( !ExprHasProperty(pE, EP_xIsSelect) ); + assert( ExprUseXList(pE) ); if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " "argument"); @@ -5895,8 +5905,9 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ int i; struct AggInfo_func *pF; for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ - ExprList *pList = pF->pFExpr->x.pList; - assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) ); + ExprList *pList; + assert( ExprUseXList(pF->pFExpr) ); + pList = pF->pFExpr->x.pList; sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0); sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); } @@ -5930,9 +5941,10 @@ static void updateAccumulator( int nArg; int addrNext = 0; int regAgg; - ExprList *pList = pF->pFExpr->x.pList; - assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) ); + ExprList *pList; + assert( ExprUseXList(pF->pFExpr) ); assert( !IsWindowFunc(pF->pFExpr) ); + pList = pF->pFExpr->x.pList; if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){ Expr *pFilter = pF->pFExpr->y.pWin->pFilter; if( pAggInfo->nAccumulator @@ -6178,8 +6190,9 @@ static int countOfViewOptimization(Parse *pParse, Select *p){ if( p->pGroupBy ) return 0; pExpr = p->pEList->a[0].pExpr; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( ExprUseUToken(pExpr) ); if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */ + assert( ExprUseXList(pExpr) ); if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */ if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */ pSub = p->pSrc->a[0].pSelect; @@ -6994,7 +7007,7 @@ int sqlite3Select( } for(i=0; inFunc; i++){ Expr *pExpr = pAggInfo->aFunc[i].pFExpr; - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( ExprUseXList(pExpr) ); sNC.ncFlags |= NC_InAggFunc; sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList); #ifndef SQLITE_OMIT_WINDOWFUNC @@ -7049,7 +7062,9 @@ int sqlite3Select( if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 - && pAggInfo->aFunc[0].pFExpr->x.pList + && ALWAYS(pAggInfo->aFunc[0].pFExpr!=0) + && ALWAYS(ExprUseXList(pAggInfo->aFunc[0].pFExpr)) + && pAggInfo->aFunc[0].pFExpr->x.pList!=0 ){ Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr; pExpr = sqlite3ExprDup(db, pExpr, 0); @@ -7370,6 +7385,7 @@ int sqlite3Select( sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc); } }else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){ + assert( ExprUseXList(pAggInfo->aFunc[0].pFExpr) ); pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList; distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b486d904d3..aae8f17b53 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2886,6 +2886,16 @@ struct Expr { #define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue) #define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse) +/* +** Macros used to ensure that the correct members of unions are accessed. +*/ +#define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0) +#define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0) +#define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0) +#define ExprUseXSelect(E) (((E)->flags&EP_xIsSelect)!=0) +#define ExprUseYTab(E) ((E)->op==TK_COLUMN) +#define ExprUseYWin(E) ((E)->flags&EP_WinFunc)!=0) +#define ExprUseYSub(E) ((E)->op==TK_IN||(E)->op==TK_SELECT||(E)->op==TK_EXISTS) /* Flags for use with Expr.vvaFlags */ diff --git a/src/treeview.c b/src/treeview.c index 27fb69cd15..a7dfe2d43d 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -583,6 +583,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ pFarg = 0; pWin = 0; }else{ + assert( ExprUseXList(pExpr) ); pFarg = pExpr->x.pList; #ifndef SQLITE_OMIT_WINDOWFUNC pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0; @@ -622,11 +623,13 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: { + assert( ExprUseXSelect(pExpr) ); sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags); sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); break; } case TK_SELECT: { + assert( ExprUseXSelect(pExpr) ); sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags); sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); break; @@ -634,7 +637,7 @@ 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) ){ + if( ExprUseXSelect(pExpr) ){ sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); }else{ sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); @@ -655,9 +658,12 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ ** Z is stored in pExpr->pList->a[1].pExpr. */ case TK_BETWEEN: { - Expr *pX = pExpr->pLeft; - Expr *pY = pExpr->x.pList->a[0].pExpr; - Expr *pZ = pExpr->x.pList->a[1].pExpr; + const Expr *pX, *pY, *pZ; + pX = pExpr->pLeft; + assert( ExprUseXList(pExpr) ); + assert( pExpr->x.pList->nExpr==2 ); + pY = pExpr->x.pList->a[0].pExpr; + pZ = pExpr->x.pList->a[1].pExpr; sqlite3TreeViewLine(pView, "BETWEEN"); sqlite3TreeViewExpr(pView, pX, 1); sqlite3TreeViewExpr(pView, pY, 1); @@ -679,6 +685,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ case TK_CASE: { sqlite3TreeViewLine(pView, "CASE"); sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); + assert( ExprUseXList(pExpr) ); sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); break; } @@ -704,6 +711,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ } case TK_VECTOR: { char *z = sqlite3_mprintf("VECTOR%s",zFlgs); + assert( ExprUseXList(pExpr) ); sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z); sqlite3_free(z); break; @@ -712,6 +720,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s", pExpr->iColumn, pExpr->iTable-1, pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : ""); + assert( ExprUseXSelect(pExpr->pLeft) ); sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0); break; } diff --git a/src/vdbemem.c b/src/vdbemem.c index 73077b4881..d381d4fc5c 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1418,6 +1418,7 @@ static int valueFromFunction( assert( pCtx!=0 ); assert( (p->flags & EP_TokenOnly)==0 ); + assert( ExprUseXList(p) ); pList = p->x.pList; if( pList ) nVal = pList->nExpr; assert( !ExprHasProperty(p, EP_IntValue) ); diff --git a/src/walker.c b/src/walker.c index 8c0308473a..f24c052d6d 100644 --- a/src/walker.c +++ b/src/walker.c @@ -75,7 +75,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ assert( !ExprHasProperty(pExpr, EP_WinFunc) ); pExpr = pExpr->pRight; continue; - }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + }else if( ExprUseXSelect(pExpr) ){ assert( !ExprHasProperty(pExpr, EP_WinFunc) ); if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; }else{ diff --git a/src/where.c b/src/where.c index 63ac4e1c12..7583f05631 100644 --- a/src/where.c +++ b/src/where.c @@ -2419,9 +2419,12 @@ 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, *pRhs; + + assert( ExprUseXList(pTerm->pExpr->pLeft) ); + pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr; + pRhs = pTerm->pExpr->pRight; + if( ExprUseXSelect(pRhs) ){ pRhs = pRhs->x.pSelect->pEList->a[i].pExpr; }else{ pRhs = pRhs->x.pList->a[i].pExpr; @@ -2582,7 +2585,7 @@ static int whereLoopAddBtreeIndex( if( eOp & WO_IN ){ Expr *pExpr = pTerm->pExpr; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUseXSelect(pExpr) ){ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ int i; nIn = 46; assert( 46==sqlite3LogEst(25) ); @@ -2723,7 +2726,7 @@ static int whereLoopAddBtreeIndex( if( nInMul==0 && pProbe->nSample && ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol) - && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) + && ((eOp & WO_IN)==0 || ExprUseXList(pTerm->pExpr)) && OptimizationEnabled(db, SQLITE_Stat4) ){ Expr *pExpr = pTerm->pExpr; diff --git a/src/wherecode.c b/src/wherecode.c index 15e4aa8393..d803c674f6 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -416,13 +416,18 @@ static Expr *removeUnindexableInClauseTerms( Expr *pNew; pNew = sqlite3ExprDup(db, pX, 0); if( db->mallocFailed==0 ){ - ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */ - ExprList *pOrigLhs = pNew->pLeft->x.pList; /* Original unmodified LHS */ + ExprList *pOrigRhs; /* Original unmodified RHS */ + ExprList *pOrigLhs; /* Original unmodified LHS */ ExprList *pRhs = 0; /* New RHS after modifications */ ExprList *pLhs = 0; /* New LHS after mods */ int i; /* Loop counter */ Select *pSelect; /* Pointer to the SELECT on the RHS */ + assert( ExprUseXSelect(pNew) ); + pOrigRhs = pNew->x.pSelect->pEList; + assert( pNew->pLeft!=0 ); + assert( ExprUseXList(pNew->pLeft) ); + pOrigLhs = pNew->pLeft->x.pList; for(i=iEq; inLTerm; i++){ if( pLoop->aLTerm[i]->pExpr==pX ){ int iField = pLoop->aLTerm[i]->u.x.iField - 1; @@ -540,7 +545,7 @@ static int codeEqualityTerm( } iTab = 0; - if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ + if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab); }else{ sqlite3 *db = pParse->db; @@ -1105,7 +1110,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( ExprUseXSelect(p) ){ Vdbe *v = pParse->pVdbe; int iSelect; assert( p->op==TK_SELECT ); @@ -1115,7 +1120,9 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ #endif { int i; - ExprList *pList = p->x.pList; + const ExprList *pList; + assert( ExprUseXList(p) ); + pList = p->x.pList; assert( nReg<=pList->nExpr ); for(i=0; ia[i].pExpr, iReg+i); @@ -2461,7 +2468,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; if( (pAlt->eOperator & WO_IN) - && (pAlt->pExpr->flags & EP_xIsSelect) + && ExprUseXSelect(pAlt->pExpr) && (pAlt->pExpr->x.pSelect->pEList->nExpr>1) ){ continue; diff --git a/src/whereexpr.c b/src/whereexpr.c index 336de1d302..8c73feeb33 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -195,6 +195,7 @@ static int isLikeOrGlob( #ifdef SQLITE_EBCDIC if( *pnoCase ) return 0; #endif + assert( ExprUseXList(pExpr) ); pList = pExpr->x.pList; pLeft = pList->a[1].pExpr; @@ -368,6 +369,7 @@ static int isAuxiliaryVtabOperator( Expr *pCol; /* Column reference */ int i; + assert( ExprUseXList(pExpr) ); pList = pExpr->x.pList; if( pList==0 || pList->nExpr!=2 ){ return 0; @@ -873,7 +875,7 @@ static void exprAnalyzeOrTerm( if( pNew ){ int idxNew; transferJoinMarkings(pNew, pExpr); - assert( !ExprHasProperty(pNew, EP_xIsSelect) ); + assert( ExprUseXList(pNew) ); pNew->x.pList = pList; idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); @@ -1001,6 +1003,7 @@ static int exprMightBeIndexed( assert( TK_ISop==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){ + assert( ExprUseXList(pExpr) ); pExpr = pExpr->x.pList->a[0].pExpr; } @@ -1067,7 +1070,7 @@ static void exprAnalyze( if( op==TK_IN ){ assert( pExpr->pRight==0 ); if( sqlite3ExprCheckIN(pParse, pExpr) ) return; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUseXSelect(pExpr) ){ pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect); }else{ pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList); @@ -1103,6 +1106,7 @@ static void exprAnalyze( if( pTerm->u.x.iField>0 ){ assert( op==TK_IN ); assert( pLeft->op==TK_VECTOR ); + assert( ExprUseXList(pLeft) ); pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr; } @@ -1181,9 +1185,11 @@ static void exprAnalyze( ** BETWEEN term is skipped. */ else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){ - ExprList *pList = pExpr->x.pList; + ExprList *pList; int i; static const u8 ops[] = {TK_GE, TK_LE}; + assert( ExprUseXList(pExpr) ); + pList = pExpr->x.pList; assert( pList!=0 ); assert( pList->nExpr==2 ); for(i=0; i<2; i++){ @@ -1276,6 +1282,7 @@ static void exprAnalyze( const char *zCollSeqName; /* Name of collating sequence */ const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC; + assert( ExprUseXList(pExpr) ); pLeft = pExpr->x.pList->a[1].pExpr; pStr2 = sqlite3ExprDup(db, pStr1, 0); assert( pStr1==0 || !ExprHasProperty(pStr1, EP_IntValue) ); @@ -1380,6 +1387,7 @@ static void exprAnalyze( else if( pExpr->op==TK_IN && pTerm->u.x.iField==0 && pExpr->pLeft->op==TK_VECTOR + && ALWAYS( ExprUseXSelect(pExpr) ) && pExpr->x.pSelect->pPrior==0 #ifndef SQLITE_OMIT_WINDOWFUNC && pExpr->x.pSelect->pWin==0 @@ -1543,7 +1551,7 @@ Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ if( p->pRight ){ mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight); assert( p->x.pList==0 ); - }else if( ExprHasProperty(p, EP_xIsSelect) ){ + }else if( ExprUseXSelect(p) ){ if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1; mask |= exprSelectUsage(pMaskSet, p->x.pSelect); }else if( p->x.pList ){ diff --git a/src/window.c b/src/window.c index 89439913c1..21dc285716 100644 --- a/src/window.c +++ b/src/window.c @@ -1030,7 +1030,9 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ ** window function - one for the accumulator, another for interim ** results. */ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - ExprList *pArgs = pWin->pOwner->x.pList; + ExprList *pArgs; + assert( ExprUseXList(pWin->pOwner) ); + pArgs = pWin->pOwner->x.pList; if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){ selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist); pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); @@ -1423,8 +1425,11 @@ void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){ ** regApp+1: integer value used to ensure keys are unique ** regApp+2: output of MakeRecord */ - ExprList *pList = pWin->pOwner->x.pList; - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0); + ExprList *pList; + KeyInfo *pKeyInfo; + assert( ExprUseXList(pWin->pOwner) ); + pList = pWin->pOwner->x.pList; + pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0); pWin->csrApp = pParse->nTab++; pWin->regApp = pParse->nMem+1; pParse->nMem += 3; @@ -1512,7 +1517,9 @@ static void windowCheckValue(Parse *pParse, int reg, int eCond){ ** with the object passed as the only argument to this function. */ static int windowArgCount(Window *pWin){ - ExprList *pList = pWin->pOwner->x.pList; + const ExprList *pList; + assert( ExprUseXList(pWin->pOwner) ); + pList = pWin->pOwner->x.pList; return (pList ? pList->nExpr : 0); } @@ -1697,6 +1704,7 @@ static void windowAggStep( int addrIf = 0; if( pWin->pFilter ){ int regTmp; + assert( ExprUseXList(pWin->pOwner) ); assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr ); assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 ); regTmp = sqlite3GetTempReg(pParse); @@ -1710,6 +1718,7 @@ static void windowAggStep( int iOp = sqlite3VdbeCurrentAddr(v); int iEnd; + assert( ExprUseXList(pWin->pOwner) ); nArg = pWin->pOwner->x.pList->nExpr; regArg = sqlite3GetTempRange(pParse, nArg); sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0); @@ -1724,6 +1733,7 @@ static void windowAggStep( if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ CollSeq *pColl; assert( nArg>0 ); + assert( ExprUseXList(pWin->pOwner) ); pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr); sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ); } @@ -1909,6 +1919,7 @@ static void windowReturnOneRow(WindowCodeArg *p){ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ FuncDef *pFunc = pWin->pFunc; + assert( ExprUseXList(pWin->pOwner) ); if( pFunc->zName==nth_valueName || pFunc->zName==first_valueName ){