]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Begin setting a foundation on which to convert the VM from a stack-based
authordrh <drh@noemail.net>
Wed, 2 Jan 2008 00:34:36 +0000 (00:34 +0000)
committerdrh <drh@noemail.net>
Wed, 2 Jan 2008 00:34:36 +0000 (00:34 +0000)
to a register-based machine.  Everything is still mostly stack based with
this check-in.  This change merely begins adding infrastructure to support
a register-based architecture. (CVS 4652)

FossilOrigin-Name: 051ec01f2799e095516015f2ef0180e50fac387c

17 files changed:
manifest
manifest.uuid
src/analyze.c
src/delete.c
src/expr.c
src/insert.c
src/pragma.c
src/select.c
src/sqliteInt.h
src/trigger.c
src/update.c
src/vdbe.c
src/vdbe.h
src/vdbeInt.h
src/vdbeapi.c
src/vdbeaux.c
src/where.c

index ebe09dacca01e5babee0ad9bbb678e47cde42ca7..658e313c2b04ed14f4c8989925779790979ccb49 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Optimize\strigger\scompilation\sto\savoid\spopulating\sthe\sOLD.*\sand\sNEW.*\spseudo-tables\swith\sdata\sthat\swill\snever\sbe\sused.\sSome\stesting\sto\scome.\s(CVS\s4651)
-D 2008-01-01T19:02:09
+C Begin\ssetting\sa\sfoundation\son\swhich\sto\sconvert\sthe\sVM\sfrom\sa\sstack-based\nto\sa\sregister-based\smachine.\s\sEverything\sis\sstill\smostly\sstack\sbased\swith\nthis\scheck-in.\s\sThis\schange\smerely\sbegins\sadding\sinfrastructure\sto\ssupport\na\sregister-based\sarchitecture.\s(CVS\s4652)
+D 2008-01-02T00:34:37
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -79,7 +79,7 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
 F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc
 F src/alter.c 23d18ec53ef27fcb5e5ae9ca050217231ae15a0d
-F src/analyze.c fd1a3d756c1a20fca3c505bed0398f4cdca83cb8
+F src/analyze.c cb25936f0148ee65c825a49f8064292a98050a50
 F src/attach.c 95658e74e3e0d1cbdb8658817516d4d1467fc13d
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
@@ -90,13 +90,13 @@ F src/build.c cbfd98ceb95c61c226cd60a845fa7967b66c8931
 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
-F src/delete.c 6c090aeb5e97a224ee1f232a02359ee79e8ab411
+F src/delete.c a4843531af1354882ea7dbe53fa5f46b581ae73c
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c d0969aa79a8e12f8ba49ffe97ae671bee47e37dc
+F src/expr.c c3fb939d6801071ce19243521ca444eca40b057a
 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
 F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 3c82c974150506bed75f58dec3744503bf112dd4
+F src/insert.c 355c482603c8c5151b23c3c7661cf1044ec34d29
 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 a780b33ef45dd7b3272319cf91e609d6f109a31c
-F src/pragma.c dd5b1983168eacba1a5084571775b904ea95404f
+F src/pragma.c 4a7f377a509eb14e35b09d4bf7b808ef647aad0b
 F src/prepare.c 7aeba7851773fbe3950a26b35d3389bef0eb1c62
 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
-F src/select.c 247d668f5be042b914ed8e46edf9cdb57a1eca29
+F src/select.c 55b1a99e1d28a6ec3db2870a9f3f932fb3e7cb2a
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 77895a54c2082157e169c857a2e244525ec25af7
 F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h cf993fe510f6a4cdc18e60b80eee3725c2f1001e
+F src/sqliteInt.h 942a52122bbffb8a16d606ceb531a3529f3557a1
 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
@@ -163,21 +163,21 @@ F src/test_server.c a6ece6c835e7eae835054124e09e947e422b1ac5
 F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
 F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
-F src/trigger.c 24bdfee77ce9472db91267597225506c31fc3d9b
-F src/update.c 59124a9d5d52bb411f6fba6475b93f2f443fc971
+F src/trigger.c f8e2d42cf1782ffc14a9d7cee1d1a406f9b0c8c4
+F src/update.c fee857007be57b68a7539c26cc5563d8fbaf3f82
 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
 F src/vacuum.c 25ffbd766f25bca099ead1c1e11f5528c86102b8
-F src/vdbe.c b2f1bcd4b9c9db31dbd79f387139d6740627fa8c
-F src/vdbe.h 79e09ff13b85457abe437d9814454534ebbc1fe3
-F src/vdbeInt.h 630145b9bfaa19190ab491f52658a7db550f2247
-F src/vdbeapi.c dd2c43317294e0a013e9f634ee4209a3ea459b43
-F src/vdbeaux.c 5bc14ff3da6c6b3b7f643cbc3d50a344e9b599f8
+F src/vdbe.c 56a6e80d3357622305cffe6ea509e5d643e7dadb
+F src/vdbe.h a042e6d3b567ac81f182ca5b4639807621355822
+F src/vdbeInt.h 2985f1369273e635898cf5952237efcb3fdb21f3
+F src/vdbeapi.c 4acfaab3e10c99eb66c5332979d7b14a1c3505ae
+F src/vdbeaux.c bca64691ad6bb11e45b5ccf494d9f088d23b3575
 F src/vdbeblob.c 82f51cdf9b0c0af729732fde48c824e498c0a1ca
 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
 F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4
 F src/vtab.c f819d55ef638d45e09ce00009d435da8bf16f528
-F src/where.c 4d71db7ee641cd28cdef88cc6149bd3a51d2e671
+F src/where.c 49901aac9ad568c9c92f914150e91c1663f3978d
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba
@@ -603,7 +603,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P b51782ccac28598eec7adc9302fe7d1986bfdaf8
-R 904ead844e1f41e01a54c3518029f00d
-U danielk1977
-Z 755babd79b5a2ad03f400826316421af
+P e08a33ed7255c22ce2805363f44a1d7770acb2dd
+R 31f346602d71de9f0cbdcecc99b8f06d
+U drh
+Z 1c9d96c8f34a418a83b5bab17073581f
index 8c20d9c76c4e1c7ad2bf6070b572af8473f79c0a..bfca76ce3ae7c1c1b47a059d6e6b8c3154e8c1db 100644 (file)
@@ -1 +1 @@
-e08a33ed7255c22ce2805363f44a1d7770acb2dd
\ No newline at end of file
+051ec01f2799e095516015f2ef0180e50fac387c
\ No newline at end of file
index a0d94683a9f1548d68d49b098fbe0d49315949ec..13e3ad34b1feb59f5e6073657caa92bce23a9ae7 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code associated with the ANALYZE command.
 **
-** @(#) $Id: analyze.c,v 1.24 2007/11/15 13:10:23 danielk1977 Exp $
+** @(#) $Id: analyze.c,v 1.25 2008/01/02 00:34:37 drh Exp $
 */
 #ifndef SQLITE_OMIT_ANALYZE
 #include "sqliteInt.h"
@@ -123,7 +123,7 @@ static void analyzeOneTable(
     */
     assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) );
     sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
-    VdbeComment((v, "%s", pIdx->zName));
+    VdbeComment((v, "%s", pIdx->zName));
     sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum,
         (char *)pKey, P3_KEYINFO_HANDOFF);
     nCol = pIdx->nColumn;
index 77a2c6d822f40a923fa9ffb4041051cadf28f9d3..f2a63d51f734087bbf1871dfa83024ebbfb2e12a 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.135 2008/01/01 19:02:09 danielk1977 Exp $
+** $Id: delete.c,v 1.136 2008/01/02 00:34:37 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -76,7 +76,7 @@ void sqlite3OpenTable(
   assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
   sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
   sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
-  VdbeComment((v, "%s", pTab->zName));
+  VdbeComment((v, "%s", pTab->zName));
   sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum);
   sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
 }
@@ -391,8 +391,7 @@ void sqlite3DeleteFrom(
   ** invoke the callback function.
   */
   if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
-    sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
-    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
+    sqlite3VdbeAddOp(v, OP_ResultRow, memCnt, 1);
     sqlite3VdbeSetNumCols(v, 1);
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC);
   }
index 7fd53ae6c7517fab64c61829d287da27ef74ae26..05932e2f2b544e4ed2da8d963654f5254249de14 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.321 2008/01/01 19:02:09 danielk1977 Exp $
+** $Id: expr.c,v 1.322 2008/01/02 00:34:37 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1647,7 +1647,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){
           sqlite3VdbeAddOp(v, OP_MemInt, 1, iMem);
   
           sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
-          VdbeComment((v, "%s", pIdx->zName));
+          VdbeComment((v, "%s", pIdx->zName));
           sqlite3VdbeOp3(v,OP_OpenRead,iTab,pIdx->tnum,pKey,P3_KEYINFO_HANDOFF);
           eType = IN_INDEX_INDEX;
           sqlite3VdbeAddOp(v, OP_SetNumColumns, iTab, pIdx->nColumn);
@@ -1806,11 +1806,11 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
       if( pExpr->op==TK_SELECT ){
         sop = SRT_Mem;
         sqlite3VdbeAddOp(v, OP_MemNull, iMem, 0);
-        VdbeComment((v, "Init subquery result"));
+        VdbeComment((v, "Init subquery result"));
       }else{
         sop = SRT_Exists;
         sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem);
-        VdbeComment((v, "Init EXISTS result"));
+        VdbeComment((v, "Init EXISTS result"));
       }
       sqlite3ExprDelete(pSel->pLimit);
       pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one);
@@ -2174,7 +2174,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
         sqlite3CodeSubselect(pParse, pExpr);
       }
       sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);
-      VdbeComment((v, "load subquery result"));
+      VdbeComment((v, "load subquery result"));
       break;
     }
     case TK_IN: {
@@ -2301,7 +2301,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
          assert( pExpr->iColumn == OE_Ignore );
          sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);
          sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump);
-         VdbeComment((v, "raise(IGNORE)"));
+         VdbeComment((v, "raise(IGNORE)"));
       }
       stackChng = 0;
       break;
@@ -2344,6 +2344,26 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){
 }
 #endif
 
+/*
+** Generate code to evaluate an expression and store the result in
+** a designated register.  If the target register number is negative,
+** allocate a new register to store the result.  Return the target
+** register number regardless.
+**
+** The current implementation is a rough prototype for experimental
+** purposes.  There are many optimization opportunities here.
+*/
+int sqlite3ExprIntoReg(Parse *pParse, Expr *pExpr, int target){
+  Vdbe *v = pParse->pVdbe;
+  if( v==0 ) return -1;
+  sqlite3ExprCode(pParse, pExpr);
+  if( target<0 ){
+    target = pParse->nMem++;
+  }
+  sqlite3VdbeAddOp(v, OP_MemStore, target, 1);
+  return target;
+}
+
 /*
 ** Generate code that pushes the value of every element of the given
 ** expression list onto the stack.
index 7f72e95d44f0c5f6bcb7f78bbd3a515b018d85ea..6e3440deaa4198316c53293c1cd2ef7c5c726784 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.198 2008/01/01 19:02:09 danielk1977 Exp $
+** $Id: insert.c,v 1.199 2008/01/02 00:34:37 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -129,8 +129,8 @@ static int readsTable(Vdbe *v, int iStartAddr, int iDb, Table *pTab){
       }
     }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-    if( pOp->opcode==OP_VOpen && pOp->p3==(const char*)pTab->pVtab ){
-      assert( pOp->p3!=0 );
+    if( pOp->opcode==OP_VOpen && pOp->p3.p==(const char*)pTab->pVtab ){
+      assert( pOp->p3.p!=0 );
       assert( pOp->p3type==P3_VTAB );
       return 1;
     }
@@ -875,8 +875,7 @@ void sqlite3Insert(
   ** invoke the callback function.
   */
   if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
-    sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);
-    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
+    sqlite3VdbeAddOp(v, OP_ResultRow, iCntMem, 1);
     sqlite3VdbeSetNumCols(v, 1);
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P3_STATIC);
   }
@@ -1298,7 +1297,7 @@ void sqlite3OpenTableAndIndices(
     KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
     assert( pIdx->pSchema==pTab->pSchema );
     sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
-    VdbeComment((v, "%s", pIdx->zName));
+    VdbeComment((v, "%s", pIdx->zName));
     sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF);
   }
   if( pParse->nTab<=base+i ){
@@ -1597,12 +1596,12 @@ static int xferOptimization(
     sqlite3VdbeAddOp(v, OP_Close, iDest, 0);
     sqlite3VdbeAddOp(v, OP_Integer, iDbSrc, 0);
     pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx);
-    VdbeComment((v, "%s", pSrcIdx->zName));
+    VdbeComment((v, "%s", pSrcIdx->zName));
     sqlite3VdbeOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, 
                    (char*)pKey, P3_KEYINFO_HANDOFF);
     sqlite3VdbeAddOp(v, OP_Integer, iDbDest, 0);
     pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
-    VdbeComment((v, "%s", pDestIdx->zName));
+    VdbeComment((v, "%s", pDestIdx->zName));
     sqlite3VdbeOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, 
                    (char*)pKey, P3_KEYINFO_HANDOFF);
     addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
index 9ab09f1a147c411d9c2007d282afd7b31bb2d35b..3fe341b8d7c610204caff48d903953ab838774a6 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.153 2007/12/29 13:39:20 danielk1977 Exp $
+** $Id: pragma.c,v 1.154 2008/01/02 00:34:37 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -147,12 +147,13 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
 */
 static void returnSingleInt(Parse *pParse, const char *zLabel, int value){
   Vdbe *v = sqlite3GetVdbe(pParse);
-  sqlite3VdbeAddOp(v, OP_Integer, value, 0);
+  int mem = pParse->nMem++;
+  sqlite3VdbeAddOp(v, OP_MemInt, value, mem);
   if( pParse->explain==0 ){
     sqlite3VdbeSetNumCols(v, 1);
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P3_STATIC);
   }
-  sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
+  sqlite3VdbeAddOp(v, OP_ResultRow, mem, 1);
 }
 
 #ifndef SQLITE_OMIT_FLAG_PRAGMAS
index 142244c0ddb95d8d62e513ce159aab79bdd90725..23f2c70a2174859e7d1bc6e4e7d9f7e8d6c47c25 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.373 2008/01/01 19:02:09 danielk1977 Exp $
+** $Id: select.c,v 1.374 2008/01/02 00:34:37 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -422,7 +422,7 @@ static void codeOffset(
       sqlite3VdbeAddOp(v, OP_Pop, nPop, 0);
     }
     sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
-    VdbeComment((v, "skip OFFSET records"));
+    VdbeComment((v, "skip OFFSET records"));
     sqlite3VdbeJumpHere(v, addr);
   }
 }
@@ -446,7 +446,7 @@ static void codeDistinct(
   sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3);
   sqlite3VdbeAddOp(v, OP_Pop, N+1, 0);
   sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat);
-  VdbeComment((v, "skip indistinct records"));
+  VdbeComment((v, "skip indistinct records"));
   sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0);
 }
 
@@ -1710,7 +1710,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
     sqlite3ExprCode(pParse, p->pLimit);
     sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
     sqlite3VdbeAddOp(v, OP_MemStore, iLimit, 1);
-    VdbeComment((v, "LIMIT counter"));
+    VdbeComment((v, "LIMIT counter"));
     sqlite3VdbeAddOp(v, OP_IfMemZero, iLimit, iBreak);
     sqlite3VdbeAddOp(v, OP_MemLoad, iLimit, 0);
   }
@@ -1721,7 +1721,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
     sqlite3ExprCode(pParse, p->pOffset);
     sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
     sqlite3VdbeAddOp(v, OP_MemStore, iOffset, p->pLimit==0);
-    VdbeComment((v, "OFFSET counter"));
+    VdbeComment((v, "OFFSET counter"));
     addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iOffset, 0);
     sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
     sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
@@ -1737,7 +1737,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
     addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
     sqlite3VdbeJumpHere(v, addr1);
     sqlite3VdbeAddOp(v, OP_MemStore, iLimit+1, 1);
-    VdbeComment((v, "LIMIT+OFFSET"));
+    VdbeComment((v, "LIMIT+OFFSET"));
     sqlite3VdbeJumpHere(v, addr2);
   }
 }
@@ -1887,7 +1887,7 @@ static int multiSelect(
         p->iOffset = pPrior->iOffset;
         if( p->iLimit>=0 ){
           addr = sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, 0);
-          VdbeComment((v, "Jump ahead if LIMIT reached"));
+          VdbeComment((v, "Jump ahead if LIMIT reached"));
         }
         rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff);
         p->pPrior = pPrior;
@@ -3381,9 +3381,9 @@ int sqlite3Select(
       iBMem = pParse->nMem;
       pParse->nMem += pGroupBy->nExpr;
       sqlite3VdbeAddOp(v, OP_MemInt, 0, iAbortFlag);
-      VdbeComment((v, "clear abort flag"));
+      VdbeComment((v, "clear abort flag"));
       sqlite3VdbeAddOp(v, OP_MemInt, 0, iUseFlag);
-      VdbeComment((v, "indicate accumulator empty"));
+      VdbeComment((v, "indicate accumulator empty"));
       sqlite3VdbeAddOp(v, OP_Goto, 0, addrInitializeLoop);
 
       /* Generate a subroutine that outputs a single row of the result
@@ -3395,11 +3395,11 @@ int sqlite3Select(
       */
       addrSetAbort = sqlite3VdbeCurrentAddr(v);
       sqlite3VdbeAddOp(v, OP_MemInt, 1, iAbortFlag);
-      VdbeComment((v, "set abort flag"));
+      VdbeComment((v, "set abort flag"));
       sqlite3VdbeAddOp(v, OP_Return, 0, 0);
       addrOutputRow = sqlite3VdbeCurrentAddr(v);
       sqlite3VdbeAddOp(v, OP_IfMemPos, iUseFlag, addrOutputRow+2);
-      VdbeComment((v, "Groupby result generator entry point"));
+      VdbeComment((v, "Groupby result generator entry point"));
       sqlite3VdbeAddOp(v, OP_Return, 0, 0);
       finalizeAggFunctions(pParse, &sAggInfo);
       if( pHaving ){
@@ -3412,7 +3412,7 @@ int sqlite3Select(
         goto select_end;
       }
       sqlite3VdbeAddOp(v, OP_Return, 0, 0);
-      VdbeComment((v, "end groupby result generator"));
+      VdbeComment((v, "end groupby result generator"));
 
       /* Generate a subroutine that will reset the group-by accumulator
       */
@@ -3456,7 +3456,7 @@ int sqlite3Select(
         sqlite3VdbeAddOp(v, OP_IdxInsert, sAggInfo.sortingIdx, 0);
         sqlite3WhereEnd(pWInfo);
         sqlite3VdbeAddOp(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
-        VdbeComment((v, "GROUP BY sort"));
+        VdbeComment((v, "GROUP BY sort"));
         sAggInfo.useSortingIdx = 1;
       }
 
@@ -3502,11 +3502,11 @@ int sqlite3Select(
         sqlite3VdbeAddOp(v, OP_MemMove, iAMem+j, iBMem+j);
       }
       sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow);
-      VdbeComment((v, "output one row"));
+      VdbeComment((v, "output one row"));
       sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd);
-      VdbeComment((v, "check abort flag"));
+      VdbeComment((v, "check abort flag"));
       sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset);
-      VdbeComment((v, "reset accumulator"));
+      VdbeComment((v, "reset accumulator"));
 
       /* Update the aggregate accumulators based on the content of
       ** the current row
@@ -3514,7 +3514,7 @@ int sqlite3Select(
       sqlite3VdbeResolveLabel(v, addrProcessRow);
       updateAccumulator(pParse, &sAggInfo);
       sqlite3VdbeAddOp(v, OP_MemInt, 1, iUseFlag);
-      VdbeComment((v, "indicate data in accumulator"));
+      VdbeComment((v, "indicate data in accumulator"));
 
       /* End of the loop
       */
@@ -3528,7 +3528,7 @@ int sqlite3Select(
       /* Output the final row of result
       */
       sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow);
-      VdbeComment((v, "output final row"));
+      VdbeComment((v, "output final row"));
       
     } /* endif pGroupBy */
     else {
index a59ec170f6d47bb579b1b030e70eff145c34cefe..f6ff826981369ddbb360bbfc9d6232290d2db6ab 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.627 2008/01/01 19:02:09 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.628 2008/01/02 00:34:37 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1729,6 +1729,7 @@ void sqlite3WhereEnd(WhereInfo*);
 void sqlite3ExprCodeGetColumn(Vdbe*, Table*, int, int);
 void sqlite3ExprCode(Parse*, Expr*);
 void sqlite3ExprCodeAndCache(Parse*, Expr*);
+int sqlite3ExprIntoReg(Parse*,Expr*,int);
 int sqlite3ExprCodeExprList(Parse*, ExprList*);
 void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
 void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
index 4748b4ecbab16b3a299bae503f618b38afcc2cd7..2bde7c2f0d0e38fb42999e47b05b1972bdfafd9a 100644 (file)
@@ -677,7 +677,7 @@ static int codeTriggerProgram(
   assert( pTriggerStep!=0 );
   assert( v!=0 );
   sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0);
-  VdbeComment((v, "begin trigger %s", pStepList->pTrig->name));
+  VdbeComment((v, "begin trigger %s", pStepList->pTrig->name));
   while( pTriggerStep ){
     orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
     pParse->trigStack->orconf = orconf;
@@ -727,7 +727,7 @@ static int codeTriggerProgram(
     pTriggerStep = pTriggerStep->pNext;
   }
   sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);
-  VdbeComment((v, "end trigger %s", pStepList->pTrig->name));
+  VdbeComment((v, "end trigger %s", pStepList->pTrig->name));
 
   return 0;
 }
index 2ed1142126907f1e4b62efa73baef2c9ea893aab..0edc861b44a2b6b02a7501d7fac1146039a94388 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.145 2008/01/01 19:02:09 danielk1977 Exp $
+** $Id: update.c,v 1.146 2008/01/02 00:34:37 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -59,12 +59,13 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
     sqlite3_value *pValue;
     u8 enc = ENC(sqlite3VdbeDb(v));
     Column *pCol = &pTab->aCol[i];
+    VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
     assert( i<pTab->nCol );
-    sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, pCol->affinity, &pValue);
+    sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, 
+                         pCol->affinity, &pValue);
     if( pValue ){
+      sqlite3VdbeAddOp(v, OP_DfltValue, 0, 0);
       sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
-    }else{
-      VdbeComment((v, "# %s.%s", pTab->zName, pCol->zName));
     }
   }
 }
@@ -555,8 +556,7 @@ void sqlite3Update(
   ** invoke the callback function.
   */
   if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
-    sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
-    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
+    sqlite3VdbeAddOp(v, OP_ResultRow, memCnt, 1);
     sqlite3VdbeSetNumCols(v, 1);
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P3_STATIC);
   }
index e9d69af8df1439662ff0fe686d4b82ca481bb6fe..4c1071e21a90cc49df0a3a4dfc3ed2990ad7f2d8 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.661 2007/12/17 16:20:07 drh Exp $
+** $Id: vdbe.c,v 1.662 2008/01/02 00:34:37 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -477,7 +477,7 @@ int sqlite3VdbeExec(
     popStack(&pTos, p->popStack);
     p->popStack = 0;
   }
-  p->resOnStack = 0;
+  p->pResultSet = 0;
   db->busyHandler.nBusy = 0;
   CHECK_FOR_INTERRUPT;
   sqlite3VdbeIOTraceSql(p);
@@ -679,8 +679,8 @@ case OP_Halt: {            /* no-push */
   p->rc = pOp->p1;
   p->pc = pc;
   p->errorAction = pOp->p2;
-  if( pOp->p3 ){
-    sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0);
+  if( pOp->p3.p ){
+    sqlite3SetString(&p->zErrMsg, pOp->p3.p, (char*)0);
   }
   rc = sqlite3VdbeHalt(p);
   assert( rc==SQLITE_BUSY || rc==SQLITE_OK );
@@ -733,9 +733,9 @@ case OP_Integer: {
 */
 case OP_Int64: {
   pTos++;
-  assert( pOp->p3!=0 );
+  assert( pOp->p3.p!=0 );
   pTos->flags = MEM_Int;
-  memcpy(&pTos->u.i, pOp->p3, 8);
+  memcpy(&pTos->u.i, pOp->p3.p, 8);
   break;
 }
 
@@ -747,7 +747,7 @@ case OP_Int64: {
 case OP_Real: {            /* same as TK_FLOAT, */
   pTos++;
   pTos->flags = MEM_Real;
-  memcpy(&pTos->r, pOp->p3, 8);
+  memcpy(&pTos->r, pOp->p3.p, 8);
   break;
 }
 
@@ -757,23 +757,23 @@ case OP_Real: {            /* same as TK_FLOAT, */
 ** into an OP_String before it is executed for the first time.
 */
 case OP_String8: {         /* same as TK_STRING */
-  assert( pOp->p3!=0 );
+  assert( pOp->p3.p!=0 );
   pOp->opcode = OP_String;
-  pOp->p1 = strlen(pOp->p3);
+  pOp->p1 = strlen(pOp->p3.p);
 
 #ifndef SQLITE_OMIT_UTF16
   if( encoding!=SQLITE_UTF8 ){
     pTos++;
-    sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC);
+    sqlite3VdbeMemSetStr(pTos, pOp->p3.p, -1, SQLITE_UTF8, SQLITE_STATIC);
     if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, encoding) ) goto no_mem;
     if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pTos) ) goto no_mem;
     pTos->flags &= ~(MEM_Dyn);
     pTos->flags |= MEM_Static;
     if( pOp->p3type==P3_DYNAMIC ){
-      sqlite3_free(pOp->p3);
+      sqlite3_free(pOp->p3.p);
     }
     pOp->p3type = P3_DYNAMIC;
-    pOp->p3 = pTos->z;
+    pOp->p3.p = pTos->z;
     pOp->p1 = pTos->n;
     if( pOp->p1>SQLITE_MAX_LENGTH ){
       goto too_big;
@@ -793,9 +793,9 @@ case OP_String8: {         /* same as TK_STRING */
 */
 case OP_String: {
   pTos++;
-  assert( pOp->p3!=0 );
+  assert( pOp->p3.p!=0 );
   pTos->flags = MEM_Str|MEM_Static|MEM_Term;
-  pTos->z = pOp->p3;
+  pTos->z = pOp->p3.p;
   pTos->n = pOp->p1;
   pTos->enc = encoding;
   break;
@@ -824,24 +824,24 @@ case OP_Null: {
 */
 case OP_HexBlob: {            /* same as TK_BLOB */
   pOp->opcode = OP_Blob;
-  pOp->p1 = strlen(pOp->p3)/2;
+  pOp->p1 = strlen(pOp->p3.p)/2;
   if( pOp->p1>SQLITE_MAX_LENGTH ){
     goto too_big;
   }
   if( pOp->p1 ){
-    char *zBlob = sqlite3HexToBlob(db, pOp->p3);
+    char *zBlob = sqlite3HexToBlob(db, pOp->p3.p);
     if( !zBlob ) goto no_mem;
     if( pOp->p3type==P3_DYNAMIC ){
-      sqlite3_free(pOp->p3);
+      sqlite3_free(pOp->p3.p);
     }
-    pOp->p3 = zBlob;
+    pOp->p3.p = zBlob;
     pOp->p3type = P3_DYNAMIC;
   }else{
     if( pOp->p3type==P3_DYNAMIC ){
-      sqlite3_free(pOp->p3);
+      sqlite3_free(pOp->p3.p);
     }
     pOp->p3type = P3_STATIC;
-    pOp->p3 = "";
+    pOp->p3.p = "";
   }
 
   /* Fall through to the next case, OP_Blob. */
@@ -859,7 +859,7 @@ case OP_HexBlob: {            /* same as TK_BLOB */
 case OP_Blob: {
   pTos++;
   assert( pOp->p1 <= SQLITE_MAX_LENGTH );
-  sqlite3VdbeMemSetStr(pTos, pOp->p3, pOp->p1, 0, 0);
+  sqlite3VdbeMemSetStr(pTos, pOp->p3.p, pOp->p1, 0, 0);
   pTos->enc = encoding;
   break;
 }
@@ -997,7 +997,7 @@ case OP_Callback: {            /* no-push */
   ** the stack.  Note that ephemeral data is never stored in memory 
   ** cells so we do not have to worry about them.
   */
-  pFirstColumn = &pTos[0-pOp->p1];
+  pFirstColumn = &pTos[1-pOp->p1];
   for(pMem = p->aStack; pMem<pFirstColumn; pMem++){
     Deephemeralize(pMem);
   }
@@ -1017,7 +1017,7 @@ case OP_Callback: {            /* no-push */
   /* Set up the statement structure so that it will pop the current
   ** results from the stack when the statement returns.
   */
-  p->resOnStack = 1;
+  p->pResultSet = pFirstColumn;
   p->nCallback++;
   p->popStack = pOp->p1;
   p->pc = pc + 1;
@@ -1026,6 +1026,56 @@ case OP_Callback: {            /* no-push */
   goto vdbe_return;
 }
 
+/* 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.
+*/
+case OP_ResultRow: {            /* no-push */
+  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
+  ** as side effect.
+  */
+  pMem = p->pResultSet = &p->aMem[pOp->p1];
+  for(i=0; i<pOp->p2; i++){
+    sqlite3VdbeMemNulTerminate(&pMem[i]);
+    storeTypeInfo(&pMem[i], encoding);
+  }
+
+  /* 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 *
 **
 ** Look at the first P1+2 elements of the stack.  Append them all 
@@ -1288,10 +1338,10 @@ case OP_Function: {
 
   assert( pOp->p3type==P3_FUNCDEF || pOp->p3type==P3_VDBEFUNC );
   if( pOp->p3type==P3_FUNCDEF ){
-    ctx.pFunc = (FuncDef*)pOp->p3;
+    ctx.pFunc = (FuncDef*)pOp->p3.p;
     ctx.pVdbeFunc = 0;
   }else{
-    ctx.pVdbeFunc = (VdbeFunc*)pOp->p3;
+    ctx.pVdbeFunc = (VdbeFunc*)pOp->p3.p;
     ctx.pFunc = ctx.pVdbeFunc->pFunc;
   }
 
@@ -1304,7 +1354,7 @@ case OP_Function: {
     assert( pOp>p->aOp );
     assert( pOp[-1].p3type==P3_COLLSEQ );
     assert( pOp[-1].opcode==OP_CollSeq );
-    ctx.pColl = (CollSeq *)pOp[-1].p3;
+    ctx.pColl = (CollSeq *)pOp[-1].p3.p;
   }
   if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
   (*ctx.pFunc->xFunc)(&ctx, n, apVal);
@@ -1329,7 +1379,7 @@ case OP_Function: {
   */
   if( ctx.pVdbeFunc ){
     sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1);
-    pOp->p3 = (char *)ctx.pVdbeFunc;
+    pOp->p3.p = (char *)ctx.pVdbeFunc;
     pOp->p3type = P3_VDBEFUNC;
   }
 
@@ -1724,10 +1774,10 @@ case OP_Ge: {             /* same as TK_GE, no-push */
     applyAffinity(pTos, affinity, encoding);
   }
 
-  assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 );
+  assert( pOp->p3type==P3_COLLSEQ || pOp->p3.p==0 );
   ExpandBlob(pNos);
   ExpandBlob(pTos);
-  res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3);
+  res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3.p);
   switch( pOp->opcode ){
     case OP_Eq:    res = res==0;     break;
     case OP_Ne:    res = res!=0;     break;
@@ -1982,19 +2032,22 @@ case OP_SetNumColumns: {       /* no-push */
 **
 ** Interpret the data that cursor P1 points to as a structure built using
 ** the MakeRecord instruction.  (See the MakeRecord opcode for additional
-** information about the format of the data.) Push onto the stack the value
-** of the P2-th column contained in the data. If there are less that (P2+1) 
-** values in the record, push a NULL onto the stack.
+** 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 an integer
+** register number, then the value is written into that register.
 **
 ** 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 push a NULL.  Or
-** if P3 is of type P3_MEM, then push the P3 value.  The P3 value will
-** be default value for a column that has been added using the ALTER TABLE
-** ADD COLUMN command.  If P3 is an ordinary string, just push a NULL.
-** When P3 is a string it is really just a comment describing the value
-** to be pushed, not a default value.
+** If the column contains fewer than P2 fields, then extract a NULL.  Or
+** if the next instruction is OP_DfltValue then the P3 argument to the
+** OP_DfltValue instruction will be a P3_MEM.  Use the P3 argument of
+** the OP_DfltValue instruction as the extracted value instead of NULL.
+** The OP_DfltValue P3 value will be a default value for a column 
+** that has been added using the ALTER TABLE ADD COLUMN command.
 */
 case OP_Column: {
   u32 payloadSize;   /* Number of bytes in the record */
@@ -2009,12 +2062,18 @@ case OP_Column: {
   int len;           /* The length of the serialized data for the column */
   int i;             /* Loop counter */
   char *zData;       /* Part of the record being decoded */
+  Mem *pDest;        /* Where to write the extracted value */
   Mem sMem;          /* For storing the record being decoded */
 
   sMem.flags = 0;
   assert( p1<p->nCursor );
-  pTos++;
-  pTos->flags = MEM_Null;
+  if( pOp->p3type==P3_INT32 ){
+    assert( pOp->p3.i>=0 && pOp->p3.i<p->nMem );
+    pDest = &p->aMem[pOp->p3.i];
+  }else{
+    pDest = ++pTos;
+  }
+  sqlite3VdbeMemSetNull(pDest);
 
   /* This block sets the variable payloadSize to be the total number of
   ** bytes in the record.
@@ -2071,8 +2130,8 @@ case OP_Column: {
 
   /* If payloadSize is 0, then just push a NULL onto the stack. */
   if( payloadSize==0 ){
-    assert( pTos->flags==MEM_Null );
-    break;
+    assert( pDest->flags==MEM_Null );
+    goto op_column_out;
   }
   if( payloadSize>SQLITE_MAX_LENGTH ){
     goto too_big;
@@ -2197,38 +2256,52 @@ case OP_Column: {
       }
       zData = sMem.z;
     }
-    sqlite3VdbeSerialGet((u8*)zData, aType[p2], pTos);
-    pTos->enc = encoding;
+    sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest);
+    pDest->enc = encoding;
   }else{
-    if( pOp->p3type==P3_MEM ){
-      sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static);
+    if( pOp[1].opcode==OP_DfltValue ){
+      assert( pOp[1].p3type==P3_MEM );
+      sqlite3VdbeMemShallowCopy(pDest, (Mem *)(pOp[1].p3.p), MEM_Static);
     }else{
-      pTos->flags = MEM_Null;
+      assert( pDest->flags==MEM_Null );
     }
   }
 
   /* If we dynamically allocated space to hold the data (in the
   ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
-  ** dynamically allocated space over to the pTos structure.
+  ** dynamically allocated space over to the pDest structure.
   ** This prevents a memory copy.
   */
   if( (sMem.flags & MEM_Dyn)!=0 ){
-    assert( pTos->flags & MEM_Ephem );
-    assert( pTos->flags & (MEM_Str|MEM_Blob) );
-    assert( pTos->z==sMem.z );
+    assert( pDest->flags & MEM_Ephem );
+    assert( pDest->flags & (MEM_Str|MEM_Blob) );
+    assert( pDest->z==sMem.z );
     assert( sMem.flags & MEM_Term );
-    pTos->flags &= ~MEM_Ephem;
-    pTos->flags |= MEM_Dyn|MEM_Term;
+    pDest->flags &= ~MEM_Ephem;
+    pDest->flags |= MEM_Dyn|MEM_Term;
   }
 
-  /* pTos->z might be pointing to sMem.zShort[].  Fix that so that we
+  /* pDest->z might be pointing to sMem.zShort[].  Fix that so that we
   ** can abandon sMem */
-  rc = sqlite3VdbeMemMakeWriteable(pTos);
+  rc = sqlite3VdbeMemMakeWriteable(pDest);
 
 op_column_out:
+  if( pOp[1].opcode==OP_DfltValue ){
+    pc++;
+  }
   break;
 }
 
+/* Opcode: DfltValue * * P3
+**
+** This instruction always follows an OP_Column.  This instruction
+** does nothing by itself.  It is just a place holder for the default
+** value for the previous OP_Column instruction.
+*/
+case OP_DfltValue: {       /* no-push */
+  assert( 0 );
+}
+
 /* Opcode: MakeRecord P1 P2 P3
 **
 ** Convert the top abs(P1) entries of the stack into a single entry
@@ -2265,6 +2338,24 @@ op_column_out:
 ** and appends that extra integer to the end of the record as a varint.
 ** This results in an index key.
 */
+/*
+** Opcode: RegMakeRec P1 P2 P3
+**
+** Works like OP_MakeRecord except data is taken from registers
+** rather than from the stack.  The P1 register is an integer which
+** is the number of register to use in building the new record.
+** Data is taken from P1+1, P1+2, ..., P1+mem[P1].
+*/
+/*
+** Opcode: RegMakeIRec P1 P2 P3
+**
+** Works like OP_MakeIdxRec except data is taken from registers
+** rather than from the stack.  The P1 register is an integer which
+** is the number of register to use in building the new record.
+** Data is taken from P1+1, P1+2, ..., P1+mem[P1].
+*/
+case OP_RegMakeRec:
+case OP_RegMakeIRec:
 case OP_MakeIdxRec:
 case OP_MakeRecord: {
   /* Assuming the record contains N fields, the record format looks
@@ -2302,14 +2393,31 @@ case OP_MakeRecord: {
   int i;                 /* Space used in zNewRecord[] */
   char zTemp[NBFS];      /* Space to hold small records */
 
-  leaveOnStack = ((pOp->p1<0)?1:0);
-  nField = pOp->p1 * (leaveOnStack?-1:1);
+  if( pOp->p1<0 ){
+    assert( pOp->opcode==OP_MakeRecord || pOp->opcode==OP_MakeIdxRec );
+    leaveOnStack = 1;
+    nField = -pOp->p1;
+  }else{
+    leaveOnStack = 0;
+    nField = pOp->p1;
+  }
   jumpIfNull = pOp->p2;
-  addRowid = pOp->opcode==OP_MakeIdxRec;
-  zAffinity = pOp->p3;
-
-  pData0 = &pTos[1-nField];
-  assert( pData0>=p->aStack );
+  addRowid = pOp->opcode==OP_MakeIdxRec || pOp->opcode==OP_RegMakeIRec;
+  zAffinity = pOp->p3.p;
+
+  if( pOp->opcode==OP_RegMakeRec || pOp->opcode==OP_RegMakeIRec ){
+    Mem *pCount;
+    assert( nField>=0 && nField<p->nMem );
+    pCount = &p->aMem[nField];
+    assert( pCount->flags & MEM_Int );
+    assert( pCount->u.i>=0 && pCount->u.i+nField<p->nMem );
+    assert( leaveOnStack==1 );
+    nField = pCount->u.i;
+    pData0 = &pCount[1];
+  }else{
+    pData0 = &pTos[1-nField];
+    assert( pData0>=p->aStack );
+  }
   containsNull = 0;
   file_format = p->minWriteFileFormat;
 
@@ -2771,10 +2879,10 @@ case OP_OpenWrite: {       /* no-push */
   /* We always provide a key comparison function.  If the table being
   ** opened is of type INTKEY, the comparision function will be ignored. */
   rc = sqlite3BtreeCursor(pX, p2, wrFlag,
-           sqlite3VdbeRecordCompare, pOp->p3,
+           sqlite3VdbeRecordCompare, pOp->p3.p,
            &pCur->pCursor);
   if( pOp->p3type==P3_KEYINFO ){
-    pCur->pKeyInfo = (KeyInfo*)pOp->p3;
+    pCur->pKeyInfo = (KeyInfo*)pOp->p3.p;
     pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
     pCur->pKeyInfo->enc = ENC(p->db);
   }else{
@@ -2869,15 +2977,15 @@ case OP_OpenEphemeral: {       /* no-push */
     ** opening it. If a transient table is required, just use the
     ** automatically created table with root-page 1 (an INTKEY table).
     */
-    if( pOp->p3 ){
+    if( pOp->p3.p ){
       int pgno;
       assert( pOp->p3type==P3_KEYINFO );
       rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); 
       if( rc==SQLITE_OK ){
         assert( pgno==MASTER_ROOT+1 );
         rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare,
-            pOp->p3, &pCx->pCursor);
-        pCx->pKeyInfo = (KeyInfo*)pOp->p3;
+            pOp->p3.p, &pCx->pCursor);
+        pCx->pKeyInfo = (KeyInfo*)pOp->p3.p;
         pCx->pKeyInfo->enc = ENC(p->db);
         pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
       }
@@ -3546,9 +3654,9 @@ case OP_Insert: {         /* no-push */
     pC->cacheStatus = CACHE_STALE;
 
     /* Invoke the update-hook if required. */
-    if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){
+    if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3.p ){
       const char *zDb = db->aDb[pC->iDb].zName;
-      const char *zTbl = pOp->p3;
+      const char *zTbl = pOp->p3.p;
       int op = ((pOp->p2 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
       assert( pC->isTable );
       db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey);
@@ -3586,7 +3694,7 @@ case OP_Delete: {        /* no-push */
     /* If the update-hook will be invoked, set iKey to the rowid of the
     ** row being deleted.
     */
-    if( db->xUpdateCallback && pOp->p3 ){
+    if( db->xUpdateCallback && pOp->p3.p ){
       assert( pC->isTable );
       if( pC->rowidIsValid ){
         iKey = pC->lastRowid;
@@ -3606,9 +3714,9 @@ case OP_Delete: {        /* no-push */
     pC->cacheStatus = CACHE_STALE;
 
     /* Invoke the update-hook if required. */
-    if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){
+    if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3.p ){
       const char *zDb = db->aDb[pC->iDb].zName;
-      const char *zTbl = pOp->p3;
+      const char *zTbl = pOp->p3.p;
       db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey);
       assert( pC->iDb>=0 );
     }
@@ -4058,8 +4166,8 @@ case OP_IdxGE: {        /* no-push */
     assert( pTos->flags & MEM_Blob );  /* Created using OP_MakeRecord */
     assert( pC->deferredMoveto==0 );
     ExpandBlob(pTos);
-    *pC->pIncrKey = pOp->p3!=0;
-    assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT );
+    *pC->pIncrKey = pOp->p3.p!=0;
+    assert( pOp->p3.p==0 || pOp->opcode!=OP_IdxGT );
     rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res);
     *pC->pIncrKey = 0;
     if( rc!=SQLITE_OK ){
@@ -4151,9 +4259,9 @@ case OP_Clear: {        /* no-push */
   */
 #if 0
   Btree *pBt = db->aDb[pOp->p2].pBt;
-  if( db->xUpdateCallback && pOp->p3 ){
+  if( db->xUpdateCallback && pOp->p3.p ){
     const char *zDb = db->aDb[pOp->p2].zName;
-    const char *zTbl = pOp->p3;
+    const char *zTbl = pOp->p3.p;
     BtCursor *pCur = 0;
     int fin = 0;
 
@@ -4259,7 +4367,7 @@ case OP_ParseSchema: {        /* no-push */
   initData.pzErrMsg = &p->zErrMsg;
   zSql = sqlite3MPrintf(db,
      "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s",
-     db->aDb[iDb].zName, zMaster, pOp->p3);
+     db->aDb[iDb].zName, zMaster, pOp->p3.p);
   if( zSql==0 ) goto no_mem;
   sqlite3SafetyOff(db);
   assert( db->init.busy==0 );
@@ -4299,7 +4407,7 @@ case OP_LoadAnalysis: {        /* no-push */
 ** schema consistent with what is on disk.
 */
 case OP_DropTable: {        /* no-push */
-  sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3);
+  sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3.p);
   break;
 }
 
@@ -4311,7 +4419,7 @@ case OP_DropTable: {        /* no-push */
 ** schema consistent with what is on disk.
 */
 case OP_DropIndex: {        /* no-push */
-  sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3);
+  sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3.p);
   break;
 }
 
@@ -4323,7 +4431,7 @@ case OP_DropIndex: {        /* no-push */
 ** schema consistent with what is on disk.
 */
 case OP_DropTrigger: {        /* no-push */
-  sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3);
+  sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3.p);
   break;
 }
 
@@ -4669,7 +4777,7 @@ case OP_AggStep: {        /* no-push */
     apVal[i] = pRec;
     storeTypeInfo(pRec, encoding);
   }
-  ctx.pFunc = (FuncDef*)pOp->p3;
+  ctx.pFunc = (FuncDef*)pOp->p3.p;
   assert( pOp->p1>=0 && pOp->p1<p->nMem );
   ctx.pMem = pMem = &p->aMem[pOp->p1];
   pMem->n++;
@@ -4683,7 +4791,7 @@ case OP_AggStep: {        /* no-push */
     assert( pOp>p->aOp );
     assert( pOp[-1].p3type==P3_COLLSEQ );
     assert( pOp[-1].opcode==OP_CollSeq );
-    ctx.pColl = (CollSeq *)pOp[-1].p3;
+    ctx.pColl = (CollSeq *)pOp[-1].p3.p;
   }
   (ctx.pFunc->xStep)(&ctx, n, apVal);
   popStack(&pTos, n);
@@ -4712,7 +4820,7 @@ case OP_AggFinal: {        /* no-push */
   assert( pOp->p1>=0 && pOp->p1<p->nMem );
   pMem = &p->aMem[pOp->p1];
   assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
-  rc = sqlite3VdbeMemFinalize(pMem, (FuncDef*)pOp->p3);
+  rc = sqlite3VdbeMemFinalize(pMem, (FuncDef*)pOp->p3.p);
   if( rc==SQLITE_ERROR ){
     sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pMem), (char*)0);
   }
@@ -4805,7 +4913,7 @@ case OP_TableLock: {        /* no-push */
   assert( (p->btreeMask & (1<<p1))!=0 );
   rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
   if( rc==SQLITE_LOCKED ){
-    const char *z = (const char *)pOp->p3;
+    const char *z = (const char *)pOp->p3.p;
     sqlite3SetString(&p->zErrMsg, "database table is locked: ", z, (char*)0);
   }
   break;
@@ -4819,7 +4927,7 @@ case OP_TableLock: {        /* no-push */
 ** for that table.
 */
 case OP_VBegin: {   /* no-push */
-  rc = sqlite3VtabBegin(db, (sqlite3_vtab *)pOp->p3);
+  rc = sqlite3VtabBegin(db, (sqlite3_vtab *)pOp->p3.p);
   break;
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -4831,7 +4939,7 @@ case OP_VBegin: {   /* no-push */
 ** for that table.
 */
 case OP_VCreate: {   /* no-push */
-  rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p3, &p->zErrMsg);
+  rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p3.p, &p->zErrMsg);
   break;
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -4844,7 +4952,7 @@ case OP_VCreate: {   /* no-push */
 */
 case OP_VDestroy: {   /* no-push */
   p->inVtabMethod = 2;
-  rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p3);
+  rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p3.p);
   p->inVtabMethod = 0;
   break;
 }
@@ -4861,7 +4969,7 @@ case OP_VOpen: {   /* no-push */
   Cursor *pCur = 0;
   sqlite3_vtab_cursor *pVtabCursor = 0;
 
-  sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
+  sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3.p);
   sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
 
   assert(pVtab && pModule);
@@ -4935,7 +5043,7 @@ case OP_VFilter: {   /* no-push */
 
     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
     p->inVtabMethod = 1;
-    rc = pModule->xFilter(pCur->pVtabCursor, pTos->u.i, pOp->p3, nArg, apArg);
+    rc = pModule->xFilter(pCur->pVtabCursor, pTos->u.i, pOp->p3.p, nArg, apArg);
     p->inVtabMethod = 0;
     if( rc==SQLITE_OK ){
       res = pModule->xEof(pCur->pVtabCursor);
@@ -5080,7 +5188,7 @@ case OP_VNext: {   /* no-push */
 ** to the xRename method.
 */
 case OP_VRename: {   /* no-push */
-  sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
+  sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3.p);
   assert( pVtab->pModule->xRename );
 
   Stringify(pTos, encoding);
@@ -5121,7 +5229,7 @@ case OP_VRename: {   /* no-push */
 ** is set to the value of the rowid for the row just inserted.
 */
 case OP_VUpdate: {   /* no-push */
-  sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
+  sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3.p);
   sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
   int nArg = pOp->p2;
   assert( pOp->p3type==P3_VTAB );
index eee9db2a0eb74ef494153ffdc742903f018187f8..7c4b6caf54b798c3e06771ba2d62db201f3dd340 100644 (file)
@@ -15,7 +15,7 @@
 ** or VDBE.  The VDBE implements an abstract machine that runs a
 ** simple program to access and modify the underlying database.
 **
-** $Id: vdbe.h,v 1.115 2007/11/14 06:48:48 danielk1977 Exp $
+** $Id: vdbe.h,v 1.116 2008/01/02 00:34:37 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -35,10 +35,16 @@ typedef struct Vdbe Vdbe;
 */
 struct VdbeOp {
   u8 opcode;          /* What operation to perform */
+  char p3type;        /* One of the P3_xxx constants defined below */
   int p1;             /* First operand */
   int p2;             /* Second parameter (often the jump destination) */
-  char *p3;           /* Third parameter */
-  int p3type;         /* One of the P3_xxx constants defined below */
+  union {             /* Third parameter */
+    int i;              /* Integer value if p3type==P3_INT32 */
+    char *p;            /* A pointer for all other value sof p3type */
+  } p3;
+#ifdef SQLITE_DEBUG
+  char *zComment;     /* Comment to improve readability */
+#endif
 #ifdef VDBE_PROFILE
   int cnt;            /* Number of times this instruction was executed */
   long long cycles;   /* Total time spend executing this instruction */
@@ -74,6 +80,7 @@ typedef struct VdbeOpList VdbeOpList;
 #define P3_MPRINTF  (-11) /* P3 is a string obtained from sqlite3_mprintf() */
 #define P3_REAL     (-12) /* P3 is a 64-bit floating point value */
 #define P3_INT64    (-13) /* P3 is a 64-bit signed integer */
+#define P3_INT32    (-14) /* P3 is a 32-bit signed integer */
 
 /* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure
 ** is made.  That copy is freed when the Vdbe is finalized.  But if the
@@ -116,6 +123,7 @@ typedef struct VdbeOpList VdbeOpList;
 Vdbe *sqlite3VdbeCreate(sqlite3*);
 int sqlite3VdbeAddOp(Vdbe*,int,int,int);
 int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int);
+int sqlite3VdbeOp3Int(Vdbe*,int,int,int,int);
 int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
 void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
 void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
index a807bdda33da0a4620fc76c9cc414237e900b41d..4c4111f23a359259cc27da3f498b7e8305839b27 100644 (file)
@@ -323,7 +323,7 @@ struct Vdbe {
   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 */
-  u8 resOnStack;          /* True if there are result values on the stack */
+  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 e340f27a8a75f7f3f361cf585df8d67bf0d54489..eb854c43fe48c31647da2871e56fecdb99ce3bfc 100644 (file)
@@ -293,10 +293,10 @@ static int sqlite3Step(Vdbe *p){
     if( db->xTrace && !db->init.busy ){
       assert( p->nOp>0 );
       assert( p->aOp[p->nOp-1].opcode==OP_Noop );
-      assert( p->aOp[p->nOp-1].p3!=0 );
+      assert( p->aOp[p->nOp-1].p3.p!=0 );
       assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC );
       sqlite3SafetyOff(db);
-      db->xTrace(db->pTraceArg, p->aOp[p->nOp-1].p3);
+      db->xTrace(db->pTraceArg, p->aOp[p->nOp-1].p3.p);
       if( sqlite3SafetyOn(db) ){
         p->rc = SQLITE_MISUSE;
         return SQLITE_MISUSE;
@@ -314,7 +314,7 @@ static int sqlite3Step(Vdbe *p){
     */
 #ifdef SQLITE_DEBUG
     if( (db->flags & SQLITE_SqlTrace)!=0 ){
-      sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3);
+      sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3.p);
     }
 #endif /* SQLITE_DEBUG */
 
@@ -345,9 +345,9 @@ static int sqlite3Step(Vdbe *p){
     elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime;
     assert( p->nOp>0 );
     assert( p->aOp[p->nOp-1].opcode==OP_Noop );
-    assert( p->aOp[p->nOp-1].p3!=0 );
+    assert( p->aOp[p->nOp-1].p3.p!=0 );
     assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC );
-    db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3, elapseTime);
+    db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3.p, elapseTime);
   }
 #endif
 
@@ -564,7 +564,7 @@ int sqlite3_column_count(sqlite3_stmt *pStmt){
 */
 int sqlite3_data_count(sqlite3_stmt *pStmt){
   Vdbe *pVm = (Vdbe *)pStmt;
-  if( pVm==0 || !pVm->resOnStack ) return 0;
+  if( pVm==0 || pVm->pResultSet==0 ) return 0;
   return pVm->nResColumn;
 }
 
@@ -581,10 +581,10 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
   Mem *pOut;
 
   pVm = (Vdbe *)pStmt;
-  if( pVm && pVm->resOnStack && i<pVm->nResColumn && i>=0 ){
+  if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
     sqlite3_mutex_enter(pVm->db->mutex);
     vals = sqlite3_data_count(pStmt);
-    pOut = &pVm->pTos[(1-vals)+i];
+    pOut = &pVm->pResultSet[i];
   }else{
     static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL };
     if( pVm->db ){
@@ -1001,7 +1001,7 @@ static void createVarMap(Vdbe *p){
       for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){
         if( pOp->opcode==OP_Variable ){
           assert( pOp->p1>0 && pOp->p1<=p->nVar );
-          p->azVar[pOp->p1-1] = pOp->p3;
+          p->azVar[pOp->p1-1] = pOp->p3.p;
         }
       }
       p->okVar = 1;
index b5239d650b0ef18e9a274d21c7392aa1699d852c..69d1612a755adfb56894e34e3a7c0f8f01d853ba 100644 (file)
@@ -152,7 +152,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
   pOp->opcode = op;
   pOp->p1 = p1;
   pOp->p2 = p2;
-  pOp->p3 = 0;
+  pOp->p3.p = 0;
   pOp->p3type = P3_NOTUSED;
   p->expired = 0;
 #ifdef SQLITE_DEBUG
@@ -162,14 +162,38 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
 }
 
 /*
-** Add an opcode that includes the p3 value.
+** Add an opcode that includes the p3 value as a pointer.
 */
-int sqlite3VdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3,int p3type){
+int sqlite3VdbeOp3(
+  Vdbe *p,            /* Add the opcode to this VM */
+  int op,             /* The new opcode */
+  int p1, int p2,     /* P1 and P2 operands */
+  const char *zP3,    /* The P3 operand */
+  int p3type          /* P3 operand type */
+){
   int addr = sqlite3VdbeAddOp(p, op, p1, p2);
   sqlite3VdbeChangeP3(p, addr, zP3, p3type);
   return addr;
 }
 
+/*
+** Add an opcode that includes the p3 value as an integer.
+*/
+int sqlite3VdbeOp3Int(
+  Vdbe *p,            /* Add the opcode to this VM */
+  int op,             /* The new opcode */
+  int p1, int p2,     /* P1 and P2 operands */
+  int p3              /* The P3 operand */
+){
+  int addr = sqlite3VdbeAddOp(p, op, p1, p2);
+  if( !p->db->mallocFailed ){
+    Op *pOp = &p->aOp[addr];
+    pOp->p3.i = p3;
+    pOp->p3type = P3_INT32;
+  }
+  return addr;
+}
+
 /*
 ** Create a new symbolic label for an instruction that has yet to be
 ** coded.  The symbolic label is really just a negative number.  The
@@ -378,7 +402,7 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
       pOut->opcode = pIn->opcode;
       pOut->p1 = pIn->p1;
       pOut->p2 = p2<0 ? addr + ADDR(p2) : p2;
-      pOut->p3 = pIn->p3;
+      pOut->p3.p = pIn->p3;
       pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED;
 #ifdef SQLITE_DEBUG
       if( sqlite3_vdbe_addop_trace ){
@@ -477,7 +501,7 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
   if( p && p->aOp ){
     VdbeOp *pOp = &p->aOp[addr];
     while( N-- ){
-      freeP3(pOp->p3type, pOp->p3);
+      freeP3(pOp->p3type, pOp->p3.p);
       memset(pOp, 0, sizeof(pOp[0]));
       pOp->opcode = OP_Noop;
       pOp++;
@@ -524,10 +548,10 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
     if( addr<0 ) return;
   }
   pOp = &p->aOp[addr];
-  freeP3(pOp->p3type, pOp->p3);
-  pOp->p3 = 0;
+  freeP3(pOp->p3type, pOp->p3.p);
+  pOp->p3.p = 0;
   if( zP3==0 ){
-    pOp->p3 = 0;
+    pOp->p3.p = 0;
     pOp->p3type = P3_NOTUSED;
   }else if( n==P3_KEYINFO ){
     KeyInfo *pKeyInfo;
@@ -536,7 +560,7 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
     nField = ((KeyInfo*)zP3)->nField;
     nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;
     pKeyInfo = sqlite3_malloc( nByte );
-    pOp->p3 = (char*)pKeyInfo;
+    pOp->p3.p = (char*)pKeyInfo;
     if( pKeyInfo ){
       unsigned char *aSortOrder;
       memcpy(pKeyInfo, zP3, nByte);
@@ -551,29 +575,28 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
       pOp->p3type = P3_NOTUSED;
     }
   }else if( n==P3_KEYINFO_HANDOFF ){
-    pOp->p3 = (char*)zP3;
+    pOp->p3.p = (char*)zP3;
     pOp->p3type = P3_KEYINFO;
   }else if( n<0 ){
-    pOp->p3 = (char*)zP3;
+    pOp->p3.p = (char*)zP3;
     pOp->p3type = n;
   }else{
     if( n==0 ) n = strlen(zP3);
-    pOp->p3 = sqlite3DbStrNDup(p->db, zP3, n);
+    pOp->p3.p = sqlite3DbStrNDup(p->db, zP3, n);
     pOp->p3type = P3_DYNAMIC;
   }
 }
 
 #ifndef NDEBUG
 /*
-** Replace the P3 field of the most recently coded instruction with
-** comment text.
+** Change the comment on the the most recently coded instruction.
 */
 void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
   va_list ap;
   assert( p->nOp>0 || p->aOp==0 );
-  assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 || p->db->mallocFailed );
+  assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
   va_start(ap, zFormat);
-  sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(p->db, zFormat, ap), P3_DYNAMIC);
+  p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap);
   va_end(ap);
 }
 #endif
@@ -594,12 +617,13 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
 ** Use zTemp for any required temporary buffer space.
 */
 static char *displayP3(Op *pOp, char *zTemp, int nTemp){
-  char *zP3;
+  char *zP3 = zTemp;
+  int nP3;
   assert( nTemp>=20 );
   switch( pOp->p3type ){
     case P3_KEYINFO: {
       int i, j;
-      KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3;
+      KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3.p;
       sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
       i = strlen(zTemp);
       for(j=0; j<pKeyInfo->nField; j++){
@@ -624,47 +648,63 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){
       zTemp[i++] = ')';
       zTemp[i] = 0;
       assert( i<nTemp );
-      zP3 = zTemp;
       break;
     }
     case P3_COLLSEQ: {
-      CollSeq *pColl = (CollSeq*)pOp->p3;
+      CollSeq *pColl = (CollSeq*)pOp->p3.p;
       sqlite3_snprintf(nTemp, zTemp, "collseq(%.20s)", pColl->zName);
-      zP3 = zTemp;
       break;
     }
     case P3_FUNCDEF: {
-      FuncDef *pDef = (FuncDef*)pOp->p3;
+      FuncDef *pDef = (FuncDef*)pOp->p3.p;
       sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);
-      zP3 = zTemp;
       break;
     }
     case P3_INT64: {
-      sqlite3_snprintf(nTemp, zTemp, "%lld", *(sqlite3_int64*)pOp->p3);
-      zP3 = zTemp;
+      sqlite3_snprintf(nTemp, zTemp, "%lld", *(sqlite3_int64*)pOp->p3.p);
+      break;
+    }
+    case P3_INT32: {
+      sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p3.i);
       break;
     }
     case P3_REAL: {
-      sqlite3_snprintf(nTemp, zTemp, "%.16g", *(double*)pOp->p3);
-      zP3 = zTemp;
+      sqlite3_snprintf(nTemp, zTemp, "%.16g", *(double*)pOp->p3.p);
+      break;
+    }
+    case P3_MEM: {
+      Mem *pMem = (Mem*)pOp->p3.p;
+      if( pMem->flags & MEM_Str ){
+        zP3 = pMem->z;
+      }else if( pMem->flags & MEM_Int ){
+        sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i);
+      }else if( pMem->flags & MEM_Real ){
+        sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r);
+      }else if( pMem->flags & MEM_Null ){
+        sqlite3_snprintf(nTemp, zTemp, "NULL");
+      }
       break;
     }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
     case P3_VTAB: {
-      sqlite3_vtab *pVtab = (sqlite3_vtab*)pOp->p3;
+      sqlite3_vtab *pVtab = (sqlite3_vtab*)pOp->p3.p;
       sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
-      zP3 = zTemp;
       break;
     }
 #endif
     default: {
-      zP3 = pOp->p3;
+      zP3 = pOp->p3.p;
       if( zP3==0 || pOp->opcode==OP_Noop ){
-        zP3 = "";
+        zP3 = zTemp;
+        zTemp[0] = 0;
       }
     }
   }
   assert( zP3!=0 );
+  if( pOp->zComment && zP3==zTemp && (nP3 = strlen(zP3))<nTemp ){
+    sqlite3_snprintf(nTemp-nP3, &zP3[nP3], "%s# %s",
+                     nP3>0 ? " " : "", pOp->zComment);
+  }
   return zP3;
 }
 #endif
@@ -737,10 +777,10 @@ int sqlite3VdbeList(
   ** the stack, they may become dynamic if the user calls
   ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
   */
-  if( p->pTos==&p->aStack[4] ){
-    releaseMemArray(p->aStack, 5);
+  if( p->pResultSet ){
+    releaseMemArray(p->pResultSet, 5);
+    p->pResultSet = 0;
   }
-  p->resOnStack = 0;
 
   do{
     i = p->pc++;
@@ -754,7 +794,7 @@ int sqlite3VdbeList(
     sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);
   }else{
     Op *pOp = &p->aOp[i];
-    Mem *pMem = p->aStack;
+    Mem *pMem = p->pResultSet = p->aStack;
     pMem->flags = MEM_Int;
     pMem->type = SQLITE_INTEGER;
     pMem->u.i = i;                                /* Program counter */
@@ -778,7 +818,7 @@ int sqlite3VdbeList(
     pMem->type = SQLITE_INTEGER;
     pMem++;
 
-    pMem->flags = MEM_Ephem|MEM_Str|MEM_Term;   /* P3 */
+    pMem->flags = MEM_Ephem|MEM_Str|MEM_Term;     /* P3 */
     pMem->z = displayP3(pOp, pMem->zShort, sizeof(pMem->zShort));
     assert( pMem->z!=0 );
     pMem->n = strlen(pMem->z);
@@ -788,7 +828,6 @@ int sqlite3VdbeList(
     p->nResColumn = 5 - 2*(p->explain-1);
     p->pTos = pMem;
     p->rc = SQLITE_OK;
-    p->resOnStack = 1;
     rc = SQLITE_ROW;
   }
   return rc;
@@ -804,8 +843,8 @@ void sqlite3VdbePrintSql(Vdbe *p){
   VdbeOp *pOp;
   if( nOp<1 ) return;
   pOp = &p->aOp[nOp-1];
-  if( pOp->opcode==OP_Noop && pOp->p3!=0 ){
-    const char *z = pOp->p3;
+  if( pOp->opcode==OP_Noop && pOp->p3.p!=0 ){
+    const char *z = pOp->p3.p;
     while( isspace(*(u8*)z) ) z++;
     printf("SQL: [%s]\n", z);
   }
@@ -822,10 +861,10 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
   if( sqlite3_io_trace==0 ) return;
   if( nOp<1 ) return;
   pOp = &p->aOp[nOp-1];
-  if( pOp->opcode==OP_Noop && pOp->p3!=0 ){
+  if( pOp->opcode==OP_Noop && pOp->p3.p!=0 ){
     int i, j;
     char z[1000];
-    sqlite3_snprintf(sizeof(z), z, "%s", pOp->p3);
+    sqlite3_snprintf(sizeof(z), z, "%s", pOp->p3.p);
     for(i=0; isspace((unsigned char)z[i]); i++){}
     for(j=0; z[i]; i++){
       if( isspace((unsigned char)z[i]) ){
@@ -1024,7 +1063,7 @@ static void Cleanup(Vdbe *p){
   p->contextStackTop = 0;
   sqlite3_free(p->zErrMsg);
   p->zErrMsg = 0;
-  p->resOnStack = 0;
+  p->pResultSet = 0;
 }
 
 /*
@@ -1685,9 +1724,12 @@ void sqlite3VdbeDelete(Vdbe *p){
     p->pNext->pPrev = p->pPrev;
   }
   if( p->aOp ){
-    for(i=0; i<p->nOp; i++){
-      Op *pOp = &p->aOp[i];
-      freeP3(pOp->p3type, pOp->p3);
+    Op *pOp = p->aOp;
+    for(i=0; i<p->nOp; i++, pOp++){
+      freeP3(pOp->p3type, pOp->p3.p);
+#ifdef SQLITE_DEBUG
+      sqlite3_free(pOp->zComment);
+#endif     
     }
     sqlite3_free(p->aOp);
   }
index 424df979b1229d60a7b9094f344cb8c749583359..dfe349f7c58051a02ebb3474df0647aa3591b8c4 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.266 2007/12/12 17:42:53 danielk1977 Exp $
+** $Id: where.c,v 1.267 2008/01/02 00:34:37 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1744,7 +1744,7 @@ static void codeEqualityTerm(
     eType = sqlite3FindInIndex(pParse, pX, 1);
     iTab = pX->iTable;
     sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
-    VdbeComment((v, "%.*s", pX->span.n, pX->span.z));
+    VdbeComment((v, "%.*s", pX->span.n, pX->span.z));
     if( pLevel->nIn==0 ){
       pLevel->nxt = sqlite3VdbeMakeLabel(v);
     }
@@ -2212,7 +2212,7 @@ WhereInfo *sqlite3WhereBegin(
       KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
       assert( pIx->pSchema==pTab->pSchema );
       sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
-      VdbeComment((v, "%s", pIx->zName));
+      VdbeComment((v, "%s", pIx->zName));
       sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum,
                      (char*)pKey, P3_KEYINFO_HANDOFF);
       sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
@@ -2263,7 +2263,7 @@ WhereInfo *sqlite3WhereBegin(
       if( !pParse->nMem ) pParse->nMem++;
       pLevel->iLeftJoin = pParse->nMem++;
       sqlite3VdbeAddOp(v, OP_MemInt, 0, pLevel->iLeftJoin);
-      VdbeComment((v, "init LEFT JOIN no-match flag"));
+      VdbeComment((v, "init LEFT JOIN no-match flag"));
     }
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -2606,7 +2606,7 @@ WhereInfo *sqlite3WhereBegin(
     if( pLevel->iLeftJoin ){
       pLevel->top = sqlite3VdbeCurrentAddr(v);
       sqlite3VdbeAddOp(v, OP_MemInt, 1, pLevel->iLeftJoin);
-      VdbeComment((v, "record LEFT JOIN hit"));
+      VdbeComment((v, "record LEFT JOIN hit"));
       for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){
         if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
         if( (pTerm->prereqAll & notReady)!=0 ) continue;