Update OP_Rowid, OP_Column and related opcodes to use registers. (CVS 4671)

FossilOrigin-Name: 4f3967073d2df9eae5a61b9770d5de2e1af47b4c
diff --git a/src/expr.c b/src/expr.c
index 89b820b..c6f6f41 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.327 2008/01/03 18:03:09 drh Exp $
+** $Id: expr.c,v 1.328 2008/01/03 18:44:59 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1897,23 +1897,29 @@
 
 /*
 ** Generate code that will extract the iColumn-th column from
-** table pTab and push that column value on the stack.  There
-** is an open cursor to pTab in iTable.  If iColumn<0 then
-** code is generated that extracts the rowid.
+** table pTab and store the column value in register iMem, or on
+** the stack if iMem==0.  There is an open cursor to pTab in 
+** iTable.  If iColumn<0 then code is generated that extracts the rowid.
 */
-void sqlite3ExprCodeGetColumn(Vdbe *v, Table *pTab, int iColumn, int iTable){
+void sqlite3ExprCodeGetColumn(
+  Vdbe *v,         /* The VM being created */
+  Table *pTab,     /* Description of the table we are reading from */
+  int iColumn,     /* Index of the table column */
+  int iTable,      /* The cursor pointing to the table */
+  int iReg         /* Store results here */
+){
   if( iColumn<0 ){
     int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
-    sqlite3VdbeAddOp1(v, op, iTable);
+    sqlite3VdbeAddOp2(v, op, iTable, iReg);
   }else if( pTab==0 ){
-    sqlite3VdbeAddOp2(v, OP_Column, iTable, iColumn);
+    sqlite3VdbeAddOp3(v, OP_Column, iTable, iColumn, iReg);
   }else{
     int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
-    sqlite3VdbeAddOp2(v, op, iTable, iColumn);
+    sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg);
     sqlite3ColumnDefault(v, pTab, iColumn);
 #ifndef SQLITE_OMIT_FLOATING_POINT
     if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){
-      sqlite3VdbeAddOp0(v, OP_RealAffinity);
+      sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
     }
 #endif
   }
@@ -1960,7 +1966,8 @@
         assert( pParse->ckOffset>0 );
         sqlite3VdbeAddOp2(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1);
       }else{
-        sqlite3ExprCodeGetColumn(v, pExpr->pTab, pExpr->iColumn, pExpr->iTable);
+        sqlite3ExprCodeGetColumn(v, pExpr->pTab,
+                                 pExpr->iColumn, pExpr->iTable, 0);
       }
       break;
     }
@@ -2361,12 +2368,19 @@
 */
 int sqlite3ExprIntoReg(Parse *pParse, Expr *pExpr, int target){
   Vdbe *v = pParse->pVdbe;
-  if( v==0 ) return -1;
-  sqlite3ExprCode(pParse, pExpr);
-  if( target<0 ){
+  assert( v!=0 || pParse->db->mallocFailed );
+  assert( pExpr!=0 || pParse->db->mallocFailed );
+  if( v==0 || pExpr==0 ) return -1;
+  if( target<=0 ){
     target = ++pParse->nMem;
   }
-  sqlite3VdbeAddOp2(v, OP_MemStore, target, 1);
+  if( pExpr->op==TK_COLUMN && pExpr->iTable>=0 ){
+    sqlite3ExprCodeGetColumn(v, pExpr->pTab,
+                             pExpr->iColumn, pExpr->iTable, target);
+  }else{
+    sqlite3ExprCode(pParse, pExpr);
+    sqlite3VdbeAddOp2(v, OP_MemStore, target, 1);
+  }
   return target;
 }
 
diff --git a/src/select.c b/src/select.c
index de8fd17..61ccbc4 100644
--- a/src/select.c
+++ b/src/select.c
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.381 2008/01/03 18:03:09 drh Exp $
+** $Id: select.c,v 1.382 2008/01/03 18:44:59 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -3524,7 +3524,7 @@
         for(i=0; i<sAggInfo.nColumn; i++){
           struct AggInfo_col *pCol = &sAggInfo.aCol[i];
           if( pCol->iSorterColumn<j ) continue;
-          sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn, pCol->iTable);
+          sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn,pCol->iTable,0);
           j++;
         }
         sqlite3VdbeAddOp2(v, OP_MakeRecord, j, 0);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index fad6ca9..bbac412 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.634 2008/01/03 17:31:45 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.635 2008/01/03 18:44:59 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1737,7 +1737,7 @@
 void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
 WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**);
 void sqlite3WhereEnd(WhereInfo*);
