From: dan Date: Fri, 25 Sep 2009 12:00:01 +0000 (+0000) Subject: Fix comments in fkey2.c to reflect the immediate-constraint-counter approach. X-Git-Tag: fts3-refactor~146 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bd747832704fcafaf95e09440f8e6adfe096ef35;p=thirdparty%2Fsqlite.git Fix comments in fkey2.c to reflect the immediate-constraint-counter approach. FossilOrigin-Name: 9fd54b0aa73ed74c65f7db53cb666752f13263f9 --- diff --git a/manifest b/manifest index 8f9f8b76a5..f4a6ddd82c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Prevent\sALTER\sTABLE\sfrom\sbeing\sused\sto\sadd\sa\scolumn\swith\sa\sREFERENCES\sclause\sand\sa\snon-NULL\sdefault\svalue\swhile\sforeign\skey\ssupport\sis\senabled. -D 2009-09-25T11:26:55 +C Fix\scomments\sin\sfkey2.c\sto\sreflect\sthe\simmediate-constraint-counter\sapproach. +D 2009-09-25T12:00:02 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -116,7 +116,7 @@ F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638 F src/delete.c 2a3d6fc0861b2f8dbd9feb7847b390267b281c60 F src/expr.c c7f3f718bd5c392344ec8694a41c1824f30cf375 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff -F src/fkey.c 5ec139b6d22a981a777fb195d9311068f5a8c75b +F src/fkey.c 8719d0fa09f8f08d5b21abf54a59cbcb88172b1b F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606 F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32 F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7 @@ -330,7 +330,7 @@ F test/expr.test 9f521ae22f00e074959f72ce2e55d46b9ed23f68 F test/filectrl.test 8923a6dc7630f31c8a9dd3d3d740aa0922df7bf8 F test/filefmt.test 84e3d0fe9f12d0d2ac852465c6f8450aea0d6f43 F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da -F test/fkey2.test ad58088fbc09231f125b6c7e9594720aa1374019 +F test/fkey2.test 8f857439feef71b11a13821aa407399e3ed9f494 F test/fkey3.test 2183cac9075f3aae4875106eb9255bb73618444e F test/fkey_malloc.test da912d000bb6ceb1cd11b655de1989762fa71ceb F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb @@ -755,7 +755,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 76e8e74b49be4c80b9fb20d52e9b39db8001362e -R 136d37129ec61260ba7a30de652f5973 +P 353b1b18253ab71ba38a887e555994f5469b87bd +R 686fb8f7dc051b5c786ec23c8c348ab4 U dan -Z 5dd61108ad33d708be4c046f1054dc1d +Z 007854d1d118a1cdcf5b42c76aa6bc04 diff --git a/manifest.uuid b/manifest.uuid index 5fb63b8f31..f4a31f8d70 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -353b1b18253ab71ba38a887e555994f5469b87bd \ No newline at end of file +9fd54b0aa73ed74c65f7db53cb666752f13263f9 \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index f81c6a8e23..acac588cf4 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -83,6 +83,16 @@ ** is thrown, even if the FK constraint would be satisfied after the new ** row is inserted. ** +** Immediate constraints are usually handled similarly. The only difference +** is that the counter used is stored as part of each individual statement +** object (struct Vdbe). If, after the statement has run, its immediate +** constraint counter is greater than zero, it returns SQLITE_CONSTRAINT +** and the statement transaction is rolled back. An exception is an INSERT +** statement that inserts a single row only (no triggers). In this case, +** instead of using a counter, an exception is thrown immediately if the +** INSERT violates a foreign key constraint. This is necessary as such +** an INSERT does not open a statement transaction. +** ** TODO: How should dropping a table be handled? How should renaming a ** table be handled? ** @@ -259,10 +269,9 @@ static int locateFkeyIndex( } /* -** This function is called when a row is inserted into the child table of -** foreign key constraint pFKey and, if pFKey is deferred, when a row is -** deleted from the child table of pFKey. If an SQL UPDATE is executed on -** the child table of pFKey, this function is invoked twice for each row +** This function is called when a row is inserted into or deleted from the +** child table of foreign key constraint pFKey. If an SQL UPDATE is executed +** on the child table of pFKey, this function is invoked twice for each row ** affected - once to "delete" the old row, and then again to "insert" the ** new row. ** @@ -274,15 +283,16 @@ static int locateFkeyIndex( ** ** Operation | FK type | Action taken ** -------------------------------------------------------------------------- -** INSERT immediate Throw a "foreign key constraint failed" exception. +** INSERT immediate Increment the "immediate constraint counter". +** +** DELETE immediate Decrement the "immediate constraint counter". ** ** INSERT deferred Increment the "deferred constraint counter". ** ** DELETE deferred Decrement the "deferred constraint counter". ** -** This function is never called for a delete on the child table of an -** immediate foreign key constraint. These operations are identified in -** the comment at the top of this file (fkey.c) as "I.1" and "D.1". +** These operations are identified in the comment at the top of this file +** (fkey.c) as "I.1" and "D.1". */ static void fkLookupParent( Parse *pParse, /* Parse context */ @@ -378,7 +388,11 @@ static void fkLookupParent( ** ** Operation | FK type | Action taken ** -------------------------------------------------------------------------- -** DELETE immediate Throw a "foreign key constraint failed" exception. +** DELETE immediate Increment the "immediate constraint counter". +** Or, if the ON (UPDATE|DELETE) action is RESTRICT, +** throw a "foreign key constraint failed" exception. +** +** INSERT immediate Decrement the "immediate constraint counter". ** ** DELETE deferred Increment the "deferred constraint counter". ** Or, if the ON (UPDATE|DELETE) action is RESTRICT, @@ -386,9 +400,8 @@ static void fkLookupParent( ** ** INSERT deferred Decrement the "deferred constraint counter". ** -** This function is never called for an INSERT operation on the parent table -** of an immediate foreign key constraint. These operations are identified in -** the comment at the top of this file (fkey.c) as "I.2" and "D.2". +** These operations are identified in the comment at the top of this file +** (fkey.c) as "I.2" and "D.2". */ static void fkScanChildren( Parse *pParse, /* Parse context */ @@ -405,6 +418,14 @@ static void fkScanChildren( NameContext sNameContext; /* Context used to resolve WHERE clause */ WhereInfo *pWInfo; /* Context used by sqlite3WhereXXX() */ + /* Create an Expr object representing an SQL expression like: + ** + ** = AND = ... + ** + ** The collation sequence used for the comparison should be that of + ** the parent key columns. The affinity of the parent key column should + ** be applied to each child key value before the comparison takes place. + */ for(i=0; inCol; i++){ Expr *pLeft; /* Value from parent table row */ Expr *pRight; /* Column ref to child table */ @@ -414,6 +435,8 @@ static void fkScanChildren( pLeft = sqlite3Expr(db, TK_REGISTER, 0); if( pLeft ){ + /* Set the collation sequence and affinity of the LHS of each TK_EQ + ** expression to the parent key column defaults. */ if( pIdx ){ int iCol = pIdx->aiColumn[i]; Column *pCol = &pIdx->pTable->aCol[iCol]; @@ -445,7 +468,8 @@ static void fkScanChildren( ** deferred constraint counter by nIncr for each row selected. */ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0); if( nIncr==0 ){ - /* A RESTRICT Action. */ + /* Special case: A RESTRICT Action. Throw an error immediately if one + ** of these is encountered. */ sqlite3HaltConstraint( pParse, OE_Abort, "foreign key constraint failed", P4_STATIC ); diff --git a/test/fkey2.test b/test/fkey2.test index f0d0bed3c8..0b4402c7d5 100644 --- a/test/fkey2.test +++ b/test/fkey2.test @@ -188,7 +188,7 @@ do_test fkey2-1.5.2 { # Use a collation sequence on the parent key. drop_all_tables -do_test fkey2-1.5.1 { +do_test fkey2-1.6.1 { execsql { CREATE TABLE i(i TEXT COLLATE nocase PRIMARY KEY); CREATE TABLE j(j TEXT COLLATE binary REFERENCES i(i)); @@ -198,6 +198,26 @@ do_test fkey2-1.5.1 { catchsql { DELETE FROM i } } {1 {foreign key constraint failed}} +# Use the parent key collation even if it is default and the child key +# has an explicit value. +drop_all_tables +do_test fkey2-1.6.2 { + execsql { + CREATE TABLE i(i TEXT PRIMARY KEY); -- Colseq is "BINARY" + CREATE TABLE j(j TEXT COLLATE nocase REFERENCES i(i)); + INSERT INTO i VALUES('SQLite'); + } + catchsql { INSERT INTO j VALUES('sqlite') } +} {1 {foreign key constraint failed}} +do_test fkey2-1.6.3 { + execsql { + INSERT INTO i VALUES('sqlite'); + INSERT INTO j VALUES('sqlite'); + DELETE FROM i WHERE i = 'SQLite'; + } + catchsql { DELETE FROM i WHERE i = 'sqlite' } +} {1 {foreign key constraint failed}} + #------------------------------------------------------------------------- # This section (test cases fkey2-2.*) contains tests to check that the # deferred foreign key constraint logic works.