Index: src/attach.c ================================================================== --- src/attach.c +++ src/attach.c @@ -522,18 +522,18 @@ sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); return 1; } } if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUsesRight(pExpr) ){ + if( sqlite3FixExpr(pFix, pExpr->x.pRight) ) return 1; + }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ + assert( ExprHasProperty(pExpr, EP_xIsList) ); if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; } - if( sqlite3FixExpr(pFix, pExpr->pRight) ){ - return 1; - } pExpr = pExpr->pLeft; } return 0; } int sqlite3FixExprList( Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -34,11 +34,11 @@ int op; pExpr = sqlite3ExprSkipCollate(pExpr); if( pExpr->flags & EP_Generic ) return SQLITE_AFF_NONE; op = pExpr->op; if( op==TK_SELECT ){ - assert( pExpr->flags&EP_xIsSelect ); + assert( ExprHasProperty(pExpr, EP_xIsSelect) ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); @@ -94,11 +94,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( ExprHasProperty(pExpr, EP_xIsList) ); assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; }else{ assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS ); @@ -146,12 +146,12 @@ break; } if( p->flags & EP_Collate ){ if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; - }else{ - p = p->pRight; + }else if( ExprUsesRight(p) ){ + p = p->x.pRight; } }else{ break; } } @@ -198,12 +198,12 @@ 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); + if( ExprUsesRight(pExpr) ){ + aff = sqlite3CompareAffinity(pExpr->x.pRight, aff); }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); }else if( !aff ){ aff = SQLITE_AFF_NONE; } @@ -357,14 +357,16 @@ ** referenced Expr plus one. */ static void exprSetHeight(Expr *p){ int nHeight = 0; heightOfExpr(p->pLeft, &nHeight); - heightOfExpr(p->pRight, &nHeight); - if( ExprHasProperty(p, EP_xIsSelect) ){ + if( ExprUsesRight(p) ){ + heightOfExpr(p->x.pRight, &nHeight); + }else if( ExprHasProperty(p, EP_xIsSelect) ){ heightOfSelect(p->x.pSelect, &nHeight); }else{ + assert( ExprHasProperty(p, EP_xIsList) ); heightOfExprList(p->x.pList, &nHeight); } p->nHeight = nHeight + 1; } @@ -487,12 +489,12 @@ assert( db->mallocFailed ); sqlite3ExprDelete(db, pLeft); sqlite3ExprDelete(db, pRight); }else{ if( pRight ){ - pRoot->pRight = pRight; - pRoot->flags |= EP_Collate & pRight->flags; + pRoot->x.pRight = pRight; + pRoot->flags |= (EP_Collate & pRight->flags); } if( pLeft ){ pRoot->pLeft = pLeft; pRoot->flags |= EP_Collate & pLeft->flags; } @@ -591,11 +593,11 @@ if( pNew==0 ){ sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ return 0; } pNew->x.pList = pList; - assert( !ExprHasProperty(pNew, EP_xIsSelect) ); + ExprSetProperty(pNew, EP_xIsList); sqlite3ExprSetHeight(pParse, pNew); return pNew; } /* @@ -688,18 +690,20 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p==0 ) return; /* Sanity check: Assert that the IntValue is non-negative if it exists */ assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); if( !ExprHasProperty(p, EP_TokenOnly) ){ - /* The Expr.x union is never used at the same time as Expr.pRight */ - assert( p->x.pList==0 || p->pRight==0 ); sqlite3ExprDelete(db, p->pLeft); - sqlite3ExprDelete(db, p->pRight); - if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); - if( ExprHasProperty(p, EP_xIsSelect) ){ + if( ExprHasProperty(p, EP_MemToken) ){ + sqlite3DbFree(db, p->u.zToken); + } + if( ExprUsesRight(p) ){ + sqlite3ExprDelete(db, p->x.pRight); + }else if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ + assert( ExprHasProperty(p, EP_xIsList) ); sqlite3ExprListDelete(db, p->x.pList); } } if( !ExprHasProperty(p, EP_Static) ){ sqlite3DbFree(db, p); @@ -764,11 +768,10 @@ assert( !ExprHasProperty(p, EP_MemToken) ); assert( !ExprHasProperty(p, EP_NoReduce) ); if( p->pLeft || p->x.pList ){ nSize = EXPR_REDUCEDSIZE | EP_Reduced; }else{ - assert( p->pRight==0 ); nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; } } return nSize; } @@ -802,21 +805,24 @@ 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( ExprUsesRight(p) ){ + 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 passed the ** portion of the buffer copied into by this function. */ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ Expr *pNew = 0; /* Value to return */ @@ -872,29 +878,35 @@ if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ if( ExprHasProperty(p, EP_xIsSelect) ){ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced); - }else{ + }else if( ExprHasProperty(p, EP_xIsList) ){ pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced); } } - /* 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, flags); if( ExprHasProperty(pNew, EP_Reduced) ){ pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc); - pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc); + if( ExprUsesRight(p) ){ + assert( ExprUsesRight(p) ); + pNew->x.pRight = exprDup(db, p->x.pRight, EXPRDUP_REDUCE, &zAlloc); + } } if( pzBuffer ){ *pzBuffer = zAlloc; } }else{ if( !ExprHasProperty(p, EP_TokenOnly) ){ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); - pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); + if( ExprUsesRight(p) ){ + assert( ExprUsesRight(pNew) ); + pNew->x.pRight = sqlite3ExprDup(db, p->x.pRight, 0); + } } } } } @@ -2528,12 +2540,13 @@ case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + assert( ExprUsesRight(pExpr) ); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op, r1, r2, inReg, SQLITE_STOREP2); 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); @@ -2546,13 +2559,14 @@ case TK_IS: case TK_ISNOT: { testcase( op==TK_IS ); testcase( op==TK_ISNOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + assert( ExprUsesRight(pExpr) ); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2); op = (op==TK_IS) ? TK_EQ : TK_NE; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op, r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); VdbeCoverageIf(v, op==TK_EQ); VdbeCoverageIf(v, op==TK_NE); testcase( regFree1==0 ); testcase( regFree2==0 ); @@ -2580,11 +2594,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( ExprUsesRight(pExpr) ); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2); sqlite3VdbeAddOp3(v, op, r2, r1, target); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } @@ -2654,14 +2669,14 @@ u32 constMask = 0; /* Mask of function arguments that are constant */ int i; /* Loop counter */ u8 enc = ENC(db); /* The text encoding used by this database */ CollSeq *pColl = 0; /* A collating sequence */ - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); if( ExprHasProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; }else{ + assert( ExprHasProperty(pExpr, EP_xIsList) ); pFarg = pExpr->x.pList; } nFarg = pFarg ? pFarg->nExpr : 0; assert( !ExprHasProperty(pExpr, EP_IntValue) ); zId = pExpr->u.zToken; @@ -2924,11 +2939,11 @@ Expr opCompare; /* The X==Ei expression */ Expr *pX; /* The X expression */ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; ) - assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); + assert( ExprHasProperty(pExpr, EP_xIsList) && pExpr->x.pList ); assert(pExpr->x.pList->nExpr > 0); pEList = pExpr->x.pList; aListelem = pEList->a; nExpr = pEList->nExpr; endLabel = sqlite3VdbeMakeLabel(v); @@ -2936,10 +2951,11 @@ tempX = *pX; testcase( pX->op==TK_COLUMN ); exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, ®Free1)); testcase( regFree1==0 ); opCompare.op = TK_EQ; + opCompare.flags = 0; opCompare.pLeft = &tempX; pTest = &opCompare; /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: ** The value in regFree1 might get SCopy-ed into the file result. ** So make sure that the regFree1 register is not reused for other @@ -2948,11 +2964,11 @@ } for(i=0; iop==TK_COLUMN ); @@ -3362,11 +3378,12 @@ } if( zBinOp ){ sqlite3ExplainPrintf(pOut,"%s(", zBinOp); sqlite3ExplainExpr(pOut, pExpr->pLeft); sqlite3ExplainPrintf(pOut,","); - sqlite3ExplainExpr(pOut, pExpr->pRight); + assert( ExprUsesRight(pExpr) ); + sqlite3ExplainExpr(pOut, pExpr->x.pRight); sqlite3ExplainPrintf(pOut,")"); }else if( zUniOp ){ sqlite3ExplainPrintf(pOut,"%s(", zUniOp); sqlite3ExplainExpr(pOut, pExpr->pLeft); sqlite3ExplainPrintf(pOut,")"); @@ -3480,21 +3497,24 @@ Expr compLeft; /* The x>=y term */ Expr compRight; /* The x<=z term */ Expr exprX; /* The x subexpression */ int regFree1 = 0; /* Temporary use register */ - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( ExprHasProperty(pExpr, EP_xIsList) ); exprX = *pExpr->pLeft; exprAnd.op = TK_AND; + exprAnd.flags = 0; exprAnd.pLeft = &compLeft; - exprAnd.pRight = &compRight; + exprAnd.x.pRight = &compRight; compLeft.op = TK_GE; + compLeft.flags = 0; compLeft.pLeft = &exprX; - compLeft.pRight = pExpr->x.pList->a[0].pExpr; + compLeft.x.pRight = pExpr->x.pList->a[0].pExpr; compRight.op = TK_LE; + compRight.flags = 0; compRight.pLeft = &exprX; - compRight.pRight = pExpr->x.pList->a[1].pExpr; + compRight.x.pRight = pExpr->x.pList->a[1].pExpr; exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, ®Free1)); if( jumpIfTrue ){ sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull); }else{ sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull); @@ -3541,20 +3561,22 @@ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprCachePush(pParse); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + assert( ExprUsesRight(pExpr) ); + sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); sqlite3ExprCachePop(pParse); break; } case TK_OR: { testcase( jumpIfNull==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprCachePush(pParse); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + assert( ExprUsesRight(pExpr) ); + sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull); sqlite3ExprCachePop(pParse); break; } case TK_NOT: { testcase( jumpIfNull==0 ); @@ -3567,12 +3589,13 @@ case TK_GE: case TK_NE: case TK_EQ: { testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + assert( ExprUsesRight(pExpr) ); + 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); @@ -3585,13 +3608,14 @@ case TK_IS: case TK_ISNOT: { testcase( op==TK_IS ); testcase( op==TK_ISNOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + assert( ExprUsesRight(pExpr) ); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2); op = (op==TK_IS) ? TK_EQ : TK_NE; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op, r1, r2, dest, SQLITE_NULLEQ); VdbeCoverageIf(v, op==TK_EQ); VdbeCoverageIf(v, op==TK_NE); testcase( regFree1==0 ); testcase( regFree2==0 ); @@ -3696,20 +3720,22 @@ switch( pExpr->op ){ case TK_AND: { testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprCachePush(pParse); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + assert( ExprUsesRight(pExpr) ); + sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull); sqlite3ExprCachePop(pParse); break; } case TK_OR: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprCachePush(pParse); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + assert( ExprUsesRight(pExpr) ); + sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); sqlite3ExprCachePop(pParse); break; } case TK_NOT: { @@ -3723,12 +3749,13 @@ case TK_GE: case TK_NE: case TK_EQ: { testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + assert( ExprUsesRight(pExpr) ); + 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); @@ -3741,13 +3768,14 @@ case TK_IS: case TK_ISNOT: { testcase( pExpr->op==TK_IS ); testcase( pExpr->op==TK_ISNOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + assert( ExprUsesRight(pExpr) ); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2); op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op, r1, r2, dest, SQLITE_NULLEQ); VdbeCoverageIf(v, op==TK_EQ); VdbeCoverageIf(v, op==TK_NE); testcase( regFree1==0 ); testcase( regFree2==0 ); @@ -3846,14 +3874,20 @@ return pA->op==TK_COLLATE ? 1 : 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( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2; - if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2; - if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; + if( (pA->flags&EP_xMask)!=(pB->flags&EP_xMask) ) return 2; + if( ExprUsesRight(pA) ){ + if( sqlite3ExprCompare(pA->x.pRight, pB->x.pRight, iTab) ) return 2; + }else if( ExprHasProperty(pA, EP_xIsSelect) ){ + return 2; + }else{ + assert( ExprHasProperty(pA, EP_xIsList) ); + if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; + } if( ALWAYS((combinedFlags & EP_Reduced)==0) ){ if( pA->iColumn!=pB->iColumn ) return 2; if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; } @@ -3914,11 +3948,11 @@ if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){ return 1; } if( pE2->op==TK_OR && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) - || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) + || sqlite3ExprImpliesExpr(pE1, pE2->x.pRight, iTab) ) ){ return 1; } if( pE2->op==TK_NOTNULL && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0 @@ -4117,11 +4151,11 @@ /* 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( ExprHasProperty(pExpr, EP_xIsList) ); pItem = &pAggInfo->aFunc[i]; pItem->pExpr = pExpr; pItem->iMem = ++pParse->nMem; assert( !ExprHasProperty(pExpr, EP_IntValue) ); pItem->pFunc = sqlite3FindFunction(pParse->db, Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1604,25 +1604,23 @@ setLikeOptFlag(db, "like", caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); } /* -** pExpr points to an expression which implements a function. If +** pExpr might point to an expression which implements a function. If ** it is appropriate to apply the LIKE optimization to that function ** then set aWc[0] through aWc[2] to the wildcard characters and ** return TRUE. If the function is not a LIKE-style function then ** return FALSE. */ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ FuncDef *pDef; - if( pExpr->op!=TK_FUNCTION - || !pExpr->x.pList - || pExpr->x.pList->nExpr!=2 - ){ + if( pExpr->op!=TK_FUNCTION ) return 0; + assert( ExprHasProperty(pExpr, EP_xIsList) || pExpr->x.pList==0 ); + if( !pExpr->x.pList || pExpr->x.pList->nExpr!=2 ){ return 0; } - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); pDef = sqlite3FindFunction(db, pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken), 2, 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 @@ -940,12 +940,13 @@ ** unary TK_ISNULL or TK_NOTNULL expression. */ static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ sqlite3 *db = pParse->db; if( db->mallocFailed==0 && pY->op==TK_NULL ){ pA->op = (u8)op; - sqlite3ExprDelete(db, pA->pRight); - pA->pRight = 0; + assert( ExprUsesRight(pA) ); + sqlite3ExprDelete(db, pA->x.pRight); + pA->x.pRight = 0; } } } // expr1 IS expr2 @@ -995,10 +996,11 @@ ExprList *pList = sqlite3ExprListAppend(pParse,0, X.pExpr); pList = sqlite3ExprListAppend(pParse,pList, Y.pExpr); A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, W.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = pList; + ExprSetProperty(A.pExpr, EP_xIsList); }else{ sqlite3ExprListDelete(pParse->db, pList); } if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0); A.zStart = W.zStart; @@ -1049,10 +1051,11 @@ A.pExpr = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, X.pExpr, pRHS, 0); }else{ A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Y; + ExprSetProperty(A.pExpr, EP_xIsList); sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); } if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0); @@ -1116,10 +1119,11 @@ /* CASE expressions */ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y; + ExprSetProperty(A.pExpr, EP_xIsList); sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); sqlite3ExprDelete(pParse->db, Z); } Index: src/resolve.c ================================================================== --- src/resolve.c +++ src/resolve.c @@ -195,11 +195,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 @@ -413,11 +413,11 @@ ){ 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->pLeft==0 && pExpr->x.pRight==0 ); assert( pExpr->x.pList==0 ); assert( pExpr->x.pSelect==0 ); pOrig = pEList->a[j].pExpr; if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); @@ -493,12 +493,14 @@ /* Clean up and return */ sqlite3ExprDelete(db, pExpr->pLeft); pExpr->pLeft = 0; - sqlite3ExprDelete(db, pExpr->pRight); - pExpr->pRight = 0; + if( ExprUsesRight(pExpr) ){ + sqlite3ExprDelete(db, pExpr->x.pRight); + pExpr->x.pRight = 0; + } pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); if( pExpr->op!=TK_AS ){ @@ -653,20 +655,22 @@ const char *zTable; const char *zDb; Expr *pRight; /* if( pSrcList==0 ) break; */ - pRight = pExpr->pRight; + assert( ExprUsesRight(pExpr) ); + pRight = pExpr->x.pRight; if( pRight->op==TK_ID ){ zDb = 0; zTable = pExpr->pLeft->u.zToken; zColumn = pRight->u.zToken; }else{ assert( pRight->op==TK_DOT ); + assert( ExprUsesRight(pRight) ); zDb = pExpr->pLeft->u.zToken; zTable = pRight->pLeft->u.zToken; - zColumn = pRight->pRight->u.zToken; + zColumn = pRight->x.pRight->u.zToken; } return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); } /* Resolve function names @@ -681,11 +685,11 @@ 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( ExprHasProperty(pExpr, EP_xIsList) || pList==0 ); notValidPartIdxWhere(pParse, pNC, "functions"); zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -338,11 +338,11 @@ ExprSetProperty(p, EP_FromJoin); assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(p, EP_NoReduce); p->iRightJoinTable = (i16)iTable; setJoinExpr(p->pLeft, iTable); - p = p->pRight; + p = ExprUsesRight(p) ? p->x.pRight : 0; } } /* ** This routine processes the join information for a SELECT statement. @@ -1560,11 +1560,12 @@ zName = sqlite3DbStrDup(db, zName); }else{ Expr *pColExpr = p; /* The expression that is the result column name */ Table *pTab; /* Table associated with this expression */ while( pColExpr->op==TK_DOT ){ - pColExpr = pColExpr->pRight; + assert( ExprUsesRight(pColExpr) ); + pColExpr = pColExpr->x.pRight; assert( pColExpr!=0 ); } if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; @@ -2992,21 +2993,23 @@ if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; assert( pEList!=0 && pExpr->iColumnnExpr ); - assert( pExpr->pLeft==0 && pExpr->pRight==0 ); + assert( pExpr->pLeft==0 && pExpr->x.pRight==0 ); pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); sqlite3ExprDelete(db, pExpr); pExpr = pNew; } }else{ pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); - pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUsesRight(pExpr) ){ + pExpr->x.pRight = substExpr(db, pExpr->x.pRight, iTable, pEList); + }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ substSelect(db, pExpr->x.pSelect, iTable, pEList); }else{ + assert( ExprHasProperty(pExpr, EP_xIsList) ); substExprList(db, pExpr->x.pList, iTable, pEList); } } return pExpr; } @@ -4052,13 +4055,13 @@ ** that need expanding. */ for(k=0; knExpr; k++){ pE = pEList->a[k].pExpr; if( pE->op==TK_ALL ) break; - assert( pE->op!=TK_DOT || pE->pRight!=0 ); + assert( pE->op!=TK_DOT || !ExprUsesRight(pE) || pE->x.pRight!=0 ); assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); - if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; + if( pE->op==TK_DOT && pE->x.pRight->op==TK_ALL ) break; } if( knExpr ){ /* ** If we get here it means the result set contains one or more "*" ** operators that need to be expanded. Loop through each expression @@ -4077,11 +4080,11 @@ || ((flags & SQLITE_FullColNames)==0 && (flags & SQLITE_ShortColNames)!=0) ); for(k=0; knExpr; k++){ pE = a[k].pExpr; - pRight = pE->pRight; + pRight = ExprUsesRight(pE) ? pE->x.pRight : 0; assert( pE->op!=TK_DOT || pRight!=0 ); if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); @@ -4374,11 +4377,11 @@ #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) ); + assert( ExprHasProperty(pE, EP_xIsList) || pE->x.pList==0 ); if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " "argument"); pFunc->iDistinct = -1; }else{ @@ -4398,11 +4401,11 @@ 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( ExprHasProperty(pF->pExpr, EP_xIsList) || pList==0 ); sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0, (void*)pF->pFunc, P4_FUNCDEF); } } @@ -4422,11 +4425,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( ExprHasProperty(pF->pExpr, EP_xIsList) || pList==0 ); if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP); }else{ @@ -4897,11 +4900,12 @@ if( pHaving ){ sqlite3ExprAnalyzeAggregates(&sNC, pHaving); } sAggInfo.nAccumulator = sAggInfo.nColumn; for(i=0; ix.pList==0 ); sNC.ncFlags |= NC_InAggFunc; sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList); sNC.ncFlags &= ~NC_InAggFunc; } sAggInfo.mxReg = pParse->nMem; Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -1869,28 +1869,28 @@ ** 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 */ } 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. *********************************************************************/ -#if SQLITE_MAX_EXPR_DEPTH>0 - int nHeight; /* Height of the tree headed by this node */ -#endif int iTable; /* TK_COLUMN: cursor number of table holding column ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old ** EP_Unlikely: 1000 times likelihood */ +#if SQLITE_MAX_EXPR_DEPTH>0 + int nHeight; /* Height of the tree headed by this node */ +#endif ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. ** TK_VARIABLE: variable number (always >= 1). */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 op2; /* TK_REGISTER: original value of Expr.op @@ -1912,28 +1912,34 @@ #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) */ #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 */ #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ #define EP_Constant 0x080000 /* Node is a constant */ +#define EP_xIsSelect 0x100000 /* Use x.pSelect, not x.pList or x.pRight */ +#define EP_xIsList 0x200000 /* Use x.pList, not x.pSelect or x.pRight */ +#define EP_xMask 0x300000 /* Combination of xIsSelect and xIsList */ /* ** These macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))!=0) #define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P)) #define ExprSetProperty(E,P) (E)->flags|=(P) #define ExprClearProperty(E,P) (E)->flags&=~(P) + +/* True if the x.pRight field of Expr E is valid */ +#define ExprUsesRight(E) (((E)->flags&EP_xMask)==0) + /* The ExprSetVVAProperty() macro is used for Verification, Validation, ** and Accreditation only. It works like ExprSetProperty() during VVA ** processes but is a no-op for delivery. */ Index: src/walker.c ================================================================== --- src/walker.c +++ src/walker.c @@ -43,14 +43,16 @@ testcase( ExprHasProperty(pExpr, EP_Reduced) ); rc = pWalker->xExprCallback(pWalker, pExpr); if( rc==WRC_Continue && !ExprHasProperty(pExpr,EP_TokenOnly) ){ if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( ExprUsesRight(pExpr) ){ + if( sqlite3WalkExpr(pWalker, pExpr->x.pRight) ) return WRC_Abort; + }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; }else{ + assert( ExprHasProperty(pExpr, EP_xIsList) ); if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; } } return rc & WRC_Abort; } Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -258,11 +258,12 @@ if( pExpr==0 ) return; if( pExpr->op!=op ){ whereClauseInsert(pWC, pExpr, 0); }else{ whereSplit(pWC, pExpr->pLeft, op); - whereSplit(pWC, pExpr->pRight, op); + assert( ExprUsesRight(pExpr) ); + whereSplit(pWC, pExpr->x.pRight, op); } } /* ** Initialize a WhereMaskSet object @@ -309,15 +310,17 @@ if( p==0 ) return 0; if( p->op==TK_COLUMN ){ mask = getMask(pMaskSet, p->iTable); return mask; } - mask = exprTableUsage(pMaskSet, p->pRight); - mask |= exprTableUsage(pMaskSet, p->pLeft); - if( ExprHasProperty(p, EP_xIsSelect) ){ + mask = exprTableUsage(pMaskSet, p->pLeft); + if( ExprUsesRight(p) ){ + mask |= exprTableUsage(pMaskSet, p->x.pRight); + }else if( ExprHasProperty(p, EP_xIsSelect) ){ mask |= exprSelectTableUsage(pMaskSet, p->x.pSelect); }else{ + assert( ExprHasProperty(p, EP_xIsList) ); mask |= exprListTableUsage(pMaskSet, p->x.pList); } return mask; } static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){ @@ -380,27 +383,28 @@ ** 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 expRight = (pExpr->x.pRight->flags & EP_Collate); u16 expLeft = (pExpr->pLeft->flags & EP_Collate); + assert( ExprUsesRight(pExpr) ); 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_GTeOperator & WO_EQUIV)!=0 && pScan->nEquivaEquiv) ){ int j; - pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight); + assert( ExprUsesRight(pTerm->pExpr) ); + pX = sqlite3ExprSkipCollate(pTerm->pExpr->x.pRight); assert( pX->op==TK_COLUMN ); for(j=0; jnEquiv; j+=2){ if( pScan->aEquiv[j]==pX->iTable && pScan->aEquiv[j+1]==pX->iColumn ){ break; @@ -480,20 +485,20 @@ Parse *pParse = pWC->pWInfo->pParse; pX = pTerm->pExpr; if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ continue; } - assert(pX->pLeft); - pColl = sqlite3BinaryCompareCollSeq(pParse, - pX->pLeft, pX->pRight); + assert( pX->pLeft!=0 ); + pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, + ExprUsesRight(pX) ? pX->x.pRight : 0); if( pColl==0 ) pColl = pParse->db->pDfltColl; if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){ continue; } } if( (pTerm->eOperator & WO_EQ)!=0 - && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN + && (pX = pTerm->pExpr->x.pRight)->op==TK_COLUMN && pX->iTable==pScan->aEquiv[0] && pX->iColumn==pScan->aEquiv[1] ){ continue; } @@ -1014,11 +1019,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( ExprUsesRight(pOrTerm->pExpr) ); + affRight = sqlite3ExprAffinity(pOrTerm->pExpr->x.pRight); affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft); if( affRight!=0 && affRight!=affLeft ){ okToChngToIN = 0; }else{ pOrTerm->wtFlags |= TERM_OR_OK; @@ -1040,21 +1046,22 @@ 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( ExprUsesRight(pOrTerm->pExpr) ); + 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, 0); if( pNew ){ int idxNew; transferJoinMarkings(pNew, pExpr); - assert( !ExprHasProperty(pNew, EP_xIsSelect) ); + ExprSetProperty(pNew, EP_xIsList); pNew->x.pList = pList; idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); exprAnalyze(pSrc, pWC, idxNew); pTerm = &pWC->a[idxTerm]; @@ -1114,20 +1121,20 @@ pExpr = pTerm->pExpr; assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; if( op==TK_IN ){ - assert( pExpr->pRight==0 ); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect); }else{ + assert( ExprHasProperty(pExpr, EP_xIsList) || pExpr->x.pList==0 ); pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->x.pList); } }else if( op==TK_ISNULL ){ pTerm->prereqRight = 0; - }else{ - pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); + }else if( ExprUsesRight(pExpr) ){ + pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->x.pRight); } prereqAll = exprTableUsage(pMaskSet, pExpr); if( ExprHasProperty(pExpr, EP_FromJoin) ){ Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable); prereqAll |= x; @@ -1138,18 +1145,21 @@ pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; if( allowedOp(op) ){ Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); - Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); + Expr *pRight; u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; if( pLeft->op==TK_COLUMN ){ pTerm->leftCursor = pLeft->iTable; pTerm->u.leftColumn = pLeft->iColumn; pTerm->eOperator = operatorMask(op) & opMask; } - if( pRight && pRight->op==TK_COLUMN ){ + if( ExprUsesRight(pExpr) + && (pRight = sqlite3ExprSkipCollate(pExpr->x.pRight))!=0 + && pRight->op==TK_COLUMN + ){ WhereTerm *pNew; Expr *pDup; u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ if( pTerm->leftCursor>=0 ){ int idxNew; @@ -1671,11 +1681,12 @@ 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); + assert( ExprUsesRight(pX) ); + pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->x.pRight); pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY"; n++; } } } @@ -2101,11 +2112,12 @@ } /* If possible, improve on the iLower estimate using ($P:$L). */ if( pLower ){ int bOk; /* True if value is extracted from pExpr */ - Expr *pExpr = pLower->pExpr->pRight; + Expr *pExpr = pLower->pExpr->x.pRight; + assert( ExprUsesRight(pLower->pExpr) ); assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 ); rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ tRowcnt iNew; whereKeyStats(pParse, p, pRec, 0, a); @@ -2116,11 +2128,12 @@ } /* If possible, improve on the iUpper estimate using ($P:$U). */ if( pUpper ){ int bOk; /* True if value is extracted from pExpr */ - Expr *pExpr = pUpper->pExpr->pRight; + Expr *pExpr = pUpper->pExpr->x.pRight; + assert( ExprUsesRight(pUpper->pExpr) ); assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ tRowcnt iNew; whereKeyStats(pParse, p, pRec, 1, a); @@ -2386,11 +2399,12 @@ Vdbe *v = pParse->pVdbe; int iReg; /* Register holding results */ assert( iTarget>0 ); if( pX->op==TK_EQ ){ - iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); + assert( ExprUsesRight(pX) ); + 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{ @@ -2569,11 +2583,12 @@ } } testcase( pTerm->eOperator & WO_ISNULL ); testcase( pTerm->eOperator & WO_IN ); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ - Expr *pRight = pTerm->pExpr->pRight; + Expr *pRight = pTerm->pExpr->x.pRight; + assert( ExprUsesRight(pTerm->pExpr) ); if( sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); VdbeCoverage(v); } if( zAff ){ @@ -2846,11 +2861,12 @@ if( pTerm==0 ) continue; if( pTerm->eOperator & WO_IN ){ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); addrNotFound = pLevel->addrNxt; }else{ - sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); + assert( ExprUsesRight(pTerm->pExpr) ); + sqlite3ExprCode(pParse, pTerm->pExpr->x.pRight, iTarget); } } sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, @@ -2937,11 +2953,12 @@ assert( (pStart->wtFlags & TERM_VNULL)==0 ); testcase( pStart->wtFlags & TERM_VIRTUAL ); pX = pStart->pExpr; assert( pX!=0 ); testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ - r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); + assert( ExprUsesRight(pX) ); + r1 = sqlite3ExprCodeTemp(pParse, pX->x.pRight, &rTemp); sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); VdbeComment((v, "pk")); VdbeCoverageIf(v, pX->op==TK_GT); VdbeCoverageIf(v, pX->op==TK_LE); VdbeCoverageIf(v, pX->op==TK_LT); @@ -2960,11 +2977,12 @@ assert( pX!=0 ); assert( (pEnd->wtFlags & TERM_VNULL)==0 ); testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */ testcase( pEnd->wtFlags & TERM_VIRTUAL ); memEndValue = ++pParse->nMem; - sqlite3ExprCode(pParse, pX->pRight, memEndValue); + assert( ExprUsesRight(pX) ); + sqlite3ExprCode(pParse, pX->x.pRight, memEndValue); if( pX->op==TK_LT || pX->op==TK_GT ){ testOp = bRev ? OP_Le : OP_Ge; }else{ testOp = bRev ? OP_Lt : OP_Gt; } @@ -3124,11 +3142,12 @@ 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 = pRangeStart->pExpr->x.pRight; + assert( ExprUsesRight(pRangeStart->pExpr) ); sqlite3ExprCode(pParse, pRight, regBase+nEq); if( (pRangeStart->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); @@ -3168,11 +3187,12 @@ /* 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 = pRangeEnd->pExpr->x.pRight; + assert( ExprUsesRight(pRangeEnd->pExpr) ); sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); sqlite3ExprCode(pParse, pRight, regBase+nEq); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ @@ -4227,11 +4247,12 @@ ){ Expr *pExpr = pTerm->pExpr; if( (eOp & (WO_EQ|WO_ISNULL))!=0 ){ testcase( eOp & WO_EQ ); testcase( eOp & WO_ISNULL ); - rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); + assert( ExprUsesRight(pExpr) ); + rc = whereEqualScanEst(pParse, pBuilder, pExpr->x.pRight, &nOut); }else{ rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); } assert( rc!=SQLITE_OK || nOut>0 ); if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;