Code cleanup and simplification. Three new Mem opcodes added.
The sqlite3VdbeJumpHere function added. (CVS 2730)
FossilOrigin-Name: 2471957feee57538e5e1e50a704a337f0927d10e
diff --git a/src/analyze.c b/src/analyze.c
index 855f894..67d80d5 100644
--- a/src/analyze.c
+++ b/src/analyze.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
-** @(#) $Id: analyze.c,v 1.8 2005/09/10 22:40:54 drh Exp $
+** @(#) $Id: analyze.c,v 1.9 2005/09/20 17:42:23 drh Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"
@@ -127,13 +127,11 @@
** Cells iMem through iMem+nCol are initialized to 0. The others
** are initialized to NULL.
*/
- sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
for(i=0; i<=nCol; i++){
- sqlite3VdbeAddOp(v, OP_MemStore, iMem+i, i==nCol);
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem+i);
}
- sqlite3VdbeAddOp(v, OP_Null, 0, 0);
for(i=0; i<nCol; i++){
- sqlite3VdbeAddOp(v, OP_MemStore, iMem+nCol+i+1, i==nCol-1);
+ sqlite3VdbeAddOp(v, OP_MemNull, iMem+nCol+i+1, 0);
}
/* Do the analysis.
@@ -198,7 +196,7 @@
}
sqlite3VdbeOp3(v, OP_MakeRecord, 3, 0, "ttt", 0);
sqlite3VdbeAddOp(v, OP_Insert, iStatCur, 0);
- sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, addr);
}
}
diff --git a/src/build.c b/src/build.c
index 117bdff..9857a8e 100644
--- a/src/build.c
+++ b/src/build.c
@@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.350 2005/09/16 02:48:02 drh Exp $
+** $Id: build.c,v 1.351 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -76,7 +76,7 @@
if( pParse->cookieGoto>0 ){
u32 mask;
int iDb;
- sqlite3VdbeChangeP2(v, pParse->cookieGoto-1, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
if( (mask & pParse->cookieMask)==0 ) continue;
sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
@@ -2002,7 +2002,7 @@
}
sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, 0);
sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1);
- sqlite3VdbeChangeP2(v, addr1, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp(v, OP_Close, iTab, 0);
sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
}
diff --git a/src/delete.c b/src/delete.c
index b472ddd..4f5b8a3 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.110 2005/09/08 01:58:43 drh Exp $
+** $Id: delete.c,v 1.111 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
@@ -380,7 +380,7 @@
addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0);
sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0);
sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
- sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, addr);
}
/*
diff --git a/src/expr.c b/src/expr.c
index 6324068..c77c354 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.228 2005/09/16 02:38:10 drh Exp $
+** $Id: expr.c,v 1.229 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -1292,8 +1292,7 @@
sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);
testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0);
assert( testAddr>0 || sqlite3_malloc_failed );
- sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, mem, 1);
+ sqlite3VdbeAddOp(v, OP_MemInt, 1, mem);
}
switch( pExpr->op ){
@@ -1367,7 +1366,7 @@
if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){
VdbeOp *aOp = sqlite3VdbeGetOp(v, testAddr-1);
int i;
- for(i=0; i<4; i++){
+ for(i=0; i<3; i++){
aOp[i].opcode = OP_Noop;
}
testAddr = 0;
@@ -1409,7 +1408,7 @@
}
if( testAddr ){
- sqlite3VdbeChangeP2(v, testAddr, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, testAddr);
}
return;
}
@@ -1709,7 +1708,6 @@
case TK_CASE: {
int expr_end_label;
int jumpInst;
- int addr;
int nExpr;
int i;
ExprList *pEList;
@@ -1737,8 +1735,7 @@
}
sqlite3ExprCode(pParse, aListelem[i+1].pExpr);
sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label);
- addr = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeChangeP2(v, jumpInst, addr);
+ sqlite3VdbeJumpHere(v, jumpInst);
}
if( pExpr->pLeft ){
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
@@ -1905,7 +1902,7 @@
codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull);
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
- sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
break;
}
diff --git a/src/insert.c b/src/insert.c
index 428c8cd..e19aa7d 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.142 2005/07/21 18:23:20 drh Exp $
+** $Id: insert.c,v 1.143 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
@@ -372,13 +372,13 @@
** of the program jumps to it. Create the temporary table, then jump
** back up and execute the SELECT code above.
*/
- sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, iInitCode);
sqlite3VdbeAddOp(v, OP_OpenVirtual, srcTab, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn);
sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iCleanup);
}else{
- sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, iInitCode);
}
}else{
/* This is the case if the data for the INSERT is coming from a VALUES
@@ -470,8 +470,7 @@
*/
if( db->flags & SQLITE_CountRows ){
iCntMem = pParse->nMem++;
- sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, iCntMem, 1);
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, iCntMem);
}
/* Open tables and indices if there are no row triggers */
@@ -817,7 +816,6 @@
Index *pIdx;
int seenReplace = 0;
int jumpInst1=0, jumpInst2;
- int contAddr;
int hasTwoRowids = (isUpdate && rowidChng);
v = sqlite3GetVdbe(pParse);
@@ -867,7 +865,7 @@
break;
}
}
- sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, addr);
}
/* Test all CHECK constraints
@@ -921,10 +919,9 @@
break;
}
}
- contAddr = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeChangeP2(v, jumpInst2, contAddr);
+ sqlite3VdbeJumpHere(v, jumpInst2);
if( isUpdate ){
- sqlite3VdbeChangeP2(v, jumpInst1, contAddr);
+ sqlite3VdbeJumpHere(v, jumpInst1);
sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
}
@@ -1018,11 +1015,10 @@
break;
}
}
- contAddr = sqlite3VdbeCurrentAddr(v);
#if NULL_DISTINCT_FOR_UNIQUE
- sqlite3VdbeChangeP2(v, jumpInst1, contAddr);
+ sqlite3VdbeJumpHere(v, jumpInst1);
#endif
- sqlite3VdbeChangeP2(v, jumpInst2, contAddr);
+ sqlite3VdbeJumpHere(v, jumpInst2);
}
}
diff --git a/src/pragma.c b/src/pragma.c
index 6179548..445ff36 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.99 2005/09/17 16:36:56 drh Exp $
+** $Id: pragma.c,v 1.100 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -626,14 +626,6 @@
if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
int i, j, addr;
- /* Code that initializes the integrity check program. Set the
- ** error count 0
- */
- static const VdbeOpList initCode[] = {
- { OP_Integer, 0, 0, 0},
- { OP_MemStore, 0, 1, 0},
- };
-
/* Code that appears at the end of the integrity check. If no error
** messages have been generated, output OK. Otherwise output the
** error message
@@ -650,7 +642,7 @@
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, "integrity_check", P3_STATIC);
- sqlite3VdbeAddOpList(v, ArraySize(initCode), initCode);
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, 0); /* Initialize error count to 0 */
/* Do an integrity check on each database file */
for(i=0; i<db->nDb; i++){
@@ -696,8 +688,7 @@
if( pTab->pIndex==0 ) continue;
sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
- sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, 1, 1);
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, 1);
loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0);
sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
@@ -715,39 +706,38 @@
jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0);
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
- sqlite3VdbeChangeP2(v, jmp2, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, jmp2);
}
sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1);
- sqlite3VdbeChangeP2(v, loopTop, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, loopTop);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
static const VdbeOpList cntIdx[] = {
- { OP_Integer, 0, 0, 0},
- { OP_MemStore, 2, 1, 0},
- { OP_Rewind, 0, 0, 0}, /* 2 */
+ { OP_MemInt, 0, 2, 0},
+ { OP_Rewind, 0, 0, 0}, /* 1 */
{ OP_MemIncr, 2, 0, 0},
- { OP_Next, 0, 0, 0}, /* 4 */
+ { OP_Next, 0, 0, 0}, /* 3 */
{ OP_MemLoad, 1, 0, 0},
{ OP_MemLoad, 2, 0, 0},
- { OP_Eq, 0, 0, 0}, /* 7 */
+ { OP_Eq, 0, 0, 0}, /* 6 */
{ OP_MemIncr, 0, 0, 0},
{ OP_String8, 0, 0, "wrong # of entries in index "},
- { OP_String8, 0, 0, 0}, /* 10 */
+ { OP_String8, 0, 0, 0}, /* 9 */
{ OP_Concat, 0, 0, 0},
{ OP_Callback, 1, 0, 0},
};
if( pIdx->tnum==0 ) continue;
addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
- sqlite3VdbeChangeP1(v, addr+2, j+2);
- sqlite3VdbeChangeP2(v, addr+2, addr+5);
- sqlite3VdbeChangeP1(v, addr+4, j+2);
- sqlite3VdbeChangeP2(v, addr+4, addr+3);
- sqlite3VdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx));
- sqlite3VdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
+ sqlite3VdbeChangeP1(v, addr+1, j+2);
+ sqlite3VdbeChangeP2(v, addr+1, addr+4);
+ sqlite3VdbeChangeP1(v, addr+3, j+2);
+ sqlite3VdbeChangeP2(v, addr+3, addr+2);
+ sqlite3VdbeJumpHere(v, addr+6);
+ sqlite3VdbeChangeP3(v, addr+9, pIdx->zName, P3_STATIC);
}
}
}
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
- sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
+ sqlite3VdbeJumpHere(v, addr+2);
}else
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
diff --git a/src/select.c b/src/select.c
index 118bc3b..5065be8 100644
--- a/src/select.c
+++ b/src/select.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.274 2005/09/20 13:55:18 drh Exp $
+** $Id: select.c,v 1.275 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
@@ -543,7 +543,7 @@
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1);
sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
}
- sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, addr2);
break;
}
@@ -2448,17 +2448,15 @@
static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
Vdbe *v = pParse->pVdbe;
int i;
- int addr;
struct AggInfo_func *pFunc;
if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){
return;
}
- sqlite3VdbeAddOp(v, OP_Null, 0, 0);
for(i=0; i<pAggInfo->nColumn; i++){
- addr = sqlite3VdbeAddOp(v, OP_MemStore, pAggInfo->aCol[i].iMem, 0);
+ sqlite3VdbeAddOp(v, OP_MemNull, pAggInfo->aCol[i].iMem, 0);
}
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
- addr = sqlite3VdbeAddOp(v, OP_MemStore, pFunc->iMem, 0);
+ sqlite3VdbeAddOp(v, OP_MemNull, pFunc->iMem, 0);
if( pFunc->iDistinct>=0 ){
Expr *pE = pFunc->pExpr;
if( pE->pList==0 || pE->pList->nExpr!=1 ){
@@ -2472,7 +2470,6 @@
}
}
}
- sqlite3VdbeChangeP2(v, addr, 1);
}
/*
@@ -2786,9 +2783,10 @@
/* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists
*/
- if( eDest==SRT_Mem || eDest==SRT_Exists ){
- sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_Null : OP_Integer, 0, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
+ if( eDest==SRT_Mem ){
+ sqlite3VdbeAddOp(v, OP_MemNull, iParm, 0);
+ }else if( eDest==SRT_Exists ){
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, iParm);
}
/* Open a virtual index to use for the distinct set.
@@ -2916,11 +2914,9 @@
pParse->nMem += pGroupBy->nExpr;
iBMem = pParse->nMem;
pParse->nMem += pGroupBy->nExpr;
- sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, iAbortFlag, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, iUseFlag, 1);
- sqlite3VdbeAddOp(v, OP_Null, 0, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, iAMem, 1);
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, iAbortFlag);
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, iUseFlag);
+ sqlite3VdbeAddOp(v, OP_MemNull, iAMem, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, addrInitializeLoop);
/* Generate a subroutine that outputs a single row of the result
@@ -3036,8 +3032,7 @@
*/
sqlite3VdbeResolveLabel(v, addrGroupByChange);
for(j=0; j<pGroupBy->nExpr; j++){
- sqlite3VdbeAddOp(v, OP_MemLoad, iBMem+j, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, iAMem+j, 1);
+ sqlite3VdbeAddOp(v, OP_MemMove, iAMem+j, iBMem+j);
}
sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow);
sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd);
diff --git a/src/update.c b/src/update.c
index 704775d..007d525 100644
--- a/src/update.c
+++ b/src/update.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.111 2005/09/08 01:58:43 drh Exp $
+** $Id: update.c,v 1.112 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
@@ -469,7 +469,7 @@
** all record selected by the WHERE clause have been updated.
*/
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
- sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeJumpHere(v, addr);
/* Close all tables if there were no FOR EACH ROW triggers */
if( !triggers_exist ){
diff --git a/src/vdbe.c b/src/vdbe.c
index 1410176..d7af8f0 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.490 2005/09/20 13:55:18 drh Exp $
+** $Id: vdbe.c,v 1.491 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -4177,6 +4177,39 @@
break;
}
+/* Opcode: MemNull P1 * *
+**
+** Store a NULL in memory cell P1
+*/
+case OP_MemNull: {
+ assert( pOp->p1>=0 && pOp->p1<p->nMem );
+ sqlite3VdbeMemSetNull(&p->aMem[pOp->p1]);
+ break;
+}
+
+/* Opcode: MemInt P1 P2 *
+**
+** Store the integer value P1 in memory cell P2.
+*/
+case OP_MemInt: {
+ assert( pOp->p2>=0 && pOp->p2<p->nMem );
+ sqlite3VdbeMemSetInt64(&p->aMem[pOp->p2], pOp->p1);
+ break;
+}
+
+/* Opcode: MemMove P1 P2 *
+**
+** Move the content of memory cell P2 over to memory cell P1.
+** Any prior content of P1 is erased. Memory cell P2 is left
+** containing a NULL.
+*/
+case OP_MemMove: {
+ assert( pOp->p1>=0 && pOp->p1<p->nMem );
+ assert( pOp->p2>=0 && pOp->p2<p->nMem );
+ rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], &p->aMem[pOp->p2]);
+ break;
+}
+
/* Opcode: AggStep P1 P2 P3
**
** Execute the step function for an aggregate. The
diff --git a/src/vdbe.h b/src/vdbe.h
index 6e39174..bef16fd 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.98 2005/09/07 21:22:47 drh Exp $
+** $Id: vdbe.h,v 1.99 2005/09/20 17:42:23 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@@ -104,6 +104,7 @@
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
+void sqlite3VdbeJumpHere(Vdbe*, int addr);
void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 008be0b..cba9c09 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -351,6 +351,13 @@
}
}
+/*
+** Change teh P2 operand of instruction addr so that it points to
+** the address of the next instruction to be coded.
+*/
+void sqlite3VdbeJumpHere(Vdbe *p, int addr){
+ sqlite3VdbeChangeP2(p, addr, p->nOp);
+}
/*
** Delete a P3 value if necessary.
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 05d9c88..0b7e193 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -317,6 +317,7 @@
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Null;
pMem->type = SQLITE_NULL;
+ pMem->n = 0;
}
/*
diff --git a/src/where.c b/src/where.c
index d9ddef0..e3b0e19 100644
--- a/src/where.c
+++ b/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.178 2005/09/20 08:47:20 drh Exp $
+** $Id: where.c,v 1.179 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
@@ -1597,8 +1597,7 @@
if( pLevel->iFrom>0 && (pTabItem[-1].jointype & JT_LEFT)!=0 ){
if( !pParse->nMem ) pParse->nMem++;
pLevel->iLeftJoin = pParse->nMem++;
- sqlite3VdbeAddOp(v, OP_Null, 0, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, pLevel->iLeftJoin);
VdbeComment((v, "# init LEFT JOIN no-match flag"));
}
@@ -1878,8 +1877,7 @@
*/
if( pLevel->iLeftJoin ){
pLevel->top = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
+ sqlite3VdbeAddOp(v, OP_MemInt, 1, pLevel->iLeftJoin);
VdbeComment((v, "# record LEFT JOIN hit"));
for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){
if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
@@ -1981,13 +1979,13 @@
}
if( pLevel->iLeftJoin ){
int addr;
- addr = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0);
- sqlite3VdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iIdxCur>=0));
+ addr = sqlite3VdbeAddOp(v, OP_IfMemPos, pLevel->iLeftJoin, 0);
sqlite3VdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0);
if( pLevel->iIdxCur>=0 ){
sqlite3VdbeAddOp(v, OP_NullRow, pLevel->iIdxCur, 0);
}
sqlite3VdbeAddOp(v, OP_Goto, 0, pLevel->top);
+ sqlite3VdbeJumpHere(v, addr);
}
}