Fix a problem with foreign key constraints that map from and IPK column.

FossilOrigin-Name: 84129052623dc6a175c76db602ab07fa3e57f1eb
This commit is contained in:
dan 2009-09-21 18:56:23 +00:00
parent e83c4f3a9e
commit 3606264bc9
4 changed files with 68 additions and 15 deletions

View File

@ -1,5 +1,5 @@
C Fix\scompilation\swith\sboth\sOMIT_UTF16\sand\sENABLE_STAT2\sdefined.\sTicket\s[56928bd084ea530eb8a0b3ebe5d2d9033fb1de7f|56928bd084].
D 2009-09-21T16:34:24
C Fix\sa\sproblem\swith\sforeign\skey\sconstraints\sthat\smap\sfrom\sand\sIPK\scolumn.
D 2009-09-21T18:56:24
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -116,7 +116,7 @@ F src/date.c 6d936393716d21e6dc0d4222b3443137a60ebe93
F src/delete.c 15499f5d10047d38e68ce991b3f88cbddb6e0931
F src/expr.c 638b599adad562d41c3bf90f542f9419664aa7b8
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
F src/fkey.c 0f06ecda52a75a1624e01b7f861a235d97544b98
F src/fkey.c 6aad270ae5ed7b0496e25020bce89097c2cf9c79
F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
@ -330,7 +330,7 @@ F test/expr.test 80f3cf99f786ffbac19d2b0083673e7fc797030f
F test/filectrl.test 8923a6dc7630f31c8a9dd3d3d740aa0922df7bf8
F test/filefmt.test 84e3d0fe9f12d0d2ac852465c6f8450aea0d6f43
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
F test/fkey2.test 62d02fb2c0d115715e990691961a7b679c902204
F test/fkey2.test a8055d90eec17db00847cbcd527bc870d9218551
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
F test/fts1b.test 5d8a01aefbecc8b7442b36c94c05eb7a845462d5
@ -752,7 +752,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P fb6ceed388f6d75bdc2ac2f43e5c98da74e2a448
R 899a06e4349a5ceabc5fe389e0c0c2ac
P cd850d49a12a2852258cbd7d5db56715132dff17
R d5353831002e80af9b93981303b50742
U dan
Z 4dbd21536703b59a6c4c05ce1d53ee70
Z deb48eae30b76f10abf4df096870a1c2

View File

@ -1 +1 @@
cd850d49a12a2852258cbd7d5db56715132dff17
84129052623dc6a175c76db602ab07fa3e57f1eb

View File

@ -258,7 +258,7 @@ static void fkCheckReference(
** NULL. If any are, then the constraint is satisfied. No need
** to search for a matching row in the referenced table. */
for(i=0; i<pFKey->nCol; i++){
int iReg = pFKey->aCol[i].iFrom + regData + 1;
int iReg = aiCol[i] + regData + 1;
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk);
}
@ -277,7 +277,7 @@ static void fkCheckReference(
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
if( aiCol ){
if( pFKey->nCol>1 ){
int nCol = pFKey->nCol;
int regTemp = sqlite3GetTempRange(pParse, nCol);
for(i=0; i<nCol; i++){
@ -286,7 +286,7 @@ static void fkCheckReference(
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
}else{
int iReg = pFKey->aCol[0].iFrom + regData + 1;
int iReg = aiCol[0] + regData + 1;
sqlite3VdbeAddOp3(v, OP_MakeRecord, iReg, 1, regRec);
sqlite3IndexAffinityStr(v, pIdx);
}
@ -426,7 +426,10 @@ void sqlite3FkCheck(
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
Table *pTo; /* Table referenced by this FK */
Index *pIdx = 0; /* Index on key columns in pTo */
int *aiCol = 0;
int *aiFree = 0;
int *aiCol;
int iCol;
int i;
if( pFKey->isDeferred==0 && regNew==0 ) continue;
@ -435,14 +438,26 @@ void sqlite3FkCheck(
** If either of these things cannot be located, set an error in pParse
** and return early. */
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiCol) ) return;
assert( pFKey->nCol==1 || (aiCol && pIdx) );
if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ) return;
assert( pFKey->nCol==1 || (aiFree && pIdx) );
/* If the key does not overlap with the pChanges list, skip this FK. */
if( pChanges ){
/* TODO */
}
if( aiFree ){
aiCol = aiFree;
}else{
iCol = pFKey->aCol[0].iFrom;
aiCol = &iCol;
}
for(i=0; i<pFKey->nCol; i++){
if( aiCol[i]==pTab->iPKey ){
aiCol[i] = -1;
}
}
/* Take a shared-cache advisory read-lock on the referenced table.
** Allocate a cursor to use to search the unique index on the FK
** columns in the referenced table. */
@ -456,7 +471,7 @@ void sqlite3FkCheck(
fkCheckReference(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1);
}
sqlite3DbFree(db, aiCol);
sqlite3DbFree(db, aiFree);
}
/* Loop through all the foreign key constraints that refer to this table */

View File

@ -42,6 +42,8 @@ ifcapable {!foreignkey||!trigger} {
# fkey2-6.*: Test that FK processing is automatically disabled when
# running VACUUM.
#
# fkey2-7.*: Test using an IPK as the key in the child (referencing) table.
#
# fkey2-genfkey.*: Tests that were used with the shell tool .genfkey
# command. Recycled to test the built-in implementation.
#
@ -409,6 +411,42 @@ ifcapable vacuum {
} {}
}
#-------------------------------------------------------------------------
# Test that it is possible to use an INTEGER PRIMARY KEY as the child key
# of a foreign constraint.
drop_all_tables
do_test fkey2-7.1 {
execsql {
CREATE TABLE t1(a PRIMARY KEY, b);
CREATE TABLE t2(c INTEGER PRIMARY KEY REFERENCES t1, b);
}
} {}
do_test fkey2-7.2 {
catchsql { INSERT INTO t2 VALUES(1, 'A'); }
} {1 {foreign key constraint failed}}
do_test fkey2-7.3 {
execsql {
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(2, 3);
INSERT INTO t2 VALUES(1, 'A');
}
} {}
do_test fkey2-7.4 {
execsql { UPDATE t2 SET c = 2 }
} {}
do_test fkey2-7.5 {
catchsql { UPDATE t2 SET c = 3 }
} {1 {foreign key constraint failed}}
do_test fkey2-7.6 {
catchsql { DELETE FROM t1 WHERE a = 2 }
} {1 {foreign key constraint failed}}
do_test fkey2-7.7 {
execsql { DELETE FROM t1 WHERE a = 1 }
} {}
do_test fkey2-7.8 {
catchsql { UPDATE t1 SET a = 3 }
} {1 {foreign key constraint failed}}
#-------------------------------------------------------------------------
# The following block of tests, those prefixed with "fkey2-genfkey.", are
# the same tests that were used to test the ".genfkey" command provided