From 2133d822872aa53770e68f2b8d44b3d4da32b959 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 3 Jan 2008 18:44:59 +0000 Subject: [PATCH] Update OP_Rowid, OP_Column and related opcodes to use registers. (CVS 4671) FossilOrigin-Name: 4f3967073d2df9eae5a61b9770d5de2e1af47b4c --- manifest | 20 +++++----- manifest.uuid | 2 +- src/expr.c | 42 +++++++++++++------- src/select.c | 4 +- src/sqliteInt.h | 4 +- src/vdbe.c | 101 +++++++++++++++++++++++++++++++++--------------- 6 files changed, 112 insertions(+), 61 deletions(-) diff --git a/manifest b/manifest index 5e4f597e4a..4876981577 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sVFilter\sand\sVRename\sto\suse\sregisters\sinstead\sof\sthe\svdbe\sstack\sfor\sinputs.\s(CVS\s4670) -D 2008-01-03T18:39:42 +C Update\sOP_Rowid,\sOP_Column\sand\srelated\sopcodes\sto\suse\sregisters.\s(CVS\s4671) +D 2008-01-03T18:44:59 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -92,7 +92,7 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 F src/delete.c b5f77d88cc35367cfafc2e4edcf9327d19428615 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b -F src/expr.c 4e6bd195630aa99c0fe1a17d1e913873402cb40c +F src/expr.c 97c622402ef76303a211088936bdc55fb7be9104 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 @@ -131,12 +131,12 @@ F src/pragma.c ac8d91bb15dd475d239b9d7bd5dbd7d69a9428e7 F src/prepare.c f1bb8eb642082e618a359c08e3e107490eafe0e3 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da -F src/select.c dae0e2ed8838746f89b0fd6e642e819a792168e3 +F src/select.c 6aec65bf2d73bd45914ad27d9eb8c6cb18cf7b2b 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 44c2d9976f42bf088ada24a06bbfb174e720a74e +F src/sqliteInt.h ccbd4283c7cc9cc790abf720a2157515f19fb919 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf @@ -168,7 +168,7 @@ F src/update.c b4aa2e8b6bda3b4d917c9427568fe5c85b4a0ea8 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 -F src/vdbe.c 0fa40511ae71f0acac07782c323ed4cdac73b4b0 +F src/vdbe.c b49db80b9f38c333fd52c5c879f0ee04aaf18d27 F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5 F src/vdbeInt.h 869d0f550354c1364dde1d3611d770bd1c767505 F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c @@ -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 0b849805c3a0f562d50623f406279b400d335639 -R 13147325b139cd4d2f4693ae66738f7d -U danielk1977 -Z fbbaf889648e9db07fda0b9d48b503d1 +P 253ed40aa36247fc846cc41c8612cd29899d9f8f +R e098bb2688e6d77b10a1673326b22bcb +U drh +Z e08561688fc1cefafc1989e1679d8673 diff --git a/manifest.uuid b/manifest.uuid index 9705396d8d..6f7b6a8693 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -253ed40aa36247fc846cc41c8612cd29899d9f8f \ No newline at end of file +4f3967073d2df9eae5a61b9770d5de2e1af47b4c \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 89b820b9ea..c6f6f415d5 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 @@ -1897,23 +1897,29 @@ static void codeInteger(Vdbe *v, const char *z, int n, int negateFlag){ /* ** 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 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ 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 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){ */ 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 de8fd17aad..61ccbc4812 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 @@ int sqlite3Select( for(i=0; iiSorterColumnpTab, 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 fad6ca96ab..bbac412b3d 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 sqlite3DeleteFrom(Parse*, SrcList*, Expr*); 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 d94a1d0846..6acdc0b875 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 @@ -1537,9 +1537,9 @@ case OP_MustBeInt: { /* no-push */ 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 @@ case OP_MustBeInt: { /* no-push */ ** 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 @@ case OP_RowData: { 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 && inCursor ); 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 @@ case OP_IdxDelete: { /* no-push */ 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 @@ case OP_IdxRowid: { int i = pOp->p1; BtCursor *pCrsr; Cursor *pC; + Mem *pDest; assert( i>=0 && inCursor ); 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 @@ case OP_VFilter: { /* no-push */ #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 @@ case OP_VRowid: { 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 @@ case OP_VRowid: { #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 @@ case OP_VColumn: { 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 @@ case OP_VColumn: { ** 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; } } -- 2.47.3