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

📄 where.c

📁 一个小型嵌入式数据库SQLite的源码,C语言
💻 C
📖 第 1 页 / 共 5 页
字号:
  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;  }}/*** Translate from TK_xx operator to WO_xx bitmask.*/static int operatorMask(int op){  int c;  assert( allowedOp(op) );  if( op==TK_IN ){    c = WO_IN;  }else{    c = WO_EQ<<(op-TK_EQ);  }  assert( op!=TK_IN || c==WO_IN );  assert( op!=TK_EQ || c==WO_EQ );  assert( op!=TK_LT || c==WO_LT );  assert( op!=TK_LE || c==WO_LE );  assert( op!=TK_GT || c==WO_GT );  assert( op!=TK_GE || c==WO_GE );  return c;}/*** Search for a term in the WHERE clause that is of the form "X <op> <expr>"** where X is a reference to the iColumn of table iCur and <op> is one of** the WO_xx operator codes specified by the op parameter.** Return a pointer to the term.  Return 0 if not found.*/static WhereTerm *findTerm(  WhereClause *pWC,     /* The WHERE clause to be searched */  int iCur,             /* Cursor number of LHS */  int iColumn,          /* Column number of LHS */  Bitmask notReady,     /* RHS must not overlap with this mask */  u16 op,               /* Mask of WO_xx values describing operator */  Index *pIdx           /* Must be compatible with this index, if not NULL */){  WhereTerm *pTerm;  int k;  for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){    if( pTerm->leftCursor==iCur       && (pTerm->prereqRight & notReady)==0       && pTerm->leftColumn==iColumn       && (pTerm->eOperator & op)!=0    ){      if( iCur>=0 && pIdx ){        Expr *pX = pTerm->pExpr;        CollSeq *pColl;        char idxaff;        int j;        Parse *pParse = pWC->pParse;        idxaff = pIdx->pTable->aCol[iColumn].affinity;        if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;        pColl = sqlite3ExprCollSeq(pParse, pX->pLeft);        if( !pColl ){          if( pX->pRight ){            pColl = sqlite3ExprCollSeq(pParse, pX->pRight);          }          if( !pColl ){            pColl = pParse->db->pDfltColl;          }        }        for(j=0; j<pIdx->nColumn && pIdx->aiColumn[j]!=iColumn; j++){}        assert( j<pIdx->nColumn );        if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;      }      return pTerm;    }  }  return 0;}/* Forward reference */static void exprAnalyze(SrcList*, ExprMaskSet*, WhereClause*, int);/*** Call exprAnalyze on all terms in a WHERE clause.  *****/static void exprAnalyzeAll(  SrcList *pTabList,       /* the FROM clause */  ExprMaskSet *pMaskSet,   /* table masks */  WhereClause *pWC         /* the WHERE clause to be analyzed */){  int i;  for(i=pWC->nTerm-1; i>=0; i--){    exprAnalyze(pTabList, pMaskSet, pWC, i);  }}#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION/*** Check to see if the given expression is a LIKE or GLOB operator that** can be optimized using inequality constraints.  Return TRUE if it is** so and false if not.**** In order for the operator to be optimizible, the RHS must be a string** literal that does not begin with a wildcard.  */static int isLikeOrGlob(  sqlite3 *db,      /* The database */  Expr *pExpr,      /* Test this expression */  int *pnPattern,   /* Number of non-wildcard prefix characters */  int *pisComplete  /* True if the only wildcard is % in the last character */){  const char *z;  Expr *pRight, *pLeft;  ExprList *pList;  int c, cnt;  int noCase;  char wc[3];  CollSeq *pColl;  if( !sqlite3IsLikeFunction(db, pExpr, &noCase, wc) ){    return 0;  }  pList = pExpr->pList;  pRight = pList->a[0].pExpr;  if( pRight->op!=TK_STRING ){    return 0;  }  pLeft = pList->a[1].pExpr;  if( pLeft->op!=TK_COLUMN ){    return 0;  }  pColl = pLeft->pColl;  if( pColl==0 ){    pColl = db->pDfltColl;  }  if( (pColl->type!=SQLITE_COLL_BINARY || noCase) &&      (pColl->type!=SQLITE_COLL_NOCASE || !noCase) ){    return 0;  }  sqlite3DequoteExpr(pRight);  z = (char *)pRight->token.z;  for(cnt=0; (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2]; cnt++){}  if( cnt==0 || 255==(u8)z[cnt] ){    return 0;  }  *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;  *pnPattern = cnt;  return 1;}#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */#ifndef SQLITE_OMIT_VIRTUALTABLE/*** Check to see if the given expression is of the form****         column MATCH expr**** If it is then return TRUE.  If not, return FALSE.*/static int isMatchOfColumn(  Expr *pExpr      /* Test this expression */){  ExprList *pList;  if( pExpr->op!=TK_FUNCTION ){    return 0;  }  if( pExpr->token.n!=5 ||       sqlite3StrNICmp((const char*)pExpr->token.z,"match",5)!=0 ){    return 0;  }  pList = pExpr->pList;  if( pList->nExpr!=2 ){    return 0;  }  if( pList->a[1].pExpr->op != TK_COLUMN ){    return 0;  }  return 1;}#endif /* SQLITE_OMIT_VIRTUALTABLE *//*** If the pBase expression originated in the ON or USING clause of** a join, then transfer the appropriate markings over to derived.*/static void transferJoinMarkings(Expr *pDerived, Expr *pBase){  pDerived->flags |= pBase->flags & EP_FromJoin;  pDerived->iRightJoinTable = pBase->iRightJoinTable;}/*** 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 expression of the form** "Y <op> X" is added to the WHERE clause and analyzed separately.*/static void exprAnalyze(  SrcList *pSrc,            /* the FROM clause */  ExprMaskSet *pMaskSet,    /* table masks */  WhereClause *pWC,         /* the WHERE clause */  int idxTerm               /* Index of the term to be analyzed */){  WhereTerm *pTerm = &pWC->a[idxTerm];  Expr *pExpr = pTerm->pExpr;  Bitmask prereqLeft;  Bitmask prereqAll;  int nPattern;  int isComplete;  if( sqlite3MallocFailed() ) return;  prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);  if( pExpr->op==TK_IN ){    assert( pExpr->pRight==0 );    pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->pList)                          | exprSelectTableUsage(pMaskSet, pExpr->pSelect);  }else{    pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);  }  prereqAll = exprTableUsage(pMaskSet, pExpr);  if( ExprHasProperty(pExpr, EP_FromJoin) ){    prereqAll |= getMask(pMaskSet, pExpr->iRightJoinTable);  }  pTerm->prereqAll = prereqAll;  pTerm->leftCursor = -1;  pTerm->iParent = -1;  pTerm->eOperator = 0;  if( allowedOp(pExpr->op) && (pTerm->prereqRight & prereqLeft)==0 ){    Expr *pLeft = pExpr->pLeft;    Expr *pRight = pExpr->pRight;    if( pLeft->op==TK_COLUMN ){      pTerm->leftCursor = pLeft->iTable;      pTerm->leftColumn = pLeft->iColumn;      pTerm->eOperator = operatorMask(pExpr->op);    }    if( pRight && pRight->op==TK_COLUMN ){      WhereTerm *pNew;      Expr *pDup;      if( pTerm->leftCursor>=0 ){        int idxNew;        pDup = sqlite3ExprDup(pExpr);        idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);        if( idxNew==0 ) return;        pNew = &pWC->a[idxNew];        pNew->iParent = idxTerm;        pTerm = &pWC->a[idxTerm];        pTerm->nChild = 1;        pTerm->flags |= TERM_COPIED;      }else{        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, pMaskSet, 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);    whereSplit(&sOr, pExpr, TK_OR);    exprAnalyzeAll(pSrc, pMaskSet, &sOr);    assert( sOr.nTerm>0 );    j = 0;    do{      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( pOrTerm->leftCursor==iCursor && pOrTerm->leftColumn==iColumn ){          pOrTerm->flags |= TERM_OR_OK;        }else if( (pOrTerm->flags & TERM_COPIED)!=0 ||                    ((pOrTerm->flags & TERM_VIRTUAL)!=0 &&                     (sOr.a[pOrTerm->iParent].flags & TERM_OR_OK)!=0) ){          pOrTerm->flags &= ~TERM_OR_OK;        }else{          ok = 0;        }      }    }while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && j<sOr.nTerm );    if( ok ){      ExprList *pList = 0;      Expr *pNew, *pDup;      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);      }      pDup = sqlite3Expr(TK_COLUMN, 0, 0, 0);      if( pDup ){        pDup->iTable = iCursor;        pDup->iColumn = iColumn;      }      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, pMaskSet, pWC, idxNew);        pTerm = &pWC->a[idxTerm];        pWC->a[idxNew].iParent = idxTerm;        pTerm->nChild = 1;      }else{        sqlite3ExprListDelete(pList);      }    }or_not_possible:    whereClauseClear(&sOr);  }

⌨️ 快捷键说明

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