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

📄 where.c

📁 sqlite数据库管理系统开放源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*** 2001 September 15**** The author disclaims copyright to this source code.  In place of** a legal notice, here is a blessing:****    May you do good and not evil.**    May you find forgiveness for yourself and forgive others.**    May you share freely, never taking more than you give.***************************************************************************** This module contains C code that generates VDBE code used to process** the WHERE clause of SQL statements.**** $Id: where.c,v 1.89.2.2 2004/07/19 19:30:50 drh Exp $*/#include "sqliteInt.h"/*** The query generator uses an array of instances of this structure to** help it analyze the subexpressions of the WHERE clause.  Each WHERE** clause subexpression is separated from the others by an AND operator.*/typedef struct ExprInfo ExprInfo;struct ExprInfo {  Expr *p;                /* Pointer to the subexpression */  u8 indexable;           /* True if this subexprssion is usable by an index */  short int idxLeft;      /* p->pLeft is a column in this table number. -1 if                          ** p->pLeft is not the column of any table */  short int idxRight;     /* p->pRight is a column in this table number. -1 if                          ** p->pRight is not the column of any table */  unsigned prereqLeft;    /* Bitmask of tables referenced by p->pLeft */  unsigned prereqRight;   /* Bitmask of tables referenced by p->pRight */  unsigned prereqAll;     /* Bitmask of tables referenced by p */};/*** An instance of the following structure keeps track of a mapping** between VDBE cursor numbers and bitmasks.  The VDBE cursor numbers** are small integers contained in SrcList_item.iCursor and Expr.iTable** fields.  For any given WHERE clause, we want to track which cursors** are being used, so we assign a single bit in a 32-bit word to track** that cursor.  Then a 32-bit integer is able to show the set of all** cursors being used.*/typedef struct ExprMaskSet ExprMaskSet;struct ExprMaskSet {  int n;          /* Number of assigned cursor values */  int ix[31];     /* Cursor assigned to each bit */};/*** Determine the number of elements in an array.*/#define ARRAYSIZE(X)  (sizeof(X)/sizeof(X[0]))/*** This routine is used to divide the WHERE expression into subexpressions** separated by the AND operator.**** aSlot[] is an array of subexpressions structures.** There are nSlot spaces left in this array.  This routine attempts to** split pExpr into subexpressions and fills aSlot[] with those subexpressions.** The return value is the number of slots filled.*/static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){  int cnt = 0;  if( pExpr==0 || nSlot<1 ) return 0;  if( nSlot==1 || pExpr->op!=TK_AND ){    aSlot[0].p = pExpr;    return 1;  }  if( pExpr->pLeft->op!=TK_AND ){    aSlot[0].p = pExpr->pLeft;    cnt = 1 + exprSplit(nSlot-1, &aSlot[1], pExpr->pRight);  }else{    cnt = exprSplit(nSlot, aSlot, pExpr->pLeft);    cnt += exprSplit(nSlot-cnt, &aSlot[cnt], pExpr->pRight);  }  return cnt;}/*** Initialize an expression mask set*/#define initMaskSet(P)  memset(P, 0, sizeof(*P))/*** Return the bitmask for the given cursor.  Assign a new bitmask** if this is the first time the cursor has been seen.*/static int getMask(ExprMaskSet *pMaskSet, int iCursor){  int i;  for(i=0; i<pMaskSet->n; i++){    if( pMaskSet->ix[i]==iCursor ) return 1<<i;  }  if( i==pMaskSet->n && i<ARRAYSIZE(pMaskSet->ix) ){    pMaskSet->n++;    pMaskSet->ix[i] = iCursor;    return 1<<i;  }  return 0;}/*** Destroy an expression mask set*/#define freeMaskSet(P)   /* NO-OP *//*** 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 ){    mask = getMask(pMaskSet, p->iTable);    if( mask==0 ) mask = -1;    return mask;  }  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;}/*** Return TRUE if the given operator is one of the operators that is** allowed for an indexable WHERE clause.  The allowed operators are** "=", "<", ">", "<=", ">=", and "IN".*/static int allowedOp(int op){  switch( op ){    case TK_LT:    case TK_LE:    case TK_GT:    case TK_GE:    case TK_EQ:    case TK_IN:      return 1;    default:      return 0;  }}/*** 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;    }  }}/*** 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".**** This routine attempts to find an index for pTab that generates the** correct record sequence for the given ORDER BY clause.  The return value** is a pointer to an index that does the job.  NULL is returned if the** table has no index that will generate the correct sort order.**** If there are two or more indices that generate the correct sort order** and pPreferredIdx is one of those indices, then return pPreferredIdx.**** nEqCol is the number of columns of pPreferredIdx that are used as** equality constraints.  Any index returned must have exactly this same** set of columns.  The ORDER BY clause only matches index columns beyond the** the first nEqCol columns.**** All terms of the ORDER BY clause must be either ASC or DESC.  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 Index *findSortingIndex(  Table *pTab,            /* The table to be sorted */  int base,               /* Cursor number for pTab */  ExprList *pOrderBy,     /* The ORDER BY clause */  Index *pPreferredIdx,   /* Use this index, if possible and not NULL */  int nEqCol,             /* Number of index columns used with == constraints */  int *pbRev              /* Set to 1 if ORDER BY is DESC */){  int i, j;  Index *pMatch;  Index *pIdx;  int sortOrder;  assert( pOrderBy!=0 );  assert( pOrderBy->nExpr>0 );  sortOrder = pOrderBy->a[0].sortOrder & SQLITE_SO_DIRMASK;  for(i=0; i<pOrderBy->nExpr; i++){    Expr *p;    if( (pOrderBy->a[i].sortOrder & SQLITE_SO_DIRMASK)!=sortOrder ){      /* Indices can only be used if all ORDER BY terms are either      ** DESC or ASC.  Indices cannot be used on a mixture. */      return 0;    }    if( (pOrderBy->a[i].sortOrder & SQLITE_SO_TYPEMASK)!=SQLITE_SO_UNK ){      /* Do not sort by index if there is a COLLATE clause */      return 0;    }    p = pOrderBy->a[i].pExpr;    if( p->op!=TK_COLUMN || p->iTable!=base ){      /* Can not use an index sort on anything that is not a column in the      ** left-most table of the FROM clause */      return 0;    }  }    /* If we get this far, it means the ORDER BY clause consists only of  ** ascending columns in the left-most table of the FROM clause.  Now  ** check for a matching index.  */  pMatch = 0;  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){    int nExpr = pOrderBy->nExpr;    if( pIdx->nColumn < nEqCol || pIdx->nColumn < nExpr ) continue;    for(i=j=0; i<nEqCol; i++){      if( pPreferredIdx->aiColumn[i]!=pIdx->aiColumn[i] ) break;      if( j<nExpr && pOrderBy->a[j].pExpr->iColumn==pIdx->aiColumn[i] ){ j++; }    }    if( i<nEqCol ) continue;    for(i=0; i+j<nExpr; i++){      if( pOrderBy->a[i+j].pExpr->iColumn!=pIdx->aiColumn[i+nEqCol] ) break;    }    if( i+j>=nExpr ){      pMatch = pIdx;      if( pIdx==pPreferredIdx ) break;    }  }  if( pMatch && pbRev ){    *pbRev = sortOrder==SQLITE_SO_DESC;  }  return pMatch;}/*** Disable a term in the WHERE clause.  Except, do not disable the term** if it controls a LEFT OUTER JOIN and it did not originate in the ON** or USING clause of that join.**** Consider the term t2.z='ok' in the following queries:****   (1)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'**   (2)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'**   (3)  SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'**** The t2.z='ok' is disabled in the in (2) because it did not originate** in the ON clause.  The term is disabled in (3) because it is not part** of a LEFT OUTER JOIN.  In (1), the term is not disabled.**** Disabling a term causes that term to not be tested in the inner loop** of the join.  Disabling is an optimization.  We would get the correct** results if nothing were ever disabled, but joins might run a little** slower.  The trick is to disable as much as we can without disabling** too much.  If we disabled in (1), we'd get the wrong answer.** See ticket #813.*/static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){  Expr *pExpr = *ppExpr;  if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){    *ppExpr = 0;  }}/*** Generate the beginning of the loop used for WHERE clause processing.** The return value is a pointer to an (opaque) structure that contains** information needed to terminate the loop.  Later, the calling routine** should invoke sqliteWhereEnd() with the return value of this function** in order to complete the WHERE clause processing.**** If an error occurs, this routine returns NULL.**** The basic idea is to do a nested loop, one loop for each table in** the FROM clause of a select.  (INSERT and UPDATE statements are the** same as a SELECT with only a single table in the FROM clause.)  For** example, if the SQL is this:****       SELECT * FROM t1, t2, t3 WHERE ...;**** Then the code generated is conceptually like the following:****      foreach row1 in t1 do       \    Code generated**        foreach row2 in t2 do      |-- by sqliteWhereBegin()**          foreach row3 in t3 do   /**            ...**          end                     \    Code generated**        end                        |-- by sqliteWhereEnd()**      end                         /**** There are Btree cursors associated with each table.  t1 uses cursor** number pTabList->a[0].iCursor.  t2 uses the cursor pTabList->a[1].iCursor.** And so forth.  This routine generates code to open those VDBE cursors** and sqliteWhereEnd() generates the code to close them.**** If the WHERE clause is empty, the foreach loops must each scan their** entire tables.  Thus a three-way join is an O(N^3) operation.  But if** the tables have indices and there are terms in the WHERE clause that** refer to those indices, a complete table scan can be avoided and the** code will run much faster.  Most of the work of this routine is checking** to see if there are indices that can be used to speed up the loop.**** Terms of the WHERE clause are also used to limit which rows actually** make it to the "..." in the middle of the loop.  After each "foreach",** terms of the WHERE clause that use only terms in that loop and outer** loops are evaluated and if false a jump is made around all subsequent** inner loops (or around the "..." if the test occurs within the inner-** most loop)**** OUTER JOINS**** An outer join of tables t1 and t2 is conceptally coded as follows:****    foreach row1 in t1 do**      flag = 0**      foreach row2 in t2 do**        start:**          ...**          flag = 1**      end**      if flag==0 then**        move the row2 cursor to a null row**        goto start**      fi**    end**** ORDER BY CLAUSE PROCESSING**** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement,** if there is one.  If there is no ORDER BY clause or if this routine** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL.**** If an index can be used so that the natural output order of the table** scan is correct for the ORDER BY clause, then that index is used and** *ppOrderBy is set to NULL.  This is an optimization that prevents an** unnecessary sort of the result set if an index appropriate for the** ORDER BY clause already exists.**** If the where clause loops cannot be arranged to provide the correct** output order, then the *ppOrderBy is unchanged.*/WhereInfo *sqliteWhereBegin(  Parse *pParse,       /* The parser context */  SrcList *pTabList,   /* A list of all tables to be scanned */  Expr *pWhere,        /* The WHERE clause */  int pushKey,         /* If TRUE, leave the table key on the stack */  ExprList **ppOrderBy /* An ORDER BY clause, or NULL */){  int i;                     /* Loop counter */  WhereInfo *pWInfo;         /* Will become the return value of this function */  Vdbe *v = pParse->pVdbe;   /* The virtual database engine */  int brk, cont = 0;         /* Addresses used during code generation */  int nExpr;           /* Number of subexpressions in the WHERE clause */  int loopMask;        /* One bit set for each outer loop */  int haveKey;         /* True if KEY is on the stack */  ExprMaskSet maskSet; /* The expression mask set */  int iDirectEq[32];   /* Term of the form ROWID==X for the N-th table */  int iDirectLt[32];   /* Term of the form ROWID<X or ROWID<=X */  int iDirectGt[32];   /* Term of the form ROWID>X or ROWID>=X */  ExprInfo aExpr[101]; /* The WHERE clause is divided into these expressions */  /* pushKey is only allowed if there is a single table (as in an INSERT or  ** UPDATE statement)  */  assert( pushKey==0 || pTabList->nSrc==1 );  /* Split the WHERE clause into separate subexpressions where each  ** subexpression is separated by an AND operator.  If the aExpr[]  ** array fills up, the last entry might point to an expression which  ** contains additional unfactored AND operators.  */  initMaskSet(&maskSet);  memset(aExpr, 0, sizeof(aExpr));  nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere);

⌨️ 快捷键说明

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