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

📄 where.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
        pDup = pExpr;        pNew = pTerm;      }      exprCommute(pDup);      pLeft = pDup->pLeft;      pNew->leftCursor = pLeft->iTable;      pNew->leftColumn = pLeft->iColumn;      pNew->prereqRight = prereqLeft;      pNew->prereqAll = prereqAll;      pNew->eOperator = operatorMask(pDup->op);    }  }#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION  /* If a term is the BETWEEN operator, create two new virtual terms  ** that define the range that the BETWEEN implements.  */  else if( pExpr->op==TK_BETWEEN ){    ExprList *pList = pExpr->pList;    int i;    static const u8 ops[] = {TK_GE, TK_LE};    assert( pList!=0 );    assert( pList->nExpr==2 );    for(i=0; i<2; i++){      Expr *pNewExpr;      int idxNew;      pNewExpr = sqlite3Expr(ops[i], sqlite3ExprDup(pExpr->pLeft),                             sqlite3ExprDup(pList->a[i].pExpr), 0);      idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);      exprAnalyze(pSrc, pWC, idxNew);      pTerm = &pWC->a[idxTerm];      pWC->a[idxNew].iParent = idxTerm;    }    pTerm->nChild = 2;  }#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)  /* Attempt to convert OR-connected terms into an IN operator so that  ** they can make use of indices.  Example:  **  **      x = expr1  OR  expr2 = x  OR  x = expr3  **  ** is converted into  **  **      x IN (expr1,expr2,expr3)  **  ** This optimization must be omitted if OMIT_SUBQUERY is defined because  ** the compiler for the the IN operator is part of sub-queries.  */  else if( pExpr->op==TK_OR ){    int ok;    int i, j;    int iColumn, iCursor;    WhereClause sOr;    WhereTerm *pOrTerm;    assert( (pTerm->flags & TERM_DYNAMIC)==0 );    whereClauseInit(&sOr, pWC->pParse, pMaskSet);    whereSplit(&sOr, pExpr, TK_OR);    exprAnalyzeAll(pSrc, &sOr);    assert( sOr.nTerm>=2 );    j = 0;    do{      assert( j<sOr.nTerm );      iColumn = sOr.a[j].leftColumn;      iCursor = sOr.a[j].leftCursor;      ok = iCursor>=0;      for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0 && ok; i--, pOrTerm++){        if( pOrTerm->eOperator!=WO_EQ ){          goto or_not_possible;        }        if( orTermIsOptCandidate(pOrTerm, iCursor, iColumn) ){          pOrTerm->flags |= TERM_OR_OK;        }else if( orTermHasOkDuplicate(&sOr, pOrTerm) ){          pOrTerm->flags &= ~TERM_OR_OK;        }else{          ok = 0;        }      }    }while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && j<2 );    if( ok ){      ExprList *pList = 0;      Expr *pNew, *pDup;      Expr *pLeft = 0;      for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0 && ok; i--, pOrTerm++){        if( (pOrTerm->flags & TERM_OR_OK)==0 ) continue;        pDup = sqlite3ExprDup(pOrTerm->pExpr->pRight);        pList = sqlite3ExprListAppend(pList, pDup, 0);        pLeft = pOrTerm->pExpr->pLeft;      }      assert( pLeft!=0 );      pDup = sqlite3ExprDup(pLeft);      pNew = sqlite3Expr(TK_IN, pDup, 0, 0);      if( pNew ){        int idxNew;        transferJoinMarkings(pNew, pExpr);        pNew->pList = pList;        idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);        exprAnalyze(pSrc, pWC, idxNew);        pTerm = &pWC->a[idxTerm];        pWC->a[idxNew].iParent = idxTerm;        pTerm->nChild = 1;      }else{        sqlite3ExprListDelete(pList);      }    }or_not_possible:    whereClauseClear(&sOr);  }#endif /* SQLITE_OMIT_OR_OPTIMIZATION */#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION  /* Add constraints to reduce the search space on a LIKE or GLOB  ** operator.  */  if( isLikeOrGlob(pWC->pParse->db, pExpr, &nPattern, &isComplete) ){    Expr *pLeft, *pRight;    Expr *pStr1, *pStr2;    Expr *pNewExpr1, *pNewExpr2;    int idxNew1, idxNew2;    pLeft = pExpr->pList->a[1].pExpr;    pRight = pExpr->pList->a[0].pExpr;    pStr1 = sqlite3Expr(TK_STRING, 0, 0, 0);    if( pStr1 ){      sqlite3TokenCopy(&pStr1->token, &pRight->token);      pStr1->token.n = nPattern;      pStr1->flags = EP_Dequoted;    }    pStr2 = sqlite3ExprDup(pStr1);    if( pStr2 ){      assert( pStr2->token.dyn );      ++*(u8*)&pStr2->token.z[nPattern-1];    }    pNewExpr1 = sqlite3Expr(TK_GE, sqlite3ExprDup(pLeft), pStr1, 0);    idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);    exprAnalyze(pSrc, pWC, idxNew1);    pNewExpr2 = sqlite3Expr(TK_LT, sqlite3ExprDup(pLeft), pStr2, 0);    idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);    exprAnalyze(pSrc, pWC, idxNew2);    pTerm = &pWC->a[idxTerm];    if( isComplete ){      pWC->a[idxNew1].iParent = idxTerm;      pWC->a[idxNew2].iParent = idxTerm;      pTerm->nChild = 2;    }  }#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */#ifndef SQLITE_OMIT_VIRTUALTABLE  /* Add a WO_MATCH auxiliary term to the constraint set if the  ** current expression is of the form:  column MATCH expr.  ** This information is used by the xBestIndex methods of  ** virtual tables.  The native query optimizer does not attempt  ** to do anything with MATCH functions.  */  if( isMatchOfColumn(pExpr) ){    int idxNew;    Expr *pRight, *pLeft;    WhereTerm *pNewTerm;    Bitmask prereqColumn, prereqExpr;    pRight = pExpr->pList->a[0].pExpr;    pLeft = pExpr->pList->a[1].pExpr;    prereqExpr = exprTableUsage(pMaskSet, pRight);    prereqColumn = exprTableUsage(pMaskSet, pLeft);    if( (prereqExpr & prereqColumn)==0 ){      Expr *pNewExpr;      pNewExpr = sqlite3Expr(TK_MATCH, 0, sqlite3ExprDup(pRight), 0);      idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);      pNewTerm = &pWC->a[idxNew];      pNewTerm->prereqRight = prereqExpr;      pNewTerm->leftCursor = pLeft->iTable;      pNewTerm->leftColumn = pLeft->iColumn;      pNewTerm->eOperator = WO_MATCH;      pNewTerm->iParent = idxTerm;      pTerm = &pWC->a[idxTerm];      pTerm->nChild = 1;      pTerm->flags |= TERM_COPIED;      pNewTerm->prereqAll = pTerm->prereqAll;    }  }#endif /* SQLITE_OMIT_VIRTUALTABLE */}/*** Return TRUE if any of the expressions in pList->a[iFirst...] contain** a reference to any table other than the iBase table.*/static int referencesOtherTables(  ExprList *pList,          /* Search expressions in ths list */  ExprMaskSet *pMaskSet,    /* Mapping from tables to bitmaps */  int iFirst,               /* Be searching with the iFirst-th expression */  int iBase                 /* Ignore references to this table */){  Bitmask allowed = ~getMask(pMaskSet, iBase);  while( iFirst<pList->nExpr ){    if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){      return 1;    }  }  return 0;}/*** This routine decides if pIdx can be used to satisfy the ORDER BY** clause.  If it can, it returns 1.  If pIdx cannot satisfy the** ORDER BY clause, this routine returns 0.**** pOrderBy is an ORDER BY clause from a SELECT statement.  pTab is the** left-most table in the FROM clause of that same SELECT statement and** the table has a cursor number of "base".  pIdx is an index on pTab.**** nEqCol is the number of columns of pIdx that are used as equality** constraints.  Any of these columns may be missing from the ORDER BY** clause and the match can still be a success.**** All terms of the ORDER BY that match against the index must be either** ASC or DESC.  (Terms of the ORDER BY clause past the end of a UNIQUE** index do not need to satisfy this constraint.)  The *pbRev value is** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if** the ORDER BY clause is all ASC.*/static int isSortingIndex(  Parse *pParse,          /* Parsing context */  ExprMaskSet *pMaskSet,  /* Mapping from table indices to bitmaps */  Index *pIdx,            /* The index we are testing */  int base,               /* Cursor number for the table to be sorted */  ExprList *pOrderBy,     /* The ORDER BY clause */  int nEqCol,             /* Number of index columns with == constraints */  int *pbRev              /* Set to 1 if ORDER BY is DESC */){  int i, j;                       /* Loop counters */  int sortOrder = 0;              /* XOR of index and ORDER BY sort direction */  int nTerm;                      /* Number of ORDER BY terms */  struct ExprList_item *pTerm;    /* A term of the ORDER BY clause */  sqlite3 *db = pParse->db;  assert( pOrderBy!=0 );  nTerm = pOrderBy->nExpr;  assert( nTerm>0 );  /* Match terms of the ORDER BY clause against columns of  ** the index.  **  ** Note that indices have pIdx->nColumn regular columns plus  ** one additional column containing the rowid.  The rowid column  ** of the index is also allowed to match against the ORDER BY  ** clause.  */  for(i=j=0, pTerm=pOrderBy->a; j<nTerm && i<=pIdx->nColumn; i++){    Expr *pExpr;       /* The expression of the ORDER BY pTerm */    CollSeq *pColl;    /* The collating sequence of pExpr */    int termSortOrder; /* Sort order for this term */    int iColumn;       /* The i-th column of the index.  -1 for rowid */    int iSortOrder;    /* 1 for DESC, 0 for ASC on the i-th index term */    const char *zColl; /* Name of the collating sequence for i-th index term */    pExpr = pTerm->pExpr;    if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){      /* Can not use an index sort on anything that is not a column in the      ** left-most table of the FROM clause */      break;    }    pColl = sqlite3ExprCollSeq(pParse, pExpr);    if( !pColl ){      pColl = db->pDfltColl;    }    if( i<pIdx->nColumn ){      iColumn = pIdx->aiColumn[i];      if( iColumn==pIdx->pTable->iPKey ){        iColumn = -1;      }      iSortOrder = pIdx->aSortOrder[i];      zColl = pIdx->azColl[i];    }else{      iColumn = -1;      iSortOrder = 0;      zColl = pColl->zName;    }    if( pExpr->iColumn!=iColumn || sqlite3StrICmp(pColl->zName, zColl) ){      /* Term j of the ORDER BY clause does not match column i of the index */      if( i<nEqCol ){        /* If an index column that is constrained by == fails to match an        ** ORDER BY term, that is OK.  Just ignore that column of the index        */        continue;      }else{        /* If an index column fails to match and is not constrained by ==        ** then the index cannot satisfy the ORDER BY constraint.        */        return 0;      }    }    assert( pIdx->aSortOrder!=0 );    assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 );    assert( iSortOrder==0 || iSortOrder==1 );    termSortOrder = iSortOrder ^ pTerm->sortOrder;    if( i>nEqCol ){      if( termSortOrder!=sortOrder ){        /* Indices can only be used if all ORDER BY terms past the        ** equality constraints are all either DESC or ASC. */        return 0;      }    }else{      sortOrder = termSortOrder;    }    j++;    pTerm++;    if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){      /* If the indexed column is the primary key and everything matches      ** so far and none of the ORDER BY terms to the right reference other      ** tables in the join, then we are assured that the index can be used       ** to sort because the primary key is unique and so none of the other      ** columns will make any difference      */      j = nTerm;    }  }  *pbRev = sortOrder!=0;  if( j>=nTerm ){    /* All terms of the ORDER BY clause are covered by this index so    ** this index can be used for sorting. */    return 1;  }  if( pIdx->onError!=OE_None && i==pIdx->nColumn      && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){    /* All terms of this index match some prefix of the ORDER BY clause    ** and the index is UNIQUE and no terms on the tail of the ORDER BY    ** clause reference other tables in a join.  If this is all true then    ** the order by clause is superfluous. */    return 1;  }  return 0;}/*** Check table to see if the ORDER BY clause in pOrderBy can be satisfied** by sorting in order of ROWID.  Return true if so and set *pbRev to be** true for reverse ROWID and false for forward ROWID order.*/static int sortableByRowid(  int base,               /* Cursor number for table to be sorted */  ExprList *pOrderBy,     /* The ORDER BY clause */  ExprMaskSet *pMaskSet,  /* Mapping from tables to bitmaps */  int *pbRev              /* Set to 1 if ORDER BY is DESC */){  Expr *p;  assert( pOrderBy!=0 );  assert( pOrderBy->nExpr>0 );  p = pOrderBy->a[0].pExpr;  if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1    && !referencesOtherTables(pOrderBy, pMaskSet, 1, base) ){    *pbRev = pOrderBy->a[0].sortOrder;    return 1;  }  return 0;}/*** Prepare a crude estimate of the logarithm of the input value.** The results need not be exact.  This is only used for estimating** the total cost of performing operatings with O(logN) or O(NlogN)** complexity.  Because N is just a guess, it is no great tragedy if** logN is a little off.*/static double estLog(double N){  double logN = 1;  double x = 10;  while( N>x ){    logN += 1;    x *= 10;

⌨️ 快捷键说明

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