Index: mkopcodeh.awk ================================================================== --- mkopcodeh.awk +++ mkopcodeh.awk @@ -49,11 +49,10 @@ name = $2 sub(/:/,"",name) sub("\r","",name) op[name] = -1 jump[name] = 0 - nopush[name] = 0 out2_prerelease[name] = 0 in1[name] = 0 in2[name] = 0 in3[name] = 0 out2[name] = 0 @@ -66,13 +65,11 @@ used[op[name]] = 1 sameas[op[name]] = sym } x = $i sub(",","",x) - if(x=="no-push"){ - nopush[name] = 1 - }else if(x=="jump"){ + if(x=="jump"){ jump[name] = 1 }else if(x=="out2-prerelease"){ out2_prerelease[name] = 1 }else if(x=="in1"){ in1[name] = 1 @@ -128,37 +125,36 @@ # for(i=0; i<=max; i++) bv[i] = 0; for(name in op){ x = op[name] a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0 - a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0 + # a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0 if( jump[name] ) a0 = 1; - if( nopush[name]==0 ) a1 = 2; - if( out2_prerelease[name] ) a2 = 4; - if( in1[name] ) a3 = 8; - if( in2[name] ) a4 = 16; - if( in3[name] ) a5 = 32; - if( out2[name] ) a6 = 64; - if( out3[name] ) a7 = 128; - bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15; + if( out2_prerelease[name] ) a1 = 2; + if( in1[name] ) a2 = 4; + if( in2[name] ) a3 = 8; + if( in3[name] ) a4 = 16; + if( out2[name] ) a5 = 32; + if( out3[name] ) a6 = 64; + # bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15; + bv[x] = a0+a1+a2+a3+a4+a5+a6; } print "\n" print "/* Properties such as \"out2\" or \"jump\" that are specified in" print "** comments following the \"case\" for each opcode in the vdbe.c" print "** are encoded into bitvectors as follows:" print "*/" print "#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */" - print "#define OPFLG_PUSH 0x0002 /* ~no-push: Does not push */" - print "#define OPFLG_OUT2_PRERELEASE 0x0004 /* out2-prerelease: */" - print "#define OPFLG_IN1 0x0008 /* in1: P1 is an input */" - print "#define OPFLG_IN2 0x0010 /* in2: P2 is an input */" - print "#define OPFLG_IN3 0x0020 /* in3: P3 is an input */" - print "#define OPFLG_OUT2 0x0040 /* out2: P2 is an output */" - print "#define OPFLG_OUT3 0x0080 /* out3: P3 is an output */" + print "#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */" + print "#define OPFLG_IN1 0x0004 /* in1: P1 is an input */" + print "#define OPFLG_IN2 0x0008 /* in2: P2 is an input */" + print "#define OPFLG_IN3 0x0010 /* in3: P3 is an input */" + print "#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */" + print "#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */" print "#define OPFLG_INITIALIZER {\\" for(i=0; i<=max; i++){ if( i%8==0 ) printf("/* %3d */",i) - printf " 0x%04x,", bv[i] + printf " 0x%02x,", bv[i] if( i%8==7 ) printf("\\\n"); } print "}" } Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.39 2008/01/04 22:01:03 drh Exp $ +** $Id: alter.c,v 1.40 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" #include /* @@ -351,11 +351,11 @@ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto exit_rename_table; } sqlite3BeginWriteOperation(pParse, isVirtualRename, iDb); - sqlite3ChangeCookie(db, v, iDb); + sqlite3ChangeCookie(pParse, iDb); /* If this is a virtual table, invoke the xRename() function if ** one is defined. The xRename() callback will modify the names ** of any resources used by the v-table implementation (including other ** SQLite tables) that are identified by the name of the virtual table. @@ -619,12 +619,12 @@ /* Begin a transaction and increment the schema cookie. */ sqlite3BeginWriteOperation(pParse, 0, iDb); v = sqlite3GetVdbe(pParse); if( !v ) goto exit_begin_add_column; - sqlite3ChangeCookie(db, v, iDb); + sqlite3ChangeCookie(pParse, iDb); exit_begin_add_column: sqlite3SrcListDelete(pSrc); return; } #endif /* SQLITE_ALTER_TABLE */ Index: src/attach.c ================================================================== --- src/attach.c +++ src/attach.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.68 2008/01/12 19:03:49 drh Exp $ +** $Id: attach.c,v 1.69 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_ATTACH /* @@ -325,11 +325,11 @@ pParse->nErr++; goto attach_end; } v = sqlite3GetVdbe(pParse); - regArgs = sqlite3GetTempRange(pParse, nFunc); + regArgs = sqlite3GetTempRange(pParse, 3); sqlite3ExprCode(pParse, pFilename, regArgs); sqlite3ExprCode(pParse, pDbname, regArgs+1); sqlite3ExprCode(pParse, pKey, regArgs+2); assert( v || db->mallocFailed ); Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -20,11 +20,11 @@ ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.466 2008/01/17 02:36:28 drh Exp $ +** $Id: build.c,v 1.467 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" #include /* @@ -1275,13 +1275,17 @@ ** the schema to change multiple times and for the cookie to be ** set back to prior value. But schema changes are infrequent ** and the probability of hitting the same cookie value is only ** 1 chance in 2^32. So we're safe enough. */ -void sqlite3ChangeCookie(sqlite3 *db, Vdbe *v, int iDb){ - sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, 0); - sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 0); +void sqlite3ChangeCookie(Parse *pParse, int iDb){ + int r1 = sqlite3GetTempReg(pParse); + sqlite3 *db = pParse->db; + Vdbe *v = pParse->pVdbe; + sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 0, r1); + sqlite3ReleaseTempReg(pParse, r1); } /* ** Measure the number of characters needed to output the given ** identifier. The number returned includes any quotes used @@ -1542,11 +1546,11 @@ pParse->regRoot, zStmt, pParse->regRowid ); sqlite3_free(zStmt); - sqlite3ChangeCookie(db, v, iDb); + sqlite3ChangeCookie(pParse, iDb); #ifndef SQLITE_OMIT_AUTOINCREMENT /* Check to see if we need to create an sqlite_sequence table for ** keeping track of autoincrement keys. */ @@ -2064,11 +2068,11 @@ */ if( IsVirtual(pTab) ){ sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0); } sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); - sqlite3ChangeCookie(db, v, iDb); + sqlite3ChangeCookie(pParse, iDb); } sqliteViewResetAll(db, iDb); exit_drop_table: sqlite3SrcListDelete(pName); @@ -2686,11 +2690,11 @@ /* Fill the index with data and reparse the schema. Code an OP_Expire ** to invalidate all pre-compiled statements. */ if( pTblName ){ sqlite3RefillIndex(pParse, pIndex, iMem); - sqlite3ChangeCookie(db, v, iDb); + sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(db, "name='%q'", pIndex->zName), P4_DYNAMIC); sqlite3VdbeAddOp1(v, OP_Expire, 0); } } @@ -2838,11 +2842,11 @@ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName ); - sqlite3ChangeCookie(db, v, iDb); + sqlite3ChangeCookie(pParse, iDb); destroyRootPage(pParse, pIndex->tnum, iDb); sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); } exit_drop_index: Index: src/delete.c ================================================================== --- src/delete.c +++ src/delete.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** 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.158 2008/01/17 02:36:28 drh Exp $ +** $Id: delete.c,v 1.159 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, @@ -315,11 +315,10 @@ */ if( triggers_exist ){ sqlite3VdbeResolveLabel(v, addr); } addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end); - sqlite3VdbeAddOp1(v, OP_StackDepth, -1); if( triggers_exist ){ int iData = ++pParse->nMem; /* For storing row data of OLD table */ /* If the record is no longer present in the table, jump to the @@ -456,16 +455,19 @@ int iCur, /* Cursor number for the table */ int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ ){ int i; Index *pIdx; + int r1; + r1 = sqlite3GetTempReg(pParse); for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue; - sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0); - sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, 0); + sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1); + sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, r1); } + sqlite3ReleaseTempReg(pParse, r1); } /* ** Generate code that will assemble an index key and put it on the top ** of the tack. The key with be for index pIdx which is an index on pTab. Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.346 2008/01/17 02:36:28 drh Exp $ +** $Id: expr.c,v 1.347 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" #include /* @@ -1846,11 +1846,11 @@ return out; } /* ** Generate an instruction that will put the floating point -** value described by z[0..n-1] on the stack. +** value described by z[0..n-1] into register iMem. ** ** The z[] string will probably not be zero-terminated. But the ** z[n] character is guaranteed to be something that does not look ** like the continuation of the number. */ @@ -1868,11 +1868,11 @@ } /* ** Generate an instruction that will put the integer describe by -** text z[0..n-1] on the stack. +** text z[0..n-1] into register iMem. ** ** The z[] string will probably not be zero-terminated. But the ** z[n] character is guaranteed to be something that does not look ** like the continuation of the number. */ @@ -1898,12 +1898,12 @@ } /* ** Generate code that will extract the iColumn-th column from -** table pTab and store the column value in register iMem, or on -** the stack if iMem==0. There is an open cursor to pTab in +** table pTab and store the column value in register iReg. +** There is an open cursor to pTab in ** iTable. If iColumn<0 then code is generated that extracts the rowid. */ void sqlite3ExprCodeGetColumn( Vdbe *v, /* The VM being created */ Table *pTab, /* Description of the table we are reading from */ @@ -1946,11 +1946,11 @@ int regFree1 = 0; /* If non-zero free this temporary register */ int regFree2 = 0; /* If non-zero free this temporary register */ int r1, r2, r3; /* Various register numbers */ assert( v!=0 || pParse->db->mallocFailed ); - assert( target>=0 ); + assert( target>0 && target<=pParse->nMem ); if( v==0 ) return 0; if( pExpr==0 ){ op = TK_NULL; }else{ @@ -2415,15 +2415,17 @@ ** Generate code that will evaluate expression pExpr and store the ** results in register target. The results are guaranteed to appear ** in register target. */ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ - int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); + int inReg; + + assert( target>0 && target<=pParse->nMem ); + inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); assert( pParse->pVdbe || pParse->db->mallocFailed ); if( inReg!=target && pParse->pVdbe ){ - sqlite3VdbeAddOp2(pParse->pVdbe, (inReg>0 ? OP_SCopy : OP_Move), - inReg, target); + sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); } return target; } /* @@ -2459,34 +2461,30 @@ } /* ** Generate code that pushes the value of every element of the given -** expression list onto the stack if target==0 or into a sequence of -** registers beginning at target. +** expression list into a sequence of registers beginning at target. ** ** Return the number of elements evaluated. */ int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* The expression list to be coded */ int target /* Where to write results */ ){ struct ExprList_item *pItem; - int i, n, incr = 1; + int i, n; assert( pList!=0 || pParse->db->mallocFailed ); if( pList==0 ){ return 0; } - assert( target>=0 ); + assert( target>0 ); n = pList->nExpr; - if( target==0 ){ - incr = 0; - } for(pItem=pList->a, i=n; i>0; i--, pItem++){ sqlite3ExprCode(pParse, pItem->pExpr, target); - target += incr; + target++; } return n; } /* Index: src/insert.c ================================================================== --- src/insert.c +++ src/insert.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.224 2008/01/17 02:36:28 drh Exp $ +** $Id: insert.c,v 1.225 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" /* ** Set P4 of the most recently inserted opcode to a column affinity @@ -665,11 +665,10 @@ sqlite3VdbeAddOp2(v, OP_Rewind, srcTab, iBreak); iCont = sqlite3VdbeCurrentAddr(v); }else if( pSelect ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); sqlite3VdbeResolveLabel(v, iInsertBlock); - sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0); } /* Allocate registers for holding the rowid of the new row, ** the content of the new row, and the assemblied row record. */ Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.167 2008/01/17 02:36:28 drh Exp $ +** $Id: pragma.c,v 1.168 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" #include /* Ignore this whole file if pragmas are disabled @@ -250,11 +250,11 @@ int iDb; /* Database index for */ sqlite3 *db = pParse->db; Db *pDb; Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); if( v==0 ) return; - pParse->nMem = 1; + pParse->nMem = 2; /* Interpret the [database.] part of the pragma statement. iDb is the ** index of the database this pragma is being applied to in db.aDb[]. */ iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); if( iDb<0 ) return; @@ -319,16 +319,16 @@ sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE); }else{ int size = atoi(zRight); if( size<0 ) size = -size; sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3VdbeAddOp1(v, OP_Integer, size); - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 0, 2); - addr = sqlite3VdbeAddOp2(v, OP_IfPos, 0, 0); - sqlite3VdbeAddOp1(v, OP_Integer, -size); + sqlite3VdbeAddOp2(v, OP_Integer, size, 1); + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 2, 2); + addr = sqlite3VdbeAddOp2(v, OP_IfPos, 2, 0); + sqlite3VdbeAddOp2(v, OP_Integer, -size, 1); sqlite3VdbeJumpHere(v, addr); - sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 2); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 2, 1); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } }else @@ -1107,12 +1107,12 @@ if( zRight && iDb>=0 ){ /* Write the specified cookie value */ static const VdbeOpList setCookie[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ - { OP_Integer, 0, 0, 0}, /* 1 */ - { OP_SetCookie, 0, 0, 0}, /* 2 */ + { OP_Integer, 0, 1, 0}, /* 1 */ + { OP_SetCookie, 0, 0, 1}, /* 2 */ }; int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+1, atoi(zRight)); sqlite3VdbeChangeP1(v, addr+2, iDb); Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.403 2008/01/17 02:36:28 drh Exp $ +** $Id: select.c,v 1.404 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" /* @@ -581,28 +581,33 @@ /* In this mode, write each query result to the key of the temporary ** table iParm. */ #ifndef SQLITE_OMIT_COMPOUND_SELECT case SRT_Union: { - sqlite3VdbeAddOp2(v, OP_MakeRecord, iMem, nColumn); + int r1; + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1); if( aff ){ sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC); } - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); + sqlite3ReleaseTempReg(pParse, r1); break; } /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. */ case SRT_Except: { - int addr; - addr = sqlite3VdbeAddOp2(v, OP_MakeRecord, iMem, nColumn); + int addr, r1; + r1 = sqlite3GetTempReg(pParse); + addr = sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1); sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC); - sqlite3VdbeAddOp2(v, OP_NotFound, iParm, addr+3); - sqlite3VdbeAddOp2(v, OP_Delete, iParm, 0); + sqlite3VdbeAddOp3(v, OP_NotFound, iParm, addr+3, r1); + sqlite3VdbeAddOp1(v, OP_Delete, iParm); + sqlite3ReleaseTempReg(pParse, r1); break; } #endif /* Store the result as data using a unique key. @@ -2065,10 +2070,11 @@ int tab1, tab2; int iCont, iBreak, iStart; Expr *pLimit, *pOffset; int addr; SelectDest intersectdest; + int r1; /* INTERSECT is different from the others since it requires ** two temporary tables. Hence it has its own case. Begin ** by allocating the tables we will need. */ @@ -2125,12 +2131,14 @@ } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); - iStart = sqlite3VdbeAddOp1(v, OP_RowKey, tab1); - sqlite3VdbeAddOp2(v, OP_NotFound, tab2, iCont); + r1 = sqlite3GetTempReg(pParse); + iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); + sqlite3VdbeAddOp3(v, OP_NotFound, tab2, iCont, r1); + sqlite3ReleaseTempReg(pParse, r1); rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, pOrderBy, -1, &dest, iCont, iBreak, 0); if( rc ){ rc = 1; goto multi_select_end; Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.650 2008/01/17 02:36:28 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.651 2008/01/17 16:22:15 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* @@ -1817,11 +1817,11 @@ void sqlite3RegisterBuiltinFunctions(sqlite3*); void sqlite3RegisterDateTimeFunctions(sqlite3*); int sqlite3SafetyOn(sqlite3*); int sqlite3SafetyOff(sqlite3*); int sqlite3SafetyCheck(sqlite3*); -void sqlite3ChangeCookie(sqlite3*, Vdbe*, int); +void sqlite3ChangeCookie(Parse*, int); #ifndef SQLITE_OMIT_TRIGGER void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, Expr*,int, int); void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); Index: src/trigger.c ================================================================== --- src/trigger.c +++ src/trigger.c @@ -238,11 +238,11 @@ sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrig->name, pTrig->table, z); sqlite3_free(z); - sqlite3ChangeCookie(db, v, iDb); + sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf( db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC ); } @@ -536,11 +536,11 @@ sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(pParse, iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); sqlite3VdbeChangeP4(v, base+1, pTrigger->name, 0); sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC); - sqlite3ChangeCookie(db, v, iDb); + sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp2(v, OP_Close, 0, 0); sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->name, 0); } } Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.168 2008/01/17 02:36:28 drh Exp $ +** $Id: update.c,v 1.169 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ @@ -399,11 +399,10 @@ sqlite3VdbeResolveLabel(v, addr); } /* Top of the update loop */ addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0); - sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0); if( triggers_exist ){ int regRowid; int regRow; int regCols; Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -20,17 +20,17 @@ ** ** The SQL parser generates a program which is then executed by ** the VDBE to do the work of the SQL statement. VDBE programs are ** similar in form to assembly language. The program consists of ** a linear sequence of operations. Each operation has an opcode -** and 3 operands. Operands P1 and P2 are integers. Operand P4 -** is a null-terminated string. The P2 operand must be non-negative. -** Opcodes will typically ignore one or more operands. Many opcodes -** ignore all three operands. +** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4 +** is a null-terminated string. Operand P5 is an unsigned character. +** Few opcodes use all 5 operands. ** -** Computation results are stored on a stack. Each entry on the -** stack is either an integer, a null-terminated string, a floating point +** Computation results are stored on a set of registers numbered beginning +** with 1 and going up to Vdbe.nMem. Each register can store +** either an integer, a null-terminated string, a floating point ** number, or the SQL "NULL" value. An inplicit conversion from one ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqlite3VdbeExec() ** function which does the work of interpreting a VDBE program. @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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.697 2008/01/17 02:36:28 drh Exp $ +** $Id: vdbe.c,v 1.698 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" #include #include "vdbeInt.h" @@ -83,11 +83,11 @@ int sqlite3_sort_count = 0; #endif /* ** The next global variable records the size of the largest MEM_Blob -** or MEM_Str that has appeared on the VDBE stack. The test procedures +** or MEM_Str that has been used by a VDBE opcode. The test procedures ** use this information to make sure that the zero-blob functionality ** is working correctly. This variable has no function other than to ** help verify the correct operation of the library. */ #ifdef SQLITE_TEST @@ -105,17 +105,17 @@ #else # define UPDATE_MAX_BLOBSIZE(P) #endif /* -** Release the memory associated with the given stack level. This +** Release the memory associated with a register. This ** leaves the Mem.flags field in an inconsistent state. */ #define Release(P) if((P)->flags&MEM_Dyn){ sqlite3VdbeMemRelease(P); } /* -** Convert the given stack entity into a string if it isn't one +** Convert the given register into a string if it isn't one ** already. Return non-zero if a malloc() fails. */ #define Stringify(P, enc) \ if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \ { goto no_mem; } @@ -138,16 +138,16 @@ #define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B)) /* ** An ephemeral string value (signified by the MEM_Ephem flag) contains ** a pointer to a dynamically allocated string where some other entity -** is responsible for deallocating that string. Because the stack entry -** does not control the string, it might be deleted without the stack -** entry knowing it. +** is responsible for deallocating that string. Because the register +** does not control the string, it might be deleted without the register +** knowing it. ** ** This routine converts an ephemeral string into a dynamically allocated -** string that the stack entry itself controls. In other words, it +** string that the register itself controls. In other words, it ** converts an MEM_Ephem string into an MEM_Dyn string. */ #define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} @@ -157,14 +157,14 @@ ** P if required. */ #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0) /* -** Argument pMem points at a memory cell that will be passed to a +** Argument pMem points at a regiser that will be passed to a ** user-defined function or returned to the user as the result of a query. ** The second argument, 'db_enc' is the text encoding used by the vdbe for -** stack variables. This routine sets the pMem->enc and pMem->type +** register variables. This routine sets the pMem->enc and pMem->type ** variables used by the sqlite3_value_*() routines. */ #define storeTypeInfo(A,B) _storeTypeInfo(A) static void _storeTypeInfo(Mem *pMem){ int flags = pMem->flags; @@ -188,11 +188,11 @@ ** Properties of opcodes. The OPFLG_INITIALIZER macro is ** created by mkopcodeh.awk during compilation. Data is obtained ** from the comments following the "case OP_xxxx:" statements in ** this file. */ -static unsigned short opcodeProperty[] = OPFLG_INITIALIZER; +static unsigned char opcodeProperty[] = OPFLG_INITIALIZER; /* ** Return true if an opcode has any of the OPFLG_xxx properties ** specified by mask. */ @@ -199,23 +199,10 @@ int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){ assert( opcode>0 && opcode0 ){ - N--; - Release(pTos); - pTos--; - } - *ppTos = pTos; -} - /* ** Allocate cursor number iCur. Return a pointer to it. Return NULL ** if we run out of memory. */ static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){ @@ -509,42 +496,32 @@ int pc; /* The program counter */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 encoding = ENC(db); /* The database encoding */ - Mem *pTos; /* Top entry in the operand stack */ Mem *pIn1, *pIn2, *pIn3; /* Input operands */ Mem *pOut; /* Output operand */ - int nPop = 0; /* Number of times to pop the stack */ u8 opProperty; #ifdef VDBE_PROFILE unsigned long long start; /* CPU clock count at start of opcode */ int origPc; /* Program counter at start of opcode */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif -#ifndef NDEBUG - Mem *pStackLimit; -#endif if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; assert( db->magic==SQLITE_MAGIC_BUSY ); - pTos = p->pTos; sqlite3BtreeMutexArrayEnter(&p->aMutex); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; assert( p->explain==0 ); - if( p->popStack ){ - popStack(&pTos, p->popStack); - p->popStack = 0; - } p->pResultSet = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); #ifdef SQLITE_DEBUG @@ -562,11 +539,10 @@ p->trace = stdout; } #endif for(pc=p->pc; rc==SQLITE_OK; pc++){ assert( pc>=0 && pcnOp ); - assert( pTos<=&p->aStack[pc] ); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE origPc = pc; start = hwtime(); #endif @@ -622,38 +598,21 @@ } nProgressOps++; } #endif -#ifndef NDEBUG - /* This is to check to make sure that the OPFLG_PUSH property - ** is set correctly on all opcodes. - */ - pStackLimit = pTos; - if( sqlite3VdbeOpcodeHasProperty(pOp->opcode, OPFLG_PUSH) ){ - pStackLimit++; - } - assert( pTos>=&p->aStack[-1] && pTos<=pStackLimit ); -#endif - /* Do common setup processing for any opcode that is marked ** with the "out2-prerelease" tag. Such opcodes have a single - ** output which is specified by the P2 parameter. The output - ** is normally written into the P2-th register. But if P2==0 - ** then the output is pushed onto the stack. The P2 operand + ** output which is specified by the P2 parameter. The P2 register ** is initialized to a NULL. */ opProperty = opcodeProperty[pOp->opcode]; if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){ - assert( pOp->p2>=0 ); - if( pOp->p2==0 ){ - pOut = ++pTos; - }else{ - assert( pOp->p2<=p->nMem ); - pOut = &p->aMem[pOp->p2]; - sqlite3VdbeMemRelease(pOut); - } + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; + sqlite3VdbeMemRelease(pOut); pOut->flags = MEM_Null; }else /* Do common setup for opcodes marked with one of the following ** combinations of properties. @@ -662,95 +621,48 @@ ** in1 in2 ** in1 in2 out3 ** in1 in3 ** in1 out2 ** - ** Variables pIn1 and pIn2 are made to point to the first two - ** inputs and pOut points to the output. Variable nPop holds the - ** number of times that the stack should be popped after the - ** the instruction. - */ - if( (opProperty & OPFLG_IN1)!=0 ){ - assert( pOp->p1>=0 ); - if( pOp->p1==0 ){ - pIn1 = pTos; - nPop = 1; - }else{ - assert( pOp->p1<=p->nMem ); - pIn1 = &p->aMem[pOp->p1]; - REGISTER_TRACE(pOp->p1, pIn1); - } - if( (opProperty & OPFLG_IN2)!=0 ){ - assert( pOp->p2>=0 ); - if( pOp->p2==0 ){ - pIn2 = &pTos[-nPop]; - nPop++; - }else{ - assert( pOp->p2<=p->nMem ); - pIn2 = &p->aMem[pOp->p2]; - REGISTER_TRACE(pOp->p2, pIn2); - } - if( (opProperty & OPFLG_OUT3)!=0 ){ - assert( pOp->p3>=0 ); - if( pOp->p3==0 ){ - nPop--; - if( nPop<0 ){ - assert( nPop==(-1) ); - pTos++; - nPop = 0; - } - pOut = &pTos[-nPop]; - }else{ - assert( pOp->p3<=p->nMem ); - pOut = &p->aMem[pOp->p3]; - } - } - }else if( (opProperty & OPFLG_IN3)!=0 ){ - assert( pOp->p3>=0 ); - if( pOp->p3==0 ){ - pIn3 = &pTos[-nPop]; - nPop++; - }else{ - assert( pOp->p3<=p->nMem ); - pIn3 = &p->aMem[pOp->p3]; - REGISTER_TRACE(pOp->p3, pIn3); - } - }else if( (opProperty & OPFLG_OUT2)!=0 ){ - assert( pOp->p2>=0 ); - if( pOp->p2==0 ){ - nPop--; - if( nPop<0 ){ - assert( nPop==(-1) ); - pTos++; - nPop = 0; - } - pOut = &pTos[-nPop]; - }else{ - assert( pOp->p2<=p->nMem ); - pOut = &p->aMem[pOp->p2]; - } - } - }else if( (opProperty & OPFLG_IN2)!=0 ){ - assert( pOp->p2>=0 ); - if( pOp->p2==0 ){ - pIn2 = pTos; - nPop = 1; - }else{ - assert( pOp->p2<=p->nMem ); - pIn2 = &p->aMem[pOp->p2]; - REGISTER_TRACE(pOp->p2, pIn2); - } - }else if( (opProperty & OPFLG_IN3)!=0 ){ - assert( pOp->p3>=0 ); - if( pOp->p3==0 ){ - pIn3 = pTos; - nPop = 1; - }else{ - assert( pOp->p3<=p->nMem ); - pIn3 = &p->aMem[pOp->p3]; - REGISTER_TRACE(pOp->p3, pIn3); - } + ** Variables pIn1, pIn2, and pIn3 are made to point to appropriate + ** registers for inputs. Variable pOut points to the output register. + */ + if( (opProperty & OPFLG_IN1)!=0 ){ + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + REGISTER_TRACE(pOp->p1, pIn1); + if( (opProperty & OPFLG_IN2)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pIn2 = &p->aMem[pOp->p2]; + REGISTER_TRACE(pOp->p2, pIn2); + if( (opProperty & OPFLG_OUT3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=p->nMem ); + pOut = &p->aMem[pOp->p3]; + } + }else if( (opProperty & OPFLG_IN3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=p->nMem ); + pIn3 = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pIn3); + }else if( (opProperty & OPFLG_OUT2)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; + } + }else if( (opProperty & OPFLG_IN2)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pIn2 = &p->aMem[pOp->p2]; + REGISTER_TRACE(pOp->p2, pIn2); + }else if( (opProperty & OPFLG_IN3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=p->nMem ); + pIn3 = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pIn3); } switch( pOp->opcode ){ /***************************************************************************** @@ -769,14 +681,14 @@ ** opcode and the opcodes.c file is filled with an array of strings where ** each string is the symbolic name for the corresponding opcode. If the ** case statement is followed by a comment of the form "/# same as ... #/" ** that comment is used to determine the particular value of the opcode. ** -** If a comment on the same line as the "case OP_" construction contains -** the word "no-push", then the opcode is guarenteed not to grow the -** vdbe stack when it is executed. See function opcode() in -** vdbeaux.c for details. +** Other keywords in the comment that follows each case are used to +** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[]. +** Keywords include: in1, in2, in3, out2_prerelease, out2, out3. See +** the mkopcodeh.awk script for additional information. ** ** Documentation about VDBE opcodes is generated by scanning this file ** for lines of that contain "Opcode:". That line and all subsequent ** comment lines are used in the generation of the opcode.html documentation ** file. @@ -786,54 +698,54 @@ ** Formatting is important to scripts that scan this file. ** Do not deviate from the formatting style currently in use. ** *****************************************************************************/ -/* Opcode: Goto * P2 * +/* Opcode: Goto * P2 * * * ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. */ -case OP_Goto: { /* no-push, jump */ +case OP_Goto: { /* jump */ CHECK_FOR_INTERRUPT; pc = pOp->p2 - 1; break; } -/* Opcode: Gosub * P2 * +/* Opcode: Gosub * P2 * * * ** ** Push the current address plus 1 onto the return address stack ** and then jump to address P2. ** ** The return address stack is of limited depth. If too many ** OP_Gosub operations occur without intervening OP_Returns, then ** the return address stack will fill up and processing will abort ** with a fatal error. */ -case OP_Gosub: { /* no-push, jump */ +case OP_Gosub: { /* jump */ assert( p->returnDepthreturnStack)/sizeof(p->returnStack[0]) ); p->returnStack[p->returnDepth++] = pc+1; pc = pOp->p2 - 1; break; } -/* Opcode: Return * * * +/* Opcode: Return * * * * * ** ** Jump immediately to the next instruction after the last unreturned ** OP_Gosub. If an OP_Return has occurred for all OP_Gosubs, then ** processing aborts with a fatal error. */ -case OP_Return: { /* no-push */ +case OP_Return: { assert( p->returnDepth>0 ); p->returnDepth--; pc = p->returnStack[p->returnDepth] - 1; break; } -/* Opcode: Halt P1 P2 P4 +/* Opcode: Halt P1 P2 * P4 * ** ** Exit immediately. All open cursors, Fifos, etc are closed ** automatically. ** ** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), @@ -848,12 +760,11 @@ ** ** There is an implied "Halt 0 0 0" instruction inserted at the very end of ** every program. So a jump past the last instruction of the program ** is the same as executing Halt. */ -case OP_Halt: { /* no-push */ - p->pTos = pTos; +case OP_Halt: { p->rc = pOp->p1; p->pc = pc; p->errorAction = pOp->p2; if( pOp->p4.z ){ sqlite3SetString(&p->zErrMsg, pOp->p4.z, (char*)0); @@ -866,37 +777,13 @@ rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; } goto vdbe_return; } -/* Opcode: StackDepth P1 * * -** -** If P1 is less than zero, then store the current stack depth -** in P1. If P1 is zero or greater, verify that the current stack -** depth is equal to P1 and throw an exception if it is not. -** -** This opcode is used for internal consistency checking. -*/ -case OP_StackDepth: { /* no-push */ - int n = pTos - p->aStack + 1; - if( pOp->p1<0 ){ - pOp->p1 = n; - }else if( pOp->p1!=n ){ - p->pTos = pTos; - p->rc = rc = SQLITE_INTERNAL; - p->pc = pc; - p->errorAction = OE_Rollback; - sqlite3SetString(&p->zErrMsg, "internal error: VDBE stack leak", (char*)0); - goto vdbe_return; - } - break; -} - /* Opcode: Integer P1 P2 * * * ** -** The 32-bit integer value P1 is written into register P2, or -** pushed onto the stack if P2==0. +** The 32-bit integer value P1 is written into register P2. */ case OP_Integer: { /* out2-prerelease */ pOut->flags = MEM_Int; pOut->u.i = pOp->p1; break; @@ -903,11 +790,11 @@ } /* Opcode: Int64 * P2 * P4 * ** ** P4 is a pointer to a 64-bit integer value. -** Write that value into register P2 or push onto the stack if P2 is 0. +** Write that value into register P2. */ case OP_Int64: { /* out2-prerelease */ assert( pOp->p4.pI64!=0 ); pOut->flags = MEM_Int; pOut->u.i = *pOp->p4.pI64; @@ -915,11 +802,11 @@ } /* Opcode: Real * P2 * P4 * ** ** P4 is a pointer to a 64-bit floating point value. -** Write that value into register P2 or push onto the stack if P2 is 0. +** Write that value into register P2. */ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ pOut->flags = MEM_Real; pOut->r = *pOp->p4.pReal; break; @@ -961,12 +848,11 @@ /* Fall through to the next case, OP_String */ } /* Opcode: String P1 P2 * P4 * ** -** The string value P4 of length P1 (bytes) is stored in register P2 -** or is pushed onto the stack if P2==0. +** The string value P4 of length P1 (bytes) is stored in register P2. */ case OP_String: { /* out2-prerelease */ assert( pOp->p4.z!=0 ); pOut->flags = MEM_Str|MEM_Static|MEM_Term; pOut->z = pOp->p4.z; @@ -976,12 +862,11 @@ break; } /* Opcode: Null * P2 * * * ** -** Write a NULL into register P2 or push a NULL onto the stack -** if P2==0. +** Write a NULL into register P2. */ case OP_Null: { /* out2-prerelease */ break; } @@ -988,11 +873,11 @@ #ifndef SQLITE_OMIT_BLOB_LITERAL /* Opcode: HexBlob * P2 * P4 * ** ** P4 is an UTF-8 SQL hex encoding of a blob. The blob is stored in -** register P2 or pushed onto the stack if P2 is zero. +** register P2. ** ** The first time this instruction executes, in transforms itself into a ** 'Blob' opcode with a binary blob as P4. */ case OP_HexBlob: { /* same as TK_BLOB, out2-prerelease */ @@ -1038,12 +923,11 @@ } #endif /* SQLITE_OMIT_BLOB_LITERAL */ /* Opcode: Variable P1 P2 * * * ** -** The value of variable P1 is written into register P2 or pushed -** onto the stack if P2 is zero. A variable is +** The value of variable P1 is written into register P2. A variable is ** an unknown in the original SQL string as handed to sqlite3_compile(). ** Any occurance of the '?' character in the original SQL is considered ** a variable. Variables in the SQL string are number from left to ** right beginning with 1. The values of variables are set using the ** sqlite3_bind() API. @@ -1062,44 +946,24 @@ break; } /* Opcode: Move P1 P2 * * * ** -** Move the value in P1 into P2. If P1 is positive then read from the -** P1-th register. If P1 is zero or negative read from the stack. -** When P1 is 0 read from the top the stack. When P1 is -1 read from -** the next entry down on the stack. And so forth. -** -** If P2 is zero, push the new value onto the top of the stack. -** If P2 is positive, write into the P2-th register. -** -** If P1 is zero then the stack is popped once. The stack is -** unchanged for all other values of P1. The P1 value contains -** a NULL after this operation. +** Move the value in register P1 over into register P2. Register P1 +** is left holding a NULL. It is an error for P1 and P2 to be the +** same register. */ /* Opcode: Copy P1 P2 * * * ** -** Make a copy of P1 into P2. If P1 is positive then read from the -** P1-th register. If P1 is zero or negative read from the stack. -** When P1 is 0 read from the top the stack. When P1 is -1 read from -** the next entry down on the stack. And so forth. -** -** If P2 is zero, push the new value onto the top of the stack. -** If P2 is positive, write into the P2-th register. +** Make a copy of register P1 into register P2. ** ** This instruction makes a deep copy of the value. A duplicate ** is made of any string or blob constant. See also OP_SCopy. */ /* Opcode: SCopy P1 P2 * * * ** -** Make a shallow copy of P1 into P2. If P1 is positive then read from the -** P1-th register. If P1 is zero or negative read from the stack. -** When P1 is 0 read from the top the stack. When P1 is -1 read from -** the next entry down on the stack. And so forth. -** -** If P2 is zero, push the new value onto the top of the stack. -** If P2 is positive, write into the P2-th register. +** Make a shallow copy of register P1 into register P2. ** ** This instruction makes a shallow copy of the value. If the value ** is a string or blob, then the copy is only a pointer to the ** original and hence if the original changes so will the copy. ** Worse, if the original is deallocated, the copy becomes invalid. @@ -1108,30 +972,20 @@ ** copy. */ case OP_Move: case OP_Copy: case OP_SCopy: { - if( pOp->p1<=0 ){ - pIn1 = &pTos[pOp->p1]; - assert( pIn1>=p->aStack ); - }else{ - assert( pOp->p1<=p->nMem ); - pIn1 = &p->aMem[pOp->p1]; - REGISTER_TRACE(pOp->p1, pIn1); - } - assert( pOp->p2>=0 ); - if( pOp->p2==0 ){ - pOut = ++pTos; - pOut->flags = MEM_Null; - }else{ - assert( pOp->p2<=p->nMem ); - pOut = &p->aMem[pOp->p2]; - } + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + REGISTER_TRACE(pOp->p1, pIn1); + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; assert( pOut!=pIn1 ); if( pOp->opcode==OP_Move ){ rc = sqlite3VdbeMemMove(pOut, pIn1); - if( pOp->p1==0 ) pTos--; }else{ Release(pOut); sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); if( pOp->opcode==OP_Copy ){ Deephemeralize(pOut); @@ -1139,37 +993,25 @@ } REGISTER_TRACE(pOp->p2, pOut); break; } -/* Opcode: ResultRow P1 P2 * +/* Opcode: ResultRow P1 P2 * * * ** ** The registers P1 throught P1+P2-1 contain a single row of ** results. This opcode causes the sqlite3_step() call to terminate ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt ** structure to provide access to the top P1 values as the result -** row. When the sqlite3_step() function is run again, the top P1 -** values will be automatically popped from the stack before the next -** instruction executes. +** row. */ -case OP_ResultRow: { /* no-push */ +case OP_ResultRow: { Mem *pMem; int i; assert( p->nResColumn==pOp->p2 ); assert( pOp->p1>0 ); assert( pOp->p1+pOp->p2<=p->nMem ); - /* Data in the pager might be moved or changed out from under us - ** in between the return from this sqlite3_step() call and the - ** next call to sqlite3_step(). So deephermeralize everything on - ** the stack. Note that ephemeral data is never stored in memory - ** cells so we do not have to worry about them. - */ - for(pMem = p->aStack; pMem<=pTos; pMem++){ - Deephemeralize(pMem); - } - /* Invalidate all ephemeral cursor row caches */ p->cacheCtr = (p->cacheCtr + 2)|1; /* Make sure the results of the current row are \000 terminated ** and have an assigned type. The results are deephemeralized as @@ -1182,13 +1024,11 @@ } /* Return SQLITE_ROW */ p->nCallback++; - p->popStack = 0; p->pc = pc + 1; - p->pTos = pTos; rc = SQLITE_ROW; goto vdbe_return; } /* Opcode: Concat P1 P2 P3 * * @@ -1247,17 +1087,17 @@ ** ** Subtract the value in P1 from the value in P2 and store the result ** in P3. ** If either operand is NULL, the result is NULL. */ -/* Opcode: Divide * * * +/* Opcode: Divide P1 P2 P3 * * ** ** Divide the value in P1 by the value in P2 and store the result ** in P3. If the value in P2 is zero, then the result is NULL. ** If either operand is NULL, the result is NULL. */ -/* Opcode: Remainder * * * +/* Opcode: Remainder P1 P2 P3 * * ** ** Compute the remainder after integer division of the value in ** register P1 by the value in register P2 and store the result in P3. ** If the value in register P2 is zero the result is NULL. ** If either operand is NULL, the result is NULL. @@ -1352,21 +1192,20 @@ ** ** The interface used by the implementation of the aforementioned functions ** to retrieve the collation sequence set by this opcode is not available ** publicly, only to user functions defined in func.c. */ -case OP_CollSeq: { /* no-push */ +case OP_CollSeq: { assert( pOp->p4type==P4_COLLSEQ ); break; } /* Opcode: Function P1 P2 P3 P4 P5 ** ** Invoke a user function (P4 is a pointer to a Function structure that ** defines the function) with P5 arguments taken from register P2 and -** successors, or if P2==0 from the stack. The result of the function -** is stored in register P3 or on the stack if P3==0. +** successors. The result of the function is stored in register P3. ** ** P1 is a 32-bit bitmask indicating whether or not each argument to the ** function was determined to be constant at compile time. If the first ** argument was constant then bit 0 of P1 is set. This is used to determine ** whether meta data associated with a user function argument using the @@ -1383,15 +1222,12 @@ int n = pOp->p5; apVal = p->apArg; assert( apVal || n==0 ); - if( pOp->p2==0 ){ - pArg = &pTos[1-n]; - }else{ - pArg = &p->aMem[pOp->p2]; - } + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem) ); + pArg = &p->aMem[pOp->p2]; for(i=0; ip2, pArg); } @@ -1430,13 +1266,10 @@ ** misusing sqlite, they have bigger problems than a leaked value. */ sqlite3VdbeMemRelease(&ctx.s); goto no_mem; } - if( pOp->p2==0 ){ - popStack(&pTos, n); - } /* If any auxilary data functions have been called by this user function, ** immediately call the destructor for any non-static values. */ if( ctx.pVdbeFunc ){ @@ -1449,17 +1282,14 @@ if( ctx.isError ){ sqlite3SetString(&p->zErrMsg, sqlite3_value_text(&ctx.s), (char*)0); rc = SQLITE_ERROR; } - /* Copy the result of the function to the top of the stack */ + /* Copy the result of the function into register P3 */ sqlite3VdbeChangeEncoding(&ctx.s, encoding); - if( pOp->p3==0 ){ - pOut = ++pTos; - }else{ - pOut = &p->aMem[pOp->p3]; - } + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + pOut = &p->aMem[pOp->p3]; sqlite3VdbeMemMove(pOut, &ctx.s); if( sqlite3VdbeMemTooBig(pOut) ){ goto too_big; } REGISTER_TRACE(pOp->p3, pOut); @@ -1524,12 +1354,11 @@ ** Add P2 the value in register P1. ** The result is always an integer. ** ** To force any register to be an integer, just add 0. */ -case OP_AddImm: { /* no-push, in1 */ - nPop = 0; +case OP_AddImm: { /* in1 */ sqlite3VdbeMemIntegerify(pIn1); pIn1->u.i += pOp->p2; break; } @@ -1541,18 +1370,17 @@ ** jump to P2. If the value in P1 is numeric then ** convert it into the least integer that is greater than or equal to its ** current value if P3==0, or to the least integer that is strictly ** greater than its current value if P3==1. */ -case OP_ForceInt: { /* no-push, jump, in1 */ +case OP_ForceInt: { /* jump, in1 */ i64 v; applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); if( (pIn1->flags & (MEM_Int|MEM_Real))==0 ){ pc = pOp->p2 - 1; break; } - nPop = 0; if( pIn1->flags & MEM_Int ){ v = pIn1->u.i + (pOp->p3!=0); }else{ assert( pIn1->flags & MEM_Real ); v = (sqlite3_int64)pIn1->r; @@ -1563,33 +1391,24 @@ pIn1->u.i = v; pIn1->flags = MEM_Int; break; } -/* Opcode: MustBeInt P1 P2 P3 +/* Opcode: MustBeInt P1 P2 * * * ** -** Force the value in register P1 to be an integer. If P1==0 then -** use the top of the stack. If the value in P1 -** is not an integer and cannot be converted into an integer +** Force the value in register P1 to be an integer. If the value +** in P1 is not an integer and cannot be converted into an integer ** without data loss, then jump immediately to P2, or if P2==0 ** raise an SQLITE_MISMATCH exception. -** -** If the P1==0 and the top of the stack is not an integer -** and P2 is not zero and P3 is 1, then the stack is popped. -** In all other cases, the depth of the stack is unchanged. */ -case OP_MustBeInt: { /* no-push, jump, in1 */ - nPop = 0; +case OP_MustBeInt: { /* jump, in1 */ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); if( (pIn1->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ - if( pOp->p3 && pOp->p1==0 ){ - popStack(&pTos, 1); - } pc = pOp->p2 - 1; } }else{ Release(pIn1); pIn1->flags = MEM_Int; @@ -1604,12 +1423,11 @@ ** This opcode is used when extracting information from a column that ** has REAL affinity. Such column values may still be stored as ** integers, for space efficiency, but after extraction we want them ** to have only a real value. */ -case OP_RealAffinity: { /* no-push, in1 */ - nPop = 0; +case OP_RealAffinity: { /* in1 */ if( pIn1->flags & MEM_Int ){ sqlite3VdbeMemRealify(pIn1); } break; } @@ -1622,12 +1440,11 @@ ** equivalent of printf(). Blob values are unchanged and ** are afterwards simply interpreted as text. ** ** A NULL value is not changed by this routine. It remains NULL. */ -case OP_ToText: { /* same as TK_TO_TEXT, no-push, in1 */ - nPop = 0; +case OP_ToText: { /* same as TK_TO_TEXT, in1 */ if( pIn1->flags & MEM_Null ) break; assert( MEM_Str==(MEM_Blob>>3) ); pIn1->flags |= (pIn1->flags&MEM_Blob)>>3; applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); rc = ExpandBlob(pIn1); @@ -1644,12 +1461,11 @@ ** Strings are simply reinterpreted as blobs with no change ** to the underlying data. ** ** A NULL value is not changed by this routine. It remains NULL. */ -case OP_ToBlob: { /* same as TK_TO_BLOB, no-push, in1 */ - nPop = 0; +case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */ if( pIn1->flags & MEM_Null ) break; if( (pIn1->flags & MEM_Blob)==0 ){ applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); assert( pIn1->flags & MEM_Str ); pIn1->flags |= MEM_Blob; @@ -1667,12 +1483,11 @@ ** equivalent of atoi() or atof() and store 0 if no such conversion ** is possible. ** ** A NULL value is not changed by this routine. It remains NULL. */ -case OP_ToNumeric: { /* same as TK_TO_NUMERIC, no-push, in1 */ - nPop = 0; +case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */ if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){ sqlite3VdbeMemNumerify(pIn1); } break; } @@ -1685,12 +1500,11 @@ ** If the value is text or blob, try to convert it to an integer using the ** equivalent of atoi() and store 0 if no such conversion is possible. ** ** A NULL value is not changed by this routine. It remains NULL. */ -case OP_ToInt: { /* same as TK_TO_INT, no-push, in1 */ - nPop = 0; +case OP_ToInt: { /* same as TK_TO_INT, in1 */ if( (pIn1->flags & MEM_Null)==0 ){ sqlite3VdbeMemIntegerify(pIn1); } break; } @@ -1703,12 +1517,11 @@ ** If the value is text or blob, try to convert it to an integer using the ** equivalent of atoi() and store 0 if no such conversion is possible. ** ** A NULL value is not changed by this routine. It remains NULL. */ -case OP_ToReal: { /* same as TK_TO_REAL, no-push, in1 */ - nPop = 0; +case OP_ToReal: { /* same as TK_TO_REAL, in1 */ if( (pIn1->flags & MEM_Null)==0 ){ sqlite3VdbeMemRealify(pIn1); } break; } @@ -1744,57 +1557,53 @@ ** strings and strings are considered less than blobs. ** ** If the SQLITE_STOREP2 bit of P5 is set, then do not jump. Instead, ** store a boolean result (either 0, or 1, or NULL) in register P2. */ -/* Opcode: Ne P1 P2 P4 +/* Opcode: Ne P1 P2 P3 P4 P5 ** ** This works just like the Lt opcode except that the jump is taken if ** the operands in registers P1 and P3 are not equal. See the Lt opcode for ** additional information. */ -/* Opcode: Eq P1 P2 P4 +/* Opcode: Eq P1 P2 P3 P4 P5 ** ** This works just like the Lt opcode except that the jump is taken if ** the operands in registers P1 and P3 are equal. ** See the Lt opcode for additional information. */ -/* Opcode: Le P1 P2 P4 +/* Opcode: Le P1 P2 P3 P4 P5 ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is less than or equal to the content of ** register P1. See the Lt opcode for additional information. */ -/* Opcode: Gt P1 P2 P4 +/* Opcode: Gt P1 P2 P3 P4 P5 ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is greater than the content of ** register P1. See the Lt opcode for additional information. */ -/* Opcode: Ge P1 P2 P4 +/* Opcode: Ge P1 P2 P3 P4 P5 ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is greater than or equal to the content of ** register P1. See the Lt opcode for additional information. */ -case OP_Eq: /* same as TK_EQ, no-push, jump, in1, in3 */ -case OP_Ne: /* same as TK_NE, no-push, jump, in1, in3 */ -case OP_Lt: /* same as TK_LT, no-push, jump, in1, in3 */ -case OP_Le: /* same as TK_LE, no-push, jump, in1, in3 */ -case OP_Gt: /* same as TK_GT, no-push, jump, in1, in3 */ -case OP_Ge: { /* same as TK_GE, no-push, jump, in1, in3 */ +case OP_Eq: /* same as TK_EQ, jump, in1, in3 */ +case OP_Ne: /* same as TK_NE, jump, in1, in3 */ +case OP_Lt: /* same as TK_LT, jump, in1, in3 */ +case OP_Le: /* same as TK_LE, jump, in1, in3 */ +case OP_Gt: /* same as TK_GT, jump, in1, in3 */ +case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ int flags; int res; char affinity; Mem x1, x3; flags = pIn1->flags|pIn3->flags; - /* If either value is a NULL P2 is not zero, take the jump if the least - ** significant byte of P1 is true. If P2 is zero, then push a NULL onto - ** the stack. - */ if( flags&MEM_Null ){ if( (pOp->p5 & SQLITE_NULLEQUAL)!=0 ){ /* ** When SQLITE_NULLEQUAL set and either operand is NULL ** then both operands are converted to integers prior to being @@ -1911,12 +1720,11 @@ ** ** Interpret the value in register P1 as a boolean value. Replace it ** with its complement. If the value in register P1 is NULL its value ** is unchanged. */ -case OP_Not: { /* same as TK_NOT, no-push, in1 */ - nPop = 0; +case OP_Not: { /* same as TK_NOT, in1 */ if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */ sqlite3VdbeMemIntegerify(pIn1); pIn1->u.i = !pIn1->u.i; assert( pIn1->flags==MEM_Int ); break; @@ -1926,12 +1734,11 @@ ** ** Interpret the content of register P1 as an integer. Replace it ** with its ones-complement. If the value is originally NULL, leave ** it unchanged. */ -case OP_BitNot: { /* same as TK_BITNOT, no-push, in1 */ - nPop = 0; +case OP_BitNot: { /* same as TK_BITNOT, in1 */ if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */ sqlite3VdbeMemIntegerify(pIn1); pIn1->u.i = ~pIn1->u.i; assert( pIn1->flags==MEM_Int ); break; @@ -1947,11 +1754,11 @@ ** is to say when the EXPLAIN QUERY PLAN syntax is used.) ** This opcode records information from the optimizer. It is the ** the same as a no-op. This opcodesnever appears in a real VM program. */ case OP_Explain: -case OP_Noop: { /* no-push */ +case OP_Noop: { break; } /* Opcode: If P1 P2 P3 * * ** @@ -1963,12 +1770,12 @@ ** ** Jump to P2 if the value in register P1 is False. The value is ** 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_If: /* no-push, jump, in1 */ -case OP_IfNot: { /* no-push, jump, in1 */ +case OP_If: /* jump, in1 */ +case OP_IfNot: { /* jump, in1 */ int c; if( pIn1->flags & MEM_Null ){ c = pOp->p3; }else{ #ifdef SQLITE_OMIT_FLOATING_POINT @@ -1987,15 +1794,12 @@ /* Opcode: IsNull P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is NULL. If P3 is greater ** than zero, then check all values reg(P1), reg(P1+1), ** reg(P1+2), ..., reg(P1+P3-1). -** -** If P1 is 0 then use the top of the stack instead of a register -** and pop the stack regardless of whether or not the jump is taken. */ -case OP_IsNull: { /* same as TK_ISNULL, no-push, jump, in1 */ +case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ int n = pOp->p3; assert( pOp->p3==0 || pOp->p1>0 ); do{ if( (pIn1->flags & MEM_Null)!=0 ){ pc = pOp->p2 - 1; @@ -2007,15 +1811,12 @@ } /* Opcode: NotNull P1 P2 * * * ** ** Jump to P2 if the value in register P1 is not NULL. -** -** If P1 is 0 then use the top of the stack instead of a register -** and pop the stack regardless of whether or not the jump is taken. */ -case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump, in1 */ +case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ if( (pIn1->flags & MEM_Null)==0 ){ pc = pOp->p2 - 1; } break; } @@ -2028,11 +1829,11 @@ ** This opcode sets the number of columns for cursor P1 to P2. ** ** If OP_KeyAsData is to be applied to cursor P1, it must be executed ** before this op-code. */ -case OP_SetNumColumns: { /* no-push */ +case OP_SetNumColumns: { Cursor *pC; assert( (pOp->p1)nCursor ); assert( p->apCsr[pOp->p1]!=0 ); pC = p->apCsr[pOp->p1]; pC->nField = pOp->p2; @@ -2045,13 +1846,11 @@ ** the MakeRecord instruction. (See the MakeRecord opcode for additional ** information about the format of the data.) Extract the P2-th column ** from this record. If there are less that (P2+1) ** values in the record, extract a NULL. ** -** The value extracted is pushed onto the stack. Or if P3 is a positive -** non-zero integer register number, then the value is written into that -** register. +** The value extracted is stored in register P3. ** ** If the KeyAsData opcode has previously executed on this cursor, then the ** field might be extracted from the key rather than the data. ** ** If the column contains fewer than P2 fields, then extract a NULL. Or, @@ -2074,15 +1873,12 @@ Mem *pDest; /* Where to write the extracted value */ Mem sMem; /* For storing the record being decoded */ sMem.flags = 0; assert( p1nCursor ); - if( pOp->p3>0 ){ - pDest = &p->aMem[pOp->p3]; - }else{ - pDest = ++pTos; - } + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + pDest = &p->aMem[pOp->p3]; sqlite3VdbeMemSetNull(pDest); /* This block sets the variable payloadSize to be the total number of ** bytes in the record. ** @@ -2091,13 +1887,11 @@ ** If the record is stored in a cursor, the complete record text ** might be available in the pC->aRow cache. Or it might not be. ** If the data is unavailable, zRec is set to NULL. ** ** We also compute the number of columns in the record. For cursors, - ** the number of columns is stored in the Cursor.nField element. For - ** records on the stack, the next entry down on the stack is an integer - ** which is the number of records. + ** the number of columns is stored in the Cursor.nField element. */ pC = p->apCsr[p1]; assert( pC!=0 ); #ifndef SQLITE_OMIT_VIRTUALTABLE assert( pC->pVtabCursor==0 ); @@ -2134,11 +1928,11 @@ payloadSize = 0; pCrsr = 0; nField = 0; } - /* If payloadSize is 0, then just push a NULL onto the stack. */ + /* If payloadSize is 0, then just store a NULL */ if( payloadSize==0 ){ assert( pDest->flags==MEM_Null ); goto op_column_out; } if( payloadSize>SQLITE_MAX_LENGTH ){ @@ -2225,12 +2019,12 @@ offset += sqlite3VdbeSerialTypeLen(aType[i]); }else{ /* If i is less that nField, then there are less fields in this ** record than SetNumColumns indicated there are columns in the ** table. Set the offset for any extra columns not present in - ** the record to 0. This tells code below to push a NULL onto the - ** stack instead of deserializing a value from the record. + ** the record to 0. This tells code below to store a NULL + ** instead of deserializing a value from the record. */ aOffset[i] = 0; } } Release(&sMem); @@ -2308,12 +2102,11 @@ ** records. Refer to source code comments for the details of the record ** format. ** ** P4 may be a string that is P1 characters long. The nth character of the ** string indicates the column affinity that should be used for the nth -** field of the index key (i.e. the first character of P4 corresponds to the -** lowest element on the stack). +** field of the index key. ** ** The mapping from character to affinity is given by the SQLITE_AFF_ ** macros defined in sqliteInt.h. ** ** If P4 is NULL then all index fields have the affinity NONE. @@ -2324,12 +2117,12 @@ ** ** ------------------------------------------------------------------------ ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | ** ------------------------------------------------------------------------ ** - ** Data(0) is taken from the lowest element of the stack and data(N-1) is - ** the top of the stack. + ** Data(0) is taken from register P1. Data(1) comes from register P1+1 + ** and so froth. ** ** Each type field is a varint representing the serial type of the ** corresponding data element (see sqlite3VdbeSerialType()). The ** hdr-size field is also a varint which is the offset from the beginning ** of the record to data0. @@ -2411,16 +2204,13 @@ for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */ i += sqlite3VdbeSerialPut(&zNewRecord[i], nByte-i, pRec, file_format); } assert( i==nByte ); - if( pOp->p3==0 ){ - pOut = ++pTos; - }else{ - pOut = &p->aMem[pOp->p3]; - Release(pOut); - } + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + pOut = &p->aMem[pOp->p3]; + Release(pOut); pOut->n = nByte; if( nByte<=sizeof(zTemp) ){ assert( zNewRecord==(unsigned char *)zTemp ); pOut->z = pOut->zShort; memcpy(pOut->zShort, zTemp, nByte); @@ -2451,11 +2241,11 @@ ** ** The statement is begun on the database file with index P1. The main ** database file has an index of 0 and the file used for temporary tables ** has an index of 1. */ -case OP_Statement: { /* no-push */ +case OP_Statement: { int i = pOp->p1; Btree *pBt; if( i>=0 && inDb && (pBt = db->aDb[i].pBt)!=0 && (db->autoCommit==0 || db->activeVdbeCnt>1) ){ assert( sqlite3BtreeIsInTrans(pBt) ); @@ -2474,11 +2264,11 @@ ** back any currently active btree transactions. If there are any active ** VMs (apart from this one), then the COMMIT or ROLLBACK statement fails. ** ** This instruction causes the VM to halt. */ -case OP_AutoCommit: { /* no-push */ +case OP_AutoCommit: { u8 i = pOp->p1; u8 rollback = pOp->p2; assert( i==1 || i==0 ); assert( i==1 || rollback==0 ); @@ -2499,11 +2289,10 @@ sqlite3RollbackAll(db); db->autoCommit = 1; }else{ db->autoCommit = i; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pTos = pTos; p->pc = pc; db->autoCommit = 1-i; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } @@ -2543,11 +2332,11 @@ ** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained ** on the file. ** ** If P2 is zero, then a read-lock is obtained on the database file. */ -case OP_Transaction: { /* no-push */ +case OP_Transaction: { int i = pOp->p1; Btree *pBt; assert( i>=0 && inDb ); assert( (p->btreeMask & (1<p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; - p->pTos = pTos; goto vdbe_return; } if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){ goto abort_due_to_error; } @@ -2568,12 +2356,11 @@ break; } /* Opcode: ReadCookie P1 P2 P3 * * ** -** Read cookie number P3 from database P1 and write it into register -** P2 or push it onto the stack if P2==0. +** Read cookie number P3 from database P1 and write it into register P2. ** P3==0 is the schema version. P3==1 is the database format. ** P3==2 is the recommended pager cache size, and so forth. P1==0 is ** the main database file and P1==1 is the database file used to store ** temporary tables. ** @@ -2621,11 +2408,11 @@ ** the main database file and P1==1 is the database file used to store ** temporary tables. ** ** A transaction must be started before executing this opcode. */ -case OP_SetCookie: { /* no-push, in3 */ +case OP_SetCookie: { /* in3 */ Db *pDb; assert( pOp->p2p1>=0 && pOp->p1nDb ); assert( (p->btreeMask & (1<p1))!=0 ); pDb = &db->aDb[pOp->p1]; @@ -2663,11 +2450,11 @@ ** ** Either a transaction needs to have been started or an OP_Open needs ** to be executed (to establish a read lock) before this opcode is ** invoked. */ -case OP_VerifyCookie: { /* no-push */ +case OP_VerifyCookie: { int iMeta; Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); assert( (p->btreeMask & (1<p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; @@ -2744,12 +2531,12 @@ ** in read/write mode. For a given table, there can be one or more read-only ** cursors or a single read/write cursor but not both. ** ** See also OpenRead. */ -case OP_OpenRead: /* no-push */ -case OP_OpenWrite: { /* no-push */ +case OP_OpenRead: +case OP_OpenWrite: { int i = pOp->p1; int p2 = pOp->p2; int iDb = pOp->p3; int wrFlag; Btree *pX; @@ -2768,22 +2555,15 @@ } }else{ wrFlag = 0; } if( pOp->p5 ){ - if( p2==0 ){ - assert( pTos>=p->aStack ); - sqlite3VdbeMemIntegerify(pTos); - p2 = pTos->u.i; - assert( (pTos->flags & MEM_Dyn)==0 ); - pTos--; - }else{ - assert( p2<=p->nMem ); - pIn2 = &p->aMem[p2]; - sqlite3VdbeMemIntegerify(pIn2); - p2 = pIn2->u.i; - } + assert( p2>0 ); + assert( p2<=p->nMem ); + pIn2 = &p->aMem[p2]; + sqlite3VdbeMemIntegerify(pIn2); + p2 = pIn2->u.i; assert( p2>=2 ); } assert( i>=0 ); pCur = allocateCursor(p, i, iDb); if( pCur==0 ) goto no_mem; @@ -2804,11 +2584,10 @@ } switch( rc ){ case SQLITE_BUSY: { p->pc = pc; p->rc = rc = SQLITE_BUSY; - p->pTos = &pTos[(pOp->p2<=0)]; /* Operands must remain on stack */ goto vdbe_return; } case SQLITE_OK: { int flags = sqlite3BtreeFlags(pCur->pCursor); /* Sanity checking. Only the lower four bits of the flags byte should @@ -2863,11 +2642,11 @@ ** confusion because the term "temp table", might refer either ** to a TEMP table at the SQL level, or to a table opened by ** this opcode. Then this opcode was call OpenVirtual. But ** that created confusion with the whole virtual-table idea. */ -case OP_OpenEphemeral: { /* no-push */ +case OP_OpenEphemeral: { int i = pOp->p1; Cursor *pCx; static const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | @@ -2924,11 +2703,11 @@ ** A pseudo-table created by this opcode is useful for holding the ** NEW or OLD tables in a trigger. Also used to hold the a single ** row output from the sorter so that the row can be decomposed into ** individual columns using the OP_Column opcode. */ -case OP_OpenPseudo: { /* no-push */ +case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); pCx = allocateCursor(p, i, -1); if( pCx==0 ) goto no_mem; @@ -2943,11 +2722,11 @@ /* Opcode: Close P1 * * * * ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. */ -case OP_Close: { /* no-push */ +case OP_Close: { int i = pOp->p1; if( i>=0 && inCursor ){ sqlite3VdbeFreeCursor(p, p->apCsr[i]); p->apCsr[i] = 0; } @@ -2962,44 +2741,44 @@ ** If there are no records greater than or equal to the key and P2 ** is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe */ -/* Opcode: MoveGt P1 P2 * +/* Opcode: MoveGt P1 P2 P3 * * ** ** Use the value in register P3 as a key. Reposition ** cursor P1 so that it points to the smallest entry that is greater ** than the key in register P3. ** If there are no records greater than the key and P2 is not zero, ** then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe */ -/* Opcode: MoveLt P1 P2 * +/* Opcode: MoveLt P1 P2 P3 * * ** ** Use the value in register P3 as a key. Reposition ** cursor P1 so that it points to the largest entry that is less ** than the key in register P3. ** If there are no records less than the key and P2 is not zero, ** then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe */ -/* Opcode: MoveLe P1 P2 * +/* Opcode: MoveLe P1 P2 P3 * * ** ** Use the value in register P3 as a key. Reposition ** cursor P1 so that it points to the largest entry that is less than ** or equal to the key. ** If there are no records less than or eqal to the key and P2 is not zero, ** then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt */ -case OP_MoveLt: /* no-push, jump, in3 */ -case OP_MoveLe: /* no-push, jump, in3 */ -case OP_MoveGe: /* no-push, jump, in3 */ -case OP_MoveGt: { /* no-push, jump, in3 */ +case OP_MoveLt: /* jump, in3 */ +case OP_MoveLe: /* jump, in3 */ +case OP_MoveGe: /* jump, in3 */ +case OP_MoveGt: { /* jump, in3 */ int i = pOp->p1; Cursor *pC; assert( i>=0 && inCursor ); pC = p->apCsr[i]; @@ -3070,12 +2849,12 @@ } /* Opcode: Found P1 P2 P3 * * ** ** Register P3 holds a blob constructed by MakeRecord. P1 is an index. -** If an entry that matches the top of the stack exists in P1 then -** jump to P2. If the top of the stack does not match any entry in P1 +** If an entry that matches the value in register p3 exists in P1 then +** jump to P2. If the P3 value does not match any entry in P1 ** then fall thru. The P1 cursor is left pointing at the matching entry ** if it exists. ** ** This instruction is used to implement the IN operator where the ** left-hand side is a SELECT statement. P1 may be a true index, or it @@ -3083,29 +2862,26 @@ ** statement. This instruction is also used to implement the ** DISTINCT keyword in SELECT statements. ** ** This instruction checks if index P1 contains a record for which ** the first N serialised values exactly match the N serialised values -** in the record on the stack, where N is the total number of values in -** the stack record (stack record is a prefix of the P1 record). +** in the record in register P3, where N is the total number of values in +** the P3 record (the P3 record is a prefix of the P1 record). ** ** See also: NotFound, MoveTo, IsUnique, NotExists */ /* Opcode: NotFound P1 P2 P3 * * ** ** Register P3 holds a blob constructed by MakeRecord. P1 is ** an index. If no entry exists in P1 that matches the blob then jump ** to P2. If an entry does existing, fall through. The cursor is left -** pointing to the entry that matches. The blob is popped from the stack. +** pointing to the entry that matches. ** -** The difference between this operation and Distinct is that -** Distinct does not pop the key from the stack. -** -** See also: Distinct, Found, MoveTo, NotExists, IsUnique +** See also: Found, MoveTo, NotExists, IsUnique */ -case OP_NotFound: /* no-push, jump, in3 */ -case OP_Found: { /* no-push, jump, in3 */ +case OP_NotFound: /* jump, in3 */ +case OP_Found: { /* jump, in3 */ int i = pOp->p1; int alreadyExists = 0; Cursor *pC; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); @@ -3149,28 +2925,24 @@ ** jump to P2. If any entry does exist where the index string ** matches K but the record number is not R, then the record ** number for that entry is written into P3 and control ** falls through to the next instruction. ** -** See also: Distinct, NotFound, NotExists, Found +** See also: NotFound, NotExists, Found */ -case OP_IsUnique: { /* no-push, jump, in3 */ +case OP_IsUnique: { /* jump, in3 */ int i = pOp->p1; Cursor *pCx; BtCursor *pCrsr; Mem *pK; i64 R; /* Pop the value R off the top of the stack */ assert( pOp->p4type==P4_INT32 ); - if( pOp->p4.i==0 ){ - assert( pOp->p3==0 ); - pK = &pIn3[-1]; - }else{ - pK = &p->aMem[pOp->p4.i]; - } + assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem ); + pK = &p->aMem[pOp->p4.i]; sqlite3VdbeMemIntegerify(pIn3); R = pIn3->u.i; assert( (pIn3->flags & MEM_Dyn)==0 ); assert( i>=0 && inCursor ); pCx = p->apCsr[i]; @@ -3228,38 +3000,35 @@ if( v==R ){ pc = pOp->p2 - 1; break; } - /* The final varint of the key is different from R. Push it onto - ** the stack. (The record number of an entry that violates a UNIQUE - ** constraint.) + /* The final varint of the key is different from R. Store it back + ** into register R3. (The record number of an entry that violates + ** a UNIQUE constraint.) */ - nPop = 0; pIn3->u.i = v; assert( pIn3->flags==MEM_Int ); } break; } -/* Opcode: NotExists P1 P2 P3 +/* Opcode: NotExists P1 P2 P3 * * ** -** Use the top of the stack as a integer key. Or, if P3 is non-zero, -** use the contents of register P3 as an integer key. If a record +** Use the content of register P3 as a integer key. If a record ** with that key does not exist in table of P1, then jump to P2. ** If the record does exist, then fall thru. The cursor is left -** pointing to the record if it exists. The integer key is popped -** from the stack if P3==0. +** pointing to the record if it exists. ** ** The difference between this operation and NotFound is that this ** operation assumes the key is an integer and that P1 is a table whereas ** NotFound assumes key is a blob constructed from MakeRecord and ** P1 is an index. ** -** See also: Distinct, Found, MoveTo, NotFound, IsUnique +** See also: Found, MoveTo, NotFound, IsUnique */ -case OP_NotExists: { /* no-push, jump, in3 */ +case OP_NotExists: { /* jump, in3 */ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); @@ -3288,12 +3057,11 @@ } /* Opcode: Sequence P1 P2 * * * ** ** Find the next available sequence number for cursor P1. -** Write the sequence number into register P2, or push it onto -** the stack if P2==0. +** Write the sequence number into register P2. ** The sequence number on the cursor is incremented after this ** instruction. */ case OP_Sequence: { /* out2-prerelease */ int i = pOp->p1; @@ -3307,12 +3075,12 @@ /* Opcode: NewRowid P1 P2 P3 * * ** ** Get a new integer record number (a.k.a "rowid") used as the key to a table. ** The record number is not previously used as a key in the database -** table that cursor P1 points to. The new record number is pushed -** onto the stack if P2 is 0 or written to register P2 otherwise. +** table that cursor P1 points to. The new record number is written +** written to register P2. ** ** If P3>0 then P3 is a register that holds the largest previously ** generated record number. No new record numbers are allowed to be less ** than this value. When this value reaches its maximum, a SQLITE_FULL ** error is generated. The P3 register is updated with the generated @@ -3484,11 +3252,11 @@ ** cause any problems.) ** ** This instruction only works on tables. The equivalent instruction ** for indices is OP_IdxInsert. */ -case OP_Insert: { /* no-push */ +case OP_Insert: { Mem *pData = &p->aMem[pOp->p2]; Mem *pKey = &p->aMem[pOp->p3]; int i = pOp->p1; Cursor *pC; @@ -3572,11 +3340,11 @@ ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is ** incremented (otherwise not). ** ** If P1 is a pseudo-table, then this instruction is a no-op. */ -case OP_Delete: { /* no-push */ +case OP_Delete: { int i = pOp->p1; Cursor *pC; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); @@ -3622,11 +3390,11 @@ ** This opcode resets the VMs internal change counter to 0. If P1 is true, ** then the value of the change counter is copied to the database handle ** change counter (returned by subsequent calls to sqlite3_changes()) ** before it is reset. This is used by trigger programs. */ -case OP_ResetCount: { /* no-push */ +case OP_ResetCount: { if( pOp->p1 ){ sqlite3VdbeSetChanges(db, p->nChange); } p->nChange = 0; break; @@ -3644,11 +3412,11 @@ */ /* Opcode: RowKey P1 P2 * * * ** ** Write into register P2 the complete row key for cursor P1. ** There is no interpretation of the data. -** It is just copied onto the stack or into the memory cell exactly as +** The key is copied onto the P3 register exactly as ** it is found in the database file. ** ** If the cursor is not pointing to a valid row, a NULL is ** written into P2. */ @@ -3746,17 +3514,17 @@ pOut->u.i = v; pOut->flags = MEM_Int; break; } -/* Opcode: NullRow P1 * * +/* Opcode: NullRow P1 * * * * ** ** Move the cursor P1 to a null row. Any OP_Column operations -** that occur while the cursor is on the null row will always push -** a NULL onto the stack. +** that occur while the cursor is on the null row will always +** write a NULL. */ -case OP_NullRow: { /* no-push */ +case OP_NullRow: { int i = pOp->p1; Cursor *pC; assert( i>=0 && inCursor ); pC = p->apCsr[i]; @@ -3764,19 +3532,19 @@ pC->nullRow = 1; pC->rowidIsValid = 0; break; } -/* Opcode: Last P1 P2 * +/* Opcode: Last P1 P2 * * * ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the last entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ -case OP_Last: { /* no-push, jump */ +case OP_Last: { /* jump */ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( i>=0 && inCursor ); @@ -3796,11 +3564,11 @@ } break; } -/* Opcode: Sort P1 P2 * +/* Opcode: Sort P1 P2 * * * ** ** This opcode does exactly the same thing as OP_Rewind except that ** it increments an undocumented global variable used for testing. ** ** Sorting is accomplished by writing records into a sorting index, @@ -3808,26 +3576,26 @@ ** end. We use the OP_Sort opcode instead of OP_Rewind to do the ** rewinding so that the global variable will be incremented and ** regression tests can determine whether or not the optimizer is ** correctly optimizing out sorts. */ -case OP_Sort: { /* no-push, jump */ +case OP_Sort: { /* jump */ #ifdef SQLITE_TEST sqlite3_sort_count++; sqlite3_search_count--; #endif /* Fall through into OP_Rewind */ } -/* Opcode: Rewind P1 P2 * +/* Opcode: Rewind P1 P2 * * * ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ -case OP_Rewind: { /* no-push, jump */ +case OP_Rewind: { /* jump */ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; int res; @@ -3847,28 +3615,28 @@ pc = pOp->p2 - 1; } break; } -/* Opcode: Next P1 P2 * +/* Opcode: Next P1 P2 * * * ** ** Advance cursor P1 so that it points to the next key/data pair in its ** table or index. If there are no more key/value pairs then fall through ** to the following instruction. But if the cursor advance was successful, ** jump immediately to P2. ** ** See also: Prev */ -/* Opcode: Prev P1 P2 * +/* Opcode: Prev P1 P2 * * * ** ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. */ -case OP_Prev: /* no-push, jump */ -case OP_Next: { /* no-push, jump */ +case OP_Prev: /* jump */ +case OP_Next: { /* jump */ Cursor *pC; BtCursor *pCrsr; CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1nCursor ); @@ -3898,11 +3666,11 @@ } pC->rowidIsValid = 0; break; } -/* Opcode: IdxInsert P1 P2 P3 +/* Opcode: IdxInsert P1 P2 P3 * * ** ** Register P2 holds a SQL index key made using the ** MakeIdxRec instructions. This opcode writes that key ** into the index P1. Data for the entry is nil. ** @@ -3910,11 +3678,11 @@ ** insert is likely to be an append. ** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ -case OP_IdxInsert: { /* no-push, in2 */ +case OP_IdxInsert: { /* in2 */ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); @@ -3931,16 +3699,16 @@ } } break; } -/* Opcode: IdxDelete P1 P2 * +/* Opcode: IdxDelete P1 P2 * * * ** ** The content of register P2 is an index key built using the either the ** MakeIdxRec opcode. Removes that entry from the index. */ -case OP_IdxDelete: { /* no-push, in2 */ +case OP_IdxDelete: { /* in2 */ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pIn2->flags & MEM_Blob ); assert( i>=0 && inCursor ); @@ -4028,13 +3796,13 @@ ** If P5 is non-zero then the ** index taken from register P3 is temporarily increased by ** an epsilon prior to the comparison. This makes the opcode work ** like IdxLE. */ -case OP_IdxLT: /* no-push, jump, in3 */ -case OP_IdxGT: /* no-push, jump, in3 */ -case OP_IdxGE: { /* no-push, jump, in3 */ +case OP_IdxLT: /* jump, in3 */ +case OP_IdxGT: /* jump, in3 */ +case OP_IdxGE: { /* jump, in3 */ int i= pOp->p1; Cursor *pC; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); @@ -4074,11 +3842,11 @@ ** ** If AUTOVACUUM is enabled then it is possible that another root page ** might be moved into the newly deleted root page in order to keep all ** root pages contiguous at the beginning of the database. The former ** value of the root page that moved - its value before the move occurred - -** is stored in register P2 or pushed onto the stack if P2==0. If no page +** is stored in register P2. If no page ** movement was required (because the table being dropped was already ** the last one in the database) then a zero is stored in register P2. ** If AUTOVACUUM is disabled then a zero is stored in register P2. ** ** See also: Clear @@ -4126,11 +3894,11 @@ ** P2==1 then the table to be clear is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** ** See also: Destroy */ -case OP_Clear: { /* no-push */ +case OP_Clear: { assert( (p->btreeMask & (1<p2))!=0 ); rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1); break; } @@ -4137,11 +3905,11 @@ /* Opcode: CreateTable P1 P2 * * * ** ** Allocate a new table in the main database file if P1==0 or in the ** auxiliary database file if P1==1 or in an attached database if ** P1>1. Write the root page number of the new table into -** register P2 or push it onto the stack if P2==0. +** register P2 ** ** The difference between a table and an index is this: A table must ** have a 4-byte integer key and can have arbitrary data. An index ** has an arbitrary key but no data. ** @@ -4150,11 +3918,11 @@ /* Opcode: CreateIndex P1 P2 * * * ** ** Allocate a new index in the main database file if P1==0 or in the ** auxiliary database file if P1==1 or in an attached database if ** P1>1. Write the root page number of the new table into -** register P2 or push it onto the stack if P2==0. +** register P2. ** ** See documentation on OP_CreateTable for additional information. */ case OP_CreateIndex: /* out2-prerelease */ case OP_CreateTable: { /* out2-prerelease */ @@ -4189,11 +3957,11 @@ ** schema is already loaded into the symbol table. ** ** This opcode invokes the parser to create a new virtual machine, ** then runs the new virtual machine. It is thus a reentrant opcode. */ -case OP_ParseSchema: { /* no-push */ +case OP_ParseSchema: { char *zSql; int iDb = pOp->p1; const char *zMaster; InitData initData; @@ -4229,11 +3997,11 @@ ** ** Read the sqlite_stat1 table for database P1 and load the content ** of that table into the internal index hash table. This will cause ** the analysis to be used when preparing all subsequent queries. */ -case OP_LoadAnalysis: { /* no-push */ +case OP_LoadAnalysis: { int iDb = pOp->p1; assert( iDb>=0 && iDbnDb ); rc = sqlite3AnalysisLoad(db, iDb); break; } @@ -4244,11 +4012,11 @@ ** Remove the internal (in-memory) data structures that describe ** the table named P4 in database P1. This is called after a table ** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ -case OP_DropTable: { /* no-push */ +case OP_DropTable: { sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z); break; } /* Opcode: DropIndex P1 * * P4 * @@ -4256,11 +4024,11 @@ ** Remove the internal (in-memory) data structures that describe ** the index named P4 in database P1. This is called after an index ** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ -case OP_DropIndex: { /* no-push */ +case OP_DropIndex: { sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z); break; } /* Opcode: DropTrigger P1 * * P4 * @@ -4268,11 +4036,11 @@ ** Remove the internal (in-memory) data structures that describe ** the trigger named P4 in database P1. This is called after a trigger ** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ -case OP_DropTrigger: { /* no-push */ +case OP_DropTrigger: { sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z); break; } @@ -4343,11 +4111,11 @@ /* Opcode: FifoWrite P1 * * * * ** ** Write the integer from register P1 into the Fifo. */ -case OP_FifoWrite: { /* no-push, in1 */ +case OP_FifoWrite: { /* in1 */ if( sqlite3VdbeFifoPush(&p->sFifo, sqlite3VdbeIntValue(pIn1))==SQLITE_NOMEM ){ goto no_mem; } break; } @@ -4376,11 +4144,11 @@ ** ** Save the current Vdbe context such that it can be restored by a ContextPop ** opcode. The context stores the last insert row id, the last statement change ** count, and the current statement change count. */ -case OP_ContextPush: { /* no-push */ +case OP_ContextPush: { int i = p->contextStackTop++; Context *pContext; assert( i>=0 ); /* FIX ME: This should be allocated as part of the vdbe at compile-time */ @@ -4402,11 +4170,11 @@ ** ** Restore the Vdbe context to the state it was in when contextPush was last ** executed. The context stores the last insert row id, the last statement ** change count, and the current statement change count. */ -case OP_ContextPop: { /* no-push */ +case OP_ContextPop: { Context *pContext = &p->contextStack[--p->contextStackTop]; assert( p->contextStackTop>=0 ); db->lastRowid = pContext->lastRowid; p->nChange = pContext->nChange; sqlite3VdbeFifoClear(&p->sFifo); @@ -4422,17 +4190,16 @@ ** and the value in register P2. ** ** This instruction throws an error if the memory cell is not initially ** an integer. */ -case OP_MemMax: { /* no-push, in1, in2 */ +case OP_MemMax: { /* in1, in2 */ sqlite3VdbeMemIntegerify(pIn1); sqlite3VdbeMemIntegerify(pIn2); if( pIn1->u.iu.i){ pIn1->u.i = pIn2->u.i; } - nPop = 0; break; } #endif /* SQLITE_OMIT_AUTOINCREMENT */ /* Opcode: IfPos P1 P2 * * * @@ -4440,11 +4207,11 @@ ** If the value of register P1 is 1 or greater, jump to P2. ** ** It is illegal to use this instruction on a register that does ** not contain an integer. An assertion fault will result if you try. */ -case OP_IfPos: { /* no-push, jump, in1 */ +case OP_IfPos: { /* jump, in1 */ assert( pIn1->flags==MEM_Int ); if( pIn1->u.i>0 ){ pc = pOp->p2 - 1; } break; @@ -4455,11 +4222,11 @@ ** If the value of register P1 is less than zero, jump to P2. ** ** It is illegal to use this instruction on a register that does ** not contain an integer. An assertion fault will result if you try. */ -case OP_IfNeg: { /* no-push, jump, in1 */ +case OP_IfNeg: { /* jump, in1 */ assert( pIn1->flags==MEM_Int ); if( pIn1->u.i<0 ){ pc = pOp->p2 - 1; } break; @@ -4470,11 +4237,11 @@ ** If the value of register P1 is exactly 0, jump to P2. ** ** It is illegal to use this instruction on a register that does ** not contain an integer. An assertion fault will result if you try. */ -case OP_IfZero: { /* no-push, jump, in1 */ +case OP_IfZero: { /* jump, in1 */ assert( pIn1->flags==MEM_Int ); if( pIn1->u.i==0 ){ pc = pOp->p2 - 1; } break; @@ -4488,11 +4255,11 @@ ** P3 as the accumulator. ** ** The P5 arguments are taken from register P2 and its ** successors. */ -case OP_AggStep: { /* no-push */ +case OP_AggStep: { int n = pOp->p5; int i; Mem *pMem, *pRec; sqlite3_context ctx; sqlite3_value **apVal; @@ -4540,11 +4307,11 @@ ** argument is not used by this opcode. It is only there to disambiguate ** functions that can take varying numbers of arguments. The ** P4 argument is only needed for the degenerate case where ** the step function was not previously called. */ -case OP_AggFinal: { /* no-push */ +case OP_AggFinal: { Mem *pMem; assert( pOp->p1>0 && pOp->p1<=p->nMem ); pMem = &p->aMem[pOp->p1]; assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); @@ -4564,11 +4331,11 @@ ** ** Vacuum the entire database. This opcode will cause other virtual ** machines to be created and run. It may not be called from within ** a transaction. */ -case OP_Vacuum: { /* no-push */ +case OP_Vacuum: { if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; rc = sqlite3RunVacuum(&p->zErrMsg, db); if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; break; } @@ -4579,11 +4346,11 @@ ** ** Perform a single step of the incremental vacuum procedure on ** the P1 database. If the vacuum has finished, jump to instruction ** P2. Otherwise, fall through to the next instruction. */ -case OP_IncrVacuum: { /* no-push, jump */ +case OP_IncrVacuum: { /* jump */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); assert( (p->btreeMask & (1<p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; @@ -4603,11 +4370,11 @@ ** (via sqlite3_step()). ** ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, ** then only the currently executing statement is affected. */ -case OP_Expire: { /* no-push */ +case OP_Expire: { if( !pOp->p1 ){ sqlite3ExpirePreparedStatements(db); }else{ p->expired = 1; } @@ -4629,11 +4396,11 @@ ** P2 contains the root-page of the table to lock. ** ** P4 contains a pointer to the name of the table being locked. This is only ** used to generate an error message if the lock cannot be obtained. */ -case OP_TableLock: { /* no-push */ +case OP_TableLock: { int p1 = pOp->p1; u8 isWriteLock = (p1<0); if( isWriteLock ){ p1 = (-1*p1)-1; } @@ -4652,11 +4419,11 @@ /* Opcode: VBegin * * * P4 * ** ** P4 a pointer to an sqlite3_vtab structure. Call the xBegin method ** for that table. */ -case OP_VBegin: { /* no-push */ +case OP_VBegin: { rc = sqlite3VtabBegin(db, pOp->p4.pVtab); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -4664,11 +4431,11 @@ /* Opcode: VCreate P1 * * P4 * ** ** P4 is the name of a virtual table in database P1. Call the xCreate method ** for that table. */ -case OP_VCreate: { /* no-push */ +case OP_VCreate: { rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -4676,11 +4443,11 @@ /* Opcode: VDestroy P1 * * P4 * ** ** P4 is the name of a virtual table in database P1. Call the xDestroy method ** of that table. */ -case OP_VDestroy: { /* no-push */ +case OP_VDestroy: { p->inVtabMethod = 2; rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); p->inVtabMethod = 0; break; } @@ -4691,11 +4458,11 @@ ** ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. ** P1 is a cursor number. This opcode opens a cursor to the virtual ** table and stores that cursor in P1. */ -case OP_VOpen: { /* no-push */ +case OP_VOpen: { Cursor *pCur = 0; sqlite3_vtab_cursor *pVtabCursor = 0; sqlite3_vtab *pVtab = pOp->p4.pVtab; sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; @@ -4739,11 +4506,11 @@ ** parametersneath additional parameters which are passed to ** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. ** ** A jump is made to P2 if the result set after filtering would be empty. */ -case OP_VFilter: { /* no-push, jump */ +case OP_VFilter: { /* jump */ int nArg; int iQuery; const sqlite3_module *pModule; Mem *pQuery = &p->aMem[pOp->p3]; Mem *pArgc = &pQuery[1]; @@ -4752,11 +4519,11 @@ REGISTER_TRACE(pOp->p3, pQuery); assert( pCur->pVtabCursor ); pModule = pCur->pVtabCursor->pVtab->pModule; - /* Grab the index number and argc parameters off the top of the stack. */ + /* Grab the index number and argc parameters */ assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); nArg = pArgc->u.i; iQuery = pQuery->u.i; /* Invoke the xFilter method */ @@ -4790,11 +4557,10 @@ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VRowid P1 P2 * * * ** ** Store into register P2 the rowid of ** the virtual-table that the P1 cursor is pointing to. -** If P2==0, push the value onto the stack. */ case OP_VRowid: { /* out2-prerelease */ const sqlite3_module *pModule; Cursor *pCur = p->apCsr[pOp->p1]; @@ -4821,11 +4587,10 @@ /* Opcode: VColumn P1 P2 P3 * * ** ** Store the value of the P2-th column of ** the row of the virtual-table that the ** P1 cursor is pointing to into register P3. -** Or if P3==0 push the value onto the stack. */ case OP_VColumn: { const sqlite3_module *pModule; Cursor *pCur = p->apCsr[pOp->p1]; @@ -4841,23 +4606,18 @@ sContext.s.flags = MEM_Null; sContext.s.db = db; if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); - /* Copy the result of the function to the top of the stack. We + /* Copy the result of the function to the P3 register. We ** do this regardless of whether or not an error occured to ensure any ** dynamic allocation in sContext.s (a Mem struct) is released. */ sqlite3VdbeChangeEncoding(&sContext.s, encoding); - if( pOp->p3>0 ){ - assert( pOp->p3<=p->nMem ); - pDest = &p->aMem[pOp->p3]; - REGISTER_TRACE(pOp->p3, pDest); - }else{ - pDest = ++pTos; - pDest->flags = 0; - } + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + pDest = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pDest); sqlite3VdbeMemMove(pDest, &sContext.s); UPDATE_MAX_BLOBSIZE(pDest); if( sqlite3SafetyOn(db) ){ goto abort_due_to_misuse; @@ -4876,11 +4636,11 @@ ** ** Advance virtual table P1 to the next row in its result set and ** jump to instruction P2. Or, if the virtual table has reached ** the end of its result set, then fall through to the next instruction. */ -case OP_VNext: { /* no-push, jump */ +case OP_VNext: { /* jump */ const sqlite3_module *pModule; int res = 0; Cursor *pCur = p->apCsr[pOp->p1]; assert( pCur->pVtabCursor ); @@ -4919,11 +4679,11 @@ ** ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. ** This opcode invokes the corresponding xRename method. The value ** in register P1 is passed as the zName argument to the xRename method. */ -case OP_VRename: { /* no-push */ +case OP_VRename: { sqlite3_vtab *pVtab = pOp->p4.pVtab; Mem *pName = &p->aMem[pOp->p1]; assert( pVtab->pModule->xRename ); REGISTER_TRACE(pOp->p1, pName); @@ -4961,11 +4721,11 @@ ** ** P1 is a boolean flag. If it is set to true and the xUpdate call ** is successful, then the value returned by sqlite3_last_insert_rowid() ** is set to the value of the rowid for the row just inserted. */ -case OP_VUpdate: { /* no-push */ +case OP_VUpdate: { sqlite3_vtab *pVtab = pOp->p4.pVtab; sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; int nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); if( pModule->xUpdate==0 ){ @@ -5029,19 +4789,10 @@ ** readability. From this point on down, the normal indentation rules are ** restored. *****************************************************************************/ } - /* Pop the stack if necessary */ - if( nPop ){ - popStack(&pTos, nPop); - nPop = 0; - } - - /* Make sure the stack limit was not exceeded */ - assert( pTos>=&p->aStack[-1] && pTos<=pStackLimit ); - #ifdef VDBE_PROFILE { long long elapse = hwtime() - start; pOp->cycles += elapse; pOp->cnt++; @@ -5056,40 +4807,21 @@ ** of the program. It is only here for testing and debugging. ** On the other hand, it does burn CPU cycles every time through ** the evaluator loop. So we can leave it out when NDEBUG is defined. */ #ifndef NDEBUG - /* Sanity checking on the top element of the stack. If the previous - ** instruction was VNoChange, then the flags field of the top - ** of the stack is set to 0. This is technically invalid for a memory - ** cell, so avoid calling MemSanity() in this case. - */ - if( pTos>=p->aStack && pTos->flags ){ - assert( pTos->db==db ); - sqlite3VdbeMemSanity(pTos); - assert( !sqlite3VdbeMemTooBig(pTos) ); - } assert( pc>=-1 && pcnOp ); #ifdef SQLITE_DEBUG - /* Code for tracing the vdbe stack. */ if( p->trace ){ if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc); if( (opProperty&(OPFLG_OUT2_PRERELEASE|OPFLG_OUT2))!=0 && pOp->p2>0 ){ registerTrace(p->trace, pOp->p2, pOut); } if( (opProperty&OPFLG_OUT3)!=0 && pOp->p3>0 ){ registerTrace(p->trace, pOp->p3, pOut); } - if( pTos>=p->aStack ){ - int i; - fprintf(p->trace, "Stack:"); - for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){ - memTracePrint(p->trace, &pTos[i]); - } - fprintf(p->trace,"\n"); - } } #endif /* SQLITE_DEBUG */ #endif /* NDEBUG */ } /* The end of the for(;;) loop the loops through opcodes */ @@ -5101,11 +4833,10 @@ rc = SQLITE_ERROR; }else{ rc = SQLITE_DONE; } sqlite3VdbeHalt(p); - p->pTos = pTos; /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -289,12 +289,10 @@ int nOpAlloc; /* Number of slots allocated for aOp[] */ Op *aOp; /* Space to hold the virtual machine's program */ int nLabel; /* Number of labels used */ int nLabelAlloc; /* Number of slots allocated in aLabel[] */ int *aLabel; /* Space to hold the labels */ - Mem *aStack; /* The operand stack, except string values */ - Mem *pTos; /* Top entry in the operand stack */ Mem **apArg; /* Arguments to currently executing user function */ Mem *aColName; /* Column names to return */ int nCursor; /* Number of slots in apCsr[] */ Cursor **apCsr; /* One element of this array for each open cursor */ int nVar; /* Number of entries in aVar[] */ @@ -317,11 +315,10 @@ int inTempTrans; /* True if temp database is transactioned */ int returnStack[25]; /* Return address stack for OP_Gosub & OP_Return */ int returnDepth; /* Next unused element in returnStack[] */ int nResColumn; /* Number of columns in one row of the result set */ char **azResColumn; /* Values for one row of result */ - int popStack; /* Pop the stack this much on entry to VdbeExec() */ char *zErrMsg; /* Error message written here */ Mem *pResultSet; /* Pointer to an array of results */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 changeCntOn; /* True to update the change-counter */ u8 aborted; /* True if ROLLBACK in another VM causes an abort */ Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -231,23 +231,20 @@ p->aLabel[j] = p->nOp; } } /* -** Loop through the program looking for P2 values that are negative. -** Each such value is a label. Resolve the label by setting the P2 -** value to its correct non-zero value. +** Loop through the program looking for P2 values that are negative +** on jump instructions. Each such value is a label. Resolve the +** label by setting the P2 value to its correct non-zero value. ** ** This routine is called once after all opcodes have been inserted. ** ** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument ** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by ** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array. ** -** The integer *pMaxStack is set to the maximum number of vdbe stack -** entries that static analysis reveals this program might need. -** ** This routine also does the following optimization: It scans for ** instructions that might cause a statement rollback. Such instructions ** are: ** ** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort. @@ -257,14 +254,13 @@ ** ** If no such instruction is found, then every Statement instruction ** is changed to a Noop. In this way, we avoid creating the statement ** journal file unnecessarily. */ -static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){ +static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int i; int nMaxArgs = 0; - int nMaxStack = p->nOp; Op *pOp; int *aLabel = p->aLabel; int doesStatementRollback = 0; int hasStatementBegin = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ @@ -296,13 +292,10 @@ assert( pOp[-1].opcode==OP_Integer ); n = pOp[-1].p1; if( n>nMaxArgs ) nMaxArgs = n; #endif } - if( !sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_PUSH) ){ - nMaxStack--; - } if( sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_JUMP) && pOp->p2<0 ){ assert( -1-pOp->p2nLabel ); pOp->p2 = aLabel[-1-pOp->p2]; } @@ -309,11 +302,10 @@ } sqlite3_free(p->aLabel); p->aLabel = 0; *pMaxFuncArgs = nMaxArgs; - *pMaxStack = nMaxStack; /* If we never rollback a statement transaction, then statement ** transactions are not needed. So change every OP_Statement ** opcode into an OP_Noop. This avoid a call to sqlite3OsOpenExclusive() ** which can be expensive on some platforms. @@ -737,11 +729,11 @@ */ static void releaseMemArray(Mem *p, int N){ if( p ){ while( N-->0 ){ assert( N<2 || p[0].db==p[1].db ); - sqlite3VdbeMemRelease(p++); + sqlite3VdbeMemSetNull(p++); } } } #ifndef SQLITE_OMIT_EXPLAIN @@ -749,31 +741,34 @@ ** Give a listing of the program in the virtual machine. ** ** The interface is the same as sqlite3VdbeExec(). But instead of ** running the code, it invokes the callback once for each instruction. ** This feature is used to implement "EXPLAIN". +** +** When p->explain==1, each instruction is listed. When +** p->explain==2, only OP_Explain instructions are listed and these +** are shown in a different format. p->explain==2 is used to implement +** EXPLAIN QUERY PLAN. */ int sqlite3VdbeList( Vdbe *p /* The VDBE */ ){ sqlite3 *db = p->db; int i; int rc = SQLITE_OK; + Mem *pMem = p->pResultSet = &p->aMem[1]; assert( p->explain ); if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; assert( db->magic==SQLITE_MAGIC_BUSY ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); - /* Even though this opcode does not put dynamic strings onto the - ** the stack, they may become dynamic if the user calls + /* Even though this opcode does not use dynamic strings for + ** the result, result columns may become dynamic if the user calls ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ - if( p->pResultSet ){ - releaseMemArray(p->pResultSet, 5); - p->pResultSet = 0; - } + releaseMemArray(pMem, p->nMem); do{ i = p->pc++; }while( inOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain ); if( i>=p->nOp ){ @@ -783,11 +778,10 @@ p->rc = SQLITE_INTERRUPT; rc = SQLITE_ERROR; sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0); }else{ Op *pOp = &p->aOp[i]; - Mem *pMem = p->pResultSet = p->aStack; if( p->explain==1 ){ pMem->flags = MEM_Int; pMem->type = SQLITE_INTEGER; pMem->u.i = i; /* Program counter */ pMem++; @@ -844,11 +838,10 @@ } #endif } p->nResColumn = 8 - 5*(p->explain-1); - p->pTos = pMem; p->rc = SQLITE_OK; rc = SQLITE_ROW; } return rc; } @@ -933,40 +926,31 @@ * p->aOp[] array to save memory if called when in VDBE_MAGIC_RUN * state. */ p->magic = VDBE_MAGIC_RUN; - /* No instruction ever pushes more than a single element onto the - ** stack. And the stack never grows on successive executions of the - ** same loop. So the total number of instructions is an upper bound - ** on the maximum stack depth required. (Added later:) The - ** resolveP2Values() call computes a tighter upper bound on the - ** stack size. - ** - ** Allocation all the stack space we will ever need. + /* + ** Allocation space for registers. */ - if( p->aStack==0 ){ + if( p->aMem==0 ){ int nArg; /* Maximum number of args passed to a user function. */ - int nStack; /* Maximum number of stack entries required */ - resolveP2Values(p, &nArg, &nStack); + resolveP2Values(p, &nArg); resizeOpArray(p, p->nOp); assert( nVar>=0 ); - assert( nStacknOp ); - if( isExplain ){ - nStack = 16; + if( isExplain && nMem<10 ){ + p->nMem = nMem = 10; } - p->aStack = sqlite3DbMallocZero(db, - nStack*sizeof(p->aStack[0]) /* aStack */ + p->aMem = sqlite3DbMallocZero(db, + nMem*sizeof(Mem) /* aMem */ + + nVar*sizeof(Mem) /* aVar */ + nArg*sizeof(Mem*) /* apArg */ - + nVar*sizeof(Mem) /* aVar */ + nVar*sizeof(char*) /* azVar */ - + nMem*sizeof(Mem) /* aMem */ + nCursor*sizeof(Cursor*) + 1 /* apCsr */ ); if( !db->mallocFailed ){ - p->aMem = &p->aStack[nStack-1]; /* aMem[] goes from 1..nMem */ - p->nMem = nMem; /* not from 0..nMem-1 */ + p->aMem--; /* aMem[] goes from 1..nMem */ + p->nMem = nMem; /* not from 0..nMem-1 */ p->aVar = &p->aMem[nMem+1]; p->nVar = nVar; p->okVar = 0; p->apArg = (Mem**)&p->aVar[nVar]; p->azVar = (char**)&p->apArg[nArg]; @@ -974,27 +958,28 @@ p->nCursor = nCursor; for(n=0; naVar[n].flags = MEM_Null; p->aVar[n].db = db; } - for(n=0; naStack[n].db = db; + for(n=1; n<=nMem; n++){ + p->aMem[n].flags = MEM_Null; + p->aMem[n].db = db; } } } - for(n=1; n<=p->nMem; n++){ - p->aMem[n].flags = MEM_Null; - p->aMem[n].db = db; +#ifdef SQLITE_DEBUG + for(n=1; nnMem; n++){ + assert( p->aMem[n].db==db ); + assert( p->aMem[n].flags==MEM_Null ); } +#endif - p->pTos = &p->aStack[-1]; p->pc = -1; p->rc = SQLITE_OK; p->uniqueCnt = 0; p->returnDepth = 0; p->errorAction = OE_Abort; - p->popStack = 0; p->explain |= isExplain; p->magic = VDBE_MAGIC_RUN; p->nChange = 0; p->cacheCtr = 1; p->minWriteFileFormat = 255; @@ -1063,14 +1048,10 @@ ** sorters that were left open. It also deletes the values of ** variables in the aVar[] array. */ static void Cleanup(Vdbe *p){ int i; - if( p->aStack ){ - releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack)); - p->pTos = &p->aStack[-1]; - } closeAllCursorsExceptActiveVtabs(p); releaseMemArray(&p->aMem[1], p->nMem); sqlite3VdbeFifoClear(&p->sFifo); if( p->contextStack ){ for(i=0; icontextStackTop; i++){ @@ -1662,11 +1643,10 @@ */ Cleanup(p); /* Save profiling information from this VDBE run. */ - assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || !p->aStack ); #ifdef VDBE_PROFILE { FILE *out = fopen("vdbe_profile.out", "a"); if( out ){ int i; @@ -1753,11 +1733,13 @@ } sqlite3_free(p->aOp); } releaseMemArray(p->aVar, p->nVar); sqlite3_free(p->aLabel); - sqlite3_free(p->aStack); + if( p->aMem ){ + sqlite3_free(&p->aMem[1]); + } releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); sqlite3_free(p->aColName); sqlite3_free(p->zSql); p->magic = VDBE_MAGIC_DEAD; sqlite3_free(p); Index: src/vtab.c ================================================================== --- src/vtab.c +++ src/vtab.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to help implement virtual tables. ** -** $Id: vtab.c,v 1.61 2008/01/12 12:48:08 drh Exp $ +** $Id: vtab.c,v 1.62 2008/01/17 16:22:15 drh Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" static int createModule( @@ -274,11 +274,11 @@ zStmt, pParse->regRowid ); sqlite3_free(zStmt); v = sqlite3GetVdbe(pParse); - sqlite3ChangeCookie(db, v, iDb); + sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); zWhere = sqlite3MPrintf(db, "name='%q'", pTab->zName); sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 1, 0, zWhere, P4_DYNAMIC); sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -14,11 +14,11 @@ ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** 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.282 2008/01/17 02:36:28 drh Exp $ +** $Id: where.c,v 1.283 2008/01/17 16:22:15 drh Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". @@ -2645,11 +2645,10 @@ pLevel->op = OP_Next; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, brk); } notReady &= ~getMask(&maskSet, iCur); - sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0); /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. */ for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){ Index: test/in3.test ================================================================== --- test/in3.test +++ test/in3.test @@ -11,11 +11,11 @@ # This file tests the optimisations made in November 2007 of expressions # of the following form: # # IN (SELECT FROM ) # -# $Id: in3.test,v 1.2 2007/12/10 05:03:48 danielk1977 Exp $ +# $Id: in3.test,v 1.3 2008/01/17 16:22:16 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !subquery { @@ -264,6 +264,5 @@ do_test in3-4.6 { execsql { DROP INDEX t3_i2 } } {} finish_test -