aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2017-01-09 15:44:25 +0000
committerdrh <drh@noemail.net>2017-01-09 15:44:25 +0000
commite7b554d615072f16896a6879f582c935fa252a12 (patch)
treedff182389564ac6e0415eecf10430d99f9eafca6 /src
parentf4e994b23adc5bb62356af81d9fd194796bc22cf (diff)
downloadsqlite-e7b554d615072f16896a6879f582c935fa252a12.tar.gz
sqlite-e7b554d615072f16896a6879f582c935fa252a12.zip
Modify the OP_RowData opcode so that when P3!=0 it is allowed to hold an
ephemeral copy of the content. This avoids unnecessary memcpy() operations in the xfer-optimization and VACUUM. FossilOrigin-Name: 6e106acd74da3baa5c308a76443d2f0a7c904e5e
Diffstat (limited to 'src')
-rw-r--r--src/insert.c4
-rw-r--r--src/vdbe.c27
2 files changed, 19 insertions, 12 deletions
diff --git a/src/insert.c b/src/insert.c
index e55ea2d9f..a33ee1235 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -2138,7 +2138,7 @@ static int xferOptimization(
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
- sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
if( db->flags & SQLITE_Vacuum ){
sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|
@@ -2170,7 +2170,7 @@ static int xferOptimization(
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
if( db->flags & SQLITE_Vacuum ){
/* This INSERT command is part of a VACUUM operation, which guarantees
** that the destination table is empty. If all indexed columns use
diff --git a/src/vdbe.c b/src/vdbe.c
index 5e707a623..698092eb5 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -4632,7 +4632,7 @@ case OP_SorterData: {
break;
}
-/* Opcode: RowData P1 P2 * * *
+/* Opcode: RowData P1 P2 P3 * *
** Synopsis: r[P2]=data
**
** Write into register P2 the complete row content for the row at
@@ -4646,14 +4646,26 @@ case OP_SorterData: {
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
+**
+** If P3!=0 then this opcode is allowed to make an ephermeral pointer
+** into the database page. That means that the content of the output
+** register will be invalidated as soon as the cursor moves - including
+** moves caused by other cursors that "save" the the current cursors
+** position in order that they can write to the same table. If P3==0
+** then a copy of the data is made into memory. P3!=0 is faster, but
+** P3==0 is safer.
+**
+** If P3!=0 then the content of the P2 register is unsuitable for use
+** in OP_Result and any OP_Result will invalidate the P2 register content.
+** The P2 register content is invalided by opcodes like OP_Function or
+** by any use of another cursor pointing to the same table.
*/
case OP_RowData: {
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
- pOut = &aMem[pOp->p2];
- memAboutToChange(p, pOut);
+ pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
@@ -4684,14 +4696,9 @@ case OP_RowData: {
goto too_big;
}
testcase( n==0 );
- if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){
- goto no_mem;
- }
- pOut->n = n;
- MemSetTypeFlag(pOut, MEM_Blob);
- rc = sqlite3BtreePayload(pCrsr, 0, n, pOut->z);
+ rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut);
if( rc ) goto abort_due_to_error;
- pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
+ if( !pOp->p3 ) Deephemeralize(pOut);
UPDATE_MAX_BLOBSIZE(pOut);
REGISTER_TRACE(pOp->p2, pOut);
break;