diff options
author | drh <drh@noemail.net> | 2017-08-01 19:53:43 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2017-08-01 19:53:43 +0000 |
commit | 86b40dfd33fd58dd92be682365fa28b4a5f8b31a (patch) | |
tree | dc907ac6f2a51f331ffa1faf46ab35c5c434493f /src | |
parent | b7673ede37708db59ada16666f679b27fae84c5b (diff) | |
download | sqlite-86b40dfd33fd58dd92be682365fa28b4a5f8b31a.tar.gz sqlite-86b40dfd33fd58dd92be682365fa28b4a5f8b31a.zip |
Split the OP_Last opcode into OP_Last and OP_SeekEnd. Use OP_SeekEnd to
position a cursor prior to appending. Ticket [cb91bf4290c211d].
FossilOrigin-Name: 3e02474c7bbe16891a7cfc8771cf72f64cd2c0692779037982d7d307512a4f23
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 2 | ||||
-rw-r--r-- | src/insert.c | 6 | ||||
-rw-r--r-- | src/vdbe.c | 48 |
3 files changed, 31 insertions, 25 deletions
diff --git a/src/build.c b/src/build.c index 8eab3823c..37ed309b3 100644 --- a/src/build.c +++ b/src/build.c @@ -2836,7 +2836,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); - sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); + sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx); sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); diff --git a/src/insert.c b/src/insert.c index d51e64b8f..f8e9095ea 100644 --- a/src/insert.c +++ b/src/insert.c @@ -2180,7 +2180,7 @@ static int xferOptimization( } sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); if( db->mDbFlags & DBFLAG_Vacuum ){ - sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID| OPFLAG_APPEND|OPFLAG_USESEEKRESULT; }else{ @@ -2217,7 +2217,7 @@ static int xferOptimization( ** collation sequence BINARY, then it can also be assumed that the ** index will be populated by inserting keys in strictly sorted ** order. In this case, instead of seeking within the b-tree as part - ** of every OP_IdxInsert opcode, an OP_Last is added before the + ** of every OP_IdxInsert opcode, an OP_SeekEnd is added before the ** OP_IdxInsert to seek to the point within the b-tree where each key ** should be inserted. This is faster. ** @@ -2232,7 +2232,7 @@ static int xferOptimization( } if( i==pSrcIdx->nColumn ){ idxInsFlags = OPFLAG_USESEEKRESULT; - sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); } } if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ diff --git a/src/vdbe.c b/src/vdbe.c index d9900f383..8ce5f0c5d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4776,7 +4776,17 @@ case OP_NullRow: { break; } -/* Opcode: Last P1 P2 P3 * * +/* Opcode: SeekEnd P1 * * * * +** +** Position cursor P1 at the end of the btree for the purpose of +** appending a new entry onto the btree. +** +** It is assumed that the cursor is used only for appending and so +** if the cursor is valid, then the cursor must already be pointing +** at the end of the btree and so no changes are made to +** the cursor. +*/ +/* Opcode: Last P1 P2 * * * ** ** The next use of the Rowid or Column or Prev instruction for P1 ** will refer to the last entry in the database table or index. @@ -4787,14 +4797,8 @@ case OP_NullRow: { ** This opcode leaves the cursor configured to move in reverse order, ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. -** -** If P3 is -1, then the cursor is positioned at the end of the btree -** for the purpose of appending a new entry onto the btree. In that -** case P2 must be 0. It is assumed that the cursor is used only for -** appending and so if the cursor is valid, then the cursor must already -** be pointing at the end of the btree and so no changes are made to -** the cursor. */ +case OP_SeekEnd: case OP_Last: { /* jump */ VdbeCursor *pC; BtCursor *pCrsr; @@ -4807,22 +4811,24 @@ case OP_Last: { /* jump */ pCrsr = pC->uc.pCursor; res = 0; assert( pCrsr!=0 ); - pC->seekResult = pOp->p3; #ifdef SQLITE_DEBUG - pC->seekOp = OP_Last; + pC->seekOp = pOp->opcode; #endif - if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){ - rc = sqlite3BtreeLast(pCrsr, &res); - pC->nullRow = (u8)res; - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - if( rc ) goto abort_due_to_error; - if( pOp->p2>0 ){ - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - } - }else{ + if( pOp->opcode==OP_SeekEnd ){ assert( pOp->p2==0 ); + pC->seekResult = -1; + if( sqlite3BtreeCursorIsValidNN(pCrsr) ){ + break; + } + } + rc = sqlite3BtreeLast(pCrsr, &res); + pC->nullRow = (u8)res; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + if( rc ) goto abort_due_to_error; + if( pOp->p2>0 ){ + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; } break; } |