aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/insert.c16
-rw-r--r--src/vdbe.c2
2 files changed, 17 insertions, 1 deletions
diff --git a/src/insert.c b/src/insert.c
index 8167ff78c..6ea3810a2 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -995,12 +995,26 @@ void sqlite3Insert(
#endif
{
int isReplace; /* Set to true if constraints may cause a replace */
+ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0
);
sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
+
+ /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
+ ** constraints or (b) there are no triggers and this table is not a
+ ** parent table in a foreign key constraint. It is safe to set the
+ ** flag in the second case as if any REPLACE constraint is hit, an
+ ** OP_Delete or OP_IdxDelete instruction will be executed on each
+ ** cursor that is disturbed. And these instructions both clear the
+ ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
+ ** functionality. */
+ bUseSeek = (isReplace==0 || (pTrigger==0 &&
+ ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0)
+ ));
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
- regIns, aRegIdx, 0, appendFlag, isReplace==0);
+ regIns, aRegIdx, 0, appendFlag, bUseSeek
+ );
}
}
diff --git a/src/vdbe.c b/src/vdbe.c
index 8b47a3783..c2abeced0 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -4554,6 +4554,7 @@ case OP_Delete: {
rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5);
pC->cacheStatus = CACHE_STALE;
+ pC->seekResult = 0;
if( rc ) goto abort_due_to_error;
/* Invoke the update-hook if required. */
@@ -5109,6 +5110,7 @@ case OP_IdxDelete: {
}
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
+ pC->seekResult = 0;
break;
}