Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.421 2008/03/26 12:50:15 drh Exp $ +** $Id: select.c,v 1.422 2008/03/27 17:59:02 danielk1977 Exp $ */ #include "sqliteInt.h" /* @@ -793,11 +793,11 @@ iTab = pOrderBy->iECursor; if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ pseudoTab = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn); - sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, 0); + sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Callback); } addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk); codeOffset(v, p, cont); regRow = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); @@ -831,10 +831,11 @@ case SRT_Subroutine: { int i; sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid); for(i=0; iiMem+i ); sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i); } if( eDest==SRT_Callback ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); }else{ Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.718 2008/03/25 17:23:33 drh Exp $ +** $Id: vdbe.c,v 1.719 2008/03/27 17:59:02 danielk1977 Exp $ */ #include "sqliteInt.h" #include #include "vdbeInt.h" @@ -2682,11 +2682,11 @@ } pCx->isIndex = !pCx->isTable; break; } -/* Opcode: OpenPseudo P1 * * * * +/* Opcode: OpenPseudo P1 P2 * * * ** ** 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 ** first row to be deleted. All data is deleted when the cursor is ** closed. @@ -2693,19 +2693,28 @@ ** ** A pseudo-table created by this opcode is useful for holding the ** NEW or OLD tables in a trigger. Also used to hold the a single ** row output from the sorter so that the row can be decomposed into ** individual columns using the OP_Column opcode. +** +** When OP_Insert is executed to insert a row in to the pseudo table, +** the pseudo-table cursor may or may not make it's own copy of the +** original row data. If P2 is 0, then the pseudo-table will copy the +** original row data. Otherwise, a pointer to the original memory cell +** is stored. In this case, the vdbe program must ensure that the +** memory cell containing the row data is not overwritten until the +** pseudo table is closed (or a new row is inserted into it). */ case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); pCx = allocateCursor(p, i, &pOp[-1], -1, 0); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->pseudoTable = 1; + pCx->ephemPseudoTable = pOp->p2; pCx->pIncrKey = &pCx->bogusIncrKey; pCx->isTable = 1; pCx->isIndex = 0; break; } @@ -3274,17 +3283,21 @@ pData->n = 0; }else{ assert( pData->flags & (MEM_Blob|MEM_Str) ); } if( pC->pseudoTable ){ - sqlite3_free(pC->pData); + if( !pC->ephemPseudoTable ){ + sqlite3_free(pC->pData); + } pC->iKey = iKey; pC->nData = pData->n; if( pData->flags & MEM_Dyn ){ pC->pData = pData->z; - pData->flags &= ~MEM_Dyn; - pData->flags |= MEM_Ephem; + if( !pC->ephemPseudoTable ){ + pData->flags &= ~MEM_Dyn; + pData->flags |= MEM_Ephem; + } }else{ pC->pData = sqlite3_malloc( pC->nData+2 ); if( !pC->pData ) goto no_mem; memcpy(pC->pData, pData->z, pC->nData); pC->pData[pC->nData] = 0; Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -63,10 +63,11 @@ Bool atFirst; /* True if pointing to first entry */ Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool nextRowidValid; /* True if the nextRowid field is valid */ Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ + Bool ephemPseudoTable; Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -1079,11 +1079,13 @@ pModule->xClose(pVtabCursor); (void)sqlite3SafetyOn(p->db); p->inVtabMethod = 0; } #endif - sqlite3_free(pCx->pData); + if( !pCx->ephemPseudoTable ){ + sqlite3_free(pCx->pData); + } memset(pCx, 0, sizeof(Cursor)); /* sqlite3_free(pCx->aType); */ /* sqlite3_free(pCx); */ }