1
0
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:
dan
2009-09-19 17:00:31 +00:00
parent 3991bb0dee
commit 1da40a381f
27 changed files with 1698 additions and 182 deletions

View File

@@ -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{