mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Check in implementation of foreign key constraints.
FossilOrigin-Name: d5d399811876391642937edeb9e8434dd9e356f5
This commit is contained in:
@@ -1895,6 +1895,13 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
|
||||
}
|
||||
db->nStatement--;
|
||||
p->iStatement = 0;
|
||||
|
||||
/* If the statement transaction is being rolled back, also restore the
|
||||
** database handles deferred constraint counter to the value it had when
|
||||
** the statement transaction was opened. */
|
||||
if( eOp==SAVEPOINT_ROLLBACK ){
|
||||
db->nDeferredCons = p->nStmtDefCons;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -1926,6 +1933,28 @@ void sqlite3VdbeMutexArrayEnter(Vdbe *p){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function is called when a transaction opened by the database
|
||||
** handle associated with the VM passed as an argument is about to be
|
||||
** committed. If there are outstanding deferred foreign key constraint
|
||||
** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
|
||||
**
|
||||
** If there are outstanding FK violations and this function returns
|
||||
** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT and write
|
||||
** an error message to it. Then return SQLITE_ERROR.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
||||
int sqlite3VdbeCheckDeferred(Vdbe *p){
|
||||
sqlite3 *db = p->db;
|
||||
if( db->nDeferredCons ){
|
||||
p->rc = SQLITE_CONSTRAINT;
|
||||
sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This routine is called the when a VDBE tries to halt. If the VDBE
|
||||
** has made changes and is in autocommit mode, then commit those
|
||||
@@ -2012,10 +2041,14 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
&& db->writeVdbeCnt==(p->readOnly==0)
|
||||
){
|
||||
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
|
||||
/* The auto-commit flag is true, and the vdbe program was
|
||||
** successful or hit an 'OR FAIL' constraint. This means a commit
|
||||
** is required.
|
||||
*/
|
||||
if( sqlite3VdbeCheckDeferred(p) ){
|
||||
sqlite3BtreeMutexArrayLeave(&p->aMutex);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
/* The auto-commit flag is true, the vdbe program was successful
|
||||
** or hit an 'OR FAIL' constraint and there are no deferred foreign
|
||||
** key constraints to hold up the transaction. This means a commit
|
||||
** is required. */
|
||||
rc = vdbeCommit(db, p);
|
||||
if( rc==SQLITE_BUSY ){
|
||||
sqlite3BtreeMutexArrayLeave(&p->aMutex);
|
||||
@@ -2024,6 +2057,7 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
p->rc = rc;
|
||||
sqlite3RollbackAll(db);
|
||||
}else{
|
||||
db->nDeferredCons = 0;
|
||||
sqlite3CommitInternalChanges(db);
|
||||
}
|
||||
}else{
|
||||
|
||||
Reference in New Issue
Block a user