/* ** The input to this routine is an ExprInfo structure with only the ** "p" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the ExprInfo ** structure. */ static void exprAnalyze(ExprMaskSet *pMaskSet, ExprInfo *pInfo){ Expr *pExpr = pInfo->p; pInfo->prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); pInfo->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); pInfo->prereqAll = exprTableUsage(pMaskSet, pExpr); pInfo->indexable = 0; pInfo->idxLeft = -1; pInfo->idxRight = -1; if( allowedOp(pExpr->op) && (pInfo->prereqRight & pInfo->prereqLeft)==0 ){ if( pExpr->pRight && pExpr->pRight->op==TK_COLUMN ){ pInfo->idxRight = pExpr->pRight->iTable; pInfo->indexable = 1; } if( pExpr->pLeft->op==TK_COLUMN ){ pInfo->idxLeft = pExpr->pLeft->iTable; pInfo->indexable = 1; } } }
/* ** The input to this routine is an ExprInfo structure with only the ** "p" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the ExprInfo ** structure. */ static void exprAnalyze(SrcList *pSrc, ExprMaskSet *pMaskSet, ExprInfo *pInfo){ Expr *pExpr = pInfo->p; pInfo->prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); pInfo->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); pInfo->prereqAll = exprTableUsage(pMaskSet, pExpr); pInfo->indexable = 0; pInfo->idxLeft = -1; pInfo->idxRight = -1; if( allowedOp(pExpr->op) && (pInfo->prereqRight & pInfo->prereqLeft)==0 ){ if( pExpr->pRight && pExpr->pRight->op==TK_COLUMN ){ pInfo->idxRight = pExpr->pRight->iTable; pInfo->indexable = 1; } if( pExpr->pLeft->op==TK_COLUMN ){ pInfo->idxLeft = pExpr->pLeft->iTable; pInfo->indexable = 1; } } if( pInfo->indexable ){ assert( pInfo->idxLeft!=pInfo->idxRight ); /* We want the expression to be of the form "X = expr", not "expr = X". ** So flip it over if necessary. If the expression is "X = Y", then ** we want Y to come from an earlier table than X. ** ** The collating sequence rule is to always choose the left expression. ** So if we do a flip, we also have to move the collating sequence. */ if( tableOrder(pSrc,pInfo->idxLeft)<tableOrder(pSrc,pInfo->idxRight) ){ assert( pExpr->op!=TK_IN ); SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); SWAP(Expr*,pExpr->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_GT<TK_LE ); assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE ); pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; } SWAP(unsigned, pInfo->prereqLeft, pInfo->prereqRight); SWAP(short int, pInfo->idxLeft, pInfo->idxRight); }
/* ** This routine walks (recursively) an expression tree and generates ** a bitmask indicating which tables are used in that expression ** tree. ** ** In order for this routine to work, the calling function must have ** previously invoked sqliteExprResolveIds() on the expression. See ** the header comment on that routine for additional information. ** The sqliteExprResolveIds() routines looks for column names and ** sets their opcodes to TK_COLUMN and their Expr.iTable fields to ** the VDBE cursor number of the table. */ static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p) { unsigned int mask = 0; if( p==0 ) return 0; if( p->op==TK_COLUMN ) { return getMask(pMaskSet, p->iTable); } if( p->pRight ) { mask = exprTableUsage(pMaskSet, p->pRight); } if( p->pLeft ) { mask |= exprTableUsage(pMaskSet, p->pLeft); } if( p->pList ) { int i; for(i=0; i<p->pList->nExpr; i++) { mask |= exprTableUsage(pMaskSet, p->pList->a[i].pExpr); } } return mask; }