1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

Do not check immediate foreign key constraints until the end of the statement. This matches the postgres behaviour.

FossilOrigin-Name: 1a32149cc3c722058f4ed4c81edadeb6ce5bc9e4
This commit is contained in:
dan
2009-09-23 17:29:59 +00:00
parent f1dfc4fbb3
commit 32b09f29c9
7 changed files with 94 additions and 74 deletions

View File

@@ -321,6 +321,7 @@ static Op *opIterNext(VdbeOpIter *p){
** * OP_Destroy
** * OP_VUpdate
** * OP_VRename
** * OP_FkCounter with P2==0 (immediate foreign key constraint)
**
** Then check that the value of Parse.mayAbort is true if an
** ABORT may be thrown, or false otherwise. Return true if it does
@@ -339,6 +340,9 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
while( (pOp = opIterNext(&sIter))!=0 ){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
#ifndef SQLITE_OMIT_FOREIGN_KEY
|| (opcode==OP_FkCounter && pOp->p1==1 && pOp->p2==0)
#endif
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
){
@@ -1944,10 +1948,11 @@ void sqlite3VdbeMutexArrayEnter(Vdbe *p){
** an error message to it. Then return SQLITE_ERROR.
*/
#ifndef SQLITE_OMIT_FOREIGN_KEY
int sqlite3VdbeCheckDeferred(Vdbe *p){
int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
sqlite3 *db = p->db;
if( db->nDeferredCons ){
if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
p->rc = SQLITE_CONSTRAINT;
p->errorAction = OE_Abort;
sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
return SQLITE_ERROR;
}
@@ -2029,6 +2034,11 @@ int sqlite3VdbeHalt(Vdbe *p){
}
}
}
/* Check for immediate foreign key violations. */
if( p->rc==SQLITE_OK ){
sqlite3VdbeCheckFk(p, 0);
}
/* If the auto-commit flag is set and this is the only active writer
** VM, then we do either a commit or rollback of the current transaction.
@@ -2041,7 +2051,7 @@ int sqlite3VdbeHalt(Vdbe *p){
&& db->writeVdbeCnt==(p->readOnly==0)
){
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
if( sqlite3VdbeCheckDeferred(p) ){
if( sqlite3VdbeCheckFk(p, 1) ){
sqlite3BtreeMutexArrayLeave(&p->aMutex);
return SQLITE_ERROR;
}