-void sqlite3ExprCodeGetColumn(Vdbe*, Table*, int, int);
+void sqlite3ExprCodeGetColumn(Vdbe*, Table*, int, int, int);
 void sqlite3ExprCode(Parse*, Expr*);
 void sqlite3ExprCodeAndCache(Parse*, Expr*);
 int sqlite3ExprIntoReg(Parse*,Expr*,int);
diff --git a/src/vdbe.c b/src/vdbe.c
index d94a1d0..6acdc0b 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.672 2008/01/03 18:39:42 danielk1977 Exp $
+** $Id: vdbe.c,v 1.673 2008/01/03 18:44:59 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1537,9 +1537,9 @@
   break;
 }
 
-/* Opcode: RealAffinity * * *
+/* Opcode: RealAffinity P1 * *
 **
-** If the top of the stack is an integer, convert it to a real value.
+** If register P1 holds an integer convert it to a real value.
 **
 ** This opcode is used when extracting information from a column that
 ** has REAL affinity.  Such column values may still be stored as
@@ -1547,9 +1547,16 @@
 ** to have only a real value.
 */
 case OP_RealAffinity: {                  /* no-push */
-  assert( pTos>=p->aStack );
-  if( pTos->flags & MEM_Int ){
-    sqlite3VdbeMemRealify(pTos);
+  assert( pOp->p1>=0 && pOp->p1<=p->nMem );
+  if( pOp->p1==0 ){
+    if( pTos->flags & MEM_Int ){
+      sqlite3VdbeMemRealify(pTos);
+    }
+  }else{
+    Mem *pX = &p->aMem[pOp->p1];
+    if( pX->flags & MEM_Int ){
+      sqlite3VdbeMemRealify(pX);
+    }
   }
   break;
 }
@@ -3802,36 +3809,43 @@
   break;
 }
 
-/* Opcode: Rowid P1 * *
+/* Opcode: Rowid P1 P2 * * *
 **
-** Push onto the stack an integer which is the key of the table entry that
-** P1 is currently point to.
+** Store in register P2 an integer which is the key of the table entry that
+** P1 is currently point to.  If p2==0 then pust the integer.
 */
 case OP_Rowid: {
   int i = pOp->p1;
   Cursor *pC;
   i64 v;
+  Mem *pDest;
 
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
   assert( pC!=0 );
   rc = sqlite3VdbeCursorMoveto(pC);
   if( rc ) goto abort_due_to_error;
-  pTos++;
+  if( pOp->p2>0 ){
+    assert( pOp->p2<=p->nMem );
+    pDest = &p->aMem[pOp->p2];
+    sqlite3VdbeMemRelease(pDest);
+  }else{
+    pDest = ++pTos;
+  }
   if( pC->rowidIsValid ){
     v = pC->lastRowid;
   }else if( pC->pseudoTable ){
     v = keyToInt(pC->iKey);
   }else if( pC->nullRow || pC->pCursor==0 ){
-    pTos->flags = MEM_Null;
+    pDest->flags = MEM_Null;
     break;
   }else{
     assert( pC->pCursor!=0 );
     sqlite3BtreeKeySize(pC->pCursor, &v);
     v = keyToInt(v);
   }
-  pTos->u.i = v;
-  pTos->flags = MEM_Int;
+  pDest->u.i = v;
+  pDest->flags = MEM_Int;
   break;
 }
 
@@ -4051,9 +4065,9 @@
   break;
 }
 
