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:
Wez Furlong 2003-06-04 22:40:00 +00:00
parent 82a1818fde
commit 80e7f7001d
42 changed files with 11143 additions and 7558 deletions

View file

@ -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);
}