Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -801,11 +801,12 @@ && pWalker->pParse->pTriggerTab==p->pTab ){ renameTokenFind(pWalker->pParse, p, (void*)pExpr); }else if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol - && p->pTab==pExpr->pTab + && ALWAYS(pExpr->eX==EX_Tab) + && p->pTab==pExpr->x.pTab ){ renameTokenFind(pWalker->pParse, p, (void*)pExpr); } return WRC_Continue; } @@ -1339,12 +1340,15 @@ /* ** Walker expression callback used by "RENAME TABLE". */ static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ RenameCtx *p = pWalker->u.pRename; - if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){ - renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab); + if( pExpr->op==TK_COLUMN + && ALWAYS(pExpr->eX==EX_Tab) + && p->pTab==pExpr->x.pTab + ){ + renameTokenFind(pWalker->pParse, p, (void*)&pExpr->x.pTab); } return WRC_Continue; } /* Index: src/attach.c ================================================================== --- src/attach.c +++ src/attach.c @@ -562,17 +562,23 @@ sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); return 1; } } if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; - }else{ - if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; - } - if( sqlite3FixExpr(pFix, pExpr->pRight) ){ - return 1; + switch( pExpr->eX ){ + case EX_Select: { + if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; + break; + } + case EX_List: { + if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; + break; + } + case EX_Right: { + if( sqlite3FixExpr(pFix, pExpr->x.pRight) ) return 1; + break; + } } pExpr = pExpr->pLeft; } return 0; } Index: src/delete.c ================================================================== --- src/delete.c +++ src/delete.c @@ -183,13 +183,11 @@ for(i=0; inKeyCol; i++){ Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName); pEList = sqlite3ExprListAppend(pParse, pEList, p); } pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( pLhs ){ - pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0); - } + sqlite3PExprAddExprList(pParse, pLhs, pEList); } } /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree ** and the SELECT subtree. */ Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -46,25 +46,26 @@ int op; pExpr = sqlite3ExprSkipCollate(pExpr); if( pExpr->flags & EP_Generic ) return 0; op = pExpr->op; if( op==TK_SELECT ){ - assert( pExpr->flags&EP_xIsSelect ); + assert( pExpr->eX==EX_Select ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); } if( op==TK_REGISTER ) op = pExpr->op2; #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); return sqlite3AffinityType(pExpr->u.zToken, 0); } #endif - if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){ - return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + if( (op==TK_AGG_COLUMN || op==TK_COLUMN) + && ALWAYS(pExpr->eX==EX_Tab) && pExpr->x.pTab ){ + return sqlite3TableColumnAffinity(pExpr->x.pTab, pExpr->iColumn); } if( op==TK_SELECT_COLUMN ){ - assert( pExpr->pLeft->flags&EP_xIsSelect ); + assert( pExpr->pLeft->eX==EX_Select ); return sqlite3ExprAffinity( pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr ); } return pExpr->affinity; @@ -106,11 +107,11 @@ ** or likelihood() function at the root of an expression. */ Expr *sqlite3ExprSkipCollate(Expr *pExpr){ while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){ if( ExprHasProperty(pExpr, EP_Unlikely) ){ - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->eX==EX_List ); assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; }else{ assert( pExpr->op==TK_COLLATE ); @@ -141,17 +142,18 @@ while( p ){ int op = p->op; if( p->flags & EP_Generic ) break; if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER) - && p->pTab!=0 + && p->eX==EX_Tab + && p->x.pTab!=0 ){ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ int j = p->iColumn; if( j>=0 ){ - const char *zColl = p->pTab->aCol[j].zColl; + const char *zColl = p->x.pTab->aCol[j].zColl; pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); } break; } if( op==TK_CAST || op==TK_UPLUS ){ @@ -164,24 +166,24 @@ } if( p->flags & EP_Collate ){ if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ - Expr *pNext = p->pRight; - /* The Expr.x union is never used at the same time as Expr.pRight */ - assert( p->x.pList==0 || p->pRight==0 ); + Expr *pNext = 0; /* p->flags holds EP_Collate and p->pLeft->flags does not. And ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at ** least one EP_Collate. Thus the following two ALWAYS. */ - if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){ + if( p->eX==EX_List ){ int i; for(i=0; ALWAYS(ix.pList->nExpr); i++){ if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ pNext = p->x.pList->a[i].pExpr; break; } } + }else if( p->eX==EX_Right ){ + pNext = p->x.pRight; } p = pNext; } }else{ break; @@ -256,13 +258,13 @@ assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT ); assert( pExpr->pLeft ); aff = sqlite3ExprAffinity(pExpr->pLeft); - if( pExpr->pRight ){ - aff = sqlite3CompareAffinity(pExpr->pRight, aff); - }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( pExpr->eX==EX_Right ){ + aff = sqlite3CompareAffinity(pExpr->x.pRight, aff); + }else if( pExpr->eX==EX_Select ){ aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); }else if( aff==0 ){ aff = SQLITE_AFF_BLOB; } return aff; @@ -305,12 +307,16 @@ ** is used, or the default (BINARY) if neither expression has a collating ** type. ** ** 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 ){ CollSeq *pColl; @@ -325,10 +331,17 @@ pColl = sqlite3ExprCollSeq(pParse, pRight); } } 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. */ static int codeCompare( @@ -342,11 +355,11 @@ ){ int p5; 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); sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5); return addr; @@ -437,11 +450,11 @@ Expr *pVector, /* The vector. List of expressions or a sub-SELECT */ int iField /* Which column of the vector to return */ ){ Expr *pRet; if( pVector->op==TK_SELECT ){ - assert( pVector->flags & EP_xIsSelect ); + assert( pVector->eX==EX_Select ); /* The TK_SELECT_COLUMN Expr node: ** ** pLeft: pVector containing TK_SELECT. Not deleted. ** pRight: not used. But recursively deleted. ** iColumn: Index of a column in pVector @@ -545,11 +558,11 @@ u8 op, /* Comparison operator */ u8 p5 /* SQLITE_NULLEQ or zero */ ){ 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; int regRight = 0; u8 opx = op; @@ -679,16 +692,24 @@ ** if appropriate. */ static void exprSetHeight(Expr *p){ int nHeight = 0; heightOfExpr(p->pLeft, &nHeight); - heightOfExpr(p->pRight, &nHeight); - if( ExprHasProperty(p, EP_xIsSelect) ){ - heightOfSelect(p->x.pSelect, &nHeight); - }else if( p->x.pList ){ - heightOfExprList(p->x.pList, &nHeight); - p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); + switch( p->eX ){ + case EX_Select: { + heightOfSelect(p->x.pSelect, &nHeight); + break; + } + case EX_List: { + heightOfExprList(p->x.pList, &nHeight); + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); + break; + } + case EX_Right: { + heightOfExpr(p->x.pRight, &nHeight); + break; + } } p->nHeight = nHeight + 1; } /* @@ -698,11 +719,11 @@ ** ** Also propagate all EP_Propagate flags from the Expr.x.pList into ** Expr.flags. */ void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ - if( pParse->nErr ) return; + if( p==0 || pParse->nErr ) return; exprSetHeight(p); sqlite3ExprCheckHeight(pParse, p->nHeight); } /* @@ -718,11 +739,11 @@ /* ** Propagate all EP_Propagate flags from the Expr.x.pList into ** Expr.flags. */ void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ - if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ + if( p && p->eX==EX_List ){ p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); } } #define exprSetHeight(y) #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ @@ -823,11 +844,13 @@ assert( db->mallocFailed ); sqlite3ExprDelete(db, pLeft); 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 ){ pRoot->pLeft = pLeft; pRoot->flags |= EP_Propagate & pLeft->flags; @@ -871,19 +894,37 @@ /* ** Add pSelect to the Expr.x.pSelect field. Or, if pExpr is NULL (due ** do a memory allocation failure) then delete the pSelect object. */ void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){ - if( pExpr ){ + if( pExpr && pSelect ){ + assert( pExpr->eX==EX_None ); + pExpr->eX = EX_Select; pExpr->x.pSelect = pSelect; - ExprSetProperty(pExpr, EP_xIsSelect|EP_Subquery); + ExprSetProperty(pExpr, EP_Subquery); sqlite3ExprSetHeightAndFlags(pParse, pExpr); }else{ assert( pParse->db->mallocFailed ); sqlite3SelectDelete(pParse->db, pSelect); } } + +/* +** Add ExprList to the Expr.x.pList field. Or, if pExpr is NULL (due +** do a memory allocation failure) then delete the pSelect object. +*/ +void sqlite3PExprAddExprList(Parse *pParse, Expr *pExpr, ExprList *pList){ + if( pExpr && pList ){ + assert( pExpr->eX==EX_None ); + pExpr->eX = EX_List; + pExpr->x.pList = pList; + /* sqlite3ExprSetHeightAndFlags(pParse, pExpr); // done by caller */ + }else{ + assert( pParse->db->mallocFailed ); + sqlite3ExprListDelete(pParse->db, pList); + } +} /* ** If the expression is always either TRUE or FALSE (respectively), ** then return 1. If one cannot determine the truth value of the @@ -954,13 +995,16 @@ return 0; } if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken); } - pNew->x.pList = pList; + assert( pNew->eX==EX_None ); + if( pList ){ + pNew->eX = EX_List; + pNew->x.pList = pList; + } ExprSetProperty(pNew, EP_HasFunc); - assert( !ExprHasProperty(pNew, EP_xIsSelect) ); sqlite3ExprSetHeightAndFlags(pParse, pNew); if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct); return pNew; } @@ -1050,27 +1094,40 @@ */ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ assert( p!=0 ); /* Sanity check: Assert that the IntValue is non-negative if it exists */ assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); + assert( p->eX!=EX_Select || p->x.pSelect!=0 ); + assert( p->eX!=EX_List || p->x.pList!=0 ); #ifdef SQLITE_DEBUG if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ assert( p->pLeft==0 ); - assert( p->pRight==0 ); - assert( p->x.pSelect==0 ); + assert( p->eX==EX_None || p->eX==EX_Tab ); + } + if( !ExprHasProperty(p, EP_TokenOnly) ){ + assert( p->op!=TK_FUNCTION || p->pLeft==0 ); + } + if( !ExprHasProperty(p, (EP_TokenOnly|EP_Reduced)) ){ + assert( p->pWin==0 || p->pLeft==0 ); + assert( p->pWin==0 || p->op==TK_FUNCTION ); } #endif if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){ - /* The Expr.x union is never used at the same time as Expr.pRight */ - assert( p->x.pList==0 || p->pRight==0 ); if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); - if( p->pRight ){ - sqlite3ExprDeleteNN(db, p->pRight); - }else if( ExprHasProperty(p, EP_xIsSelect) ){ - sqlite3SelectDelete(db, p->x.pSelect); - }else{ - sqlite3ExprListDelete(db, p->x.pList); + switch( p->eX ){ + case EX_Select: { + sqlite3SelectDelete(db, p->x.pSelect); + break; + } + case EX_List: { + sqlite3ExprListDelete(db, p->x.pList); + break; + } + case EX_Right: { + sqlite3ExprDelete(db, p->x.pRight); + break; + } } if( !ExprHasProperty(p, EP_Reduced) ){ sqlite3WindowDelete(db, p->pWin); } } @@ -1080,10 +1137,33 @@ } } void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p ) sqlite3ExprDeleteNN(db, p); } + +void sqlite3ExprClearXUnion(sqlite3 *db, Expr *p){ + switch( p->eX ){ + case EX_Select: { + sqlite3SelectDelete(db, p->x.pSelect); + break; + } + case EX_List: { + sqlite3ExprListDelete(db, p->x.pList); + break; + } + case EX_Right: { + sqlite3ExprDelete(db, p->x.pRight); + break; + } + } + p->eX = EX_None; +} +void sqlite3ExprAddTab(sqlite3 *db, Expr *pExpr, Table *pTab){ + sqlite3ExprClearXUnion(db, pExpr); + pExpr->eX = EX_Tab; + pExpr->x.pTab = pTab; +} /* ** Return the number of bytes allocated for the expression structure ** passed as the first argument. This is always one of EXPR_FULLSIZE, ** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE. @@ -1142,14 +1222,13 @@ }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); 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; } } return nSize; } @@ -1183,21 +1262,22 @@ static int dupedExprSize(Expr *p, int flags){ int nByte = 0; 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; } /* ** 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. */ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ Expr *pNew; /* Value to return */ @@ -1246,34 +1326,46 @@ /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken); pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); pNew->flags |= staticFlag; + assert( pNew->eX==p->eX ); + assert( pNew->eV==p->eV ); /* Copy the p->u.zToken string, if any. */ if( nToken ){ char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; memcpy(zToken, p->u.zToken, nToken); } if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ - if( ExprHasProperty(p, EP_xIsSelect) ){ - pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); - }else{ - pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); + switch( p->eX ){ + case EX_Select: { + assert( pNew->eX==EX_Select ); + pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); + if( pNew->x.pSelect==0 ) pNew->eX = EX_None; + break; + } + case EX_List: { + assert( pNew->eX==EX_List ); + pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); + if( pNew->x.pList==0 ) pNew->eX = EX_None; + break; + } } } - /* Fill in pNew->pLeft and pNew->pRight. */ + /* Fill in pNew->pLeft and pNew->x.pRight. */ if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ zAlloc += dupedExprNodeSize(p, dupFlags); if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ pNew->pLeft = p->pLeft ? exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; - pNew->pRight = p->pRight ? - exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; + if( p->eX==EX_Right ){ + pNew->x.pRight = exprDup(db, p->x.pRight, EXPRDUP_REDUCE, &zAlloc); + } } if( pzBuffer ){ *pzBuffer = zAlloc; } }else{ @@ -1285,16 +1377,19 @@ } #endif /* SQLITE_OMIT_WINDOWFUNC */ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; - assert( p->iColumn==0 || p->pRight==0 ); - assert( p->pRight==0 || p->pRight==p->pLeft ); + assert( p->iColumn==0 || p->eX!=EX_Right ); + /* OLD: assert( p->pRight==0 || p->x.pRight==p->pLeft ); */ }else{ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); } - pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); + if( p->eX==EX_Right ){ + pNew->x.pRight = sqlite3ExprDup(db, p->x.pRight, 0); + if( pNew->x.pRight==0 ) pNew->eX = EX_None; + } } } } return pNew; } @@ -1367,12 +1462,12 @@ && pOldExpr->op==TK_SELECT_COLUMN && (pNewExpr = pItem->pExpr)!=0 ){ 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 ); assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 ); assert( pPriorSelectCol==pItem[-1].pExpr->pLeft ); @@ -1614,11 +1709,13 @@ assert( pFirst!=0 ); assert( pFirst->op==TK_SELECT_COLUMN ); /* 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 ** the RHS and LHS sizes match during code generation. */ pFirst->iTable = pColumns->nId; @@ -1952,11 +2049,11 @@ } } } /* Check if pExpr is a sub-select. If so, consider it variable. */ - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( pExpr->eX==EX_Select ){ pWalker->eCode = 0; return WRC_Abort; } return exprNodeIsConstant(pWalker, pExpr); @@ -2086,13 +2183,14 @@ case TK_STRING: case TK_FLOAT: case TK_BLOB: return 0; case TK_COLUMN: + assert( p->eX==EX_Tab ); return ExprHasProperty(p, EP_CanBeNull) || - p->pTab==0 || /* Reference to column of index on expression */ - (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); + p->x.pTab==0 || /* Reference to column of index on expression */ + (p->iColumn>=0 && p->x.pTab->aCol[p->iColumn].notNull==0); default: return 1; } } @@ -2158,12 +2256,14 @@ Select *p; SrcList *pSrc; ExprList *pEList; Table *pTab; int i; - if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */ - if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */ + if( pX->eX!=EX_Select ) return 0; /* Not a subquery */ + if( ExprHasProperty(pX, EP_VarSelect) ){ + return 0; /* Correlated subq */ + } p = pX->x.pSelect; if( p->pPrior ) return 0; /* Not a compound SELECT */ if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); @@ -2217,11 +2317,11 @@ ** right-hand side. Return TRUE if that list is constant. */ static int sqlite3InRhsIsConstant(Expr *pIn){ Expr *pLHS; int res; - assert( !ExprHasProperty(pIn, EP_xIsSelect) ); + assert( pIn->eX!=EX_Select ); pLHS = pIn->pLeft; pIn->pLeft = 0; res = sqlite3ExprIsConstant(pIn); pIn->pLeft = pLHS; return res; @@ -2328,11 +2428,11 @@ /* If the RHS of this IN(...) operator is a SELECT, and if it matters ** whether or not the SELECT result contains NULL values, check whether ** or not NULL is actually possible (it may not be, for example, due ** to NOT NULL constraints in the schema). If no NULL values are possible, ** set prRhsHasNull to 0 before continuing. */ - if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){ + if( prRhsHasNull && pX->eX==EX_Select ){ int i; ExprList *pEList = pX->x.pSelect->pEList; for(i=0; inExpr; i++){ if( sqlite3ExprCanBeNull(pEList->a[i].pExpr) ) break; } @@ -2424,11 +2524,11 @@ colUsed = 0; /* Columns of index used so far */ 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 ); for(j=0; jaiColumn[j]!=pRhs->iColumn ) continue; @@ -2481,12 +2581,12 @@ ** and the RHS is not constant or has two or fewer terms, ** then it is not worth creating an ephemeral table to evaluate ** the IN operator so return IN_INDEX_NOOP. */ if( eType==0 - && (inFlags & IN_INDEX_NOOP_OK) - && !ExprHasProperty(pX, EP_xIsSelect) + && (inFlags & IN_INDEX_NOOP_OK)!=0 + && pX->eX==EX_List && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) ){ eType = IN_INDEX_NOOP; } @@ -2497,11 +2597,11 @@ u32 savedNQueryLoop = pParse->nQueryLoop; int rMayHaveNull = 0; eType = IN_INDEX_EPH; if( inFlags & IN_INDEX_LOOP ){ pParse->nQueryLoop = 0; - if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){ + if( pX->pLeft->iColumn<0 && pX->eX==EX_List ){ eType = IN_INDEX_ROWID; } }else if( prRhsHasNull ){ *prRhsHasNull = rMayHaveNull = ++pParse->nMem; } @@ -2530,11 +2630,11 @@ ** string is eventually freed using sqlite3DbFree(). */ static char *exprINAffinity(Parse *pParse, Expr *pExpr){ Expr *pLeft = pExpr->pLeft; int nVal = sqlite3ExprVectorSize(pLeft); - Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0; + Select *pSelect = (pExpr->eX==EX_Select) ? pExpr->x.pSelect : 0; char *zRet; assert( pExpr->op==TK_IN ); zRet = sqlite3DbMallocRaw(pParse->db, nVal+1); if( zRet ){ @@ -2578,11 +2678,11 @@ ** ** "row value misused" */ void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){ #ifndef SQLITE_OMIT_SUBQUERY - if( pExpr->flags & EP_xIsSelect ){ + if( pExpr->eX==EX_Select ){ sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1); }else #endif { sqlite3ErrorMsg(pParse, "row value misused"); @@ -2670,11 +2770,12 @@ pExpr->iTable = pParse->nTab++; addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, (isRowid?0:nVal)); pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + assert( pExpr->eX==EX_Select || pExpr->eX==EX_List ); + if( pExpr->eX==EX_Select ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ @@ -2705,11 +2806,11 @@ assert( pEList!=0 ); assert( pEList->nExpr>0 ); assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); for(i=0; iaColl[i] = sqlite3BinaryCompareCollSeq( + pKeyInfo->aColl[i] = sqlite3ComparisonCollSeq( pParse, p, pEList->a[i].pExpr ); } } }else if( ALWAYS(pExpr->x.pList!=0) ){ @@ -2799,11 +2900,11 @@ Expr *pLimit; /* New limit expression */ testcase( pExpr->op==TK_EXISTS ); testcase( pExpr->op==TK_SELECT ); assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); - assert( ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->eX==EX_Select ); pSel = pExpr->x.pSelect; ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY", jmpIfDynamic>=0?"":"CORRELATED ")); nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; @@ -2856,11 +2957,11 @@ ** columns as the vector on the LHS. Or, if the RHS of the IN() is not ** a sub-query, that the LHS is a vector of size 1. */ int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){ int nVector = sqlite3ExprVectorSize(pIn->pLeft); - if( (pIn->flags & EP_xIsSelect) ){ + if( pIn->eX==EX_Select ){ if( nVector!=pIn->x.pSelect->pEList->nExpr ){ sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector); return 1; } }else if( nVector!=1 ){ @@ -2986,11 +3087,11 @@ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); int labelOk = sqlite3VdbeMakeLabel(v); int r2, regToFree; int regCkNull = 0; int ii; - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->eX==EX_List ); if( destIfNull!=destIfFalse ){ regCkNull = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull); } for(ii=0; iinExpr; ii++){ @@ -3375,12 +3476,14 @@ ** constraints, and that constant is coded by the pExpr->pLeft ** expresssion. However, make sure the constant has the correct ** datatype by applying the Affinity of the table column to the ** constant. */ + int aff; int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target); - int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + assert( pExpr->eX==EX_Tab ); + aff = sqlite3TableColumnAffinity(pExpr->x.pTab, pExpr->iColumn); if( aff!=SQLITE_AFF_BLOB ){ static const char zAff[] = "B\000C\000D\000E"; assert( SQLITE_AFF_BLOB=='A' ); assert( SQLITE_AFF_TEXT=='B' ); if( iReg!=target ){ @@ -3400,11 +3503,12 @@ /* Coding an expression that is part of an index where column names ** in the index refer to the table to which the index belongs */ iTab = pParse->iSelfTab - 1; } } - return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + assert( pExpr->eX==EX_Tab ); + return sqlite3ExprCodeGetColumn(pParse, pExpr->x.pTab, pExpr->iColumn, iTab, target, pExpr->op2); } case TK_INTEGER: { codeInteger(pParse, pExpr, 0, target); @@ -3489,12 +3593,13 @@ Expr *pLeft = pExpr->pLeft; if( sqlite3ExprIsVector(pLeft) ){ 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); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); @@ -3527,11 +3632,12 @@ assert( TK_SLASH==OP_Divide ); testcase( op==TK_SLASH ); assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT ); 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 ); break; } @@ -3546,10 +3652,11 @@ assert( !ExprHasProperty(pExpr, EP_IntValue) ); codeReal(v, pLeft->u.zToken, 1, target); return target; #endif }else{ + memset(&tempX, 0, sizeof(tempX)); tempX.op = TK_INTEGER; tempX.flags = EP_IntValue|EP_TokenOnly; tempX.u.iValue = 0; r1 = sqlite3ExprCodeTemp(pParse, &tempX, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); @@ -3570,11 +3677,12 @@ case TK_TRUTH: { int isTrue; /* IS TRUE or IS NOT TRUE */ 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); sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !isTrue, isTrue ^ bNormal); break; @@ -3624,11 +3732,11 @@ if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ /* SQL functions can be expensive. So try to move constant functions ** out of the inner loop, even if that means an extra OP_Copy. */ return sqlite3ExprCodeAtInit(pParse, pExpr, -1); } - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->eX==EX_List || pExpr->eX==EX_None ); if( ExprHasProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; }else{ pFarg = pExpr->x.pList; } @@ -3858,22 +3966,25 @@ ** ** p1==0 -> old.rowid p1==3 -> new.rowid ** p1==1 -> old.a p1==4 -> new.a ** p1==2 -> old.b p1==5 -> new.b */ - Table *pTab = pExpr->pTab; + Table *pTab; + assert( pExpr->eX==EX_Tab ); + pTab = pExpr->x.pTab; int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; assert( pExpr->iTable==0 || pExpr->iTable==1 ); assert( pExpr->iColumn>=-1 && pExpr->iColumnnCol ); assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey ); assert( p1>=0 && p1<(pTab->nCol*2+2) ); sqlite3VdbeAddOp2(v, OP_Param, p1, target); + assert( pExpr->eX==EX_Tab ); VdbeComment((v, "r[%d]=%s.%s", target, (pExpr->iTable ? "new" : "old"), - (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName) + (pExpr->iColumn<0 ? "rowid" : pExpr->x.pTab->aCol[pExpr->iColumn].zName) )); #ifndef SQLITE_OMIT_FLOATING_POINT /* If the column has REAL affinity, it may currently be stored as an ** integer. Use OP_RealAffinity to make sure it is really real. @@ -3933,12 +4044,12 @@ struct ExprList_item *aListelem; /* Array of WHEN terms */ Expr opCompare; /* The X==Ei expression */ Expr *pX; /* The X expression */ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ - assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); - assert(pExpr->x.pList->nExpr > 0); + assert( pExpr->eX==EX_List ); + assert( pExpr->x.pList->nExpr > 0); pEList = pExpr->x.pList; aListelem = pEList->a; nExpr = pEList->nExpr; endLabel = sqlite3VdbeMakeLabel(v); if( (pX = pExpr->pLeft)!=0 ){ @@ -3957,11 +4068,12 @@ regFree1 = 0; } for(i=0; iop==TK_COLUMN ); @@ -4266,21 +4378,24 @@ memset(&compLeft, 0, sizeof(Expr)); memset(&compRight, 0, sizeof(Expr)); memset(&exprAnd, 0, sizeof(Expr)); - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->eX==EX_List ); exprX = *pExpr->pLeft; exprAnd.op = TK_AND; exprAnd.pLeft = &compLeft; - exprAnd.pRight = &compRight; + exprAnd.x.pRight = &compRight; + exprAnd.eX = EX_Right; compLeft.op = TK_GE; compLeft.pLeft = &exprX; - compLeft.pRight = pExpr->x.pList->a[0].pExpr; + compLeft.x.pRight = pExpr->x.pList->a[0].pExpr; + compLeft.eX = EX_Right; compRight.op = TK_LE; compRight.pLeft = &exprX; - compRight.pRight = pExpr->x.pList->a[1].pExpr; + compRight.x.pRight = pExpr->x.pList->a[1].pExpr; + compRight.eX = EX_Right; exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1)); if( xJump ){ xJump(pParse, &exprAnd, dest, jumpIfNull); }else{ /* Mark the expression is being from the ON or USING clause of a join @@ -4333,18 +4448,20 @@ switch( op ){ case TK_AND: { 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: { testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); @@ -4353,11 +4470,12 @@ case TK_TRUTH: { int isNot; /* IS NOT TRUE or IS NOT FALSE */ 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 ){ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, isNot ? SQLITE_JUMPIFNULL : 0); @@ -4381,12 +4499,13 @@ case TK_NE: case TK_EQ: { 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); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); @@ -4499,18 +4618,20 @@ switch( pExpr->op ){ 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; } case TK_NOT: { testcase( jumpIfNull==0 ); @@ -4520,11 +4641,12 @@ case TK_TRUTH: { int isNot; /* IS NOT TRUE or IS NOT FALSE */ 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 ){ /* IS TRUE and IS NOT FALSE */ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, @@ -4551,12 +4673,13 @@ case TK_NE: case TK_EQ: { 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); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); @@ -4728,15 +4851,19 @@ return 2; } } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){ - if( combinedFlags & EP_xIsSelect ) return 2; + if( pA->eX==EX_Select || pA->eX!=pB->eX ) return 2; if( (combinedFlags & EP_FixedCol)==0 && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; - if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2; - if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; + if( pA->eX==EX_Right ){ + if( sqlite3ExprCompare(pParse,pA->x.pRight,pB->x.pRight,iTab) ) return 2; + } + if( pA->eX==EX_List ){ + if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; + } assert( (combinedFlags & EP_Reduced)==0 ); if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){ if( pA->iColumn!=pB->iColumn ) return 2; if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; @@ -4827,13 +4954,14 @@ */ 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; } if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); @@ -4897,12 +5025,13 @@ testcase( pExpr->op==TK_NE ); testcase( pExpr->op==TK_LT ); testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); - if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab)) - || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab)) + assert( pExpr->eX==EX_Right ); + if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->x.pTab)) + || (pExpr->x.pRight->op==TK_COLUMN && IsVirtual(pExpr->x.pRight->x.pTab)) ){ return WRC_Prune; } default: return WRC_Continue; @@ -5129,11 +5258,12 @@ } if( (k>=pAggInfo->nColumn) && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 ){ pCol = &pAggInfo->aCol[k]; - pCol->pTab = pExpr->pTab; + assert( pExpr->eX==EX_Tab ); + pCol->pTab = pExpr->x.pTab; pCol->iTable = pExpr->iTable; pCol->iColumn = pExpr->iColumn; pCol->iMem = ++pParse->nMem; pCol->iSorterColumn = -1; pCol->pExpr = pExpr; @@ -5187,18 +5317,18 @@ /* pExpr is original. Make a new entry in pAggInfo->aFunc[] */ u8 enc = ENC(pParse->db); i = addAggInfoFunc(pParse->db, pAggInfo); if( i>=0 ){ - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->eX==EX_List || pExpr->eX==EX_None ); pItem = &pAggInfo->aFunc[i]; pItem->pExpr = pExpr; pItem->iMem = ++pParse->nMem; assert( !ExprHasProperty(pExpr, EP_IntValue) ); pItem->pFunc = sqlite3FindFunction(pParse->db, pExpr->u.zToken, - pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); + pExpr->eX==EX_List ? pExpr->x.pList->nExpr : 0, enc, 0); if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; }else{ pItem->iDistinct = -1; } Index: src/fkey.c ================================================================== --- src/fkey.c +++ src/fkey.c @@ -500,11 +500,15 @@ int iCursor, /* The open cursor on the table */ i16 iCol /* The column that is wanted */ ){ Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); if( pExpr ){ - pExpr->pTab = pTab; + assert( pExpr->eX==EX_None ); + if( pTab ){ + pExpr->x.pTab = pTab; + pExpr->eX = EX_Tab; + } pExpr->iTable = iCursor; pExpr->iColumn = iCol; } return pExpr; } Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1846,11 +1846,11 @@ FuncDef *pDef; int nExpr; if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){ return 0; } - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->eX==EX_List ); nExpr = pExpr->x.pList->nExpr; pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0); if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){ return 0; } Index: src/parse.y ================================================================== --- src/parse.y +++ src/parse.y @@ -934,16 +934,15 @@ Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); if( p ){ /* memset(p, 0, sizeof(Expr)); */ p->op = (u8)op; p->affinity = 0; + p->eX = EX_None; p->flags = EP_Leaf; p->iAgg = -1; - p->pLeft = p->pRight = 0; - p->x.pList = 0; + p->pLeft = 0; p->pAggInfo = 0; - p->pTab = 0; p->op2 = 0; p->iTable = 0; p->iColumn = 0; #ifndef SQLITE_OMIT_WINDOWFUNC p->pWin = 0; @@ -1050,15 +1049,11 @@ } expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. { ExprList *pList = sqlite3ExprListAppend(pParse, X, Y); A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( A ){ - A->x.pList = pList; - }else{ - sqlite3ExprListDelete(pParse->db, pList); - } + sqlite3PExprAddExprList(pParse, A, pList); } expr(A) ::= expr(A) AND(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);} expr(A) ::= expr(A) OR(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);} expr(A) ::= expr(A) LT|GT|GE|LE(OP) expr(Y). @@ -1102,14 +1097,15 @@ %include { /* A routine to convert a binary TK_IS or TK_ISNOT expression into a ** 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; } } } // expr1 IS expr2 @@ -1141,15 +1137,11 @@ between_op(A) ::= NOT BETWEEN. {A = 1;} expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { ExprList *pList = sqlite3ExprListAppend(pParse,0, X); pList = sqlite3ExprListAppend(pParse,pList, Y); A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0); - if( A ){ - A->x.pList = pList; - }else{ - sqlite3ExprListDelete(pParse->db, pList); - } + sqlite3PExprAddExprList(pParse, A, pList); if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); } %ifndef SQLITE_OMIT_SUBQUERY %type in_op {int} in_op(A) ::= IN. {A = 0;} @@ -1193,16 +1185,12 @@ pRHS->flags |= EP_Generic; } A = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A, pRHS); }else{ A = sqlite3PExpr(pParse, TK_IN, A, 0); - if( A ){ - A->x.pList = Y; - sqlite3ExprSetHeightAndFlags(pParse, A); - }else{ - sqlite3ExprListDelete(pParse->db, Y); - } + sqlite3PExprAddExprList(pParse, A, Y); + sqlite3ExprSetHeightAndFlags(pParse, A); if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); } } expr(A) ::= LP select(X) RP. { A = sqlite3PExpr(pParse, TK_SELECT, 0, 0); @@ -1229,17 +1217,12 @@ %endif SQLITE_OMIT_SUBQUERY /* CASE expressions */ expr(A) ::= CASE case_operand(X) case_exprlist(Y) case_else(Z) END. { A = sqlite3PExpr(pParse, TK_CASE, X, 0); - if( A ){ - A->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y; - sqlite3ExprSetHeightAndFlags(pParse, A); - }else{ - sqlite3ExprListDelete(pParse->db, Y); - sqlite3ExprDelete(pParse->db, Z); - } + sqlite3PExprAddExprList(pParse,A,Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y); + sqlite3ExprSetHeightAndFlags(pParse, A); } %type case_exprlist {ExprList*} %destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);} case_exprlist(A) ::= case_exprlist(A) WHEN expr(Y) THEN expr(Z). { A = sqlite3ExprListAppend(pParse,A, Y); Index: src/resolve.c ================================================================== --- src/resolve.c +++ src/resolve.c @@ -162,11 +162,11 @@ ** pExpr->pTab Points to the Table structure of X.Y (even if ** X and/or Y are implied.) ** 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 ** can be used. The zTable variable is the name of the table (the "Y"). This ** value can be NULL if zDb is also NULL. If zTable is NULL it @@ -201,11 +201,10 @@ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; - pExpr->pTab = 0; ExprSetVVAProperty(pExpr, EP_NoReduce); /* Translate the schema name in zDb into a pointer to the corresponding ** schema. If not found, pSchema will remain NULL and nothing will match ** resulting in an appropriate error message toward the end of this routine @@ -263,11 +262,11 @@ assert( zTabName!=0 ); if( sqlite3StrICmp(zTabName, zTab)!=0 ){ continue; } if( IN_RENAME_OBJECT && pItem->zAlias ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab); + sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->x.pTab); } } if( 0==(cntTab++) ){ pMatch = pItem; } @@ -289,17 +288,17 @@ } } } if( pMatch ){ pExpr->iTable = pMatch->iCursor; - pExpr->pTab = pMatch->pTab; + sqlite3ExprAddTab(db, pExpr, pMatch->pTab); /* RIGHT JOIN not (yet) supported */ assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } - pSchema = pExpr->pTab->pSchema; + pSchema = pExpr->x.pTab->pSchema; } } /* if( pSrcList ) */ #if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) /* If we have not already resolved the name, then maybe @@ -352,11 +351,11 @@ #ifndef SQLITE_OMIT_UPSERT if( pExpr->iTable==2 ){ testcase( iCol==(-1) ); if( IN_RENAME_OBJECT ){ pExpr->iColumn = iCol; - pExpr->pTab = pTab; + sqlite3ExprAddTab(db, pExpr, pTab); eNewExprOp = TK_COLUMN; }else{ pExpr->iTable = pNC->uNC.pUpsert->regData + iCol; eNewExprOp = TK_REGISTER; ExprSetProperty(pExpr, EP_Alias); @@ -374,11 +373,11 @@ }else{ testcase( iCol==31 ); testcase( iCol==32 ); pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<pTab = pTab; + sqlite3ExprAddTab(db, pExpr, pTab); pExpr->iColumn = (i16)iCol; eNewExprOp = TK_TRIGGER; #endif /* SQLITE_OMIT_TRIGGER */ } } @@ -427,13 +426,11 @@ assert( pEList!=0 ); for(j=0; jnExpr; j++){ char *zAs = pEList->a[j].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ Expr *pOrig; - assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - assert( pExpr->x.pList==0 ); - assert( pExpr->x.pSelect==0 ); + assert( pExpr->pLeft==0 ); pOrig = pEList->a[j].pExpr; if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); return WRC_Abort; } @@ -474,11 +471,10 @@ */ if( cnt==0 && zTab==0 ){ assert( pExpr->op==TK_ID ); if( ExprHasProperty(pExpr,EP_DblQuoted) ){ pExpr->op = TK_STRING; - pExpr->pTab = 0; return WRC_Prune; } if( sqlite3ExprIdToTrueFalse(pExpr) ){ return WRC_Prune; } @@ -520,12 +516,15 @@ /* Clean up and return */ 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: if( cnt==1 ){ assert( pNC!=0 ); @@ -552,13 +551,13 @@ */ Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){ Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); if( p ){ struct SrcList_item *pItem = &pSrc->a[iSrc]; - p->pTab = pItem->pTab; + sqlite3ExprAddTab(db, p, pItem->pTab); p->iTable = pItem->iCursor; - if( p->pTab->iPKey==iCol ){ + if( p->x.pTab->iPKey==iCol ){ p->iColumn = -1; }else{ p->iColumn = (ynVar)iCol; testcase( iCol==BMS ); testcase( iCol==BMS-1 ); @@ -675,45 +674,54 @@ zTable = 0; zColumn = pExpr->u.zToken; }else{ Expr *pLeft = pExpr->pLeft; notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); - pRight = pExpr->pRight; + assert( pExpr->eX==EX_Right ); + pRight = pExpr->x.pRight; if( pRight->op==TK_ID ){ zDb = 0; }else{ assert( pRight->op==TK_DOT ); + assert( pRight->eX==EX_Right ); zDb = pLeft->u.zToken; pLeft = pRight->pLeft; - pRight = pRight->pRight; + pRight = pRight->x.pRight; } zTable = pLeft->u.zToken; zColumn = pRight->u.zToken; if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); - } - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft); + if( pExpr->eX==EX_Tab ){ + sqlite3RenameTokenRemap(pParse, (void*)&pExpr->x.pTab,(void*)pLeft); + } } } return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); } /* Resolve function names */ case TK_FUNCTION: { - ExprList *pList = pExpr->x.pList; /* The argument list */ - int n = pList ? pList->nExpr : 0; /* Number of arguments */ + ExprList *pList; /* The argument list */ + int n; /* Number of arguments */ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ u8 enc = ENC(pParse->db); /* The database encoding */ - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->eX==EX_List || pExpr->eX==EX_None ); + if( pExpr->eX==EX_List ){ + pList = pExpr->x.pList; + n = pList->nExpr; + }else{ + pList = 0; + n = 0; + } zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); if( pDef==0 ){ pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); @@ -874,11 +882,11 @@ case TK_SELECT: case TK_EXISTS: testcase( pExpr->op==TK_EXISTS ); #endif case TK_IN: { testcase( pExpr->op==TK_IN ); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( pExpr->eX==EX_Select ){ int nRef = pNC->nRef; notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr); sqlite3WalkSelect(pWalker, pExpr->x.pSelect); assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ @@ -896,11 +904,12 @@ case TK_ISNOT: { Expr *pRight; 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 ){ pExpr->op2 = pExpr->op; pExpr->op = TK_TRUTH; @@ -924,12 +933,12 @@ nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr); if( nRight==nLeft ){ 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 ); testcase( pExpr->op==TK_NE ); testcase( pExpr->op==TK_LT ); Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -388,18 +388,18 @@ while( p ){ ExprSetProperty(p, EP_FromJoin); 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; } } /* Undo the work of setJoinExpr(). In the expression tree p, convert every ** term that is marked with EP_FromJoin and iRightJoinTable==iTable into @@ -411,18 +411,18 @@ while( p ){ if( ExprHasProperty(p, EP_FromJoin) && (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; } } /* ** This routine processes the join information for a SELECT statement. @@ -801,12 +801,16 @@ ExprList *pExtra = 0; for(i=0; inExpr; i++){ struct ExprList_item *pItem = &pEList->a[i]; if( pItem->u.x.iOrderByCol==0 ){ Expr *pExpr = pItem->pExpr; - Table *pTab = pExpr->pTab; - if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab) + Table *pTab; + if( pExpr->op==TK_COLUMN + && pExpr->iColumn>=0 + && ALWAYS(pExpr->eX==EX_Tab) + && (pTab = pExpr->x.pTab)!=0 + && !IsVirtual(pTab) && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF) ){ int j; for(j=0; jaDefer[j].iCsr==pExpr->iTable ) break; @@ -820,20 +824,22 @@ Index *pPk = 0; if( !HasRowid(pTab) ){ pPk = sqlite3PrimaryKeyIndex(pTab); nKey = pPk->nKeyCol; } + assert( pExpr->eX==EX_Tab ); for(k=0; kiTable = pExpr->iTable; - pNew->pTab = pExpr->pTab; + pNew->eX = EX_Tab; + pNew->x.pTab = pExpr->x.pTab; pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); } } - pSort->aDefer[nDefer].pTab = pExpr->pTab; + pSort->aDefer[nDefer].pTab = pExpr->x.pTab; pSort->aDefer[nDefer].iCsr = pExpr->iTable; pSort->aDefer[nDefer].nKey = nKey; nDefer++; } } @@ -1678,11 +1684,11 @@ ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT ** branch below. */ break; } - assert( pTab && pExpr->pTab==pTab ); + assert( pTab && pExpr->eX==EX_Tab && pExpr->x.pTab==pTab ); if( pS ){ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ @@ -1734,11 +1740,11 @@ ** statement. */ NameContext sNC; Select *pS = pExpr->x.pSelect; Expr *p = pS->pEList->a[0].pExpr; - assert( ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->eX==EX_Select ); sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; sNC.pParse = pNC->pParse; zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); break; @@ -1863,19 +1869,21 @@ for(i=0; inExpr; i++){ Expr *p = pEList->a[i].pExpr; assert( p!=0 ); assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */ - assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */ + /* Covering idx not yet coded: */ + assert( p->op!=TK_COLUMN || (p->eX==EX_Tab && p->x.pTab!=0) ); if( pEList->a[i].zName ){ /* An AS clause always takes first priority */ char *zName = pEList->a[i].zName; sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); }else if( srcName && p->op==TK_COLUMN ){ char *zCol; int iCol = p->iColumn; - pTab = p->pTab; + assert( p->eX==EX_Tab ); + pTab = p->x.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iColnCol) ); if( iCol<0 ){ zCol = "rowid"; @@ -1955,18 +1963,21 @@ if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS " phrase, use as the name */ }else{ Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr); while( pColExpr->op==TK_DOT ){ - pColExpr = pColExpr->pRight; + assert( pColExpr->eX==EX_Right ); + pColExpr = pColExpr->x.pRight; assert( pColExpr!=0 ); } assert( pColExpr->op!=TK_AGG_COLUMN ); if( pColExpr->op==TK_COLUMN ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; - Table *pTab = pColExpr->pTab; + Table *pTab; + assert( pColExpr->eX==EX_Tab ); + pTab = pColExpr->x.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; }else if( pColExpr->op==TK_ID ){ assert( !ExprHasProperty(pColExpr, EP_IntValue) ); @@ -2123,19 +2134,19 @@ } /* ** 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 ** the limit and offset. If there is no limit and/or offset, then ** 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. ** ** The iOffset register (if it exists) is initialized to the value ** of the OFFSET. The iLimit register is initialized to LIMIT. Register @@ -2180,14 +2191,14 @@ sqlite3ExprCode(pParse, pLimit->pLeft, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); 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); VdbeComment((v, "LIMIT+OFFSET")); } @@ -3440,11 +3451,11 @@ }else{ Expr *pNew; 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{ sqlite3 *db = pSubst->pParse->db; if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){ @@ -3469,15 +3480,24 @@ }else{ if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){ pExpr->iTable = pSubst->iNewTable; } pExpr->pLeft = substExpr(pSubst, pExpr->pLeft); - pExpr->pRight = substExpr(pSubst, pExpr->pRight); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - substSelect(pSubst, pExpr->x.pSelect, 1); - }else{ - substExprList(pSubst, pExpr->x.pList); + switch( pExpr->eX ){ + case EX_Select: { + substSelect(pSubst, pExpr->x.pSelect, 1); + break; + } + case EX_List: { + substExprList(pSubst, pExpr->x.pList); + break; + } + case EX_Right: { + pExpr->x.pRight = substExpr(pSubst, pExpr->x.pRight); + if( pExpr->x.pRight==0 ) pExpr->eX = EX_None; + break; + } } } return pExpr; } static void substExprList( @@ -3713,11 +3733,13 @@ ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET ** because they could be computed at compile-time. But when LIMIT and OFFSET ** 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) */ } if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */ @@ -4108,30 +4130,32 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){ Expr *pRight, *pLeft; 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); } } @@ -4314,11 +4338,12 @@ if( pSubq->pLimit!=0 ){ 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; } if( isLeftJoin && (ExprHasProperty(pWhere,EP_FromJoin)==0 @@ -4900,13 +4925,13 @@ ** that need expanding. */ 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 ){ /* ** If we get here it means the result set contains one or more "*" @@ -4920,11 +4945,11 @@ && (flags & SQLITE_ShortColNames)==0; 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) ){ /* This particular expression does not need to be expanded. @@ -5240,12 +5265,12 @@ #endif sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg); for(pFunc=pAggInfo->aFunc, i=0; inFunc; i++, pFunc++){ if( pFunc->iDistinct>=0 ){ Expr *pE = pFunc->pExpr; - assert( !ExprHasProperty(pE, EP_xIsSelect) ); - if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){ + assert( pE->eX==EX_List || pE->eX==EX_None ); + if( pE->eX==EX_None || pE->x.pList->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " "argument"); pFunc->iDistinct = -1; }else{ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0); @@ -5264,11 +5289,12 @@ Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pF; for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ ExprList *pList = pF->pExpr->x.pList; - assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); + assert( pF->pExpr->eX==EX_List || pF->pExpr->eX==EX_None ); + assert( pF->pExpr->eX==EX_List || pList==0 ); sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0); sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); } } @@ -5294,11 +5320,11 @@ for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ int nArg; int addrNext = 0; int regAgg; ExprList *pList = pF->pExpr->x.pList; - assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); + assert( pF->pExpr->eX==EX_List || pF->pExpr->eX==EX_None ); if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); }else{ @@ -6184,14 +6210,15 @@ minMaxFlag = minMaxQuery(db, sAggInfo.aFunc[0].pExpr, &pMinMaxOrderBy); }else{ minMaxFlag = WHERE_ORDERBY_NORMAL; } for(i=0; ix.pList); - sNC.ncFlags &= ~NC_InAggFunc; + if( sAggInfo.aFunc[i].pExpr->eX==EX_List ){ + sNC.ncFlags |= NC_InAggFunc; + sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList); + sNC.ncFlags &= ~NC_InAggFunc; + } } sAggInfo.mxReg = pParse->nMem; if( db->mallocFailed ) goto select_end; #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x400 ){ Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2417,10 +2417,12 @@ ** allocated, regardless of whether or not EP_Reduced is set. */ struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ + u8 eV; /* Which element of v-union is used */ + u8 eX; /* Which element of x-union is used */ u32 flags; /* Various flags. EP_* See below */ union { char *zToken; /* Token value. Zero terminated and dequoted */ int iValue; /* Non-negative integer value if EP_IntValue */ } u; @@ -2429,14 +2431,16 @@ ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ Expr *pLeft; /* Left subnode */ - Expr *pRight; /* Right subnode */ union { + Expr *pRight; /* Right subnode */ ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */ Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */ + Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL + ** for a column of an index on an expression */ } x; /* If the EP_Reduced flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. @@ -2457,17 +2461,29 @@ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 op2; /* TK_REGISTER: original value of Expr.op ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ - Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL - ** for a column of an index on an expression */ #ifndef SQLITE_OMIT_WINDOWFUNC Window *pWin; /* Window definition for window functions */ #endif }; +/* +** Allowed values for the Expr.eV and Expr.eX fields: +*/ +#define EV_None 0 /* Expr.v is not used */ +#define EV_Left 1 /* Expr.v.pLeft */ +#define EV_Vector 2 /* Expr.v.pVector */ +#define EV_Win 3 /* Expr.v.pWin */ + +#define EX_None 0 /* Expr.x is not used */ +#define EX_Right 1 /* Expr.x.pRight */ +#define EX_List 2 /* Expr.x.pList */ +#define EX_Select 3 /* Expr.x.pSelect */ +#define EX_Tab 4 /* Expr.x.pTab */ + /* ** The following are the meanings of bits in the Expr.flags field. */ #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ @@ -2478,11 +2494,11 @@ #define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ #define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */ #define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ -#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ +/* 0x000800 -- Available for reuse */ #define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */ #define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ #define EP_Static 0x008000 /* Held in memory not obtained from malloc() */ #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ @@ -3792,14 +3808,17 @@ Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); Expr *sqlite3Expr(sqlite3*,int,const char*); void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); void sqlite3PExprAddSelect(Parse*, Expr*, Select*); +void sqlite3PExprAddExprList(Parse*, Expr*, ExprList*); +void sqlite3ExprAddTab(sqlite3*, Expr*, Table*); Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int); void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); void sqlite3ExprDelete(sqlite3*, Expr*); +void sqlite3ExprClearXUnion(sqlite3*,Expr*); ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); void sqlite3ExprListSetSortOrder(ExprList*,int); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); @@ -4383,11 +4402,12 @@ int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); 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 int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); Index: src/treeview.c ================================================================== --- src/treeview.c +++ src/treeview.c @@ -236,14 +236,14 @@ if( p->pOrderBy ){ sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); } 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); } if( p->pPrior ){ @@ -466,13 +466,13 @@ int x; const char *azOp[] = { "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; } case TK_SPAN: { @@ -530,14 +530,19 @@ break; } case TK_IN: { sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags); sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); - }else{ - sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); + switch( pExpr->eX ){ + case EX_Select: { + sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); + break; + } + case EX_List: { + sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); + break; + } } break; } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -594,11 +599,12 @@ } #endif 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: { sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR"); break; @@ -619,11 +625,12 @@ } } 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); } sqlite3TreeViewPop(pView); Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -1373,13 +1373,13 @@ } 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); } } #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ Index: src/vtab.c ================================================================== --- src/vtab.c +++ src/vtab.c @@ -1051,12 +1051,11 @@ int rc = 0; /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; - pTab = pExpr->pTab; - if( pTab==0 ) return pDef; + if( pExpr->eX!=EX_Tab || (pTab = pExpr->x.pTab)==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; pVtab = sqlite3GetVTable(db, pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; Index: src/walker.c ================================================================== --- src/walker.c +++ src/walker.c @@ -43,18 +43,23 @@ while(1){ rc = pWalker->xExprCallback(pWalker, pExpr); if( rc ) return rc & WRC_Abort; if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; - assert( pExpr->x.pList==0 || pExpr->pRight==0 ); - if( pExpr->pRight ){ - pExpr = pExpr->pRight; - continue; - }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; - }else if( pExpr->x.pList ){ - if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; + switch( pExpr->eX ){ + case EX_Right: { + pExpr = pExpr->x.pRight; + continue; + } + case EX_Select: { + if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; + break; + } + case EX_List: { + if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; + break; + } } #ifndef SQLITE_OMIT_WINDOWFUNC if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){ Window *pWin = pExpr->pWin; if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort; Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -251,11 +251,13 @@ pScan->pIdxExpr,iCur)==0) && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) ){ 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++){ if( pScan->aiCur[j]==pX->iTable && pScan->aiColumn[j]==pX->iColumn ){ @@ -276,19 +278,19 @@ pX = pTerm->pExpr; if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ 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] ){ testcase( pTerm->eOperator & WO_IS ); continue; @@ -787,11 +789,11 @@ testcase( iCol==BMS ); if( (idxCols & cMask)==0 ){ 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++; } } } @@ -1004,11 +1006,12 @@ assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); 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; if( op==WO_GT ) pIdxCons[j].op = WO_GE; } @@ -1364,15 +1367,17 @@ sqlite3_value *p2 = 0; /* Value extracted from pUpper */ sqlite3_value *pVal = 0; /* Value extracted from record */ 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; } if( p1 || p2 ){ int i; @@ -1530,11 +1535,13 @@ } /* 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; u16 mask = WO_GT|WO_LE; if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); @@ -1547,11 +1554,13 @@ } /* 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; u16 mask = WO_GT|WO_LE; if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); @@ -2277,11 +2286,13 @@ }else{ /* In the absence of explicit truth probabilities, use heuristics to ** 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; }else{ k = 20; @@ -2326,13 +2337,17 @@ /* Test if comparison i of pTerm is compatible with column (i+nEq) ** of the index. If not, exit the loop. */ char aff; /* Comparison affinity */ char idxaff = 0; /* Indexed columns affinity */ CollSeq *pColl; /* Comparison collation sequence */ - Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr; - Expr *pRhs = pTerm->pExpr->pRight; - if( pRhs->flags & EP_xIsSelect ){ + Expr *pLhs; + Expr *pRhs; + pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr; + assert( pTerm->pExpr->eX==EX_Right ); + pRhs = pTerm->pExpr->x.pRight; + assert( pRhs->eX==EX_Select || pRhs->eX==EX_List ); + if( pRhs->eX==EX_Select ){ pRhs = pRhs->x.pSelect->pEList->a[i].pExpr; }else{ pRhs = pRhs->x.pList->a[i].pExpr; } @@ -2351,11 +2366,11 @@ testcase( pLhs->iColumn==XN_ROWID ); aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs)); 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; } return i; } @@ -2486,28 +2501,33 @@ || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 ); if( eOp & WO_IN ){ Expr *pExpr = pTerm->pExpr; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ - int i; - nIn = 46; assert( 46==sqlite3LogEst(25) ); - - /* The expression may actually be of the form (x, y) IN (SELECT...). - ** In this case there is a separate term for each of (x) and (y). - ** However, the nIn multiplier should only be applied once, not once - ** for each such term. The following loop checks that pTerm is the - ** first such term in use, and sets nIn back to 0 if it is not. */ - for(i=0; inLTerm-1; i++){ - if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0; - } - }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ - /* "x IN (value, value, ...)" */ - nIn = sqlite3LogEst(pExpr->x.pList->nExpr); - assert( nIn>0 ); /* RHS always has 2 or more terms... The parser - ** changes "x IN (?)" into "x=?". */ + switch( pExpr->eX ){ + case EX_Select: { + /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ + int i; + nIn = 46; assert( 46==sqlite3LogEst(25) ); + + /* The expression may actually be of the form (x, y) IN (SELECT...). + ** In this case there is a separate term for each of (x) and (y). + ** However, the nIn multiplier should only be applied once, not once + ** for each such term. The following loop checks that pTerm is the + ** first such term in use, and sets nIn back to 0 if it is not. */ + for(i=0; inLTerm-1; i++){ + if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0; + } + break; + } + case EX_List: { + /* "x IN (value, value, ...)" */ + nIn = sqlite3LogEst(pExpr->x.pList->nExpr); + assert( nIn>0 ); /* RHS always has 2 or more terms... The parser + ** changes "x IN (?)" into "x=?". */ + break; + } } if( pProbe->hasStat1 ){ LogEst M, logK, safetyMargin; /* Let: ** N = the total number of rows in the table @@ -2618,20 +2638,21 @@ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 tRowcnt nOut = 0; if( nInMul==0 && pProbe->nSample && pNew->u.btree.nEq<=pProbe->nSampleCol - && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) + && ((eOp & WO_IN)==0 || pTerm->pExpr->eX==EX_List) && OptimizationEnabled(db, SQLITE_Stat34) ){ Expr *pExpr = pTerm->pExpr; - if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ + if( (eOp & (WO_EQ|WO_IS))!=0 ){ testcase( eOp & WO_EQ ); testcase( eOp & WO_IS ); testcase( eOp & WO_ISNULL ); - rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); - }else{ + assert( pExpr->eX==EX_Right ); + rc = whereEqualScanEst(pParse, pBuilder, pExpr->x.pRight, &nOut); + }else if( pExpr->eX==EX_List ){ rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); } if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */ if( nOut ){ @@ -2781,11 +2802,12 @@ int i; WhereTerm *pTerm; 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++){ Expr *pExpr = pTerm->pExpr; if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) @@ -3236,11 +3258,11 @@ if( iCons>=0 && iConsnConstraint ){ CollSeq *pC = 0; 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); } return zRet; } Index: src/wherecode.c ================================================================== --- src/wherecode.c +++ src/wherecode.c @@ -433,11 +433,13 @@ pOrigLhs->a[iField].pExpr = 0; } } sqlite3ExprListDelete(db, pOrigRhs); sqlite3ExprListDelete(db, pOrigLhs); + assert( pNew->pLeft->eX==EX_List ); pNew->pLeft->x.pList = pLhs; + if( pLhs==0 ) pNew->pLeft->eX = EX_None; pNew->x.pSelect->pEList = pRhs; if( pLhs && pLhs->nExpr==1 ){ /* Take care here not to generate a TK_VECTOR containing only a ** single value. Since the parser never creates such a vector, some ** of the subroutines do not handle this case. */ @@ -500,11 +502,12 @@ int iReg; /* Register holding results */ 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); #ifndef SQLITE_OMIT_SUBQUERY }else{ @@ -536,11 +539,11 @@ for(i=iEq;inLTerm; i++){ assert( pLoop->aLTerm[i]!=0 ); if( pLoop->aLTerm[i]->pExpr==pX ) nEq++; } - if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ + if( pX->eX!=EX_Select || pX->x.pSelect->pEList->nExpr==1 ){ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); }else{ sqlite3 *db = pParse->db; pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX); @@ -732,19 +735,21 @@ }else{ sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); } } if( pTerm->eOperator & WO_IN ){ - if( pTerm->pExpr->flags & EP_xIsSelect ){ + if( pTerm->pExpr->eX==EX_Select ){ /* No affinity ever needs to be (or should be) applied to a value ** from the RHS of an "? IN (SELECT ...)" expression. The ** sqlite3FindInIndex() routine has already ensured that the ** affinity of the comparison has been applied to the value. */ 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); } if( zAff ){ @@ -1072,11 +1077,11 @@ */ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ assert( nReg>0 ); if( p && sqlite3ExprIsVector(p) ){ #ifndef SQLITE_OMIT_SUBQUERY - if( (p->flags & EP_xIsSelect) ){ + if( p->eX==EX_Select ){ Vdbe *v = pParse->pVdbe; int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0); sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1); }else #endif @@ -1115,11 +1120,11 @@ IdxExprTrans *pX = p->u.pIdxTrans; if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ pExpr->op = TK_COLUMN; pExpr->iTable = pX->iIdxCur; pExpr->iColumn = pX->iIdxCol; - pExpr->pTab = 0; + /* pExpr->pTab = 0; */ return WRC_Prune; }else{ return WRC_Continue; } } @@ -1260,11 +1265,12 @@ if( NEVER(pTerm==0) ) continue; if( pTerm->eOperator & WO_IN ){ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); addrNotFound = pLevel->addrNxt; }else{ - Expr *pRight = pTerm->pExpr->pRight; + Expr *pExpr = pTerm->pExpr; + Expr *pRight = pExpr->eX==EX_Right ? pExpr->x.pRight : 0; codeExprOrVector(pParse, pRight, iTarget, 1); } } sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); @@ -1305,12 +1311,15 @@ ** the IN constraint is not satisfied */ pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0); 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); } pCompare->pLeft = 0; sqlite3ExprDelete(db, pCompare); @@ -1391,13 +1400,14 @@ assert( (pStart->wtFlags & TERM_VNULL)==0 ); testcase( pStart->wtFlags & TERM_VIRTUAL ); 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 ); testcase( pX->op==TK_LE ); op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1]; @@ -1404,11 +1414,11 @@ assert( pX->op!=TK_GT || op==OP_SeekGE ); assert( pX->op!=TK_GE || op==OP_SeekGE ); 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)]; } sqlite3VdbeAddOp3(v, op, iCur, addrBrk, r1); VdbeComment((v, "pk")); @@ -1424,23 +1434,24 @@ } if( pEnd ){ 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); } } start = sqlite3VdbeCurrentAddr(v); pLevel->op = bRev ? OP_Prev : OP_Next; @@ -1620,11 +1631,13 @@ start_constraints = pRangeStart || nEq>0; /* 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 && sqlite3ExprCanBeNull(pRight) ){ @@ -1672,11 +1685,13 @@ /* Load the value for the inequality constraint at the end of the ** range (if any). */ 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 && sqlite3ExprCanBeNull(pRight) ){ @@ -2192,11 +2207,11 @@ pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN|WO_IS, 0); if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; if( (pAlt->eOperator & WO_IN) - && (pAlt->pExpr->flags & EP_xIsSelect) + && (pAlt->pExpr->eX==EX_Select) && (pAlt->pExpr->x.pSelect->pEList->nExpr>1) ){ continue; } testcase( pAlt->eOperator & WO_EQ ); Index: src/whereexpr.c ================================================================== --- src/whereexpr.c +++ src/whereexpr.c @@ -117,27 +117,29 @@ ** the left hand side of a comparison overrides any collation sequence ** attached to the right. For the same reason the EP_Collate flag ** 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 ** it to be searched first. */ 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 ); assert( TK_GT>TK_EQ ); assert( TK_GTop!=TK_COLUMN - || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) /* Value might be numeric */ + || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT + || NEVER(pLeft->eX!=EX_Tab) + || IsVirtual(pLeft->x.pTab) /* Value might be numeric */ ){ sqlite3ExprDelete(db, pPrefix); sqlite3ValueFree(pVal); return 0; } @@ -380,11 +383,11 @@ ** ** vtab_column MATCH expression ** MATCH(expression,vtab_column) */ pCol = pList->a[1].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + if( pCol->op==TK_COLUMN && pCol->eX==EX_Tab && IsVirtual(pCol->x.pTab) ){ for(i=0; iu.zToken, aOp[i].zOp)==0 ){ *peOp2 = aOp[i].eOp2; *ppRight = pList->a[0].pExpr; *ppLeft = pCol; @@ -402,16 +405,16 @@ ** Historically, xFindFunction expected to see lower-case function ** names. But for this use case, xFindFunction is expected to deal ** with function names in an arbitrary case. */ pCol = pList->a[0].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + if( pCol->op==TK_COLUMN && pCol->eX==EX_Tab && IsVirtual(pCol->x.pTab) ){ sqlite3_vtab *pVtab; sqlite3_module *pMod; void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); void *pNotUsed; - pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab; + pVtab = sqlite3GetVTable(db, pCol->x.pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; if( pMod->xFindFunction!=0 ){ i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); @@ -424,15 +427,16 @@ } } }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){ int res = 0; Expr *pLeft = pExpr->pLeft; - Expr *pRight = pExpr->pRight; - if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){ + Expr *pRight = 0; + if( pLeft->op==TK_COLUMN && pLeft->eX==EX_Tab && IsVirtual(pLeft->x.pTab) ){ res++; } - if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){ + if( pExpr->eX==EX_Right && (pRight = pExpr->x.pRight)->op==TK_COLUMN + && pRight->eX==EX_Tab && IsVirtual(pRight->x.pTab) ){ res++; SWAP(Expr*, pLeft, pRight); } *ppLeft = pLeft; *ppRight = pRight; @@ -514,14 +518,18 @@ if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; 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) ){ eOp = WO_LE; }else{ @@ -825,11 +833,12 @@ int affLeft, affRight; /* If the right-hand side is also a column, then the affinities ** 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; }else{ pOrTerm->wtFlags |= TERM_OR_OK; @@ -851,29 +860,32 @@ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; assert( pOrTerm->eOperator & WO_EQ ); assert( pOrTerm->leftCursor==iCursor ); assert( pOrTerm->u.leftColumn==iColumn ); - pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); + assert( pOrTerm->pExpr->eX==EX_Right ); + pDup = sqlite3ExprDup(db, pOrTerm->pExpr->x.pRight, 0); pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup); pLeft = pOrTerm->pExpr->pLeft; } assert( pLeft!=0 ); pDup = sqlite3ExprDup(db, pLeft, 0); pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0); - if( pNew ){ + if( pNew && pList ){ int idxNew; transferJoinMarkings(pNew, pExpr); - assert( !ExprHasProperty(pNew, EP_xIsSelect) ); + assert( pNew->eX==EX_None ); + pNew->eX = EX_List; pNew->x.pList = pList; idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); exprAnalyze(pSrc, pWC, idxNew); - /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */ + /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm used again */ markTermAsChild(pWC, idxNew, idxTerm); }else{ sqlite3ExprListDelete(db, pList); + sqlite3ExprDelete(db, pNew); } } } } #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ @@ -898,19 +910,20 @@ CollSeq *pColl; if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; 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); } /* ** Recursively walk the expressions of a SELECT statement and generate ** a bitmask indicating which tables are used in that expression @@ -1051,21 +1064,29 @@ pExpr = pTerm->pExpr; assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; if( op==TK_IN ){ - assert( pExpr->pRight==0 ); + assert( pExpr->eX!=EX_Right ); if( sqlite3ExprCheckIN(pParse, pExpr) ) return; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect); - }else{ - pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList); - } - }else if( op==TK_ISNULL ){ - pTerm->prereqRight = 0; - }else{ - pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); + switch( pExpr->eX ){ + case EX_Select: { + pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect); + break; + } + case EX_List: { + pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet,pExpr->x.pList); + break; + } + } + }else{ + 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); if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT; if( ExprHasProperty(pExpr, EP_FromJoin) ){ @@ -1082,14 +1103,20 @@ pTerm->leftCursor = -1; pTerm->iParent = -1; 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 ); pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr; } @@ -1326,21 +1353,22 @@ ** This is only required if at least one side of the comparison operation ** is not a sub-select. */ if( pWC->op==TK_AND && (pExpr->op==TK_EQ || pExpr->op==TK_IS) && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1 - && sqlite3ExprVectorSize(pExpr->pRight)==nLeft - && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 - || (pExpr->pRight->flags & EP_xIsSelect)==0) + && ALWAYS(pExpr->eX==EX_Right) + && sqlite3ExprVectorSize(pExpr->x.pRight)==nLeft + && ( pExpr->pLeft->eX!=EX_Select || pExpr->x.pRight->eX!=EX_Select ) ){ int i; for(i=0; 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); exprAnalyze(pSrc, pWC, idxNew); } @@ -1444,12 +1472,13 @@ pWC->op = op; if( pE2==0 ) return; 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); } } /* ** Initialize a preallocated WhereClause structure. @@ -1504,18 +1533,24 @@ assert( p->op!=TK_IF_NULL_ROW ); return 0; } mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0; if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft); - if( p->pRight ){ - mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight); - assert( p->x.pList==0 ); - }else if( ExprHasProperty(p, EP_xIsSelect) ){ - if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1; - mask |= exprSelectUsage(pMaskSet, p->x.pSelect); - }else if( p->x.pList ){ - mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList); + switch( p->eX ){ + case EX_Right: { + mask |= sqlite3WhereExprUsageNN(pMaskSet, p->x.pRight); + break; + } + case EX_Select: { + if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1; + mask |= exprSelectUsage(pMaskSet, p->x.pSelect); + break; + } + case EX_List: { + mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList); + break; + } } return mask; } Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0; @@ -1581,11 +1616,12 @@ } pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; - pColRef->pTab = pTab; + pColRef->x.pTab = pTab; + pColRef->eX = EX_Tab; pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); } } Index: test/bestindex5.test ================================================================== --- test/bestindex5.test +++ test/bestindex5.test @@ -12,11 +12,11 @@ # method. # set testdir [file dirname $argv0] source $testdir/tester.tcl -set testprefix bestindex4 +set testprefix bestindex5 ifcapable !vtab { finish_test return } @@ -245,6 +245,5 @@ do_execsql_test 3.5 { SELECT rowid, * FROM t4 WHERE rowid!=1 OR x!='245'; } {} finish_test -