mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-16 23:02:26 +03:00
Remove the rowhash object from the code. Rowset now fills its role. (CVS 6535)
FossilOrigin-Name: e963bed0fe3ce5fa32f04b930e5ed0956dc2aa47
This commit is contained in:
49
src/where.c
49
src/where.c
@@ -16,7 +16,7 @@
|
||||
** so is applicable. Because this module is responsible for selecting
|
||||
** indices, you might also think of this module as the "query optimizer".
|
||||
**
|
||||
** $Id: where.c,v 1.384 2009/04/21 17:23:05 danielk1977 Exp $
|
||||
** $Id: where.c,v 1.385 2009/04/22 02:15:49 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -2414,14 +2414,11 @@ static Bitmask codeOneLoopStart(
|
||||
** 1) If pWInfo->regRowSet is non-zero, then the rowid must be inserted
|
||||
** into the RowSet object stored in register pWInfo->regRowSet.
|
||||
**
|
||||
** 2) If pWInfo->regRowHash is non-zero, then the rowid must be inserted
|
||||
** into the RowHash object stored in register pWInfo->regRowHash.
|
||||
**
|
||||
** Extracting a rowid value from a VDBE cursor is not always a cheap
|
||||
** operation, especially if the rowid is being extracted from an index
|
||||
** cursor. If the rowid value is available as a by-product of the code
|
||||
** generated to create the top of the scan loop, then it can be reused
|
||||
** for either of the two purposes enumerated above without extracting
|
||||
** without extracting
|
||||
** it from a cursor. The following two variables are used to communicate
|
||||
** the availability of the rowid value to the C-code at the end of this
|
||||
** function that generates the rowid-handling VDBE code.
|
||||
@@ -2437,7 +2434,7 @@ static Bitmask codeOneLoopStart(
|
||||
iCur = pTabItem->iCursor;
|
||||
bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
|
||||
omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
|
||||
&& (wctrlFlags & WHERE_FILL_ROWHASH)==0;
|
||||
&& (wctrlFlags & WHERE_FILL_ROWTEST)==0;
|
||||
regRowSet = pWInfo->regRowSet;
|
||||
codeRowSetEarly = 0;
|
||||
|
||||
@@ -2817,22 +2814,22 @@ static Bitmask codeOneLoopStart(
|
||||
** In the example, there are three indexed terms connected by OR.
|
||||
** The top of the loop looks like this:
|
||||
**
|
||||
** Null 1 # Zero the row-hash in reg 1
|
||||
** Null 1 # Zero the rowset in reg 1
|
||||
**
|
||||
** Then, for each indexed term, the following. The arguments to
|
||||
** RowHash are such that the rowid of the current row is inserted
|
||||
** into the row-hash. If it is already present, control skips the
|
||||
** RowSetTest are such that the rowid of the current row is inserted
|
||||
** into the RowSet. If it is already present, control skips the
|
||||
** Gosub opcode and jumps straight to the code generated by WhereEnd().
|
||||
**
|
||||
** sqlite3WhereBegin(<term>)
|
||||
** RowHash # Insert rowid into rowhash
|
||||
** RowSetTest # Insert rowid into rowset
|
||||
** Gosub 2 A
|
||||
** sqlite3WhereEnd()
|
||||
**
|
||||
** Following the above, code to terminate the loop. Label A, the target
|
||||
** of the Gosub above, jumps to the instruction right after the Goto.
|
||||
**
|
||||
** Null 1 # Zero the row-hash in reg 1
|
||||
** Null 1 # Zero the rowset in reg 1
|
||||
** Goto B # The loop is finished.
|
||||
**
|
||||
** A: <loop body> # Return data, whatever.
|
||||
@@ -2842,14 +2839,14 @@ static Bitmask codeOneLoopStart(
|
||||
** B: <after the loop>
|
||||
**
|
||||
*/
|
||||
const int f = WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FILL_ROWHASH;
|
||||
const int f = WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FILL_ROWTEST;
|
||||
|
||||
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
|
||||
WhereTerm *pFinal; /* Final subterm within the OR-clause. */
|
||||
SrcList oneTab; /* Shortened table list */
|
||||
|
||||
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
|
||||
int regRowhash = ++pParse->nMem; /* Register for RowHash object */
|
||||
int regRowset = ++pParse->nMem; /* Register for RowSet object */
|
||||
int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
|
||||
int iRetInit; /* Address of regReturn init */
|
||||
int ii;
|
||||
@@ -2866,8 +2863,8 @@ static Bitmask codeOneLoopStart(
|
||||
oneTab.nAlloc = 1;
|
||||
oneTab.a[0] = *pTabItem;
|
||||
|
||||
/* Initialize the row-hash register to contain NULL. An SQL NULL is
|
||||
** equivalent to an empty row-hash.
|
||||
/* Initialize the rowset register to contain NULL. An SQL NULL is
|
||||
** equivalent to an empty rowset.
|
||||
**
|
||||
** Also initialize regReturn to contain the address of the instruction
|
||||
** immediately following the OP_Return at the bottom of the loop. This
|
||||
@@ -2877,7 +2874,7 @@ static Bitmask codeOneLoopStart(
|
||||
** fall through to the next instruction, just as an OP_Next does if
|
||||
** called on an uninitialized cursor.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowhash);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
|
||||
iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
|
||||
|
||||
/* iReleaseReg = iRowidReg = sqlite3GetTempReg(pParse); */
|
||||
@@ -2888,18 +2885,18 @@ static Bitmask codeOneLoopStart(
|
||||
|
||||
/* Loop through table entries that match term pOrTerm. */
|
||||
pSubWInfo = sqlite3WhereBegin(
|
||||
pParse, &oneTab, pOrTerm->pExpr, 0, f, regRowhash);
|
||||
pParse, &oneTab, pOrTerm->pExpr, 0, f, regRowset);
|
||||
if( pSubWInfo ){
|
||||
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
||||
/* The call to sqlite3WhereBegin has coded an OP_RowHash
|
||||
** at instruction iRowHash. Set P2 (the jump target) of this
|
||||
/* The call to sqlite3WhereBegin has coded an OP_RowSetTest
|
||||
** at instruction iRowSet. Set P2 (the jump target) of this
|
||||
** instruction to jump past the OP_Gosub coded below. This way,
|
||||
** if the rowid is already in the hash-table, the body of the
|
||||
** loop is not executed.
|
||||
*/
|
||||
int iRowHash = pSubWInfo->iRowidHandler;
|
||||
sqlite3VdbeChangeP2(v, iRowHash, sqlite3VdbeCurrentAddr(v) + 1);
|
||||
sqlite3VdbeChangeP4(v, iRowHash, (char *)iSet, P4_INT32);
|
||||
int iRowSet = pSubWInfo->iRowidHandler;
|
||||
sqlite3VdbeChangeP2(v, iRowSet, sqlite3VdbeCurrentAddr(v) + 1);
|
||||
sqlite3VdbeChangeP4(v, iRowSet, (char *)iSet, P4_INT32);
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
|
||||
|
||||
/* Finish the loop through table entries that match term pOrTerm. */
|
||||
@@ -2908,7 +2905,7 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
}
|
||||
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowhash);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
|
||||
sqlite3VdbeResolveLabel(v, iLoopBody);
|
||||
|
||||
@@ -2998,8 +2995,8 @@ static Bitmask codeOneLoopStart(
|
||||
if( pWInfo->wctrlFlags&WHERE_FILL_ROWSET ){
|
||||
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, iRowidReg);
|
||||
}else{
|
||||
assert( pWInfo->wctrlFlags&WHERE_FILL_ROWHASH );
|
||||
sqlite3VdbeAddOp3(v, OP_RowHash, regRowSet, 0, iRowidReg);
|
||||
assert( pWInfo->wctrlFlags&WHERE_FILL_ROWTEST );
|
||||
sqlite3VdbeAddOp3(v, OP_RowSetTest, regRowSet, 0, iRowidReg);
|
||||
}
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, iReleaseReg);
|
||||
@@ -3189,7 +3186,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
|
||||
pWInfo->wctrlFlags = wctrlFlags;
|
||||
pMaskSet = (WhereMaskSet*)&pWC[1];
|
||||
assert( regRowSet==0 || (wctrlFlags&(WHERE_FILL_ROWSET|WHERE_FILL_ROWHASH)) );
|
||||
assert( regRowSet==0 || (wctrlFlags&(WHERE_FILL_ROWSET|WHERE_FILL_ROWTEST)) );
|
||||
|
||||
/* Split the WHERE clause into separate subexpressions where each
|
||||
** subexpression is separated by an AND operator.
|
||||
|
||||
Reference in New Issue
Block a user