-/* Opcode: IdxRowid P1 * *
+/* Opcode: IdxRowid P1 P2 * * *
 **
-** Push onto the stack an integer which is the last entry in the record at
+** Write into register P2 an integer which is the last entry in the record at
 ** the end of the index key pointed to by cursor P1.  This integer should be
 ** the rowid of the table entry to which this index entry points.
 **
@@ -4063,25 +4077,32 @@
   int i = pOp->p1;
   BtCursor *pCrsr;
   Cursor *pC;
+  Mem *pDest;
 
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
-  pTos++;
-  pTos->flags = MEM_Null;
+  if( pOp->p2>0 ){
+    assert( pOp->p2<=p->nMem );
+    pDest = &p->aMem[pOp->p2];
+    sqlite3VdbeMemRelease(pDest);
+  }else{
+    pDest = ++pTos;
+  }
+  pDest->flags = MEM_Null;
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     i64 rowid;
 
     assert( pC->deferredMoveto==0 );
     assert( pC->isTable==0 );
     if( pC->nullRow ){
-      pTos->flags = MEM_Null;
+      pDest->flags = MEM_Null;
     }else{
       rc = sqlite3VdbeIdxRowid(pCrsr, &rowid);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
-      pTos->flags = MEM_Int;
-      pTos->u.i = rowid;
+      pDest->flags = MEM_Int;
+      pDest->u.i = rowid;
     }
   }
   break;
@@ -5051,10 +5072,11 @@
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VRowid P1 * *
+/* Opcode: VRowid P1 P2 *
 **
-** Push an integer onto the stack which is the rowid of
+** Store into register P2  the rowid of
 ** the virtual-table that the P1 cursor is pointing to.
+** If P2==0, push the value onto the stack.
 */
 case OP_VRowid: {
   const sqlite3_module *pModule;
@@ -5067,14 +5089,21 @@
     rc = SQLITE_ERROR;
   } else {
     sqlite_int64 iRow;
+    Mem *pDest;
 
     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
     rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
     if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
 
-    pTos++;
-    pTos->flags = MEM_Int;
-    pTos->u.i = iRow;
+    if( pOp->p2>0 ){
+      assert( pOp->p2<=p->nMem );
+      pDest = &p->aMem[pOp->p2];
+      sqlite3VdbeMemRelease(pDest);
+    }else{
+      pDest = ++pTos;
+    }
+    pDest->flags = MEM_Int;
+    pDest->u.i = iRow;
   }
 
   break;
@@ -5082,10 +5111,12 @@
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VColumn P1 P2 *
+/* Opcode: VColumn P1 P2 P3
 **
-** Push onto the stack the value of the P2-th column of
-** the row of the virtual-table that the P1 cursor is pointing to.
+** Store the value of the P2-th column of
+** the row of the virtual-table that the 
+** P1 cursor is pointing to into register P3.
+** Or if P3==0 push the value onto the stack.
 */
 case OP_VColumn: {
   const sqlite3_module *pModule;
@@ -5097,6 +5128,7 @@
     sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xColumn", 0);
     rc = SQLITE_ERROR;
   } else {
+    Mem *pDest;
     sqlite3_context sContext;
     memset(&sContext, 0, sizeof(sContext));
     sContext.s.flags = MEM_Null;
@@ -5109,14 +5141,19 @@
     ** dynamic allocation in sContext.s (a Mem struct) is  released.
     */
     sqlite3VdbeChangeEncoding(&sContext.s, encoding);
-    pTos++;
-    pTos->flags = 0;
-    sqlite3VdbeMemMove(pTos, &sContext.s);
+    if( pOp->p3>0 ){
+      assert( pOp->p3<=p->nMem );
+      pDest = &p->aMem[pOp->p3];
+    }else{
+      pDest = ++pTos;
+      pDest->flags = 0;
+    }
+    sqlite3VdbeMemMove(pDest, &sContext.s);
 
     if( sqlite3SafetyOn(db) ){
       goto abort_due_to_misuse;
     }
-    if( sqlite3VdbeMemTooBig(pTos) ){
+    if( sqlite3VdbeMemTooBig(pDest) ){
       goto too_big;
     }
   }