diff options
author | drh <drh@noemail.net> | 2017-01-09 15:44:25 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2017-01-09 15:44:25 +0000 |
commit | e7b554d615072f16896a6879f582c935fa252a12 (patch) | |
tree | dff182389564ac6e0415eecf10430d99f9eafca6 /src | |
parent | f4e994b23adc5bb62356af81d9fd194796bc22cf (diff) | |
download | sqlite-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.c | 4 | ||||
-rw-r--r-- | src/vdbe.c | 27 |
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; |