aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2015-09-14 14:45:50 +0000
committerdrh <drh@noemail.net>2015-09-14 14:45:50 +0000
commitb0264eeca104038cc8d99270be0d38ab159e21a0 (patch)
treee92fffecb5737f7ad8664f25479ee5b5ee76c8f8 /src
parent66336f3755fa6f37212b6cb3218c61d44945ea78 (diff)
downloadsqlite-b0264eeca104038cc8d99270be0d38ab159e21a0.tar.gz
sqlite-b0264eeca104038cc8d99270be0d38ab159e21a0.zip
Use symbolic names ONEPASS_OFF, ONEPASS_SINGLE, and ONEPASS_MULTI for the
various modes of the one-pass optimization. FossilOrigin-Name: 16e56bdadef903c6439a487f2683388aeeb0c625
Diffstat (limited to 'src')
-rw-r--r--src/delete.c40
-rw-r--r--src/insert.c6
-rw-r--r--src/sqliteInt.h3
-rw-r--r--src/where.c25
-rw-r--r--src/whereInt.h2
-rw-r--r--src/wherecode.c2
6 files changed, 43 insertions, 35 deletions
diff --git a/src/delete.c b/src/delete.c
index caf73ab2b..7c2f3fcd0 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -235,7 +235,7 @@ void sqlite3DeleteFrom(
int iDb; /* Database number */
int memCnt = -1; /* Memory cell used for change counting */
int rcauth; /* Value returned by authorization callback */
- int eOnePass; /* Non-zero for one-pass algorithm without the FIFO */
+ int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */
Index *pPk; /* The PRIMARY KEY index on the table */
@@ -400,14 +400,14 @@ void sqlite3DeleteFrom(
** to be deleted, based on the WHERE clause. Set variable eOnePass
** to indicate the strategy used to implement this delete:
**
- ** 0: Two-pass approach - use a FIFO for rowids/PK values.
- ** 1: One-pass approach - at most one row deleted.
- ** 2: One-pass approach - any number of rows may be deleted.
+ ** ONEPASS_OFF: Two-pass approach - use a FIFO for rowids/PK values.
+ ** ONEPASS_SINGLE: One-pass approach - at most one row deleted.
+ ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted.
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
if( pWInfo==0 ) goto delete_from_cleanup;
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
- assert( IsVirtual(pTab)==0 || eOnePass==0 );
+ assert( IsVirtual(pTab)==0 || eOnePass==ONEPASS_OFF );
/* Keep track of the number of rows to be deleted */
if( db->flags & SQLITE_CountRows ){
@@ -428,7 +428,7 @@ void sqlite3DeleteFrom(
if( iKey>pParse->nMem ) pParse->nMem = iKey;
}
- if( eOnePass ){
+ if( eOnePass!=ONEPASS_OFF ){
/* For ONEPASS, no need to store the rowid/primary-key. There is only
** one, so just keep it in its register(s) and fall through to the
** delete code. */
@@ -460,7 +460,7 @@ void sqlite3DeleteFrom(
/* If this DELETE cannot use the ONEPASS strategy, this is the
** end of the WHERE loop */
- if( eOnePass ){
+ if( eOnePass!=ONEPASS_OFF ){
addrBypass = sqlite3VdbeMakeLabel(v);
}else{
sqlite3WhereEnd(pWInfo);
@@ -473,7 +473,7 @@ void sqlite3DeleteFrom(
*/
if( !isView ){
int iAddrOnce = 0;
- if( eOnePass==2 ){
+ if( eOnePass==ONEPASS_MULTI ){
iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
}
testcase( IsVirtual(pTab) );
@@ -481,13 +481,13 @@ void sqlite3DeleteFrom(
&iDataCur, &iIdxCur);
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
- if( eOnePass==2 ) sqlite3VdbeJumpHere(v, iAddrOnce);
+ if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
}
/* Set up a loop over the rowids/primary-keys that were found in the
** where-clause loop above.
*/
- if( eOnePass ){
+ if( eOnePass!=ONEPASS_OFF ){
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
if( aToOpen[iDataCur-iTabCur] ){
assert( pPk!=0 || pTab->pSelect!=0 );
@@ -525,7 +525,7 @@ void sqlite3DeleteFrom(
}
/* End of the loop over all rowids/primary-keys. */
- if( eOnePass ){
+ if( eOnePass!=ONEPASS_OFF ){
sqlite3VdbeResolveLabel(v, addrBypass);
sqlite3WhereEnd(pWInfo);
}else if( pPk ){
@@ -601,13 +601,13 @@ delete_from_cleanup:
** single memory location iPk.
**
** eMode:
-** Parameter eMode may be passed either 0, 1 or 2. If it is passed a
-** non-zero value, then it is guaranteed that cursor iDataCur already
-** points to the row to delete. If it is passed 0, then this function
-** must seek iDataCur to the entry identified by iPk and nPk before
-** reading from it.
+** Parameter eMode may be passed either ONEPASS_OFF (0), ONEPASS_SINGLE, or
+** ONEPASS_MULTI. If eMode is not ONEPASS_OFF, then the cursor
+** iDataCur already points to the row to delete. If eMode is ONEPASS_OFF
+** then this function must seek iDataCur to the entry identified by iPk
+** and nPk before reading from it.
**
-** If eMode is passed the value 2, then this call is being made as part
+** If eMode is ONEPASS_MULTI, then this call is being made as part
** of a ONEPASS delete that affects multiple rows. In this case, if
** iIdxNoSeek is a valid cursor number (>=0), then its position should
** be preserved following the delete operation. Or, if iIdxNoSeek is not
@@ -629,7 +629,7 @@ void sqlite3GenerateRowDelete(
i16 nPk, /* Number of PRIMARY KEY memory cells */
u8 count, /* If non-zero, increment the row change counter */
u8 onconf, /* Default ON CONFLICT policy for triggers */
- u8 eMode, /* See explanation above */
+ u8 eMode, /* ONEPASS_OFF, _SINGLE, or _MULTI. See above */
int iIdxNoSeek /* Cursor number of cursor that does not need seeking */
){
Vdbe *v = pParse->pVdbe; /* Vdbe */
@@ -647,7 +647,7 @@ void sqlite3GenerateRowDelete(
** not attempt to delete it or fire any DELETE triggers. */
iLabel = sqlite3VdbeMakeLabel(v);
opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
- if( eMode==0 ){
+ if( eMode==ONEPASS_OFF ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
VdbeCoverageIf(v, opSeek==OP_NotExists);
VdbeCoverageIf(v, opSeek==OP_NotFound);
@@ -715,7 +715,7 @@ void sqlite3GenerateRowDelete(
if( iIdxNoSeek>=0 ){
sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek);
}
- sqlite3VdbeChangeP5(v, eMode==2);
+ sqlite3VdbeChangeP5(v, eMode==ONEPASS_MULTI);
}
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
diff --git a/src/insert.c b/src/insert.c
index 21e1a2577..613277835 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -1347,7 +1347,8 @@ void sqlite3GenerateConstraintChecks(
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
- regNewData, 1, 0, OE_Replace, 1, -1);
+ regNewData, 1, 0, OE_Replace,
+ ONEPASS_SINGLE, -1);
}else if( pTab->pIndex ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0, -1);
@@ -1528,7 +1529,8 @@ void sqlite3GenerateConstraintChecks(
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
- regR, nPkField, 0, OE_Replace, pIdx==pPk, -1);
+ regR, nPkField, 0, OE_Replace,
+ (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), -1);
seenReplace = 1;
break;
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 7fc3464d1..747f19b39 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3381,6 +3381,9 @@ int sqlite3WhereIsSorted(WhereInfo*);
int sqlite3WhereContinueLabel(WhereInfo*);
int sqlite3WhereBreakLabel(WhereInfo*);
int sqlite3WhereOkOnePass(WhereInfo*, int*);
+#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */
+#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */
+#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
diff --git a/src/where.c b/src/where.c
index 526e06afe..69b7c064e 100644
--- a/src/where.c
+++ b/src/where.c
@@ -69,9 +69,11 @@ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
}
/*
-** Return TRUE if an UPDATE or DELETE statement can operate directly on
-** the rowids returned by a WHERE clause. Return FALSE if doing an
-** UPDATE or DELETE might change subsequent WHERE clause results.
+** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to
+** operate directly on the rowis returned by a WHERE clause. Return
+** ONEPASS_SINGLE (1) if the statement can operation directly because only
+** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass
+** optimization can be used on multiple
**
** If the ONEPASS optimization is used (if this routine returns true)
** then also write the indices of open cursors used by ONEPASS
@@ -85,7 +87,7 @@ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
*/
int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){
memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2);
- return pWInfo->okOnePass;
+ return pWInfo->eOnePass;
}
/*
@@ -4017,6 +4019,7 @@ WhereInfo *sqlite3WhereBegin(
pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
+ assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
pMaskSet = &pWInfo->sMaskSet;
sWLB.pWInfo = pWInfo;
sWLB.pWC = &pWInfo->sWC;
@@ -4209,7 +4212,7 @@ WhereInfo *sqlite3WhereBegin(
if( bOnerow || ( (wctrlFlags & WHERE_ONEPASS_MULTIROW)
&& 0==(wsFlags & WHERE_VIRTUALTABLE)
)){
- pWInfo->okOnePass = bOnerow ? 1 : 2;
+ pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
if( HasRowid(pTabList->a[0].pTab) ){
pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY;
}
@@ -4243,15 +4246,15 @@ WhereInfo *sqlite3WhereBegin(
if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
&& (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){
int op = OP_OpenRead;
- if( pWInfo->okOnePass ){
+ if( pWInfo->eOnePass!=ONEPASS_OFF ){
op = OP_OpenWrite;
pWInfo->aiCurOnePass[0] = pTabItem->iCursor;
};
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
assert( pTabItem->iCursor==pLevel->iTabCur );
- testcase( !pWInfo->okOnePass && pTab->nCol==BMS-1 );
- testcase( !pWInfo->okOnePass && pTab->nCol==BMS );
- if( !pWInfo->okOnePass && pTab->nCol<BMS && HasRowid(pTab) ){
+ testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 );
+ testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS );
+ if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && HasRowid(pTab) ){
Bitmask b = pTabItem->colUsed;
int n = 0;
for(; b; b=b>>1, n++){}
@@ -4279,7 +4282,7 @@ WhereInfo *sqlite3WhereBegin(
** WITHOUT ROWID table. No need for a separate index */
iIndexCur = pLevel->iTabCur;
op = 0;
- }else if( pWInfo->okOnePass ){
+ }else if( pWInfo->eOnePass!=ONEPASS_OFF ){
Index *pJ = pTabItem->pTab->pIndex;
iIndexCur = iIdxCur;
assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
@@ -4487,7 +4490,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
&& (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0
){
int ws = pLoop->wsFlags;
- if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){
+ if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
}
if( (ws & WHERE_INDEXED)!=0
diff --git a/src/whereInt.h b/src/whereInt.h
index 65c118004..cae09acc8 100644
--- a/src/whereInt.h
+++ b/src/whereInt.h
@@ -412,7 +412,7 @@ struct WhereInfo {
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
u8 sorted; /* True if really sorted (not just grouped) */
- u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
+ u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
u8 nLevel; /* Number of nested loop */
diff --git a/src/wherecode.c b/src/wherecode.c
index 1f65a93e6..4fb608401 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -1069,7 +1069,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
- if( pWInfo->okOnePass ){
+ if( pWInfo->eOnePass!=ONEPASS_OFF ){
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
VdbeCoverage(v);
}else{