]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
All essential opcodes can now operate out of registers and completely
authordrh <drh@noemail.net>
Wed, 9 Jan 2008 23:04:12 +0000 (23:04 +0000)
committerdrh <drh@noemail.net>
Wed, 9 Jan 2008 23:04:12 +0000 (23:04 +0000)
avoid the stack.  Many still optionally use the stack to support legacy
code generation, but the stack is not required.  The next step is to
update all code generation to avoid using the stack. (CVS 4700)

FossilOrigin-Name: e3cf1c1c114bcda8fe577beb5ee55b4a651b96db

15 files changed:
manifest
manifest.uuid
src/analyze.c
src/attach.c
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/pragma.c
src/select.c
src/sqliteInt.h
src/update.c
src/vdbe.c
src/vdbeaux.c
src/where.c

index c3dfa2f6f0ec9b586fa77fa47884d430598a7ab7..079fcf066e02ae37e8e4aff9b29eab310895d08a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sthe\sbuild\sfor\sAIX\sand\sother\ssystems\swhere\s"char"\sis\sunsigned\sby\sdefault.\s(CVS\s4699)
-D 2008-01-09T18:31:45
+C All\sessential\sopcodes\scan\snow\soperate\sout\sof\sregisters\sand\scompletely\navoid\sthe\sstack.\s\sMany\sstill\soptionally\suse\sthe\sstack\sto\ssupport\slegacy\ncode\sgeneration,\sbut\sthe\sstack\sis\snot\srequired.\s\sThe\snext\sstep\sis\sto\nupdate\sall\scode\sgeneration\sto\savoid\susing\sthe\sstack.\s(CVS\s4700)
+D 2008-01-09T23:04:12
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -79,24 +79,24 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
 F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc
 F src/alter.c 5a54f58d9481ac14c4e58b702f3f8758dee84d04
-F src/analyze.c 6327934f5a4ec38b71f085482df4a05db0a99126
-F src/attach.c 1c96631e56cdc51d3d70736bf61f1fe01c62cbea
+F src/analyze.c 6cd38a981cac4491d71f99bfc10df32139b3a16a
+F src/attach.c 61f0cae7b1a0e7c3b5f5286be5dc1a7c4d7112d2
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
 F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef
 F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb
 F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76
-F src/build.c 22b50a462d7b2be82e29071069d1c3daf29e953f
+F src/build.c 785139de34c0141208f7f70865bcc603e29faf70
 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
-F src/delete.c 971f5f774d121cfb790630a878a54c939b5b1494
+F src/delete.c 4f760fb7e9b0bb3cf05534bb9d43ea9e726b7e74
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c f1bee4f35fef3078fdbf9075f2b18e41202ccb09
+F src/expr.c 27971029714d4b24081cf20b35e7c96d0e148311
 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
 F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 4443b9026fe9be6c64a689879c564dcd8b7cbcb3
+F src/insert.c 8630ee92dac91944c9f7b75847fa4ef74292b220
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
@@ -127,16 +127,16 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429
 F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa
 F src/parse.y 2ae06e8d3190faace49c5b82e7cea1fc60d084a1
-F src/pragma.c 355d53bc64b70d2dfcd9a1c4a9c5c2ea87da2857
+F src/pragma.c bc6063d91d56a8b3cdad9e3478bba86700759cc4
 F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
-F src/select.c 8570d4db93e115227393fd3cdf88be28d9ac585b
+F src/select.c 7b88e17052dce3c89530cd6be014505b00d6ff4c
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
 F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h 884eb3db36efe571ce371309592ad44fefb91c9a
+F src/sqliteInt.h c2866ab4a8eb42e4daffe30d19afc82952ed67c1
 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
@@ -164,20 +164,20 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
 F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
 F src/trigger.c 1e77b3c21c129ad01f7f23a497ae1d224b4e5bc4
-F src/update.c 93c7bca744988798c8898d024512954683e3e370
+F src/update.c 18f2f3af050399da584fe94548d7e15aa45e884d
 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
-F src/vdbe.c cf1f4de3b96226da2b53fd01b843d5bb0d58f723
+F src/vdbe.c b094a8834bc44e790aef0b0024daf45570b7d56e
 F src/vdbe.h a9166e1601f5b74c20516a74182773a20baee43e
 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
 F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
-F src/vdbeaux.c 2f716ebde79aa5bd83231c61269000413d8710f0
+F src/vdbeaux.c 53cc9e2d3a870fe64f23c43b9417f28118e58d8f
 F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf
 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
 F src/vdbemem.c a94f3e9e85578ba457133ad3446fc6114a03ec5a
 F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
-F src/where.c 8c2bedcc61961a470c358b8c1466c7d8915bc722
+F src/where.c 9705df3c2b78ea8e02a768be8ac5d3f7a2902f1e
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba
@@ -605,7 +605,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 92deff07bba2089bbe011f44defb3a0ac1362d56
-R d2a91e2bbc73e1392892ecb0f6b599b2
+P 47672af0c658573c6b305d224c6901058b8c0e00
+R 6d8b60c5adc02caf36922454c955c896
 U drh
-Z ad96d49ec8605701787cc205558d1dd0
+Z d27dfd6a1a930c2fffbab0aa79d70acf
index 7806e8d5a29543a15ecc429769ff8e2b992ebbbf..b5ab594d57fc897ce52291202723abd2e31fa2dc 100644 (file)
@@ -1 +1 @@
-47672af0c658573c6b305d224c6901058b8c0e00
\ No newline at end of file
+e3cf1c1c114bcda8fe577beb5ee55b4a651b96db
\ No newline at end of file
index afb9c0af8fd272cebd960b3198583c308fd02bb2..2560dd8a70062dcb4e7d5cb19d0e2dc3e90ae03c 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code associated with the ANALYZE command.
 **
-** @(#) $Id: analyze.c,v 1.35 2008/01/08 23:54:25 drh Exp $
+** @(#) $Id: analyze.c,v 1.36 2008/01/09 23:04:12 drh Exp $
 */
 #ifndef SQLITE_OMIT_ANALYZE
 #include "sqliteInt.h"
@@ -73,6 +73,9 @@ static void openStatTable(
     sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1");
   }
   sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb);
+  if( iRootPage==0 ){
+    sqlite3VdbeChangeP5(v, 1);
+  }
   sqlite3VdbeAddOp2(v, OP_SetNumColumns, iStatCur, 3);
 }
 
index 768d91ae2a3fb743bf184fc95ce7eb25be94ffe2..7519546683620d379fb671da5cfd85e8fc6c6339 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the ATTACH and DETACH commands.
 **
-** $Id: attach.c,v 1.66 2008/01/03 23:44:53 drh Exp $
+** $Id: attach.c,v 1.67 2008/01/09 23:04:12 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -332,7 +332,8 @@ static void codeAttach(
 
   assert( v || db->mallocFailed );
   if( v ){
-    sqlite3VdbeAddOp2(v, OP_Function, 0, nFunc);
+    sqlite3VdbeAddOp0(v, OP_Function);
+    sqlite3VdbeChangeP5(v, nFunc);
     pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
     sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);
 
index 99d6f743162630f71e3c283f2202082d35548e7f..f83a8aed7b67e69934c01d6c521436cba4d4008b 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.461 2008/01/06 00:25:22 drh Exp $
+** $Id: build.c,v 1.462 2008/01/09 23:04:12 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1496,6 +1496,7 @@ void sqlite3EndTable(
 
       sqlite3VdbeAddOp0(v, OP_Copy);
       sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, 0, iDb);
+      sqlite3VdbeChangeP5(v, 1);
       pParse->nTab = 2;
       sqlite3SelectDestInit(&dest, SRT_Table, 1);
       sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
@@ -1834,7 +1835,7 @@ void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
 */ 
 static void destroyRootPage(Parse *pParse, int iTable, int iDb){
   Vdbe *v = sqlite3GetVdbe(pParse);
-  sqlite3VdbeAddOp2(v, OP_Destroy, iTable, iDb);
+  sqlite3VdbeAddOp3(v, OP_Destroy, iTable, 0, iDb);
 #ifndef SQLITE_OMIT_AUTOVACUUM
   /* OP_Destroy pushes an integer onto the stack. If this integer
   ** is non-zero, then it is the root page number of a table moved to
@@ -2246,6 +2247,9 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   pKey = sqlite3IndexKeyinfo(pParse, pIndex);
   sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
                     (char *)pKey, P4_KEYINFO_HANDOFF);
+  if( memRootPage>=0 ){
+    sqlite3VdbeChangeP5(v, 1);
+  }
   sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
   addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
   sqlite3GenerateIndexKey(v, pIndex, iTab);
@@ -2255,7 +2259,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
     sqlite3VdbeChangeP2(v, curaddr-1, addr2);
     sqlite3VdbeAddOp1(v, OP_Rowid, iTab);
     sqlite3VdbeAddOp2(v, OP_AddImm, 0, 1);
-    sqlite3VdbeAddOp2(v, OP_IsUnique, iIdx, addr2);
+    sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, addr2, 0, 0, P4_INT32);
     sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort, 0,
                     "indexed columns are not unique", P4_STATIC);
     assert( db->mallocFailed || addr2==sqlite3VdbeCurrentAddr(v) );
index 21f9ce0d63445e6f91287cdc012622247d5c9eac..80c2ab43efcbfa9362c9be181a7560c6cdd3b292 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** in order to generate code for DELETE FROM statements.
 **
-** $Id: delete.c,v 1.154 2008/01/08 23:54:25 drh Exp $
+** $Id: delete.c,v 1.155 2008/01/09 23:04:12 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -369,7 +369,7 @@ void sqlite3DeleteFrom(
 
       /* Populate the OLD.* pseudo-table */
       if( old_col_mask ){
-        sqlite3VdbeAddOp3(v, OP_RowData, iCur, 0, iData);
+        sqlite3VdbeAddOp2(v, OP_RowData, iCur, iData);
       }else{
         sqlite3VdbeAddOp2(v, OP_Null, 0, iData);
       }
index b332f4531a042b7edf2bc0baecaea8e8e21573be..39004b15ce8162c51d78cbb1400186bbba20f5c8 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.339 2008/01/09 02:15:39 drh Exp $
+** $Id: expr.c,v 1.340 2008/01/09 23:04:12 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -2210,8 +2210,9 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
         if( !pColl ) pColl = pParse->db->pDfltColl; 
         sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
       }
-      sqlite3VdbeAddOp4(v, OP_Function, constMask, nExpr, 0,
+      sqlite3VdbeAddOp4(v, OP_Function, constMask, 0, 0,
                         (char*)pDef, P4_FUNCDEF);
+      sqlite3VdbeChangeP5(v, nExpr);
       break;
     }
 #ifndef SQLITE_OMIT_SUBQUERY
index ea1e7c5c56d27994e4a69bfd3806d71b63c7c032..b9931abab1b8f11948086dfbe3b1c5b80c9f5a3c 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.219 2008/01/09 02:15:39 drh Exp $
+** $Id: insert.c,v 1.220 2008/01/09 23:04:12 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1184,7 +1184,7 @@ void sqlite3GenerateConstraintChecks(
     /* Check to see if the new index entry will be unique */
     sqlite3VdbeAddOp1(v, OP_SCopy, aRegIdx[iCur]);
     sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
-    j3 = sqlite3VdbeAddOp2(v, OP_IsUnique, baseCur+iCur+1, 0);
+    j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0, 0, 0, P4_INT32);
 
     /* Generate code that executes if the new index entry is not unique */
     assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
@@ -1617,7 +1617,7 @@ static int xferOptimization(
     addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0);
     assert( pDest->autoInc==0 );
   }
-  sqlite3VdbeAddOp2(v, OP_RowData, iSrc, 0);
+  sqlite3VdbeAddOp1(v, OP_RowData, iSrc);
   sqlite3CodeInsert(pParse,iDest,OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
   sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
   sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
@@ -1638,7 +1638,7 @@ static int xferOptimization(
                       (char*)pKey, P4_KEYINFO_HANDOFF);
     VdbeComment((v, "%s", pDestIdx->zName));
     addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
-    sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, 0);
+    sqlite3VdbeAddOp1(v, OP_RowKey, iSrc);
     sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, 0, 1);
     sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
     sqlite3VdbeJumpHere(v, addr1);
index 96fabbd5d1178d75d47ce1dbf4c83ca4e1f013c7..63c3dc3cbee63f7b0f9742ea81d11b4109f5ee68 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.163 2008/01/09 02:15:39 drh Exp $
+** $Id: pragma.c,v 1.164 2008/01/09 23:04:12 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -854,6 +854,7 @@ void sqlite3Pragma(
       }
     }
     sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1);
+    pParse->nMem = 1;
 
     /* Do an integrity check on each database file */
     for(i=0; i<db->nDb; i++){
@@ -874,22 +875,25 @@ void sqlite3Pragma(
       for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
         Table *pTab = sqliteHashData(x);
         Index *pIdx;
-        sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 0);
+        sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt);
         cnt++;
         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-          sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 0);
+          sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt);
           cnt++;
         }
       }
       if( cnt==0 ) continue;
-      sqlite3VdbeAddOp2(v, OP_IntegrityCk, 1, i);
-      addr = sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0);
-      sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0,
+      if( pParse->nMem < cnt+3 ){
+        pParse->nMem = cnt+3;
+      }
+      sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
+      sqlite3VdbeChangeP5(v, i);
+      addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2);
+      sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
          sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
          P4_DYNAMIC);
-      sqlite3VdbeAddOp2(v, OP_Pull, 1, 0);
-      sqlite3VdbeAddOp0(v, OP_Concat);
-      sqlite3VdbeAddOp2(v, OP_Callback, 1, 0);
+      sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 2);
+      sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
       sqlite3VdbeJumpHere(v, addr);
 
       /* Make sure all the indices are constructed correctly.
index d8c4c9fe75bdf235cd1354ab5748bb32c21ea6c7..794b9af6f3e2ac2a2910060f24f09adca377fe65 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.394 2008/01/09 02:15:42 drh Exp $
+** $Id: select.c,v 1.395 2008/01/09 23:04:12 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -438,31 +438,8 @@ static void codeOffset(
 }
 
 /*
-** Add code that will check to make sure the top N elements of the
-** stack are distinct.  iTab is a sorting index that holds previously
-** seen combinations of the N values.  A new entry is made in iTab
-** if the current N values are new.
-**
-** A jump to addrRepeat is made and the N+1 values are popped from the
-** stack if the top N elements are not distinct.
-*/
-static void codeDistinct_OLD(
-  Vdbe *v,           /* Generate code into this VM */
-  int iTab,          /* A sorting index used to test for distinctness */
-  int addrRepeat,    /* Jump to here if not distinct */
-  int N              /* The top N elements of the stack must be distinct */
-){
-  sqlite3VdbeAddOp2(v, OP_MakeRecord, -N, 0);
-  sqlite3VdbeAddOp2(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3);
-  sqlite3VdbeAddOp2(v, OP_Pop, N+1, 0);
-  sqlite3VdbeAddOp2(v, OP_Goto, 0, addrRepeat);
-  VdbeComment((v, "skip indistinct records"));
-  sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, 0);
-}
-
-/*
-** Add code that will check to make sure the top N elements of the
-** stack are distinct.  iTab is a sorting index that holds previously
+** Add code that will check to make sure the N registers starting at iMem
+** form a distinct entry.  iTab is a sorting index that holds previously
 ** seen combinations of the N values.  A new entry is made in iTab
 ** if the current N values are new.
 **
@@ -2135,7 +2112,7 @@ static int multiSelect(
       iCont = sqlite3VdbeMakeLabel(v);
       computeLimitRegisters(pParse, p, iBreak);
       sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak);
-      iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, 0);
+      iStart = sqlite3VdbeAddOp1(v, OP_RowKey, tab1);
       sqlite3VdbeAddOp2(v, OP_NotFound, tab2, iCont);
       rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
                              pOrderBy, -1, &dest, iCont, iBreak, 0);
@@ -3021,17 +2998,20 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
   for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
     int nArg;
     int addrNext = 0;
+    int regAgg;
     ExprList *pList = pF->pExpr->pList;
     if( pList ){
       nArg = pList->nExpr;
       sqlite3ExprCodeExprList(pParse, pList, 0);
+      regAgg = sqlite3StackToReg(pParse, nArg);
     }else{
       nArg = 0;
+      regAgg = 0;
     }
     if( pF->iDistinct>=0 ){
       addrNext = sqlite3VdbeMakeLabel(v);
       assert( nArg==1 );
-      codeDistinct_OLD(v, pF->iDistinct, addrNext, 1);
+      codeDistinct(v, pF->iDistinct, addrNext, 1, regAgg);
     }
     if( pF->pFunc->needCollSeq ){
       CollSeq *pColl = 0;
@@ -3046,8 +3026,9 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
       }
       sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
     }
-    sqlite3VdbeAddOp4(v, OP_AggStep, pF->iMem, nArg, 0, 
+    sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
                       (void*)pF->pFunc, P4_FUNCDEF);
+    sqlite3VdbeChangeP5(v, nArg);
     if( addrNext ){
       sqlite3VdbeResolveLabel(v, addrNext);
     }
index b48e1cd6271abbc4d43a78918d3fbdc0e4a85610..ef1aab0d9a8ce7fd0608aba6ae8e3030ca4dda7f 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.644 2008/01/08 23:54:25 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.645 2008/01/09 23:04:12 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -481,7 +481,7 @@ struct sqlite3 {
   u8 autoCommit;                /* The auto-commit flag. */
   u8 temp_store;                /* 1: file 2: memory 0: default */
   u8 mallocFailed;              /* True if we have seen a malloc failure */
-  char nextAutovac;             /* Autovac setting after VACUUM if >=0 */
+  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
   int nTable;                   /* Number of tables in the database */
   CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
   i64 lastRowid;                /* ROWID of most recent insert (see above) */
index 824b06183a16c64b8cea4191f05de07aac3eef90..0457075464719551b98b764fb78c5e579b12e3d7 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.165 2008/01/09 02:15:42 drh Exp $
+** $Id: update.c,v 1.166 2008/01/09 23:04:12 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -414,7 +414,7 @@ void sqlite3Update(
     if( !old_col_mask ){
       sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
     }else{
-      sqlite3VdbeAddOp2(v, OP_RowData, iCur, 0);
+      sqlite3VdbeAddOp1(v, OP_RowData, iCur);
     }
     sqlite3CodeInsert(pParse, oldIdx, 0);
 
index 535770e14af983a6ea22223dfe01a35d50d0676f..b5063fb4a54cc74843d586a998a790fa88761798 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.690 2008/01/09 02:15:42 drh Exp $
+** $Id: vdbe.c,v 1.691 2008/01/09 23:04:12 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1435,11 +1435,12 @@ case OP_CollSeq: {             /* no-push */
   break;
 }
 
-/* Opcode: Function P1 P2 P4
+/* Opcode: Function P1 P2 P3 P4 P5
 **
 ** Invoke a user function (P4 is a pointer to a Function structure that
-** defines the function) with P2 arguments taken from the stack.  Pop all
-** arguments from the stack and push back the result.
+** 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.
 **
 ** 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
@@ -1455,12 +1456,16 @@ case OP_Function: {
   Mem *pArg;
   sqlite3_context ctx;
   sqlite3_value **apVal;
-  int n = pOp->p2;
+  int n = pOp->p5;
 
   apVal = p->apArg;
   assert( apVal || n==0 );
 
-  pArg = &pTos[1-n];
+  if( pOp->p2==0 ){
+    pArg = &pTos[1-n];
+  }else{
+    pArg = &p->aMem[pOp->p2];
+  }
   for(i=0; i<n; i++, pArg++){
     apVal[i] = pArg;
     storeTypeInfo(pArg, encoding);
@@ -1502,7 +1507,9 @@ case OP_Function: {
     sqlite3VdbeMemRelease(&ctx.s);
     goto no_mem;
   }
-  popStack(&pTos, n);
+  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.
@@ -1521,41 +1528,42 @@ case OP_Function: {
 
   /* Copy the result of the function to the top of the stack */
   sqlite3VdbeChangeEncoding(&ctx.s, encoding);
-  pTos++;
-  pTos->flags = 0;
-  sqlite3VdbeMemMove(pTos, &ctx.s);
-  if( sqlite3VdbeMemTooBig(pTos) ){
+  if( pOp->p3==0 ){
+    pOut = ++pTos;
+  }else{
+    pOut = &p->aMem[pOp->p3];
+  }
+  sqlite3VdbeMemMove(pOut, &ctx.s);
+  if( sqlite3VdbeMemTooBig(pOut) ){
     goto too_big;
   }
   break;
 }
 
-/* Opcode: BitAnd * * *
+/* Opcode: BitAnd P1 P2 P3 * *
 **
-** Pop the top two elements from the stack.  Convert both elements
-** to integers.  Push back onto the stack the bit-wise AND of the
-** two elements.
+** Take the bit-wise AND of the values in register P1 and P2 and
+** store the result in register P3.
 ** If either operand is NULL, the result is NULL.
 */
-/* Opcode: BitOr * * *
+/* Opcode: BitOr P1 P2 P3 * *
 **
-** Pop the top two elements from the stack.  Convert both elements
-** to integers.  Push back onto the stack the bit-wise OR of the
-** two elements.
+** Take the bit-wise OR of the values in register P1 and P2 and
+** store the result in register P3.
 ** If either operand is NULL, the result is NULL.
 */
-/* Opcode: ShiftLeft * * *
+/* Opcode: ShiftLeft P1 P2 P3 * *
 **
-** Pop the top two elements from the stack.  Convert both elements
-** to integers.  Push back onto the stack the second element shifted
-** left by N bits where N is the top element on the stack.
+** Shift the integer value in register P2 to the left by the
+** number of bits specified by the integer in P1.
+** Store the result in register P3.
 ** If either operand is NULL, the result is NULL.
 */
-/* Opcode: ShiftRight * * *
+/* Opcode: ShiftRight P1 P2 P3 * *
 **
-** Pop the top two elements from the stack.  Convert both elements
-** to integers.  Push back onto the stack the second element shifted
-** right by N bits where N is the top element on the stack.
+** Shift the integer value in register P2 to the right by the
+** number of bits specified by the integer in P1.
+** Store the result in register P3.
 ** If either operand is NULL, the result is NULL.
 */
 case OP_BitAnd:                 /* same as TK_BITAND, in1, in2, out3 */
@@ -1970,10 +1978,10 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
   break;
 }
 
-/* Opcode: Not * * *
+/* Opcode: Not P1 * * * *
 **
-** Interpret the top of the stack as a boolean value.  Replace it
-** with its complement.  If the top of the stack is NULL its value
+** 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 */
@@ -1981,28 +1989,28 @@ case OP_Not: {                /* same as TK_NOT, no-push, in1 */
   if( pIn1->flags & MEM_Null ) break;  /* Do nothing to NULLs */
   sqlite3VdbeMemIntegerify(pIn1);
   assert( (pIn1->flags & MEM_Dyn)==0 );
-  pIn1->u.i = !pTos->u.i;
+  pIn1->u.i = !pIn1->u.i;
   pIn1->flags = MEM_Int;
   break;
 }
 
-/* Opcode: BitNot * * *
+/* Opcode: BitNot P1 * * * *
 **
-** Interpret the top of the stack as an value.  Replace it
-** with its ones-complement.  If the top of the stack is NULL its
-** value is unchanged.
+** 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;
   if( pIn1->flags & MEM_Null ) break;  /* Do nothing to NULLs */
   sqlite3VdbeMemIntegerify(pIn1);
   assert( (pIn1->flags & MEM_Dyn)==0 );
-  pIn1->u.i = ~pTos->u.i;
+  pIn1->u.i = ~pIn1->u.i;
   pIn1->flags = MEM_Int;
   break;
 }
 
-/* Opcode: Noop * * *
+/* Opcode: Noop * * * * *
 **
 ** Do nothing.  This instruction is often useful as a jump
 ** destination.
@@ -2070,7 +2078,7 @@ case OP_StackIsNull: {            /* no-push, jump */
   break;
 }
 
-/* Opcode: IsNull P1 P2 *
+/* Opcode: IsNull P1 P2 * * *
 **
 ** Jump to P2 if the value in register P1 is NULL.
 **
@@ -2084,7 +2092,7 @@ case OP_IsNull: {            /* same as TK_ISNULL, no-push, jump, in1 */
   break;
 }
 
-/* Opcode: NotNull P1 P2 *
+/* Opcode: NotNull P1 P2 * * *
 **
 ** Jump to P2 if the value in register P1 is not NULL.  
 **
@@ -2098,7 +2106,7 @@ case OP_NotNull: {            /* same as TK_NOTNULL, no-push, jump, in1 */
   break;
 }
 
-/* Opcode: SetNumColumns P1 P2 *
+/* Opcode: SetNumColumns P1 P2 * * *
 **
 ** Before the OP_Column opcode can be executed on a cursor, this
 ** opcode must be called to set the number of fields in the table.
@@ -2527,7 +2535,7 @@ case OP_MakeRecord: {        /* jump */
   ** required to store it.
   */
   if( addRowid ){
-    pRowid = &pTos[0-nField];
+    pRowid = &pData0[-1];
     assert( pRowid>=p->aStack );
     sqlite3VdbeMemIntegerify(pRowid);
     serial_type = sqlite3VdbeSerialType(pRowid, 0);
@@ -2609,7 +2617,7 @@ case OP_MakeRecord: {        /* jump */
   break;
 }
 
-/* Opcode: Statement P1 * *
+/* Opcode: Statement P1 * * * *
 **
 ** Begin an individual statement transaction which is part of a larger
 ** BEGIN..COMMIT transaction.  This is needed so that the statement
@@ -2636,7 +2644,7 @@ case OP_Statement: {       /* no-push */
   break;
 }
 
-/* Opcode: AutoCommit P1 P2 *
+/* Opcode: AutoCommit P1 P2 * * *
 **
 ** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll
 ** back any currently active btree transactions. If there are any active
@@ -2693,7 +2701,7 @@ case OP_AutoCommit: {       /* no-push */
   break;
 }
 
-/* Opcode: Transaction P1 P2 *
+/* Opcode: Transaction P1 P2 * * *
 **
 ** Begin a transaction.  The transaction ends when a Commit or Rollback
 ** opcode is encountered.  Depending on the ON CONFLICT setting, the
@@ -2780,9 +2788,10 @@ case OP_ReadCookie: {               /* out2-prerelease */
   break;
 }
 
-/* Opcode: SetCookie P1 P2 *
+/* Opcode: SetCookie P1 P2 P3 * *
 **
-** Write the top of the stack into cookie number P2 of database P1.
+** Write the content of register P3 (interpreted as an integer)
+** into cookie number P2 of database P1.
 ** P2==0 is the schema version.  P2==1 is the database format.
 ** P2==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
@@ -2790,27 +2799,24 @@ case OP_ReadCookie: {               /* out2-prerelease */
 **
 ** A transaction must be started before executing this opcode.
 */
-case OP_SetCookie: {       /* no-push */
+case OP_SetCookie: {       /* no-push, in3 */
   Db *pDb;
   assert( pOp->p2<SQLITE_N_BTREE_META );
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
   assert( (p->btreeMask & (1<<pOp->p1))!=0 );
   pDb = &db->aDb[pOp->p1];
   assert( pDb->pBt!=0 );
-  assert( pTos>=p->aStack );
-  sqlite3VdbeMemIntegerify(pTos);
+  sqlite3VdbeMemIntegerify(pIn3);
   /* See note about index shifting on OP_ReadCookie */
-  rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->u.i);
+  rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pIn3->u.i);
   if( pOp->p2==0 ){
     /* When the schema cookie changes, record the new cookie internally */
-    pDb->pSchema->schema_cookie = pTos->u.i;
+    pDb->pSchema->schema_cookie = pIn3->u.i;
     db->flags |= SQLITE_InternChanges;
   }else if( pOp->p2==1 ){
     /* Record changes in the file format */
-    pDb->pSchema->file_format = pTos->u.i;
+    pDb->pSchema->file_format = pIn3->u.i;
   }
-  assert( (pTos->flags & MEM_Dyn)==0 );
-  pTos--;
   if( pOp->p1==1 ){
     /* Invalidate all prepared statements whenever the TEMP database
     ** schema is changed.  Ticket #1644 */
@@ -2873,16 +2879,17 @@ case OP_VerifyCookie: {       /* no-push */
   break;
 }
 
-/* Opcode: OpenRead P1 P2 P3 P4 *
+/* Opcode: OpenRead P1 P2 P3 P4 P5
 **
 ** Open a read-only cursor for the database table whose root page is
 ** P2 in a database file.  The database file is determined by P3. 
-** 0 means the main database and 1 means the database used for 
+** P3==0 means the main database and P3==1 means the database used for 
 ** temporary tables.  Give the new cursor an identifier of P1.  The P1
 ** values need not be contiguous but all P1 values should be small integers.
 ** It is an error for P1 to be negative.
 **
-** If P2==0 then take the root page number from the top of the stack.
+** If P5!=0 then use the content of register P2 as the root page, not
+** the value of P2 itself.
 **
 ** There will be a read lock on the database whenever there is an
 ** open cursor.  If the database was unlocked prior to this instruction
@@ -2899,10 +2906,11 @@ case OP_VerifyCookie: {       /* no-push */
 **
 ** See also OpenWrite.
 */
-/* Opcode: OpenWrite P1 P2 P3 P4 *
+/* Opcode: OpenWrite P1 P2 P3 P4 P5
 **
 ** Open a read/write cursor named P1 on the table or index whose root
-** page is P2.  If P2==0 then take the root page number from the stack.
+** page is P2.  Or if P5!=0 use the content of register P2 to find the
+** root page.
 **
 ** The P4 value is a pointer to a KeyInfo structure that defines the
 ** content and collating sequence of indices.  P4 is NULL for cursors
@@ -2937,12 +2945,19 @@ case OP_OpenWrite: {       /* no-push */
   }else{
     wrFlag = 0;
   }
-  if( p2<=0 ){
-    assert( pTos>=p->aStack );
-    sqlite3VdbeMemIntegerify(pTos);
-    p2 = pTos->u.i;
-    assert( (pTos->flags & MEM_Dyn)==0 );
-    pTos--;
+  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>=2 );
   }
   assert( i>=0 );
@@ -3008,7 +3023,7 @@ case OP_OpenWrite: {       /* no-push */
   break;
 }
 
-/* Opcode: OpenEphemeral P1 P2 P4
+/* Opcode: OpenEphemeral P1 P2 * P4 *
 **
 ** Open a new cursor P1 to a transient table.
 ** The cursor is always opened read/write even if 
@@ -3075,7 +3090,7 @@ case OP_OpenEphemeral: {       /* no-push */
   break;
 }
 
-/* Opcode: OpenPseudo P1 * *
+/* Opcode: OpenPseudo P1 * * * *
 **
 ** Open a new cursor that points to a fake table that contains a single
 ** row of data.  Any attempt to write a second row of data causes the
@@ -3101,7 +3116,7 @@ case OP_OpenPseudo: {       /* no-push */
   break;
 }
 
-/* Opcode: Close P1 * *
+/* Opcode: Close P1 * * * *
 **
 ** Close a cursor previously opened as P1.  If P1 is not
 ** currently open, this instruction is a no-op.
@@ -3115,11 +3130,11 @@ case OP_Close: {       /* no-push */
   break;
 }
 
-/* Opcode: MoveGe P1 P2 *
+/* Opcode: MoveGe P1 P2 P3 * *
 **
-** Pop the top of the stack and use its value as a key.  Reposition
+** Use the value in register P3 as a key.  Reposition
 ** cursor P1 so that it points to the smallest entry that is greater
-** than or equal to the key that was popped ffrom the stack.
+** than or equal to the key in register P3.
 ** If there are no records greater than or equal to the key and P2 
 ** is not zero, then jump to P2.
 **
@@ -3127,9 +3142,9 @@ case OP_Close: {       /* no-push */
 */
 /* Opcode: MoveGt P1 P2 *
 **
-** Pop the top of the stack and use its value as a key.  Reposition
+** 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 from the stack.
+** than the key in register P3.
 ** If there are no records greater than the key and P2 is not zero,
 ** then jump to P2.
 **
@@ -3137,9 +3152,9 @@ case OP_Close: {       /* no-push */
 */
 /* Opcode: MoveLt P1 P2 *
 **
-** Pop the top of the stack and use its value as a key.  Reposition
+** 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 from the stack.
+** than the key in register P3.
 ** If there are no records less than the key and P2 is not zero,
 ** then jump to P2.
 **
@@ -3147,22 +3162,21 @@ case OP_Close: {       /* no-push */
 */
 /* Opcode: MoveLe P1 P2 *
 **
-** Pop the top of the stack and use its value as a key.  Reposition
+** 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 that was popped from the stack.
+** 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 */
-case OP_MoveLe:         /* no-push, jump */
-case OP_MoveGe:         /* no-push, jump */
-case OP_MoveGt: {       /* no-push, jump */
+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 */
   int i = pOp->p1;
   Cursor *pC;
 
-  assert( pTos>=p->aStack );
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
   assert( pC!=0 );
@@ -3172,26 +3186,22 @@ case OP_MoveGt: {       /* no-push, jump */
     pC->nullRow = 0;
     *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
     if( pC->isTable ){
-      i64 iKey;
-      sqlite3VdbeMemIntegerify(pTos);
-      iKey = intToKey(pTos->u.i);
+      i64 iKey = sqlite3VdbeIntValue(pIn3);
       if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){
         pC->movetoTarget = iKey;
         pC->deferredMoveto = 1;
-        assert( (pTos->flags & MEM_Dyn)==0 );
-        pTos--;
         break;
       }
       rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
-      pC->lastRowid = pTos->u.i;
+      pC->lastRowid = iKey;
       pC->rowidIsValid = res==0;
     }else{
-      assert( pTos->flags & MEM_Blob );
-      ExpandBlob(pTos);
-      rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res);
+      assert( pIn3->flags & MEM_Blob );
+      ExpandBlob(pIn3);
+      rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
@@ -3232,14 +3242,12 @@ case OP_MoveGt: {       /* no-push, jump */
       }
     }
   }
-  Release(pTos);
-  pTos--;
   break;
 }
 
-/* Opcode: Distinct P1 P2 *
+/* Opcode: Distinct P1 P2 P3 * *
 **
-** Use the top of the stack as a record created using MakeRecord.  P1 is a
+** Use register P3 as a record created using MakeRecord.  P1 is a
 ** cursor on a table that declared as an index.  If that table contains an
 ** entry that matches the top of the stack fall thru.  If the top of the stack
 ** matches no entry in P1 then jump to P2.
@@ -3248,7 +3256,7 @@ case OP_MoveGt: {       /* no-push, jump */
 ** record on the top of the stack is not popped.
 **
 ** This instruction is similar to NotFound except that this operation
-** does not pop the key from the stack.
+** does not pop the key from the stack when P3==0.
 **
 ** The instruction is used to implement the DISTINCT operator on SELECT
 ** statements.  The P1 table is not a true index but rather a record of
@@ -3256,9 +3264,9 @@ case OP_MoveGt: {       /* no-push, jump */
 **
 ** See also: Found, NotFound, MoveTo, IsUnique, NotExists
 */
-/* Opcode: Found P1 P2 *
+/* Opcode: Found P1 P2 P3 * *
 **
-** Top of the stack holds a blob constructed by MakeRecord.  P1 is an index.
+** 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
 ** then fall thru.  The P1 cursor is left pointing at the matching entry
@@ -3276,9 +3284,9 @@ case OP_MoveGt: {       /* no-push, jump */
 **
 ** See also: Distinct, NotFound, MoveTo, IsUnique, NotExists
 */
-/* Opcode: NotFound P1 P2 *
+/* Opcode: NotFound P1 P2 P3 * *
 **
-** The top of the stack holds a blob constructed by MakeRecord.  P1 is
+** 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.
@@ -3288,24 +3296,22 @@ case OP_MoveGt: {       /* no-push, jump */
 **
 ** See also: Distinct, Found, MoveTo, NotExists, IsUnique
 */
-case OP_Distinct:       /* no-push, jump */
-case OP_NotFound:       /* no-push, jump */
-case OP_Found: {        /* no-push, jump */
+case OP_Distinct:       /* no-push, jump, in3 */
+case OP_NotFound:       /* no-push, jump, in3 */
+case OP_Found: {        /* no-push, jump, in3 */
   int i = pOp->p1;
   int alreadyExists = 0;
   Cursor *pC;
-  assert( pTos>=p->aStack );
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
   if( (pC = p->apCsr[i])->pCursor!=0 ){
     int res;
     assert( pC->isTable==0 );
-    assert( pTos->flags & MEM_Blob );
-    Stringify(pTos, encoding);
+    assert( pIn3->flags & MEM_Blob );
     if( pOp->opcode==OP_Found ){
       pC->pKeyInfo->prefixIsEqual = 1;
     }
-    rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res);
+    rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res);
     pC->pKeyInfo->prefixIsEqual = 0;
     if( rc!=SQLITE_OK ){
       break;
@@ -3319,19 +3325,17 @@ case OP_Found: {        /* no-push, jump */
   }else{
     if( !alreadyExists ) pc = pOp->p2 - 1;
   }
-  if( pOp->opcode!=OP_Distinct ){
-    Release(pTos);
-    pTos--;
+  if( pOp->opcode==OP_Distinct ){
+    nPop = 0;
   }
   break;
 }
 
-/* Opcode: IsUnique P1 P2 *
+/* Opcode: IsUnique P1 P2 P3 P4 *
 **
-** The top of the stack is an integer record number.  Call this
-** record number R.  The next on the stack is an index key created
-** using MakeIdxRec.  Call it K.  This instruction pops R from the
-** stack but it leaves K unchanged.
+** The P3 register contains an integer record number.  Call this
+** record number R.  The P4 register contains an index key created
+** using MakeIdxRec.  Call it K.
 **
 ** P1 is an index.  So it has no data and its key consists of a
 ** record generated by OP_MakeRecord where the last field is the 
@@ -3342,25 +3346,30 @@ case OP_Found: {        /* no-push, jump */
 ** If there is no such entry, then there is an immediate
 ** 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 pushed onto the stack and control
+** number for that entry is written into P3 and control
 ** falls through to the next instruction.
 **
 ** See also: Distinct, NotFound, NotExists, Found
 */
-case OP_IsUnique: {        /* no-push, jump */
+case OP_IsUnique: {        /* no-push, jump, in3 */
   int i = pOp->p1;
-  Mem *pNos = &pTos[-1];
   Cursor *pCx;
   BtCursor *pCrsr;
+  Mem *pK;
   i64 R;
 
   /* Pop the value R off the top of the stack
   */
-  assert( pNos>=p->aStack );
-  sqlite3VdbeMemIntegerify(pTos);
-  R = pTos->u.i;
-  assert( (pTos->flags & MEM_Dyn)==0 );
-  pTos--;
+  assert( pOp->p4type==P4_INT32 );
+  if( pOp->p4.i==0 ){
+    assert( pOp->p3==0 );
+    pK = &pIn3[-1];
+  }else{
+    pK = &p->aMem[pOp->p4.i];
+  }
+  sqlite3VdbeMemIntegerify(pIn3);
+  R = pIn3->u.i;
+  assert( (pIn3->flags & MEM_Dyn)==0 );
   assert( i>=0 && i<p->nCursor );
   pCx = p->apCsr[i];
   assert( pCx!=0 );
@@ -3375,10 +3384,9 @@ case OP_IsUnique: {        /* no-push, jump */
 
     /* Make sure K is a string and make zKey point to K
     */
-    assert( pNos->flags & MEM_Blob );
-    Stringify(pNos, encoding);
-    zKey = pNos->z;
-    nKey = pNos->n;
+    assert( pK->flags & MEM_Blob );
+    zKey = pK->z;
+    nKey = pK->n;
 
     szRowid = sqlite3VdbeIdxRowidLen((u8*)zKey);
     len = nKey-szRowid;
@@ -3424,9 +3432,9 @@ case OP_IsUnique: {        /* no-push, jump */
     ** the stack.  (The record number of an entry that violates a UNIQUE
     ** constraint.)
     */
-    pTos++;
-    pTos->u.i = v;
-    pTos->flags = MEM_Int;
+    nPop = 0;
+    pIn3->u.i = v;
+    pIn3->flags = MEM_Int;
   }
   break;
 }
@@ -3434,11 +3442,11 @@ case OP_IsUnique: {        /* no-push, jump */
 /* 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 memory cell P3 as an integer key. If a record 
+** use the contents of register P3 as an 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 (unless it was read from a memory cell).
+** from the stack if P3==0.
 **
 ** The difference between this operation and NotFound is that this
 ** operation assumes the key is an integer and that P1 is a table whereas
@@ -3447,29 +3455,20 @@ case OP_IsUnique: {        /* no-push, jump */
 **
 ** See also: Distinct, Found, MoveTo, NotFound, IsUnique
 */
-case OP_NotExists: {        /* no-push, jump */
+case OP_NotExists: {        /* no-push, jump, in3 */
   int i = pOp->p1;
   Cursor *pC;
   BtCursor *pCrsr;
-  Mem *pKey;
-  if( pOp->p3 ){
-    assert( pOp->p3<=p->nMem );
-    pKey = &p->aMem[pOp->p3];
-    REGISTER_TRACE(pOp->p3, pKey);
-  }else{
-    pKey = pTos;
-    assert( pTos>=p->aStack );
-  }
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     int res;
     u64 iKey;
-    assert( pKey->flags & MEM_Int );
+    assert( pIn3->flags & MEM_Int );
     assert( p->apCsr[i]->isTable );
-    iKey = intToKey(pKey->u.i);
+    iKey = intToKey(pIn3->u.i);
     rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res);
-    pC->lastRowid = pKey->u.i;
+    pC->lastRowid = pIn3->u.i;
     pC->rowidIsValid = res==0;
     pC->nullRow = 0;
     pC->cacheStatus = CACHE_STALE;
@@ -3483,10 +3482,6 @@ case OP_NotExists: {        /* no-push, jump */
       pC->rowidIsValid = 0;
     }
   }
-  if( pOp->p3==0 ){
-    Release(pTos);
-    pTos--;
-  }
   break;
 }
 
@@ -3500,7 +3495,6 @@ case OP_NotExists: {        /* no-push, jump */
 */
 case OP_Sequence: {           /* out2-prerelease */
   int i = pOp->p1;
-  assert( pTos>=p->aStack );
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
   pOut->u.i = p->apCsr[i]->seqCount++;
@@ -3509,17 +3503,17 @@ case OP_Sequence: {           /* out2-prerelease */
 }
 
 
-/* Opcode: NewRowid P1 P2 P3
+/* 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 memory cell P2 otherwise.
+** onto the stack if P2 is 0 or written to register P2 otherwise.
 **
-** If P3>0 then P3 is a memory cell that holds the largest previously
+** 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 memory cell is updated with the generated
+** error is generated.  The P3 register is updated with the generated
 ** record number.  This P3 mechanism is used to help implement the
 ** AUTOINCREMENT feature.
 */
@@ -3757,7 +3751,7 @@ case OP_Insert: {         /* no-push */
   break;
 }
 
-/* Opcode: Delete P1 P2 P4
+/* Opcode: Delete P1 P2 * P4 *
 **
 ** Delete the record at which the P1 cursor is currently pointing.
 **
@@ -3829,41 +3823,33 @@ case OP_ResetCount: {        /* no-push */
   break;
 }
 
-/* Opcode: RowData P1 * P3
+/* Opcode: RowData P1 P2 * * *
 **
-** Push onto the stack the complete row data for cursor P1. Or if P3 
-** is a positive non-zero integer register number, then the value 
-** is written into that register. There is no interpretation of the data.  
-** It is just copied onto the stack or into the memory cell exactly as 
+** Write into register P2 the complete row data for cursor P1.
+** There is no interpretation of the data.  
+** It is just copied onto the P2 register exactly as 
 ** it is found in the database file.
 **
 ** If the cursor is not pointing to a valid row, a NULL value is
-** pushed/inserted instead.
+** written into P2.
 */
-/* Opcode: RowKey P1 * P3
+/* Opcode: RowKey P1 P2 * * *
 **
-** Push onto the stack the complete row key for cursor P1. Or if P3 
-** is a positive non-zero integer register number, then the value 
-** is written into that register. There is no interpretation of the data.  
+** 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 
 ** it is found in the database file.
 **
-** If the cursor is not pointing to a valid row, a NULL is pushed
-** onto the stack.
+** If the cursor is not pointing to a valid row, a NULL is
+** written into P2.
 */
-case OP_RowKey:
-case OP_RowData: {
+case OP_RowKey:             /* out2-prerelease */
+case OP_RowData: {          /* out2-prerelease */
   int i = pOp->p1;
   Cursor *pC;
   u32 n;
-  Mem *pOut;
 
   /* Note that RowKey and RowData are really exactly the same instruction */
-  if( pOp->p3 ){
-    pOut = &p->aMem[pOp->p3];
-  }else{
-    pOut = ++pTos;
-  }
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
   assert( pC->isTable || pOp->opcode==OP_RowKey );
@@ -3917,7 +3903,6 @@ case OP_RowData: {
     pOut->flags = MEM_Null;
   }
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
-  REGISTER_TRACE(pOp->p3, pOut);
   break;
 }
 
@@ -4194,68 +4179,64 @@ case OP_IdxRowid: {              /* out2-prerelease */
   break;
 }
 
-/* Opcode: IdxGT P1 P2 *
+/* Opcode: IdxGT P1 P2 P3 * *
 **
-** The top of the stack is an index entry that omits the ROWID.  Compare
-** the top of stack against the index that P1 is currently pointing to.
+** The value in register P3 is an index entry that omits the ROWID.  Compare
+** the value in register P3 against the index that P1 is currently pointing to.
 ** Ignore the ROWID on the P1 index.
 **
-** The top of the stack might have fewer columns that P1.
+** The P3 value might have fewer columns that P1 index.
 **
-** If the P1 index entry is greater than the top of the stack
+** If the P1 index entry is greater than the value in register P3
 ** then jump to P2.  Otherwise fall through to the next instruction.
-** In either case, the stack is popped once.
 */
-/* Opcode: IdxGE P1 P2 P4
+/* Opcode: IdxGE P1 P2 P3 * P5
 **
-** The top of the stack is an index entry that omits the ROWID.  Compare
-** the top of stack against the index that P1 is currently pointing to.
+** The value in register P3 is an index entry that omits the ROWID.  Compare
+** this value against the index that P1 is currently pointing to.
 ** Ignore the ROWID on the P1 index.
 **
-** If the P1 index entry is greater than or equal to the top of the stack
-** then jump to P2.  Otherwise fall through to the next instruction.
-** In either case, the stack is popped once.
+** If the P1 index entry is greater than or equal to the value in 
+** register P3 then jump to P2.  Otherwise fall through to the next 
+** instruction.
 **
-** If P4 is the "+" string (or any other non-NULL string) then the
-** index taken from the top of the stack is temporarily increased by
-** an epsilon prior to the comparison.  This make the opcode work
-** like IdxGT except that if the key from the stack is a prefix of
+** If P5 is non-zero then the value in register P3 is temporarily
+** increased by an epsilon prior to the comparison.  This make the opcode work
+** like IdxGT except that if the key from register P3 is a prefix of
 ** the key in the cursor, the result is false whereas it would be
 ** true with IdxGT.
 */
-/* Opcode: IdxLT P1 P2 P4
+/* Opcode: IdxLT P1 P2 P3 * P5
 **
-** The top of the stack is an index entry that omits the ROWID.  Compare
-** the top of stack against the index that P1 is currently pointing to.
+** The value in register P3 is an index entry that omits the ROWID.  Compare
+** the this value against the index that P1 is currently pointing to.
 ** Ignore the ROWID on the P1 index.
 **
-** If the P1 index entry is less than  the top of the stack
+** If the P1 index entry is less than the register P3 value
 ** then jump to P2.  Otherwise fall through to the next instruction.
-** In either case, the stack is popped once.
 **
-** If P4 is the "+" string (or any other non-NULL string) then the
-** index taken from the top of the stack is temporarily increased by
+** 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 */
-case OP_IdxGT:          /* no-push, jump */
-case OP_IdxGE: {        /* no-push, jump */
+case OP_IdxLT:          /* no-push, jump, in3 */
+case OP_IdxGT:          /* no-push, jump, in3 */
+case OP_IdxGE: {        /* no-push, jump, in3 */
   int i= pOp->p1;
   Cursor *pC;
 
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
-  assert( pTos>=p->aStack );
   if( (pC = p->apCsr[i])->pCursor!=0 ){
     int res;
  
-    assert( pTos->flags & MEM_Blob );  /* Created using OP_MakeRecord */
+    assert( pIn3->flags & MEM_Blob );  /* Created using OP_MakeRecord */
     assert( pC->deferredMoveto==0 );
-    ExpandBlob(pTos);
-    *pC->pIncrKey = pOp->p4.z!=0;
-    assert( pOp->p4.z==0 || pOp->opcode!=OP_IdxGT );
-    rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res);
+    ExpandBlob(pIn3);
+    *pC->pIncrKey = pOp->p5!=0;
+    assert( pOp->opcode!=OP_IdxGT || pOp->p5==0 );
+    rc = sqlite3VdbeIdxKeyCompare(pC, pIn3->n, (u8*)pIn3->z, &res);
     *pC->pIncrKey = 0;
     if( rc!=SQLITE_OK ){
       break;
@@ -4269,32 +4250,30 @@ case OP_IdxGE: {        /* no-push, jump */
       pc = pOp->p2 - 1 ;
     }
   }
-  Release(pTos);
-  pTos--;
   break;
 }
 
-/* Opcode: Destroy P1 P2 *
+/* Opcode: Destroy P1 P2 P3 * *
 **
 ** Delete an entire database table or index whose root page in the database
 ** file is given by P1.
 **
-** The table being destroyed is in the main database file if P2==0.  If
-** P2==1 then the table to be clear is in the auxiliary database file
+** The table being destroyed is in the main database file if P3==0.  If
+** P3==1 then the table to be clear is in the auxiliary database file
 ** that is used to store tables create using CREATE TEMPORARY TABLE.
 **
 ** 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 pushed onto the stack.  If no page movement was required (because
-** the table being dropped was already the last one in the database) then
-** a zero is pushed onto the stack.  If AUTOVACUUM is disabled
-** then a zero is pushed onto the stack.
+** is stored in register P2 or pushed onto the stack if P2==0.  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
 */
-case OP_Destroy: {
+case OP_Destroy: {     /* out2-prerelease */
   int iMoved;
   int iCnt;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -4312,15 +4291,15 @@ case OP_Destroy: {
     rc = SQLITE_LOCKED;
     p->errorAction = OE_Abort;
   }else{
+    int iDb = pOp->p3;
     assert( iCnt==1 );
-    assert( (p->btreeMask & (1<<pOp->p2))!=0 );
-    rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
-    pTos++;
-    pTos->flags = MEM_Int;
-    pTos->u.i = iMoved;
+    assert( (p->btreeMask & (1<<iDb))!=0 );
+    rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
+    pOut->flags = MEM_Int;
+    pOut->u.i = iMoved;
 #ifndef SQLITE_OMIT_AUTOVACUUM
     if( rc==SQLITE_OK && iMoved!=0 ){
-      sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1);
+      sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1);
     }
 #endif
   }
@@ -4340,41 +4319,6 @@ case OP_Destroy: {
 ** See also: Destroy
 */
 case OP_Clear: {        /* no-push */
-
-  /* For consistency with the way other features of SQLite operate
-  ** with a truncate, we will also skip the update callback.
-  */
-#if 0
-  Btree *pBt = db->aDb[pOp->p2].pBt;
-  if( db->xUpdateCallback && pOp->p4.p ){
-    const char *zDb = db->aDb[pOp->p2].zName;
-    const char *zTbl = pOp->p4.p;
-    BtCursor *pCur = 0;
-    int fin = 0;
-
-    rc = sqlite3BtreeCursor(pBt, pOp->p1, 0, 0, 0, &pCur);
-    if( rc!=SQLITE_OK ){
-      goto abort_due_to_error;
-    }
-    for(
-      rc=sqlite3BtreeFirst(pCur, &fin); 
-      rc==SQLITE_OK && !fin; 
-      rc=sqlite3BtreeNext(pCur, &fin)
-    ){
-      i64 iKey;
-      rc = sqlite3BtreeKeySize(pCur, &iKey);
-      if( rc ){
-        break;
-      }
-      iKey = keyToInt(iKey);
-      db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey);
-    }
-    sqlite3BtreeCloseCursor(pCur);
-    if( rc!=SQLITE_OK ){
-      goto abort_due_to_error;
-    }
-  }
-#endif
   assert( (p->btreeMask & (1<<pOp->p2))!=0 );
   rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
   break;
@@ -4419,13 +4363,13 @@ case OP_CreateTable: {          /* out2-prerelease */
   }
   rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
   if( rc==SQLITE_OK ){
-    pTos->u.i = pgno;
-    pTos->flags = MEM_Int;
+    pOut->u.i = pgno;
+    pOut->flags = MEM_Int;
   }
   break;
 }
 
-/* Opcode: ParseSchema P1 P2 P4
+/* Opcode: ParseSchema P1 P2 * P4 *
 **
 ** Read and parse all entries from the SQLITE_MASTER table of database P1
 ** that match the WHERE clause P4.  P2 is the "force" flag.   Always do
@@ -4471,7 +4415,7 @@ case OP_ParseSchema: {        /* no-push */
 }
 
 #if !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER)
-/* Opcode: LoadAnalysis P1 * *
+/* Opcode: LoadAnalysis P1 * * * *
 **
 ** Read the sqlite_stat1 table for database P1 and load the content
 ** of that table into the internal index hash table.  This will cause
@@ -4485,7 +4429,7 @@ case OP_LoadAnalysis: {        /* no-push */
 }
 #endif /* !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER)  */
 
-/* Opcode: DropTable P1 * P4
+/* Opcode: DropTable P1 * * P4 *
 **
 ** Remove the internal (in-memory) data structures that describe
 ** the table named P4 in database P1.  This is called after a table
@@ -4497,7 +4441,7 @@ case OP_DropTable: {        /* no-push */
   break;
 }
 
-/* Opcode: DropIndex P1 * P4
+/* Opcode: DropIndex P1 * * P4 *
 **
 ** Remove the internal (in-memory) data structures that describe
 ** the index named P4 in database P1.  This is called after an index
@@ -4509,7 +4453,7 @@ case OP_DropIndex: {        /* no-push */
   break;
 }
 
-/* Opcode: DropTrigger P1 * P4
+/* Opcode: DropTrigger P1 * * P4 *
 **
 ** Remove the internal (in-memory) data structures that describe
 ** the trigger named P4 in database P1.  This is called after a trigger
@@ -4523,105 +4467,95 @@ case OP_DropTrigger: {        /* no-push */
 
 
 #ifndef SQLITE_OMIT_INTEGRITY_CHECK
-/* Opcode: IntegrityCk P1 P2 *
+/* Opcode: IntegrityCk P1 P2 P3 * P5
 **
-** Do an analysis of the currently open database.  Push onto the
-** stack the text of an error message describing any problems.
-** If no problems are found, push a NULL onto the stack.
+** Do an analysis of the currently open database.  Store in
+** register P1 the text of an error message describing any problems.
+** If no problems are found, store a NULL in register P1.
 **
-** P1 is the address of a memory cell that contains the maximum
-** number of allowed errors.  At most mem[P1] errors will be reported.
-** In other words, the analysis stops as soon as mem[P1] errors are 
-** seen.  Mem[P1] is updated with the number of errors remaining.
+** The register P3 contains the maximum number of allowed errors.
+** At most reg[P3] errors will be reported.
+** In other words, the analysis stops as soon as reg[P1] errors are 
+** seen.  Reg[P1] is updated with the number of errors remaining.
 **
 ** The root page numbers of all tables in the database are integer
-** values on the stack.  This opcode pulls as many integers as it
-** can off of the stack and uses those numbers as the root pages.
+** stored in reg[P1], reg[P1+1], reg[P1+2], ....  There are P2 tables
+** total.
 **
-** If P2 is not zero, the check is done on the auxiliary database
+** If P5 is not zero, the check is done on the auxiliary database
 ** file, not the main database file.
 **
 ** This opcode is used to implement the integrity_check pragma.
 */
 case OP_IntegrityCk: {
-  int nRoot;
-  int *aRoot;
-  int j;
-  int nErr;
-  char *z;
-  Mem *pnErr;
-
-  for(nRoot=0; &pTos[-nRoot]>=p->aStack; nRoot++){
-    if( (pTos[-nRoot].flags & MEM_Int)==0 ) break;
-  }
+  int nRoot;      /* Number of tables to check.  (Number of root pages.) */
+  int *aRoot;     /* Array of rootpage numbers for tables to be checked */
+  int j;          /* Loop counter */
+  int nErr;       /* Number of errors reported */
+  char *z;        /* Text of the error report */
+  Mem *pnErr;     /* Register keeping track of errors remaining */
+  
+  nRoot = pOp->p2;
   assert( nRoot>0 );
   aRoot = sqlite3_malloc( sizeof(int)*(nRoot+1) );
   if( aRoot==0 ) goto no_mem;
-  j = pOp->p1;
-  assert( j>0 && j<=p->nMem );
-  pnErr = &p->aMem[j];
+  assert( pOp->p3>0 && pOp->p3<=p->nMem );
+  pnErr = &p->aMem[pOp->p3];
   assert( (pnErr->flags & MEM_Int)!=0 );
+  assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
+  pIn1 = &p->aMem[pOp->p1];
   for(j=0; j<nRoot; j++){
-    aRoot[j] = (pTos-j)->u.i;
+    aRoot[j] = sqlite3VdbeIntValue(&pIn1[j]);
   }
   aRoot[j] = 0;
-  popStack(&pTos, nRoot);
-  pTos++;
-  assert( pOp->p2>=0 && pOp->p2<db->nDb );
-  assert( (p->btreeMask & (1<<pOp->p2))!=0 );
-  z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot,
+  assert( pOp->p5<db->nDb );
+  assert( (p->btreeMask & (1<<pOp->p5))!=0 );
+  z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
                                  pnErr->u.i, &nErr);
   pnErr->u.i -= nErr;
+  Release(pIn1);
   if( nErr==0 ){
     assert( z==0 );
-    pTos->flags = MEM_Null;
+    pIn1->flags = MEM_Null;
   }else{
-    pTos->z = z;
-    pTos->n = strlen(z);
-    pTos->flags = MEM_Str | MEM_Dyn | MEM_Term;
-    pTos->xDel = 0;
+    pIn1->z = z;
+    pIn1->n = strlen(z);
+    pIn1->flags = MEM_Str | MEM_Dyn | MEM_Term;
+    pIn1->xDel = 0;
   }
-  pTos->enc = SQLITE_UTF8;
-  sqlite3VdbeChangeEncoding(pTos, encoding);
+  pIn1->enc = SQLITE_UTF8;
+  sqlite3VdbeChangeEncoding(pIn1, encoding);
   sqlite3_free(aRoot);
   break;
 }
 #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
-/* Opcode: FifoWrite P1 * *
+/* Opcode: FifoWrite P1 * * * *
 **
-** Write the integer from memory cell P1 into the Fifo.
+** Write the integer from register P1 into the Fifo.
 */
-case OP_FifoWrite: {        /* no-push */
-  Mem *pReg = &p->aMem[pOp->p1];
-  assert( pOp->p1>0 && pOp->p1<=p->nMem );
-  REGISTER_TRACE(pOp->p1, pReg);
-  sqlite3VdbeMemIntegerify(pReg);
-  if( sqlite3VdbeFifoPush(&p->sFifo, pReg->u.i)==SQLITE_NOMEM ){
+case OP_FifoWrite: {        /* no-push, in1 */
+  if( sqlite3VdbeFifoPush(&p->sFifo, sqlite3VdbeIntValue(pIn1))==SQLITE_NOMEM ){
     goto no_mem;
   }
   break;
 }
 
-/* Opcode: FifoRead P1 P2 *
+/* Opcode: FifoRead P1 P2 * * *
 **
-** Attempt to read a single integer from the Fifo. If P1 is zero,
-** push the result onto the stack. Otherwise, store the read integer 
-** in register P1.
+** Attempt to read a single integer from the Fifo.  Store that
+** integer in register P1.
 ** 
-** If the Fifo is empty do not push an entry onto the stack or set
-** a memory register but instead jump to P2.
+** If the Fifo is empty jump to P2.
 */
 case OP_FifoRead: {         /* jump */
-  i64 v;
   CHECK_FOR_INTERRUPT;
-  if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
+  assert( pOp->p1>0 && pOp->p1<=p->nMem );
+  pOut = &p->aMem[pOp->p1];
+  Release(pOut);
+  pOut->flags = MEM_Int;
+  if( sqlite3VdbeFifoPop(&p->sFifo, &pOut->u.i)==SQLITE_DONE ){
     pc = pOp->p2 - 1;
-  }else{
-    Mem *pOut = &p->aMem[pOp->p1];
-    assert( pOp->p1>0 && pOp->p1<=p->nMem );
-    sqlite3VdbeMemSetInt64(pOut, v);
-    REGISTER_TRACE(pOp->p1, pOut);
   }
   break;
 }
@@ -4671,36 +4605,30 @@ case OP_ContextPop: {        /* no-push */
 #endif /* #ifndef SQLITE_OMIT_TRIGGER */
 
 #ifndef SQLITE_OMIT_AUTOINCREMENT
-/* Opcode: MemMax P1 P2 *
+/* Opcode: MemMax P1 P2 * * *
 **
-** Set the value of memory cell P1 to the maximum of its current value
-** and the value in cell P2, or the value on the top of the stack if P2
-** is zero. The stack is unchanged in either case.
+** Set the value of register P1 to the maximum of its current value
+** 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 */
-  int i = pOp->p1;
-  Mem *pMem;
-  Mem *pNew = (pOp->p2?(&p->aMem[pOp->p2]):pTos);
-  assert( pOp->p2 || pTos>=p->aStack );
-  assert( i>0 && i<=p->nMem );
-  pMem = &p->aMem[i];
-  sqlite3VdbeMemIntegerify(pMem);
-  sqlite3VdbeMemIntegerify(pNew);
-  if( pMem->u.i<pNew->u.i){
-    pMem->u.i = pNew->u.i;
+case OP_MemMax: {        /* no-push, in1, in2 */
+  sqlite3VdbeMemIntegerify(pIn1);
+  sqlite3VdbeMemIntegerify(pIn2);
+  if( pIn1->u.i<pIn2->u.i){
+    pIn1->u.i = pIn2->u.i;
   }
+  nPop = 0;
   break;
 }
 #endif /* SQLITE_OMIT_AUTOINCREMENT */
 
-/* Opcode: IfPos P1 P2 *
+/* Opcode: IfPos P1 P2 * * *
 **
-** If the value of memory cell P1 is 1 or greater, jump to P2.
+** If the value of register P1 is 1 or greater, jump to P2.
 **
-** It is illegal to use this instruction on a memory cell that does
+** 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 */
@@ -4711,11 +4639,11 @@ case OP_IfPos: {        /* no-push, jump, in1 */
   break;
 }
 
-/* Opcode: IfNeg P1 P2 *
+/* Opcode: IfNeg P1 P2 * * *
 **
-** If the value of memory cell P1 is less than zero, jump to P2. 
+** If the value of register P1 is less than zero, jump to P2. 
 **
-** It is illegal to use this instruction on a memory cell that does
+** 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 */
@@ -4726,11 +4654,11 @@ case OP_IfNeg: {        /* no-push, jump, in1 */
   break;
 }
 
-/* Opcode: IfZero P1 P2 *
+/* Opcode: IfZero P1 P2 * * *
 **
-** If the value of memory cell P1 is exactly 0, jump to P2. 
+** If the value of register P1 is exactly 0, jump to P2. 
 **
-** It is illegal to use this instruction on a memory cell that does
+** 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 */
@@ -4741,25 +4669,25 @@ case OP_IfZero: {        /* no-push, jump, in1 */
   break;
 }
 
-/* Opcode: AggStep P1 P2 P4
+/* Opcode: AggStep * P2 P3 P4 P5
 **
 ** Execute the step function for an aggregate.  The
-** function has P2 arguments.  P4 is a pointer to the FuncDef
-** structure that specifies the function.  Use memory location
-** P1 as the accumulator.
+** function has P5 arguments.   P4 is a pointer to the FuncDef
+** structure that specifies the function.  Use register
+** P3 as the accumulator.
 **
-** The P2 arguments are popped from the stack.
+** The P5 arguments are taken from register P2 and its
+** successors.
 */
 case OP_AggStep: {        /* no-push */
-  int n = pOp->p2;
+  int n = pOp->p5;
   int i;
   Mem *pMem, *pRec;
   sqlite3_context ctx;
   sqlite3_value **apVal;
 
   assert( n>=0 );
-  pRec = &pTos[1-n];
-  assert( pRec>=p->aStack );
+  pRec = &p->aMem[pOp->p2];
   apVal = p->apArg;
   assert( apVal || n==0 );
   for(i=0; i<n; i++, pRec++){
@@ -4767,8 +4695,8 @@ case OP_AggStep: {        /* no-push */
     storeTypeInfo(pRec, encoding);
   }
   ctx.pFunc = pOp->p4.pFunc;
-  assert( pOp->p1>0 && pOp->p1<=p->nMem );
-  ctx.pMem = pMem = &p->aMem[pOp->p1];
+  assert( pOp->p3>0 && pOp->p3<=p->nMem );
+  ctx.pMem = pMem = &p->aMem[pOp->p3];
   pMem->n++;
   ctx.s.flags = MEM_Null;
   ctx.s.z = 0;
@@ -4783,7 +4711,6 @@ case OP_AggStep: {        /* no-push */
     ctx.pColl = pOp[-1].p4.pColl;
   }
   (ctx.pFunc->xStep)(&ctx, n, apVal);
-  popStack(&pTos, n);
   if( ctx.isError ){
     sqlite3SetString(&p->zErrMsg, sqlite3_value_text(&ctx.s), (char*)0);
     rc = SQLITE_ERROR;
@@ -4792,7 +4719,7 @@ case OP_AggStep: {        /* no-push */
   break;
 }
 
-/* Opcode: AggFinal P1 P2 P4
+/* Opcode: AggFinal P1 P2 * P4 *
 **
 ** Execute the finalizer function for an aggregate.  P1 is
 ** the memory location that is the accumulator for the aggregate.
@@ -4821,7 +4748,7 @@ case OP_AggFinal: {        /* no-push */
 
 
 #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
-/* Opcode: Vacuum * * *
+/* Opcode: Vacuum * * * * *
 **
 ** Vacuum the entire database.  This opcode will cause other virtual
 ** machines to be created and run.  It may not be called from within
@@ -4836,7 +4763,7 @@ case OP_Vacuum: {        /* no-push */
 #endif
 
 #if !defined(SQLITE_OMIT_AUTOVACUUM)
-/* Opcode: IncrVacuum P1 P2 *
+/* Opcode: IncrVacuum P1 P2 * * *
 **
 ** Perform a single step of the incremental vacuum procedure on
 ** the P1 database. If the vacuum has finished, jump to instruction
@@ -4857,7 +4784,7 @@ case OP_IncrVacuum: {        /* no-push, jump */
 }
 #endif
 
-/* Opcode: Expire P1 * *
+/* Opcode: Expire P1 * * * *
 **
 ** Cause precompiled statements to become expired. An expired statement
 ** fails with an error code of SQLITE_SCHEMA if it is ever executed 
@@ -4876,7 +4803,7 @@ case OP_Expire: {        /* no-push */
 }
 
 #ifndef SQLITE_OMIT_SHARED_CACHE
-/* Opcode: TableLock P1 P2 P4
+/* Opcode: TableLock P1 P2 * P4 *
 **
 ** Obtain a lock on a particular table. This instruction is only used when
 ** the shared-cache feature is enabled. 
@@ -4910,7 +4837,7 @@ case OP_TableLock: {        /* no-push */
 #endif /* SQLITE_OMIT_SHARED_CACHE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VBegin * * P4
+/* Opcode: VBegin * * * P4 *
 **
 ** P4 a pointer to an sqlite3_vtab structure. Call the xBegin method 
 ** for that table.
@@ -4922,7 +4849,7 @@ case OP_VBegin: {   /* no-push */
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VCreate P1 * P4
+/* Opcode: VCreate P1 * * P4 *
 **
 ** P4 is the name of a virtual table in database P1. Call the xCreate method
 ** for that table.
@@ -4934,7 +4861,7 @@ case OP_VCreate: {   /* no-push */
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VDestroy P1 * P4
+/* Opcode: VDestroy P1 * * P4 *
 **
 ** P4 is the name of a virtual table in database P1.  Call the xDestroy method
 ** of that table.
@@ -4948,7 +4875,7 @@ case OP_VDestroy: {   /* no-push */
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VOpen P1 * P4
+/* Opcode: VOpen P1 * * P4 *
 **
 ** 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
@@ -5049,7 +4976,7 @@ case OP_VFilter: {   /* no-push, jump */
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VRowid P1 P2 *
+/* Opcode: VRowid P1 P2 * * *
 **
 ** Store into register P2  the rowid of
 ** the virtual-table that the P1 cursor is pointing to.
@@ -5079,7 +5006,7 @@ case OP_VRowid: {             /* out2-prerelease */
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VColumn P1 P2 P3
+/* Opcode: VColumn P1 P2 P3 * *
 **
 ** Store the value of the P2-th column of
 ** the row of the virtual-table that the 
@@ -5132,7 +5059,7 @@ case OP_VColumn: {
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VNext P1 P2 *
+/* Opcode: VNext P1 P2 * * *
 **
 ** Advance virtual table P1 to the next row in its result set and
 ** jump to instruction P2.  Or, if the virtual table has reached
@@ -5175,7 +5102,7 @@ case OP_VNext: {   /* no-push, jump */
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VRename P1 * P4
+/* Opcode: VRename P1 * * P4 *
 **
 ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
 ** This opcode invokes the corresponding xRename method. The value
@@ -5200,7 +5127,7 @@ case OP_VRename: {   /* no-push */
 #endif
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VUpdate P1 P2 P3 P4
+/* Opcode: VUpdate P1 P2 P3 P4 *
 **
 ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
 ** This opcode invokes the corresponding xUpdate method. P2 values
index a8853f3ee09f5352665109c59f2bfec5af87a60e..296e8e73ce6ed7be8153750c5a5727d887d5aa7b 100644 (file)
@@ -270,7 +270,9 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
   for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
     u8 opcode = pOp->opcode;
 
-    if( opcode==OP_Function || opcode==OP_AggStep 
+    if( opcode==OP_Function ){
+      if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
+    }else if( opcode==OP_AggStep 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
         || opcode==OP_VUpdate
 #endif
@@ -532,7 +534,10 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
   pOp = &p->aOp[addr];
   freeP4(pOp->p4type, pOp->p4.p);
   pOp->p4.p = 0;
-  if( zP4==0 ){
+  if( n==P4_INT32 ){
+    pOp->p4.i = (int)zP4;
+    pOp->p4type = n;
+  }else if( zP4==0 ){
     pOp->p4.p = 0;
     pOp->p4type = P4_NOTUSED;
   }else if( n==P4_KEYINFO ){
index 9f13fa194606ce84616b7800441e9abdc980ad47..0fd137ada0b3fdffca6b4fd633c4c754eb528389 100644 (file)
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.279 2008/01/09 02:15:42 drh Exp $
+** $Id: where.c,v 1.280 2008/01/09 23:04:13 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -2549,7 +2549,7 @@ WhereInfo *sqlite3WhereBegin(
         sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
         sqlite3VdbeAddOp2(v, testOp, iIdxCur, nxt);
         if( (topEq && !bRev) || (!btmEq && bRev) ){
-          sqlite3VdbeChangeP4(v, -1, "+", P4_STATIC);
+          sqlite3VdbeChangeP5(v, 1);
         }
       }
       if( topLimit | btmLimit ){
@@ -2618,7 +2618,8 @@ WhereInfo *sqlite3WhereBegin(
         /* Scan in the forward order */
         sqlite3VdbeAddOp2(v, (isMinQuery?OP_MoveGt:OP_MoveGe), iIdxCur, nxt);
         start = sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
-        sqlite3VdbeAddOp4(v, OP_IdxGE, iIdxCur, nxt, 0, "+", P4_STATIC);
+        sqlite3VdbeAddOp2(v, OP_IdxGE, iIdxCur, nxt);
+        sqlite3VdbeChangeP5(v, 1);
         pLevel->op = OP_Next;
       }
       if( !omitTable ){