aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expr.c14
-rw-r--r--src/select.c13
-rw-r--r--src/vdbe.c17
-rw-r--r--src/vdbe.h2
-rw-r--r--src/vdbeaux.c13
-rw-r--r--src/vdbeblob.c4
-rw-r--r--src/where.c3
7 files changed, 38 insertions, 28 deletions
diff --git a/src/expr.c b/src/expr.c
index 7bfcf5733..6fd08b27f 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1462,8 +1462,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
int iMem = ++pParse->nMem;
int iAddr;
- iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+ iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
eType = IN_INDEX_ROWID;
@@ -1494,8 +1493,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
char *pKey;
pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
- iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+ iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF);
@@ -1580,6 +1578,7 @@ int sqlite3CodeSubselect(
int rReg = 0; /* Register storing resulting */
Vdbe *v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return 0;
+ assert( sqlite3VdbeCurrentAddr(v)>0 );
sqlite3ExprCachePush(pParse);
/* This code must be run in its entirety every time it is encountered
@@ -1594,8 +1593,7 @@ int sqlite3CodeSubselect(
*/
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
int mem = ++pParse->nMem;
- sqlite3VdbeAddOp1(v, OP_If, mem);
- testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
+ testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
assert( testAddr>0 || pParse->db->mallocFailed );
}
@@ -1695,7 +1693,7 @@ int sqlite3CodeSubselect(
** expression we need to rerun this code each time.
*/
if( testAddr && !sqlite3ExprIsConstant(pE2) ){
- sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
+ sqlite3VdbeChangeToNoop(v, testAddr);
testAddr = 0;
}
@@ -1766,7 +1764,7 @@ int sqlite3CodeSubselect(
}
if( testAddr ){
- sqlite3VdbeJumpHere(v, testAddr-1);
+ sqlite3VdbeJumpHere(v, testAddr);
}
sqlite3ExprCachePop(pParse, 1);
diff --git a/src/select.c b/src/select.c
index 2ddc751b5..277f5c026 100644
--- a/src/select.c
+++ b/src/select.c
@@ -3831,7 +3831,7 @@ int sqlite3Select(
** is a register allocated to hold the subroutine return address
*/
int topAddr = sqlite3VdbeAddOp0(v, OP_Goto);
- int regOnce = 0;
+ int onceAddr = 0;
assert( pItem->addrFillSub==0 );
pItem->addrFillSub = topAddr+1;
pItem->regReturn = ++pParse->nMem;
@@ -3839,15 +3839,14 @@ int sqlite3Select(
/* If the subquery is no correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery
** once. */
- regOnce = ++pParse->nMem;
- sqlite3VdbeAddOp1(v, OP_If, regOnce);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, regOnce);
+ int regOnce = ++pParse->nMem;
+ onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
- if( regOnce ) sqlite3VdbeJumpHere(v, topAddr+1);
+ if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
sqlite3VdbeJumpHere(v, topAddr);
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, topAddr+1);
@@ -3991,7 +3990,7 @@ int sqlite3Select(
** into an OP_Noop.
*/
if( addrSortIndex>=0 && pOrderBy==0 ){
- sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
+ sqlite3VdbeChangeToNoop(v, addrSortIndex);
p->addrOpenEphm[2] = -1;
}
@@ -4274,7 +4273,7 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
}else{
sqlite3WhereEnd(pWInfo);
- sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
+ sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
/* Output the final row of result
diff --git a/src/vdbe.c b/src/vdbe.c
index 906058c1f..4f7fd6bbe 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -2021,6 +2021,16 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
break;
}
+/* Opcode: Once P1 P2 * * *
+**
+** Jump to P2 if the value in register P1 is a not null or zero. If
+** the value is NULL or zero, fall through and change the P1 register
+** to an integer 1.
+**
+** When P1 is not used otherwise in a program, this opcode falls through
+** once and jumps on all subsequent invocations. It is the equivalent
+** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
+*/
/* Opcode: If P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is true. The value
@@ -2033,6 +2043,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
** is considered true if it has a numeric value of zero. If the value
** in P1 is NULL then take the jump if P3 is true.
*/
+case OP_Once: /* jump, in1 */
case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
int c;
@@ -2049,6 +2060,12 @@ case OP_IfNot: { /* jump, in1 */
}
if( c ){
pc = pOp->p2-1;
+ }else if( pOp->opcode==OP_Once ){
+ assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
+ memAboutToChange(p, pIn1);
+ pIn1->flags = MEM_Int;
+ pIn1->u.i = 1;
+ REGISTER_TRACE(pOp->p1, pIn1);
}
break;
}
diff --git a/src/vdbe.h b/src/vdbe.h
index f4691c0e8..948c73bca 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -180,7 +180,7 @@ void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
-void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
+void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index b00768477..1d5f713af 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -670,18 +670,15 @@ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
}
/*
-** Change N opcodes starting at addr to No-ops.
+** Change the opcode at addr into OP_Noop
*/
-void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
+void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
if( p->aOp ){
VdbeOp *pOp = &p->aOp[addr];
sqlite3 *db = p->db;
- while( N-- ){
- freeP4(db, pOp->p4type, pOp->p4.p);
- memset(pOp, 0, sizeof(pOp[0]));
- pOp->opcode = OP_Noop;
- pOp++;
- }
+ freeP4(db, pOp->p4type, pOp->p4.p);
+ memset(pOp, 0, sizeof(pOp[0]));
+ pOp->opcode = OP_Noop;
}
}
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index a8728e6d2..ae77a47ba 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -273,7 +273,7 @@ int sqlite3_blob_open(
/* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE
- sqlite3VdbeChangeToNoop(v, 2, 1);
+ sqlite3VdbeChangeToNoop(v, 2);
#else
sqlite3VdbeChangeP1(v, 2, iDb);
sqlite3VdbeChangeP2(v, 2, pTab->tnum);
@@ -283,7 +283,7 @@ int sqlite3_blob_open(
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
- sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
+ sqlite3VdbeChangeToNoop(v, 4 - flags);
sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
sqlite3VdbeChangeP3(v, 3 + flags, iDb);
diff --git a/src/where.c b/src/where.c
index 21fb7f45f..17490b0e8 100644
--- a/src/where.c
+++ b/src/where.c
@@ -1994,8 +1994,7 @@ static void constructAutomaticIndex(
v = pParse->pVdbe;
assert( v!=0 );
regIsInit = ++pParse->nMem;
- addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
+ addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);
/* Count the number of columns that will be added to the index
** and used to match WHERE clause constraints */