📄 where.c
字号:
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 */ return 0; } pColl = sqlite3ExprCollSeq(pParse, pExpr); if( !pColl ) pColl = db->pDfltColl; if( pExpr->iColumn!=pIdx->aiColumn[i] || pColl!=pIdx->keyInfo.aColl[i] ){ /* 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; } } if( i>nEqCol ){ if( pTerm->sortOrder!=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 = pTerm->sortOrder; } j++; pTerm++; } /* The index can be used for sorting if all terms of the ORDER BY clause ** or covered or if we ran out of index columns and the it is a UNIQUE ** index. */ if( j>=nTerm || (i>=pIdx->nColumn && pIdx->onError!=OE_None) ){ *pbRev = sortOrder==SQLITE_SO_DESC; 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 */ 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 ){ *pbRev = pOrderBy->a[0].sortOrder; return 1; } return 0;}/*** 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 originates** 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 code that builds a probe for an index. Details:**** * Check the top nColumn entries on the stack. If any** of those entries are NULL, jump immediately to brk,** which is the loop exit, since no index entry will match** if any part of the key is NULL.**** * Construct a probe entry from the top nColumn entries in** the stack with affinities appropriate for index pIdx.*/static void buildIndexProbe(Vdbe *v, int nColumn, int brk, Index *pIdx){ sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, brk); sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3IndexAffinityStr(v, pIdx);}/*** Generate code for an equality term of the WHERE clause. An equality** term can be either X=expr or X IN (...). pTerm is the X. */static void codeEqualityTerm( Parse *pParse, /* The parsing context */ ExprInfo *pTerm, /* The term of the WHERE clause to be coded */ int brk, /* Jump here to abandon the loop */ WhereLevel *pLevel /* When level of the FROM clause we are working on */){ Expr *pX = pTerm->p; if( pX->op!=TK_IN ){ assert( pX->op==TK_EQ ); sqlite3ExprCode(pParse, pX->pRight);#ifndef SQLITE_OMIT_SUBQUERY }else{ int iTab; Vdbe *v = pParse->pVdbe; sqlite3CodeSubselect(pParse, pX); iTab = pX->iTable; sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk); VdbeComment((v, "# %.*s", pX->span.n, pX->span.z)); pLevel->inP2 = sqlite3VdbeAddOp(v, OP_Column, iTab, 0); pLevel->inOp = OP_Next; pLevel->inP1 = iTab;#endif } disableTerm(pLevel, &pTerm->p);}/*** The number of bits in a Bitmask*/#define BMS (sizeof(Bitmask)*8-1)/*** 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 sqlite3WhereEnd() 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 sqlite3WhereBegin()** foreach row3 in t3 do /** ...** end \ Code generated** end |-- by sqlite3WhereEnd()** 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 sqlite3WhereEnd() generates the code to close them.**** The code that sqlite3WhereBegin() generates leaves the cursors named** in pTabList pointing at their appropriate entries. The [...] code** can use OP_Column and OP_Rowid opcodes on these cursors to extract** data from the various tables of the loop.**** 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 *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ 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 */ Bitmask loopMask; /* One bit set for each outer loop */ ExprInfo *pTerm; /* A single term in the WHERE clause; ptr to aExpr[] */ ExprMaskSet maskSet; /* The expression mask set */ int iDirectEq[BMS]; /* Term of the form ROWID==X for the N-th table */ int iDirectLt[BMS]; /* Term of the form ROWID<X or ROWID<=X */ int iDirectGt[BMS]; /* Term of the form ROWID>X or ROWID>=X */ ExprInfo aExpr[101]; /* The WHERE clause is divided into these terms */ struct SrcList_item *pTabItem; /* A single entry from pTabList */ WhereLevel *pLevel; /* A single level in the pWInfo list */ /* The number of terms in the FROM clause is limited by the number of ** bits in a Bitmask */ if( pTabList->nSrc>sizeof(Bitmask)*8 ){ sqlite3ErrorMsg(pParse, "at most %d tables in a join", sizeof(Bitmask)*8); return 0; } /* 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); if( nExpr==ARRAYSIZE(aExpr) ){ sqlite3ErrorMsg(pParse, "WHERE clause too complex - no more " "than %d terms allowed", (int)ARRAYSIZE(aExpr)-1); return 0; } /* Allocate and initialize the WhereInfo structure that will become the ** return value. */ pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel)); if( sqlite3_malloc_failed ){ sqliteFree(pWInfo); /* Avoid leaking memory when malloc fails */ return 0; } pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->iBreak = sqlite3VdbeMakeLabel(v); /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstant(pWhere)) ){ sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1); pWhere = 0; } /* Analyze all of the subexpressions. */ for(i=0; i<pTabList->nSrc; i++){ createMask(&maskSet, pTabList->a[i].iCursor); } for(pTerm=aExpr, i=0; i<nExpr; i++, pTerm++){ exprAnalyze(pTabList, &maskSet, pTerm); } /* Figure out what index to use (if any) for each nested loop. ** Make pWInfo->a[i].pIdx point to the index to use for the i-th nested ** loop where i==0 is the outer loop and i==pTabList->nSrc-1 is the inner ** loop. ** ** If terms exist that use the ROWID of any table, then set the ** iDirectEq[], iDirectLt[], or iDirectGt[] elements for that table ** to the index of the term containing the ROWID. We always prefer ** to use a ROWID which can directly access a table rather than an ** index which requires reading an index first to get the rowid then ** doing a second read of the actual database table. ** ** Actually, if there are more than 32 tables in the join, only the ** first 32 tables are candidates for indices. This is (again) due ** to the limit of 32 bits in an integer bitmask. */ loopMask = 0; pTabItem = pTabList->a; pLevel = pWInfo->a; for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++,pTabItem++,pLevel++){ int j; int iCur = pTabItem->iCursor; /* The cursor for this table */ Bitmask mask = getMask(&maskSet, iCur); /* Cursor mask for this table */ Table *pTab = pTabItem->pTab; Index *pIdx; Index *pBestIdx = 0; int bestScore = 0; int bestRev = 0; /* Check to see if there is an expression that uses only the ** ROWID field of this table. For terms of the form ROWID==expr ** set iDirectEq[i] to the index of the term. For terms of the ** form ROWID<expr or ROWID<=expr set iDirectLt[i] to the term index. ** For terms like ROWID>expr or ROWID>=expr set iDirectGt[i]. ** ** (Added:) Treat ROWID IN expr like ROWID=expr. */ pLevel->iIdxCur = -1; iDirectEq[i] = -1; iDirectLt[i] = -1; iDirectGt[i] = -1; for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){ Expr *pX = pTerm->p; if( pTerm->idxLeft==iCur && pX->pLeft->iColumn<0 && (pTerm->prereqRight & loopMask)==pTerm->prereqRight ){ switch( pX->op ){ case TK_IN: case TK_EQ: iDirectEq[i] = j; break; case TK_LE: case TK_LT: iDirectLt[i] = j; break; case TK_GE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -