⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 where.c

📁 sqlite最新源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  pDerived->iRightJoinTable = pBase->iRightJoinTable;}#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)/*** Analyze a term that consists of two or more OR-connected** subterms.  So in:****     ... WHERE  (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13)**                          ^^^^^^^^^^^^^^^^^^^^**** This routine analyzes terms such as the middle term in the above example.** A WhereOrTerm object is computed and attached to the term under** analysis, regardless of the outcome of the analysis.  Hence:****     WhereTerm.wtFlags   |=  TERM_ORINFO**     WhereTerm.u.pOrInfo  =  a dynamically allocated WhereOrTerm object**** The term being analyzed must have two or more of OR-connected subterms.** A single subterm might be a set of AND-connected sub-subterms.** Examples of terms under analysis:****     (A)     t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5**     (B)     x=expr1 OR expr2=x OR x=expr3**     (C)     t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)**     (D)     x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')**     (E)     (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)**** CASE 1:**** If all subterms are of the form T.C=expr for some single column of C** a single table T (as shown in example B above) then create a new virtual** term that is an equivalent IN expression.  In other words, if the term** being analyzed is:****      x = expr1  OR  expr2 = x  OR  x = expr3**** then create a new virtual term like this:****      x IN (expr1,expr2,expr3)**** CASE 2:**** If all subterms are indexable by a single table T, then set****     WhereTerm.eOperator              =  WO_OR**     WhereTerm.u.pOrInfo->indexable  |=  the cursor number for table T**** A subterm is "indexable" if it is of the form** "T.C <op> <expr>" where C is any column of table T and ** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".** A subterm is also indexable if it is an AND of two or more** subsubterms at least one of which is indexable.  Indexable AND ** subterms have their eOperator set to WO_AND and they have** u.pAndInfo set to a dynamically allocated WhereAndTerm object.**** From another point of view, "indexable" means that the subterm could** potentially be used with an index if an appropriate index exists.** This analysis does not consider whether or not the index exists; that** is something the bestIndex() routine will determine.  This analysis** only looks at whether subterms appropriate for indexing exist.**** All examples A through E above all satisfy case 2.  But if a term** also statisfies case 1 (such as B) we know that the optimizer will** always prefer case 1, so in that case we pretend that case 2 is not** satisfied.**** It might be the case that multiple tables are indexable.  For example,** (E) above is indexable on tables P, Q, and R.**** Terms that satisfy case 2 are candidates for lookup by using** separate indices to find rowids for each subterm and composing** the union of all rowids using a RowSet object.  This is similar** to "bitmap indices" in other database engines.**** OTHERWISE:**** If neither case 1 nor case 2 apply, then leave the eOperator set to** zero.  This term is not useful for search.*/static void exprAnalyzeOrTerm(  SrcList *pSrc,            /* the FROM clause */  WhereClause *pWC,         /* the complete WHERE clause */  int idxTerm               /* Index of the OR-term to be analyzed */){  Parse *pParse = pWC->pParse;            /* Parser context */  sqlite3 *db = pParse->db;               /* Database connection */  WhereTerm *pTerm = &pWC->a[idxTerm];    /* The term to be analyzed */  Expr *pExpr = pTerm->pExpr;             /* The expression of the term */  WhereMaskSet *pMaskSet = pWC->pMaskSet; /* Table use masks */  int i;                                  /* Loop counters */  WhereClause *pOrWc;       /* Breakup of pTerm into subterms */  WhereTerm *pOrTerm;       /* A Sub-term within the pOrWc */  WhereOrInfo *pOrInfo;     /* Additional information associated with pTerm */  Bitmask chngToIN;         /* Tables that might satisfy case 1 */  Bitmask indexable;        /* Tables that are indexable, satisfying case 2 */  /*  ** Break the OR clause into its separate subterms.  The subterms are  ** stored in a WhereClause structure containing within the WhereOrInfo  ** object that is attached to the original OR clause term.  */  assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 );  assert( pExpr->op==TK_OR );  pTerm->u.pOrInfo = pOrInfo = sqlite3DbMallocZero(db, sizeof(*pOrInfo));  if( pOrInfo==0 ) return;  pTerm->wtFlags |= TERM_ORINFO;  pOrWc = &pOrInfo->wc;  whereClauseInit(pOrWc, pWC->pParse, pMaskSet);  whereSplit(pOrWc, pExpr, TK_OR);  exprAnalyzeAll(pSrc, pOrWc);  if( db->mallocFailed ) return;  assert( pOrWc->nTerm>=2 );  /*  ** Compute the set of tables that might satisfy cases 1 or 2.  */  indexable = chngToIN = ~(Bitmask)0;  for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){    if( (pOrTerm->eOperator & WO_SINGLE)==0 ){      WhereAndInfo *pAndInfo;      assert( pOrTerm->eOperator==0 );      assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );      chngToIN = 0;      pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));      if( pAndInfo ){        WhereClause *pAndWC;        WhereTerm *pAndTerm;        int j;        Bitmask b = 0;        pOrTerm->u.pAndInfo = pAndInfo;        pOrTerm->wtFlags |= TERM_ANDINFO;        pOrTerm->eOperator = WO_AND;        pAndWC = &pAndInfo->wc;        whereClauseInit(pAndWC, pWC->pParse, pMaskSet);        whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);        exprAnalyzeAll(pSrc, pAndWC);        testcase( db->mallocFailed );        if( !db->mallocFailed ){          for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){            assert( pAndTerm->pExpr );            if( allowedOp(pAndTerm->pExpr->op) ){              b |= getMask(pMaskSet, pAndTerm->leftCursor);            }          }        }        indexable &= b;      }    }else if( pOrTerm->wtFlags & TERM_COPIED ){      /* Skip this term for now.  We revisit it when we process the      ** corresponding TERM_VIRTUAL term */    }else{      Bitmask b;      b = getMask(pMaskSet, pOrTerm->leftCursor);      if( pOrTerm->wtFlags & TERM_VIRTUAL ){        WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];        b |= getMask(pMaskSet, pOther->leftCursor);      }      indexable &= b;      if( pOrTerm->eOperator!=WO_EQ ){        chngToIN = 0;      }else{        chngToIN &= b;      }    }  }  /*  ** Record the set of tables that satisfy case 2.  The set might be  ** empty.  */  pOrInfo->indexable = indexable;  pTerm->eOperator = indexable==0 ? 0 : WO_OR;  /*  ** chngToIN holds a set of tables that *might* satisfy case 1.  But  ** we have to do some additional checking to see if case 1 really  ** is satisfied.  */  if( chngToIN ){    int okToChngToIN = 0;     /* True if the conversion to IN is valid */    int iColumn = -1;         /* Column index on lhs of IN operator */    int iCursor = -1;         /* Table cursor common to all terms */    int j = 0;                /* Loop counter */    /* Search for a table and column that appears on one side or the    ** other of the == operator in every subterm.  That table and column    ** will be recorded in iCursor and iColumn.  There might not be any    ** such table and column.  Set okToChngToIN if an appropriate table    ** and column is found but leave okToChngToIN false if not found.    */    for(j=0; j<2 && !okToChngToIN; j++){      pOrTerm = pOrWc->a;      for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){        assert( pOrTerm->eOperator==WO_EQ );        pOrTerm->wtFlags &= ~TERM_OR_OK;        if( pOrTerm->leftCursor==iColumn ) continue;        if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ) continue;        iColumn = pOrTerm->u.leftColumn;        iCursor = pOrTerm->leftCursor;        break;      }      if( i<0 ){        assert( j==1 );        assert( (chngToIN&(chngToIN-1))==0 );        assert( chngToIN==getMask(pMaskSet, iColumn) );        break;      }      okToChngToIN = 1;      for(; i>=0 && okToChngToIN; i--, pOrTerm++){        assert( pOrTerm->eOperator==WO_EQ );        if( pOrTerm->leftCursor!=iCursor ){          pOrTerm->wtFlags &= ~TERM_OR_OK;        }else if( pOrTerm->u.leftColumn!=iColumn ){          okToChngToIN = 0;        }else{          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);          affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);          if( affRight!=0 && affRight!=affLeft ){            okToChngToIN = 0;          }else{            pOrTerm->wtFlags |= TERM_OR_OK;          }        }      }    }    /* At this point, okToChngToIN is true if original pTerm satisfies    ** case 1.  In that case, construct a new virtual term that is     ** pTerm converted into an IN operator.    */    if( okToChngToIN ){      Expr *pDup;            /* A transient duplicate expression */      ExprList *pList = 0;   /* The RHS of the IN operator */      Expr *pLeft = 0;       /* The LHS of the IN operator */      Expr *pNew;            /* The complete IN operator */      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);        pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0);        pLeft = pOrTerm->pExpr->pLeft;      }      assert( pLeft!=0 );      pDup = sqlite3ExprDup(db, pLeft);      pNew = sqlite3Expr(db, TK_IN, pDup, 0, 0);      if( pNew ){        int idxNew;        transferJoinMarkings(pNew, pExpr);        pNew->pList = pList;        idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);        testcase( idxNew==0 );        exprAnalyze(pSrc, pWC, idxNew);        pTerm = &pWC->a[idxTerm];        pWC->a[idxNew].iParent = idxTerm;        pTerm->nChild = 1;      }else{        sqlite3ExprListDelete(db, pList);      }      pTerm->eOperator = 0;  /* case 1 trumps case 2 */    }  }}#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY *//*** The input to this routine is an WhereTerm structure with only the** "pExpr" field filled in.  The job of this routine is to analyze the** subexpression and populate all the other fields of the WhereTerm** structure.**** If the expression is of the form "<expr> <op> X" it gets commuted** to the standard form of "X <op> <expr>".**** If the expression is of the form "X <op> Y" where both X and Y are** columns, then the original expression is unchanged and a new virtual** term of the form "Y <op> X" is added to the WHERE clause and** analyzed separately.  The original term is marked with TERM_COPIED** and the new term is marked with TERM_DYNAMIC (because it's pExpr** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it** is a commuted copy of a prior term.)  The original term has nChild=1** and the copy has idxParent set to the index of the original term.*/static void exprAnalyze(  SrcList *pSrc,            /* the FROM clause */  WhereClause *pWC,         /* the WHERE clause */  int idxTerm               /* Index of the term to be analyzed */){  WhereTerm *pTerm;                /* The term to be analyzed */  WhereMaskSet *pMaskSet;          /* Set of table index masks */  Expr *pExpr;                     /* The expression to be analyzed */  Bitmask prereqLeft;              /* Prerequesites of the pExpr->pLeft */  Bitmask prereqAll;               /* Prerequesites of pExpr */  Bitmask extraRight = 0;  int nPattern;  int isComplete;  int noCase;  int op;                          /* Top-level operator.  pExpr->op */  Parse *pParse = pWC->pParse;     /* Parsing context */  sqlite3 *db = pParse->db;        /* Database connection */  if( db->mallocFailed ){    return;  }  pTerm = &pWC->a[idxTerm];  pMaskSet = pWC->pMaskSet;  pExpr = pTerm->pExpr;  prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);  op = pExpr->op;  if( op==TK_IN ){    assert( pExpr->pRight==0 );    pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->pList)                          | exprSelectTableUsage(pMaskSet, pExpr->pSelect);  }else if( op==TK_ISNULL ){    pTerm->prereqRight = 0;  }else{    pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);  }  prereqAll = exprTableUsage(pMaskSet, pExpr);  if( ExprHasProperty(pExpr, EP_FromJoin) ){    Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable);    prereqAll |= x;    extraRight = x-1;  /* ON clause terms may not be used with an index                       ** on left table of a LEFT JOIN.  Ticket #3015 */  }  pTerm->prereqAll = prereqAll;  pTerm->leftCursor = -1;  pTerm->iParent = -1;  pTerm->eOperator = 0;  if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){    Expr *pLeft = pExpr->pLeft;    Expr *pRight = pExpr->pRight;    if( pLeft->op==TK_COLUMN ){      pTerm->leftCursor = pLeft->iTable;      pTerm->u.leftColumn = pLeft->iColumn;      pTerm->eOperator = operatorMask(op);    }    if( pRight && pRight->op==TK_COLUMN ){      WhereTerm *pNew;      Expr *pDup;      if( pTerm->leftCursor>=0 ){        int idxNew;        pDup = sqlite3ExprDup(db, pExpr);        if( db->mallocFailed ){          sqlite3ExprDelete(db, pDup);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -