mirror of
https://github.com/php/php-src.git
synced 2025-08-20 09:24:05 +02:00
Update bundled library to version 2.8.2.
Make OnUpdateInt compatible with ZE2. Fix the makefile fragment for non-gnu makes
This commit is contained in:
parent
82a1818fde
commit
80e7f7001d
42 changed files with 11143 additions and 7558 deletions
|
@ -10,8 +10,7 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This module contains C code that generates VDBE code used to process
|
||||
** the WHERE clause of SQL statements. Also found here are subroutines
|
||||
** to generate VDBE code to evaluate expressions.
|
||||
** the WHERE clause of SQL statements.
|
||||
**
|
||||
** $Id$
|
||||
*/
|
||||
|
@ -37,6 +36,21 @@ struct ExprInfo {
|
|||
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[32]; /* Cursor assigned to each bit */
|
||||
};
|
||||
|
||||
/*
|
||||
** Determine the number of elements in an array.
|
||||
*/
|
||||
|
@ -68,37 +82,61 @@ static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){
|
|||
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. Bit 0 of the mask is set if table base+0 is used. Bit 1
|
||||
** is set if table base+1 is used. And so forth.
|
||||
** 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.
|
||||
**
|
||||
** "base" is the cursor number (the value of the iTable field) that
|
||||
** corresponds to the first entry in the list of tables that appear
|
||||
** in the FROM clause of a SELECT. For UPDATE and DELETE statements
|
||||
** there is just a single table with "base" as the cursor number.
|
||||
** 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(int base, Expr *p){
|
||||
static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
|
||||
unsigned int mask = 0;
|
||||
if( p==0 ) return 0;
|
||||
if( p->op==TK_COLUMN ){
|
||||
return 1<< (p->iTable - base);
|
||||
return getMask(pMaskSet, p->iTable);
|
||||
}
|
||||
if( p->pRight ){
|
||||
mask = exprTableUsage(base, p->pRight);
|
||||
mask = exprTableUsage(pMaskSet, p->pRight);
|
||||
}
|
||||
if( p->pLeft ){
|
||||
mask |= exprTableUsage(base, p->pLeft);
|
||||
mask |= exprTableUsage(pMaskSet, p->pLeft);
|
||||
}
|
||||
if( p->pList ){
|
||||
int i;
|
||||
for(i=0; i<p->pList->nExpr; i++){
|
||||
mask |= exprTableUsage(base, p->pList->a[i].pExpr);
|
||||
mask |= exprTableUsage(pMaskSet, p->pList->a[i].pExpr);
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
|
@ -128,25 +166,22 @@ static int allowedOp(int op){
|
|||
** "p" field filled in. The job of this routine is to analyze the
|
||||
** subexpression and populate all the other fields of the ExprInfo
|
||||
** structure.
|
||||
**
|
||||
** "base" is the cursor number (the value of the iTable field) that
|
||||
** corresponds to the first entry in the table list.
|
||||
*/
|
||||
static void exprAnalyze(int base, ExprInfo *pInfo){
|
||||
static void exprAnalyze(ExprMaskSet *pMaskSet, ExprInfo *pInfo){
|
||||
Expr *pExpr = pInfo->p;
|
||||
pInfo->prereqLeft = exprTableUsage(base, pExpr->pLeft);
|
||||
pInfo->prereqRight = exprTableUsage(base, pExpr->pRight);
|
||||
pInfo->prereqAll = exprTableUsage(base, pExpr);
|
||||
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 - base;
|
||||
pInfo->idxRight = pExpr->pRight->iTable;
|
||||
pInfo->indexable = 1;
|
||||
}
|
||||
if( pExpr->pLeft->op==TK_COLUMN ){
|
||||
pInfo->idxLeft = pExpr->pLeft->iTable - base;
|
||||
pInfo->idxLeft = pExpr->pLeft->iTable;
|
||||
pInfo->indexable = 1;
|
||||
}
|
||||
}
|
||||
|
@ -263,9 +298,9 @@ static Index *findSortingIndex(
|
|||
** end /
|
||||
**
|
||||
** There are Btree cursors associated with each table. t1 uses cursor
|
||||
** "base". t2 uses cursor "base+1". And so forth. This routine generates
|
||||
** the code to open those cursors. sqliteWhereEnd() generates the code
|
||||
** to close them.
|
||||
** 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
|
||||
|
@ -315,7 +350,6 @@ static Index *findSortingIndex(
|
|||
*/
|
||||
WhereInfo *sqliteWhereBegin(
|
||||
Parse *pParse, /* The parser context */
|
||||
int base, /* VDBE cursor index for left-most table in pTabList */
|
||||
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 */
|
||||
|
@ -328,6 +362,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
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 */
|
||||
|
@ -343,6 +378,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
** 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) ){
|
||||
|
@ -364,14 +400,13 @@ WhereInfo *sqliteWhereBegin(
|
|||
}
|
||||
pWInfo->pParse = pParse;
|
||||
pWInfo->pTabList = pTabList;
|
||||
pWInfo->base = base;
|
||||
pWInfo->peakNTab = pWInfo->savedNTab = pParse->nTab;
|
||||
pWInfo->iBreak = sqliteVdbeMakeLabel(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 && sqliteExprIsConstant(pWhere) ){
|
||||
if( pWhere && (pTabList->nSrc==0 || sqliteExprIsConstant(pWhere)) ){
|
||||
sqliteExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1);
|
||||
pWhere = 0;
|
||||
}
|
||||
|
@ -379,7 +414,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
/* Analyze all of the subexpressions.
|
||||
*/
|
||||
for(i=0; i<nExpr; i++){
|
||||
exprAnalyze(base, &aExpr[i]);
|
||||
exprAnalyze(&maskSet, &aExpr[i]);
|
||||
|
||||
/* If we are executing a trigger body, remove all references to
|
||||
** new.* and old.* tables from the prerequisite masks.
|
||||
|
@ -387,13 +422,13 @@ WhereInfo *sqliteWhereBegin(
|
|||
if( pParse->trigStack ){
|
||||
int x;
|
||||
if( (x = pParse->trigStack->newIdx) >= 0 ){
|
||||
int mask = ~(1 << (x - base));
|
||||
int mask = ~getMask(&maskSet, x);
|
||||
aExpr[i].prereqRight &= mask;
|
||||
aExpr[i].prereqLeft &= mask;
|
||||
aExpr[i].prereqAll &= mask;
|
||||
}
|
||||
if( (x = pParse->trigStack->oldIdx) >= 0 ){
|
||||
int mask = ~(1 << (x - base));
|
||||
int mask = ~getMask(&maskSet, x);
|
||||
aExpr[i].prereqRight &= mask;
|
||||
aExpr[i].prereqLeft &= mask;
|
||||
aExpr[i].prereqAll &= mask;
|
||||
|
@ -420,8 +455,9 @@ WhereInfo *sqliteWhereBegin(
|
|||
loopMask = 0;
|
||||
for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++){
|
||||
int j;
|
||||
int idx = i;
|
||||
Table *pTab = pTabList->a[idx].pTab;
|
||||
int iCur = pTabList->a[i].iCursor; /* The cursor for this table */
|
||||
int mask = getMask(&maskSet, iCur); /* Cursor mask for this table */
|
||||
Table *pTab = pTabList->a[i].pTab;
|
||||
Index *pIdx;
|
||||
Index *pBestIdx = 0;
|
||||
int bestScore = 0;
|
||||
|
@ -439,7 +475,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
iDirectLt[i] = -1;
|
||||
iDirectGt[i] = -1;
|
||||
for(j=0; j<nExpr; j++){
|
||||
if( aExpr[j].idxLeft==idx && aExpr[j].p->pLeft->iColumn<0
|
||||
if( aExpr[j].idxLeft==iCur && aExpr[j].p->pLeft->iColumn<0
|
||||
&& (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
|
||||
switch( aExpr[j].p->op ){
|
||||
case TK_IN:
|
||||
|
@ -450,7 +486,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
case TK_GT: iDirectGt[i] = j; break;
|
||||
}
|
||||
}
|
||||
if( aExpr[j].idxRight==idx && aExpr[j].p->pRight->iColumn<0
|
||||
if( aExpr[j].idxRight==iCur && aExpr[j].p->pRight->iColumn<0
|
||||
&& (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){
|
||||
switch( aExpr[j].p->op ){
|
||||
case TK_EQ: iDirectEq[i] = j; break;
|
||||
|
@ -462,7 +498,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
}
|
||||
}
|
||||
if( iDirectEq[i]>=0 ){
|
||||
loopMask |= 1<<idx;
|
||||
loopMask |= mask;
|
||||
pWInfo->a[i].pIdx = 0;
|
||||
continue;
|
||||
}
|
||||
|
@ -501,7 +537,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
|
||||
if( pIdx->nColumn>32 ) continue; /* Ignore indices too many columns */
|
||||
for(j=0; j<nExpr; j++){
|
||||
if( aExpr[j].idxLeft==idx
|
||||
if( aExpr[j].idxLeft==iCur
|
||||
&& (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
|
||||
int iColumn = aExpr[j].p->pLeft->iColumn;
|
||||
int k;
|
||||
|
@ -536,7 +572,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
}
|
||||
}
|
||||
}
|
||||
if( aExpr[j].idxRight==idx
|
||||
if( aExpr[j].idxRight==iCur
|
||||
&& (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){
|
||||
int iColumn = aExpr[j].p->pRight->iColumn;
|
||||
int k;
|
||||
|
@ -589,7 +625,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
pWInfo->a[i].pIdx = pBestIdx;
|
||||
pWInfo->a[i].score = bestScore;
|
||||
pWInfo->a[i].bRev = 0;
|
||||
loopMask |= 1<<idx;
|
||||
loopMask |= mask;
|
||||
if( pBestIdx ){
|
||||
pWInfo->a[i].iCur = pParse->nTab++;
|
||||
pWInfo->peakNTab = pParse->nTab;
|
||||
|
@ -620,7 +656,8 @@ WhereInfo *sqliteWhereBegin(
|
|||
pSortIdx = 0;
|
||||
}else{
|
||||
int nEqCol = (pWInfo->a[0].score+4)/8;
|
||||
pSortIdx = findSortingIndex(pTab, base, *ppOrderBy, pIdx, nEqCol, &bRev);
|
||||
pSortIdx = findSortingIndex(pTab, pTabList->a[0].iCursor,
|
||||
*ppOrderBy, pIdx, nEqCol, &bRev);
|
||||
}
|
||||
if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){
|
||||
if( pIdx==0 ){
|
||||
|
@ -636,21 +673,18 @@ WhereInfo *sqliteWhereBegin(
|
|||
/* Open all tables in the pTabList and all indices used by those tables.
|
||||
*/
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
int openOp;
|
||||
Table *pTab;
|
||||
|
||||
pTab = pTabList->a[i].pTab;
|
||||
if( pTab->isTransient || pTab->pSelect ) continue;
|
||||
openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
|
||||
sqliteVdbeAddOp(v, openOp, base+i, pTab->tnum);
|
||||
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
|
||||
sqliteVdbeAddOp(v, OP_OpenRead, pTabList->a[i].iCursor, pTab->tnum);
|
||||
sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
|
||||
if( i==0 && !pParse->schemaVerified &&
|
||||
(pParse->db->flags & SQLITE_InTrans)==0 ){
|
||||
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
|
||||
pParse->schemaVerified = 1;
|
||||
}
|
||||
sqliteCodeVerifySchema(pParse, pTab->iDb);
|
||||
if( pWInfo->a[i].pIdx!=0 ){
|
||||
sqliteVdbeAddOp(v, openOp, pWInfo->a[i].iCur, pWInfo->a[i].pIdx->tnum);
|
||||
sqliteVdbeAddOp(v, OP_Integer, pWInfo->a[i].pIdx->iDb, 0);
|
||||
sqliteVdbeAddOp(v, OP_OpenRead,
|
||||
pWInfo->a[i].iCur, pWInfo->a[i].pIdx->tnum);
|
||||
sqliteVdbeChangeP3(v, -1, pWInfo->a[i].pIdx->zName, P3_STATIC);
|
||||
}
|
||||
}
|
||||
|
@ -660,7 +694,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
loopMask = 0;
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
int j, k;
|
||||
int idx = i;
|
||||
int iCur = pTabList->a[i].iCursor;
|
||||
Index *pIdx;
|
||||
WhereLevel *pLevel = &pWInfo->a[i];
|
||||
|
||||
|
@ -686,9 +720,9 @@ WhereInfo *sqliteWhereBegin(
|
|||
k = iDirectEq[i];
|
||||
assert( k<nExpr );
|
||||
assert( aExpr[k].p!=0 );
|
||||
assert( aExpr[k].idxLeft==idx || aExpr[k].idxRight==idx );
|
||||
assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
|
||||
brk = pLevel->brk = sqliteVdbeMakeLabel(v);
|
||||
if( aExpr[k].idxLeft==idx ){
|
||||
if( aExpr[k].idxLeft==iCur ){
|
||||
Expr *pX = aExpr[k].p;
|
||||
if( pX->op!=TK_IN ){
|
||||
sqliteExprCode(pParse, aExpr[k].p->pRight);
|
||||
|
@ -712,7 +746,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
cont = pLevel->cont = sqliteVdbeMakeLabel(v);
|
||||
sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
|
||||
haveKey = 0;
|
||||
sqliteVdbeAddOp(v, OP_NotExists, base+idx, brk);
|
||||
sqliteVdbeAddOp(v, OP_NotExists, iCur, brk);
|
||||
pLevel->op = OP_Noop;
|
||||
}else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){
|
||||
/* Case 2: There is an index and all terms of the WHERE clause that
|
||||
|
@ -726,7 +760,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
for(k=0; k<nExpr; k++){
|
||||
Expr *pX = aExpr[k].p;
|
||||
if( pX==0 ) continue;
|
||||
if( aExpr[k].idxLeft==idx
|
||||
if( aExpr[k].idxLeft==iCur
|
||||
&& (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
|
||||
&& pX->pLeft->iColumn==pIdx->aiColumn[j]
|
||||
){
|
||||
|
@ -753,7 +787,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
break;
|
||||
}
|
||||
}
|
||||
if( aExpr[k].idxRight==idx
|
||||
if( aExpr[k].idxRight==iCur
|
||||
&& aExpr[k].p->op==TK_EQ
|
||||
&& (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
|
||||
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
|
||||
|
@ -796,7 +830,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
if( i==pTabList->nSrc-1 && pushKey ){
|
||||
haveKey = 1;
|
||||
}else{
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0);
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
|
||||
haveKey = 0;
|
||||
}
|
||||
pLevel->p1 = pLevel->iCur;
|
||||
|
@ -813,8 +847,8 @@ WhereInfo *sqliteWhereBegin(
|
|||
k = iDirectGt[i];
|
||||
assert( k<nExpr );
|
||||
assert( aExpr[k].p!=0 );
|
||||
assert( aExpr[k].idxLeft==idx || aExpr[k].idxRight==idx );
|
||||
if( aExpr[k].idxLeft==idx ){
|
||||
assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
|
||||
if( aExpr[k].idxLeft==iCur ){
|
||||
sqliteExprCode(pParse, aExpr[k].p->pRight);
|
||||
}else{
|
||||
sqliteExprCode(pParse, aExpr[k].p->pLeft);
|
||||
|
@ -823,17 +857,17 @@ WhereInfo *sqliteWhereBegin(
|
|||
if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){
|
||||
sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, base+idx, brk);
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
|
||||
aExpr[k].p = 0;
|
||||
}else{
|
||||
sqliteVdbeAddOp(v, OP_Rewind, base+idx, brk);
|
||||
sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
|
||||
}
|
||||
if( iDirectLt[i]>=0 ){
|
||||
k = iDirectLt[i];
|
||||
assert( k<nExpr );
|
||||
assert( aExpr[k].p!=0 );
|
||||
assert( aExpr[k].idxLeft==idx || aExpr[k].idxRight==idx );
|
||||
if( aExpr[k].idxLeft==idx ){
|
||||
assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
|
||||
if( aExpr[k].idxLeft==iCur ){
|
||||
sqliteExprCode(pParse, aExpr[k].p->pRight);
|
||||
}else{
|
||||
sqliteExprCode(pParse, aExpr[k].p->pLeft);
|
||||
|
@ -850,10 +884,10 @@ WhereInfo *sqliteWhereBegin(
|
|||
}
|
||||
start = sqliteVdbeCurrentAddr(v);
|
||||
pLevel->op = OP_Next;
|
||||
pLevel->p1 = base+idx;
|
||||
pLevel->p1 = iCur;
|
||||
pLevel->p2 = start;
|
||||
if( testOp!=OP_Noop ){
|
||||
sqliteVdbeAddOp(v, OP_Recno, base+idx, 0);
|
||||
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
|
||||
sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
|
||||
sqliteVdbeAddOp(v, testOp, 0, brk);
|
||||
}
|
||||
|
@ -866,10 +900,10 @@ WhereInfo *sqliteWhereBegin(
|
|||
|
||||
brk = pLevel->brk = sqliteVdbeMakeLabel(v);
|
||||
cont = pLevel->cont = sqliteVdbeMakeLabel(v);
|
||||
sqliteVdbeAddOp(v, OP_Rewind, base+idx, brk);
|
||||
sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
|
||||
start = sqliteVdbeCurrentAddr(v);
|
||||
pLevel->op = OP_Next;
|
||||
pLevel->p1 = base+idx;
|
||||
pLevel->p1 = iCur;
|
||||
pLevel->p2 = start;
|
||||
haveKey = 0;
|
||||
}else{
|
||||
|
@ -895,7 +929,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
for(j=0; j<nEqColumn; j++){
|
||||
for(k=0; k<nExpr; k++){
|
||||
if( aExpr[k].p==0 ) continue;
|
||||
if( aExpr[k].idxLeft==idx
|
||||
if( aExpr[k].idxLeft==iCur
|
||||
&& aExpr[k].p->op==TK_EQ
|
||||
&& (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
|
||||
&& aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
|
||||
|
@ -904,7 +938,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
aExpr[k].p = 0;
|
||||
break;
|
||||
}
|
||||
if( aExpr[k].idxRight==idx
|
||||
if( aExpr[k].idxRight==iCur
|
||||
&& aExpr[k].p->op==TK_EQ
|
||||
&& (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
|
||||
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
|
||||
|
@ -940,7 +974,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
for(k=0; k<nExpr; k++){
|
||||
Expr *pExpr = aExpr[k].p;
|
||||
if( pExpr==0 ) continue;
|
||||
if( aExpr[k].idxLeft==idx
|
||||
if( aExpr[k].idxLeft==iCur
|
||||
&& (pExpr->op==TK_LT || pExpr->op==TK_LE)
|
||||
&& (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
|
||||
&& pExpr->pLeft->iColumn==pIdx->aiColumn[j]
|
||||
|
@ -950,7 +984,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
aExpr[k].p = 0;
|
||||
break;
|
||||
}
|
||||
if( aExpr[k].idxRight==idx
|
||||
if( aExpr[k].idxRight==iCur
|
||||
&& (pExpr->op==TK_GT || pExpr->op==TK_GE)
|
||||
&& (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
|
||||
&& pExpr->pRight->iColumn==pIdx->aiColumn[j]
|
||||
|
@ -995,7 +1029,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
for(k=0; k<nExpr; k++){
|
||||
Expr *pExpr = aExpr[k].p;
|
||||
if( pExpr==0 ) continue;
|
||||
if( aExpr[k].idxLeft==idx
|
||||
if( aExpr[k].idxLeft==iCur
|
||||
&& (pExpr->op==TK_GT || pExpr->op==TK_GE)
|
||||
&& (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
|
||||
&& pExpr->pLeft->iColumn==pIdx->aiColumn[j]
|
||||
|
@ -1005,7 +1039,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
aExpr[k].p = 0;
|
||||
break;
|
||||
}
|
||||
if( aExpr[k].idxRight==idx
|
||||
if( aExpr[k].idxRight==iCur
|
||||
&& (pExpr->op==TK_LT || pExpr->op==TK_LE)
|
||||
&& (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
|
||||
&& pExpr->pRight->iColumn==pIdx->aiColumn[j]
|
||||
|
@ -1051,7 +1085,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
if( i==pTabList->nSrc-1 && pushKey ){
|
||||
haveKey = 1;
|
||||
}else{
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0);
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
|
||||
haveKey = 0;
|
||||
}
|
||||
|
||||
|
@ -1061,7 +1095,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
pLevel->p1 = pLevel->iCur;
|
||||
pLevel->p2 = start;
|
||||
}
|
||||
loopMask |= 1<<idx;
|
||||
loopMask |= getMask(&maskSet, iCur);
|
||||
|
||||
/* Insert code to test every subexpression that can be completely
|
||||
** computed using the current set of tables.
|
||||
|
@ -1074,7 +1108,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
}
|
||||
if( haveKey ){
|
||||
haveKey = 0;
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0);
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
|
||||
}
|
||||
sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
|
||||
aExpr[j].p = 0;
|
||||
|
@ -1097,7 +1131,7 @@ WhereInfo *sqliteWhereBegin(
|
|||
** no outer joins with DELETE and UPDATE.
|
||||
*/
|
||||
haveKey = 0;
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0);
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
|
||||
}
|
||||
sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
|
||||
aExpr[j].p = 0;
|
||||
|
@ -1106,8 +1140,9 @@ WhereInfo *sqliteWhereBegin(
|
|||
}
|
||||
pWInfo->iContinue = cont;
|
||||
if( pushKey && !haveKey ){
|
||||
sqliteVdbeAddOp(v, OP_Recno, base, 0);
|
||||
sqliteVdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0);
|
||||
}
|
||||
freeMaskSet(&maskSet);
|
||||
return pWInfo;
|
||||
}
|
||||
|
||||
|
@ -1118,7 +1153,6 @@ WhereInfo *sqliteWhereBegin(
|
|||
void sqliteWhereEnd(WhereInfo *pWInfo){
|
||||
Vdbe *v = pWInfo->pParse->pVdbe;
|
||||
int i;
|
||||
int base = pWInfo->base;
|
||||
WhereLevel *pLevel;
|
||||
SrcList *pTabList = pWInfo->pTabList;
|
||||
|
||||
|
@ -1136,7 +1170,7 @@ void sqliteWhereEnd(WhereInfo *pWInfo){
|
|||
int addr;
|
||||
addr = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0);
|
||||
sqliteVdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iCur>=0));
|
||||
sqliteVdbeAddOp(v, OP_NullRow, base+i, 0);
|
||||
sqliteVdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0);
|
||||
if( pLevel->iCur>=0 ){
|
||||
sqliteVdbeAddOp(v, OP_NullRow, pLevel->iCur, 0);
|
||||
}
|
||||
|
@ -1145,9 +1179,11 @@ void sqliteWhereEnd(WhereInfo *pWInfo){
|
|||
}
|
||||
sqliteVdbeResolveLabel(v, pWInfo->iBreak);
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
if( pTabList->a[i].pTab->isTransient ) continue;
|
||||
Table *pTab = pTabList->a[i].pTab;
|
||||
assert( pTab!=0 );
|
||||
if( pTab->isTransient || pTab->pSelect ) continue;
|
||||
pLevel = &pWInfo->a[i];
|
||||
sqliteVdbeAddOp(v, OP_Close, base+i, 0);
|
||||
sqliteVdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0);
|
||||
if( pLevel->pIdx!=0 ){
|
||||
sqliteVdbeAddOp(v, OP_Close, pLevel->iCur, 0);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue