1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Make sure one-pass DELETE for WITHOUT ROWID tables correctly positions the

PRIMARY KEY cursor.  Make the same fix for UPDATE.

FossilOrigin-Name: 6bd5750b7d5da221b0689f6df6be5ed0dce61bec
This commit is contained in:
drh
2013-11-17 02:42:02 +00:00
parent c51331d16d
commit 83d47afe24
4 changed files with 27 additions and 16 deletions

View File

@@ -461,7 +461,8 @@ void sqlite3DeleteFrom(
sqlite3WhereEnd(pWInfo);
if( okOnePass ){
/* Bypass the delete logic below if the WHERE loop found zero rows */
addrBypass = sqlite3VdbeAddOp0(v, OP_Goto);
addrBypass = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBypass);
sqlite3VdbeJumpHere(v, addrDelete);
}
@@ -483,6 +484,10 @@ void sqlite3DeleteFrom(
if( okOnePass ){
/* Just one row. Hence the top-of-loop is a no-op */
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
if( aToOpen[iDataCur-iTabCur] ){
assert( pPk!=0 );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
}
}else if( pPk ){
addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur);
sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey);
@@ -510,7 +515,7 @@ void sqlite3DeleteFrom(
/* End of the loop over all rowids/primary-keys. */
if( okOnePass ){
sqlite3VdbeJumpHere(v, addrBypass);
sqlite3VdbeResolveLabel(v, addrBypass);
}else if( pPk ){
sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1);
sqlite3VdbeJumpHere(v, addrLoop);
@@ -617,6 +622,7 @@ void sqlite3GenerateRowDelete(
if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
u32 mask; /* Mask of OLD.* columns in use */
int iCol; /* Iterator used while populating OLD.* */
int addrStart; /* Start of BEFORE trigger programs */
/* TODO: Could use temporary registers here. Also could attempt to
** avoid copying the contents of the rowid register. */
@@ -637,15 +643,19 @@ void sqlite3GenerateRowDelete(
}
/* Invoke BEFORE DELETE trigger programs. */
addrStart = sqlite3VdbeCurrentAddr(v);
sqlite3CodeRowTrigger(pParse, pTrigger,
TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
);
/* Seek the cursor to the row to be deleted again. It may be that
** the BEFORE triggers coded above have already removed the row
** being deleted. Do not attempt to delete the row a second time, and
** do not fire AFTER triggers. */
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
/* If any BEFORE triggers were coded, then seek the cursor to the
** row to be deleted again. It may be that the BEFORE triggers moved
** the cursor or of already deleted the row that the cursor was
** pointing to.
*/
if( addrStart<sqlite3VdbeCurrentAddr(v) ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
}
/* Do FK processing. This call checks that any FK constraints that
** refer to this table (i.e. constraints attached to other tables)