Add PRAGMA foreign_key_check. Name the child and parent tables as part of
a "foreign key mismatch" error. FossilOrigin-Name: e408dc9080594dc464b8763dece6b365772c6105
This commit is contained in:
commit
b2bb176b70
23
manifest
23
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sthe\ssegfault\sproblem\sof\sticket\s[a7b7803e8d1e869]\swhich\sinvolved\nthe\suse\sof\s"AS"\snamed\sresult\scolumns\sas\slogical\sterms\sof\sthe\sWHERE\sclause.
|
||||
D 2012-12-19T16:58:02.074
|
||||
C Add\sPRAGMA\sforeign_key_check.\s\sName\sthe\schild\sand\sparent\stables\sas\spart\sof\na\s"foreign\skey\smismatch"\serror.
|
||||
D 2012-12-20T01:15:20.959
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 690d441a758cbffd13e814dc2724a721a6ebd400
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -132,7 +132,7 @@ F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/delete.c 9b8d308979114991e5dc7cee958316e07186941d
|
||||
F src/expr.c 0e41d66d868b37dbc0e041c342e0036fad27e705
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c dcb7c37a4bf526ded7b24a01a60fe071bcd160a2
|
||||
F src/fkey.c 5b7a12e2f8620e855b0478a9a6798df9967bb277
|
||||
F src/func.c 8147799b048065a1590805be464d05b4913e652c
|
||||
F src/global.c e59ecd2c553ad0d4bfbc84ca71231336f8993a7a
|
||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||
@ -168,7 +168,7 @@ F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
|
||||
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
|
||||
F src/pragma.c 015723c48072781d2740e310ab04dc92956b76d1
|
||||
F src/pragma.c 1ff115f620d9496fe5018306b644ab9ef7e26a3c
|
||||
F src/prepare.c 931ad0d852a0df48f79adcba6ce79ca5f475625c
|
||||
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
@ -179,7 +179,7 @@ F src/shell.c e392dd1ccbb77cc1d75a8367a89b473c24bea019
|
||||
F src/sqlite.h.in 39cc33bb08897c748fe3383c29ccf56585704177
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||
F src/sqliteInt.h f7581eb79d822a6993d6aa31baf1e67e6ff17d19
|
||||
F src/sqliteInt.h 2e5d50f26abf7cbc6162117735379d412f4091da
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -383,7 +383,7 @@ F test/e_delete.test 89aa84d3d1bd284a0689ede04bce10226a5aeaa5
|
||||
F test/e_droptrigger.test afd5c4d27dec607f5997a66bf7e2498a082cb235
|
||||
F test/e_dropview.test 583411e470458c5d76148542cfb5a5fa84c8f93e
|
||||
F test/e_expr.test 5489424d3d9a452ac3701cdf4b680ae31a157894
|
||||
F test/e_fkey.test a79ab1d3213c7ac64621eec28f8e8bb219775445
|
||||
F test/e_fkey.test 89a2ff734a33693b997534eff90724573948be7b
|
||||
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
||||
F test/e_insert.test d5331cc95e101af2508159fc98b6801631659ffe
|
||||
F test/e_reindex.test dfedfc32c5a282b0596c6537cbcd4217fbb1a216
|
||||
@ -409,10 +409,11 @@ F test/fallocate.test b5d34437bd7ab01d41b1464b8117aefd4d32160e
|
||||
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
|
||||
F test/filefmt.test ffa17b5aebc3eb4b1e3be1ccb5ee906ffbd97f6e
|
||||
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
|
||||
F test/fkey2.test 080969fe219b3b082b0e097ac18c6af2e5b0631f
|
||||
F test/fkey2.test 5aa44e7153928a1f002803f94aaab4c76a7ceac2
|
||||
F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e
|
||||
F test/fkey4.test c6c8f9f9be885f95c85c7bceb26f243ad906fd49
|
||||
F test/fkey_malloc.test c3a12acd053c976de09036498eef09b83afa4a80
|
||||
F test/fkey5.test 0bf64f2d19ad80433ca0b24edbf604a18b353d5f
|
||||
F test/fkey_malloc.test bb74c9cb8f8fceed03b58f8a7ef2df98520bbd51
|
||||
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
|
||||
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
|
||||
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
|
||||
@ -1027,7 +1028,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 7fecced466d86a66b0b751c5b5608141e134fe2d 0ae142178d5ff874a4df58d699adad3a41e3d8d2
|
||||
R 50795a0c6ec500ee7d72d138c83ca2b4
|
||||
P b3c9e8f81275fe07272c01f66b16c16417f034af b5a8f3160b5dc1397312add3c5410e7e0a12b75e
|
||||
R c25a7b70b2b47eedc79e89bea857f6d5
|
||||
U drh
|
||||
Z dd417560d581bba91dab25239d7f612a
|
||||
Z 54888f90388c5aea5593479ed7ab2502
|
||||
|
@ -1 +1 @@
|
||||
b3c9e8f81275fe07272c01f66b16c16417f034af
|
||||
e408dc9080594dc464b8763dece6b365772c6105
|
16
src/fkey.c
16
src/fkey.c
@ -142,7 +142,7 @@
|
||||
** A foreign key constraint requires that the key columns in the parent
|
||||
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
|
||||
** Given that pParent is the parent table for foreign key constraint pFKey,
|
||||
** search the schema a unique index on the parent key columns.
|
||||
** search the schema for a unique index on the parent key columns.
|
||||
**
|
||||
** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
|
||||
** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
|
||||
@ -178,7 +178,7 @@
|
||||
** into pParse. If an OOM error occurs, non-zero is returned and the
|
||||
** pParse->db->mallocFailed flag is set.
|
||||
*/
|
||||
static int locateFkeyIndex(
|
||||
int sqlite3FkLocateIndex(
|
||||
Parse *pParse, /* Parse context to store any error in */
|
||||
Table *pParent, /* Parent table of FK constraint pFKey */
|
||||
FKey *pFKey, /* Foreign key to find index for */
|
||||
@ -275,7 +275,9 @@ static int locateFkeyIndex(
|
||||
|
||||
if( !pIdx ){
|
||||
if( !pParse->disableTriggers ){
|
||||
sqlite3ErrorMsg(pParse, "foreign key mismatch");
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"foreign key mismatch - \"%w\" referencing \"%w\"",
|
||||
pFKey->pFrom->zName, pFKey->zTo);
|
||||
}
|
||||
sqlite3DbFree(pParse->db, aiCol);
|
||||
return 1;
|
||||
@ -736,7 +738,7 @@ void sqlite3FkCheck(
|
||||
}else{
|
||||
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
|
||||
}
|
||||
if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
|
||||
if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
|
||||
assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
|
||||
if( !isIgnoreErrors || db->mallocFailed ) return;
|
||||
if( pTo==0 ){
|
||||
@ -816,7 +818,7 @@ void sqlite3FkCheck(
|
||||
continue;
|
||||
}
|
||||
|
||||
if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
|
||||
if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
|
||||
if( !isIgnoreErrors || db->mallocFailed ) return;
|
||||
continue;
|
||||
}
|
||||
@ -871,7 +873,7 @@ u32 sqlite3FkOldmask(
|
||||
}
|
||||
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
|
||||
Index *pIdx = 0;
|
||||
locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
|
||||
sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
|
||||
if( pIdx ){
|
||||
for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
|
||||
}
|
||||
@ -997,7 +999,7 @@ static Trigger *fkActionTrigger(
|
||||
int i; /* Iterator variable */
|
||||
Expr *pWhen = 0; /* WHEN clause for the trigger */
|
||||
|
||||
if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
|
||||
if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
|
||||
assert( aiCol || pFKey->nCol==1 );
|
||||
|
||||
for(i=0; i<pFKey->nCol; i++){
|
||||
|
114
src/pragma.c
114
src/pragma.c
@ -1114,6 +1114,120 @@ void sqlite3Pragma(
|
||||
}else
|
||||
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
|
||||
|
||||
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
||||
if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
|
||||
FKey *pFK; /* A foreign key constraint */
|
||||
Table *pTab; /* Child table contain "REFERENCES" keyword */
|
||||
Table *pParent; /* Parent table that child points to */
|
||||
Index *pIdx; /* Index in the parent table */
|
||||
int i; /* Loop counter: Foreign key number for pTab */
|
||||
int j; /* Loop counter: Field of the foreign key */
|
||||
HashElem *k; /* Loop counter: Next table in schema */
|
||||
int x; /* result variable */
|
||||
int regResult; /* 3 registers to hold a result row */
|
||||
int regKey; /* Register to hold key for checking the FK */
|
||||
int regRow; /* Registers to hold a row from pTab */
|
||||
int addrTop; /* Top of a loop checking foreign keys */
|
||||
int addrOk; /* Jump here if the key is OK */
|
||||
int *aiCols; /* child to parent column mapping */
|
||||
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
regResult = pParse->nMem+1;
|
||||
pParse->nMem += 4;
|
||||
regKey = ++pParse->nMem;
|
||||
regRow = ++pParse->nMem;
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
sqlite3VdbeSetNumCols(v, 4);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
|
||||
while( k ){
|
||||
if( zRight ){
|
||||
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
|
||||
k = 0;
|
||||
}else{
|
||||
pTab = (Table*)sqliteHashData(k);
|
||||
k = sqliteHashNext(k);
|
||||
}
|
||||
if( pTab==0 || pTab->pFKey==0 ) continue;
|
||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
||||
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
|
||||
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
|
||||
P4_TRANSIENT);
|
||||
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
|
||||
if( pParent==0 ) break;
|
||||
pIdx = 0;
|
||||
sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
|
||||
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
|
||||
if( x==0 ){
|
||||
if( pIdx==0 ){
|
||||
sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
|
||||
}else{
|
||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
|
||||
}
|
||||
}else{
|
||||
k = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( pFK ) break;
|
||||
if( pParse->nTab<i ) pParse->nTab = i;
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
|
||||
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
|
||||
assert( pParent!=0 );
|
||||
pIdx = 0;
|
||||
aiCols = 0;
|
||||
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
|
||||
assert( x==0 );
|
||||
addrOk = sqlite3VdbeMakeLabel(v);
|
||||
if( pIdx==0 ){
|
||||
int iKey = pFK->aCol[0].iFrom;
|
||||
assert( iKey>=0 && iKey<pTab->nCol );
|
||||
if( iKey!=pTab->iPKey ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
|
||||
sqlite3ColumnDefault(v, pTab, iKey, regRow);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
|
||||
sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
|
||||
sqlite3VdbeCurrentAddr(v)+3);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
|
||||
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
|
||||
}else{
|
||||
for(j=0; j<pFK->nCol; j++){
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
|
||||
aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
|
||||
sqlite3VdbeChangeP4(v, -1,
|
||||
sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
|
||||
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
|
||||
pFK->zTo, P4_TRANSIENT);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
|
||||
sqlite3VdbeResolveLabel(v, addrOk);
|
||||
sqlite3DbFree(db, aiCols);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
|
||||
sqlite3VdbeJumpHere(v, addrTop);
|
||||
}
|
||||
}else
|
||||
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
|
||||
|
||||
#ifndef NDEBUG
|
||||
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
|
||||
if( zRight ){
|
||||
|
@ -3210,8 +3210,10 @@ const char *sqlite3JournalModename(int);
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
||||
void sqlite3FkDelete(sqlite3 *, Table*);
|
||||
int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
|
||||
#else
|
||||
#define sqlite3FkDelete(a,b)
|
||||
#define sqlite3FkLocateIndex(a,b,c,d,e)
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -627,7 +627,8 @@ proc test_efkey_57 {tn isError sql} {
|
||||
execsql $sql
|
||||
do_test e_fkey-18.$tn {
|
||||
catchsql { INSERT INTO t2 VALUES(NULL) }
|
||||
} [lindex {{0 {}} {1 {foreign key mismatch}}} $isError]
|
||||
} [lindex {{0 {}} {/1 {foreign key mismatch - ".*" referencing ".*"}/}} \
|
||||
$isError]
|
||||
}
|
||||
test_efkey_57 2 0 { CREATE TABLE t1(x PRIMARY KEY) }
|
||||
test_efkey_57 3 0 { CREATE TABLE t1(x UNIQUE) }
|
||||
@ -698,16 +699,16 @@ do_test e_fkey-19.2 {
|
||||
} {}
|
||||
do_test e_fkey-19.2 {
|
||||
catchsql { INSERT INTO child4 VALUES('xxx', 5) }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child4" referencing "parent"}}
|
||||
do_test e_fkey-19.3 {
|
||||
catchsql { INSERT INTO child5 VALUES('xxx', 6) }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child5" referencing "parent"}}
|
||||
do_test e_fkey-19.4 {
|
||||
catchsql { INSERT INTO child6 VALUES(2, 3) }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child6" referencing "parent"}}
|
||||
do_test e_fkey-19.5 {
|
||||
catchsql { INSERT INTO child7 VALUES(3) }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child7" referencing "parent"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test errors in the database schema that are detected while preparing
|
||||
@ -765,12 +766,12 @@ do_test e_fkey-20.1 {
|
||||
|
||||
foreach {tn tbl ptbl err} {
|
||||
2 c1 {} "no such table: main.nosuchtable"
|
||||
3 c2 p2 "foreign key mismatch"
|
||||
4 c3 p3 "foreign key mismatch"
|
||||
5 c4 p4 "foreign key mismatch"
|
||||
6 c5 p5 "foreign key mismatch"
|
||||
7 c6 p6 "foreign key mismatch"
|
||||
8 c7 p7 "foreign key mismatch"
|
||||
3 c2 p2 "foreign key mismatch - \"c2\" referencing \"p2\""
|
||||
4 c3 p3 "foreign key mismatch - \"c3\" referencing \"p3\""
|
||||
5 c4 p4 "foreign key mismatch - \"c4\" referencing \"p4\""
|
||||
6 c5 p5 "foreign key mismatch - \"c5\" referencing \"p5\""
|
||||
7 c6 p6 "foreign key mismatch - \"c6\" referencing \"p6\""
|
||||
8 c7 p7 "foreign key mismatch - \"c7\" referencing \"p7\""
|
||||
} {
|
||||
do_test e_fkey-20.$tn.1 {
|
||||
catchsql "INSERT INTO $tbl VALUES('a', 'b')"
|
||||
@ -820,22 +821,22 @@ do_test e_fkey-21.2 {
|
||||
} {}
|
||||
do_test e_fkey-21.3 {
|
||||
catchsql { INSERT INTO child9 VALUES('I') }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child9" referencing "parent2"}}
|
||||
do_test e_fkey-21.4 {
|
||||
catchsql { INSERT INTO child9 VALUES('II') }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child9" referencing "parent2"}}
|
||||
do_test e_fkey-21.5 {
|
||||
catchsql { INSERT INTO child9 VALUES(NULL) }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child9" referencing "parent2"}}
|
||||
do_test e_fkey-21.6 {
|
||||
catchsql { INSERT INTO child10 VALUES('I', 'II', 'III') }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child10" referencing "parent2"}}
|
||||
do_test e_fkey-21.7 {
|
||||
catchsql { INSERT INTO child10 VALUES(1, 2, 3) }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child10" referencing "parent2"}}
|
||||
do_test e_fkey-21.8 {
|
||||
catchsql { INSERT INTO child10 VALUES(NULL, NULL, NULL) }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "child10" referencing "parent2"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test errors that are reported when creating the child table.
|
||||
@ -1151,7 +1152,7 @@ do_test e_fkey-28.8 {
|
||||
CREATE TABLE c(a, b, FOREIGN KEY(a,b) REFERENCES p);
|
||||
}
|
||||
catchsql {DELETE FROM p}
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "c" referencing "p"}}
|
||||
do_test e_fkey-28.9 {
|
||||
drop_all_tables
|
||||
execsql {
|
||||
@ -1159,7 +1160,7 @@ do_test e_fkey-28.9 {
|
||||
CREATE TABLE c(a REFERENCES p);
|
||||
}
|
||||
catchsql {DELETE FROM p}
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "c" referencing "p"}}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -2729,11 +2730,11 @@ do_test e_fkey-60.3 {
|
||||
do_test e_fkey-60.4 {
|
||||
execsql { CREATE TABLE nosuchtable(x PRIMARY KEY) }
|
||||
catchsql { DELETE FROM p }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "c2" referencing "p"}}
|
||||
do_test e_fkey-60.5 {
|
||||
execsql { DROP TABLE c1 }
|
||||
catchsql { DELETE FROM p }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "c2" referencing "p"}}
|
||||
do_test e_fkey-60.6 {
|
||||
execsql { DROP TABLE c2 }
|
||||
execsql { DELETE FROM p }
|
||||
|
@ -139,14 +139,21 @@ set FkeySimpleTests {
|
||||
4.17 "UPDATE t7 SET a = 10" {0 {}}
|
||||
|
||||
5.1 "INSERT INTO t9 VALUES(1, 3)" {1 {no such table: main.nosuchtable}}
|
||||
5.2 "INSERT INTO t10 VALUES(1, 3)" {1 {foreign key mismatch}}
|
||||
5.2 "INSERT INTO t10 VALUES(1, 3)"
|
||||
{1 {foreign key mismatch - "t10" referencing "t9"}}
|
||||
}
|
||||
|
||||
do_test fkey2-1.1.0 {
|
||||
execsql [string map {/D/ {}} $FkeySimpleSchema]
|
||||
} {}
|
||||
foreach {tn zSql res} $FkeySimpleTests {
|
||||
do_test fkey2-1.1.$tn { catchsql $zSql } $res
|
||||
do_test fkey2-1.1.$tn.1 { catchsql $zSql } $res
|
||||
do_test fkey2-1.1.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {}
|
||||
do_test fkey2-1.1.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {}
|
||||
do_test fkey2-1.1.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {}
|
||||
do_test fkey2-1.1.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {}
|
||||
do_test fkey2-1.1.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {}
|
||||
do_test fkey2-1.1.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {}
|
||||
}
|
||||
drop_all_tables
|
||||
|
||||
@ -155,6 +162,12 @@ do_test fkey2-1.2.0 {
|
||||
} {}
|
||||
foreach {tn zSql res} $FkeySimpleTests {
|
||||
do_test fkey2-1.2.$tn { catchsql $zSql } $res
|
||||
do_test fkey2-1.2.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {}
|
||||
do_test fkey2-1.2.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {}
|
||||
do_test fkey2-1.2.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {}
|
||||
do_test fkey2-1.2.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {}
|
||||
do_test fkey2-1.2.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {}
|
||||
do_test fkey2-1.2.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {}
|
||||
}
|
||||
drop_all_tables
|
||||
|
||||
@ -165,6 +178,12 @@ do_test fkey2-1.3.0 {
|
||||
foreach {tn zSql res} $FkeySimpleTests {
|
||||
if {$res == "0 {}"} { set res {0 1} }
|
||||
do_test fkey2-1.3.$tn { catchsql $zSql } $res
|
||||
do_test fkey2-1.3.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {}
|
||||
do_test fkey2-1.3.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {}
|
||||
do_test fkey2-1.3.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {}
|
||||
do_test fkey2-1.3.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {}
|
||||
do_test fkey2-1.3.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {}
|
||||
do_test fkey2-1.3.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {}
|
||||
}
|
||||
execsql { PRAGMA count_changes = 0 }
|
||||
drop_all_tables
|
||||
@ -681,7 +700,7 @@ foreach zSql [list {
|
||||
do_test fkey2-10.1.[incr tn] {
|
||||
execsql $zSql
|
||||
catchsql { INSERT INTO c DEFAULT VALUES }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {/1 {foreign key mismatch - "c" referencing "."}/}
|
||||
}
|
||||
|
||||
# "rowid" cannot be used as part of a child or parent key definition
|
||||
@ -709,7 +728,7 @@ do_test fkey2-10.2.1 {
|
||||
INSERT INTO t1(rowid, a, b) VALUES(1, 1, 1);
|
||||
INSERT INTO t2 VALUES(1, 1);
|
||||
}
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "t2" referencing "t1"}}
|
||||
do_test fkey2-10.2.2 {
|
||||
drop_all_tables
|
||||
catchsql {
|
||||
@ -1223,7 +1242,7 @@ do_test fkey-2.14.3.8 {
|
||||
CREATE TABLE cc(a, b, FOREIGN KEY(a, b) REFERENCES pp(x, z));
|
||||
}
|
||||
catchsql { INSERT INTO cc VALUES(1, 2) }
|
||||
} {1 {foreign key mismatch}}
|
||||
} {1 {foreign key mismatch - "cc" referencing "pp"}}
|
||||
do_test fkey-2.14.3.9 {
|
||||
execsql { DROP TABLE cc }
|
||||
} {}
|
||||
|
310
test/fkey5.test
Normal file
310
test/fkey5.test
Normal file
@ -0,0 +1,310 @@
|
||||
# 2012 December 17
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# This file tests the PRAGMA foreign_key_check command.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable {!foreignkey} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_test fkey5-1.1 {
|
||||
db eval {
|
||||
CREATE TABLE p1(a INTEGER PRIMARY KEY); INSERT INTO p1 VALUES(88),(89);
|
||||
CREATE TABLE p2(a INT PRIMARY KEY); INSERT INTO p2 VALUES(77),(78);
|
||||
CREATE TABLE p3(a TEXT PRIMARY KEY);
|
||||
INSERT INTO p3 VALUES(66),(67),('alpha'),('BRAVO');
|
||||
CREATE TABLE p4(a TEXT PRIMARY KEY COLLATE nocase);
|
||||
INSERT INTO p4 VALUES('alpha'),('BRAVO'),('55'),('Delta'),('ECHO');
|
||||
CREATE TABLE p5(a INTEGER PRIMARY KEY, b, c, UNIQUE(b,c));
|
||||
INSERT INTO p5 VALUES(1,'Alpha','abc'),(2,'beta','def');
|
||||
CREATE TABLE p6(a INTEGER PRIMARY KEY, b TEXT COLLATE nocase,
|
||||
c TEXT COLLATE rtrim, UNIQUE(b,c));
|
||||
INSERT INTO p6 VALUES(1,'Alpha','abc '),(2,'bETA','def ');
|
||||
|
||||
CREATE TABLE c1(x INTEGER PRIMARY KEY references p1);
|
||||
CREATE TABLE c2(x INTEGER PRIMARY KEY references p2);
|
||||
CREATE TABLE c3(x INTEGER PRIMARY KEY references p3);
|
||||
CREATE TABLE c4(x INTEGER PRIMARY KEY references p4);
|
||||
CREATE TABLE c5(x INT references p1);
|
||||
CREATE TABLE c6(x INT references p2);
|
||||
CREATE TABLE c7(x INT references p3);
|
||||
CREATE TABLE c8(x INT references p4);
|
||||
CREATE TABLE c9(x TEXT UNIQUE references p1);
|
||||
CREATE TABLE c10(x TEXT UNIQUE references p2);
|
||||
CREATE TABLE c11(x TEXT UNIQUE references p3);
|
||||
CREATE TABLE c12(x TEXT UNIQUE references p4);
|
||||
CREATE TABLE c13(x TEXT COLLATE nocase references p3);
|
||||
CREATE TABLE c14(x TEXT COLLATE nocase references p4);
|
||||
CREATE TABLE c15(x, y, FOREIGN KEY(x,y) REFERENCES p5(b,c));
|
||||
CREATE TABLE c16(x, y, FOREIGN KEY(x,y) REFERENCES p5(c,b));
|
||||
CREATE TABLE c17(x, y, FOREIGN KEY(x,y) REFERENCES p6(b,c));
|
||||
CREATE TABLE c18(x, y, FOREIGN KEY(x,y) REFERENCES p6(c,b));
|
||||
CREATE TABLE c19(x TEXT COLLATE nocase, y TEXT COLLATE rtrim,
|
||||
FOREIGN KEY(x,y) REFERENCES p5(b,c));
|
||||
CREATE TABLE c20(x TEXT COLLATE nocase, y TEXT COLLATE rtrim,
|
||||
FOREIGN KEY(x,y) REFERENCES p5(c,b));
|
||||
CREATE TABLE c21(x TEXT COLLATE nocase, y TEXT COLLATE rtrim,
|
||||
FOREIGN KEY(x,y) REFERENCES p6(b,c));
|
||||
CREATE TABLE c22(x TEXT COLLATE nocase, y TEXT COLLATE rtrim,
|
||||
FOREIGN KEY(x,y) REFERENCES p6(c,b));
|
||||
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-1.2 {
|
||||
db eval {
|
||||
INSERT INTO c1 VALUES(90),(87),(88);
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c1 87 p1 0 c1 90 p1 0}
|
||||
do_test fkey5-1.3 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c1);
|
||||
}
|
||||
} {c1 87 p1 0 c1 90 p1 0}
|
||||
do_test fkey5-1.4 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c2);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test fkey5-2.0 {
|
||||
db eval {
|
||||
INSERT INTO c5 SELECT x FROM c1;
|
||||
DELETE FROM c1;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c5 1 p1 0 c5 3 p1 0}
|
||||
do_test fkey5-2.1 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c5);
|
||||
}
|
||||
} {c5 1 p1 0 c5 3 p1 0}
|
||||
do_test fkey5-2.2 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c1);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test fkey5-3.0 {
|
||||
db eval {
|
||||
INSERT INTO c9 SELECT x FROM c5;
|
||||
DELETE FROM c5;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c9 1 p1 0 c9 3 p1 0}
|
||||
do_test fkey5-3.1 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c9);
|
||||
}
|
||||
} {c9 1 p1 0 c9 3 p1 0}
|
||||
do_test fkey5-3.2 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c5);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test fkey5-4.0 {
|
||||
db eval {
|
||||
DELETE FROM c9;
|
||||
INSERT INTO c2 VALUES(79),(77),(76);
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c2 76 p2 0 c2 79 p2 0}
|
||||
do_test fkey5-4.1 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c2);
|
||||
}
|
||||
} {c2 76 p2 0 c2 79 p2 0}
|
||||
do_test fkey5-4.2 {
|
||||
db eval {
|
||||
INSERT INTO c6 SELECT x FROM c2;
|
||||
DELETE FROM c2;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c6 1 p2 0 c6 3 p2 0}
|
||||
do_test fkey5-4.3 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c6);
|
||||
}
|
||||
} {c6 1 p2 0 c6 3 p2 0}
|
||||
do_test fkey5-4.4 {
|
||||
db eval {
|
||||
INSERT INTO c10 SELECT x FROM c6;
|
||||
DELETE FROM c6;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c10 1 p2 0 c10 3 p2 0}
|
||||
do_test fkey5-4.5 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c10);
|
||||
}
|
||||
} {c10 1 p2 0 c10 3 p2 0}
|
||||
|
||||
do_test fkey5-5.0 {
|
||||
db eval {
|
||||
DELETE FROM c10;
|
||||
INSERT INTO c3 VALUES(68),(67),(65);
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c3 65 p3 0 c3 68 p3 0}
|
||||
do_test fkey5-5.1 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c3);
|
||||
}
|
||||
} {c3 65 p3 0 c3 68 p3 0}
|
||||
do_test fkey5-5.2 {
|
||||
db eval {
|
||||
INSERT INTO c7 SELECT x FROM c3;
|
||||
INSERT INTO c7 VALUES('Alpha'),('alpha'),('foxtrot');
|
||||
DELETE FROM c3;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c7 1 p3 0 c7 3 p3 0 c7 4 p3 0 c7 6 p3 0}
|
||||
do_test fkey5-5.3 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c7);
|
||||
}
|
||||
} {c7 1 p3 0 c7 3 p3 0 c7 4 p3 0 c7 6 p3 0}
|
||||
do_test fkey5-5.4 {
|
||||
db eval {
|
||||
INSERT INTO c11 SELECT x FROM c7;
|
||||
DELETE FROM c7;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c11 1 p3 0 c11 3 p3 0 c11 4 p3 0 c11 6 p3 0}
|
||||
do_test fkey5-5.5 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c11);
|
||||
}
|
||||
} {c11 1 p3 0 c11 3 p3 0 c11 4 p3 0 c11 6 p3 0}
|
||||
|
||||
do_test fkey5-6.0 {
|
||||
db eval {
|
||||
DELETE FROM c11;
|
||||
INSERT INTO c4 VALUES(54),(55),(56);
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c4 54 p4 0 c4 56 p4 0}
|
||||
do_test fkey5-6.1 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c4);
|
||||
}
|
||||
} {c4 54 p4 0 c4 56 p4 0}
|
||||
do_test fkey5-6.2 {
|
||||
db eval {
|
||||
INSERT INTO c8 SELECT x FROM c4;
|
||||
INSERT INTO c8 VALUES('Alpha'),('ALPHA'),('foxtrot');
|
||||
DELETE FROM c4;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c8 1 p4 0 c8 3 p4 0 c8 6 p4 0}
|
||||
do_test fkey5-6.3 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c8);
|
||||
}
|
||||
} {c8 1 p4 0 c8 3 p4 0 c8 6 p4 0}
|
||||
do_test fkey5-6.4 {
|
||||
db eval {
|
||||
INSERT INTO c12 SELECT x FROM c8;
|
||||
DELETE FROM c8;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c12 1 p4 0 c12 3 p4 0 c12 6 p4 0}
|
||||
do_test fkey5-6.5 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c12);
|
||||
}
|
||||
} {c12 1 p4 0 c12 3 p4 0 c12 6 p4 0}
|
||||
|
||||
do_test fkey5-7.1 {
|
||||
db eval {
|
||||
INSERT OR IGNORE INTO c13 SELECT * FROM c12;
|
||||
INSERT OR IGNORE INTO C14 SELECT * FROM c12;
|
||||
DELETE FROM c12;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
} {c14 1 p4 0 c14 3 p4 0 c14 6 p4 0 c13 1 p3 0 c13 2 p3 0 c13 3 p3 0 c13 4 p3 0 c13 5 p3 0 c13 6 p3 0}
|
||||
do_test fkey5-7.2 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c14);
|
||||
}
|
||||
} {c14 1 p4 0 c14 3 p4 0 c14 6 p4 0}
|
||||
do_test fkey5-7.3 {
|
||||
db eval {
|
||||
PRAGMA foreign_key_check(c13);
|
||||
}
|
||||
} {c13 1 p3 0 c13 2 p3 0 c13 3 p3 0 c13 4 p3 0 c13 5 p3 0 c13 6 p3 0}
|
||||
|
||||
do_test fkey5-8.0 {
|
||||
db eval {
|
||||
DELETE FROM c13;
|
||||
DELETE FROM c14;
|
||||
INSERT INTO c19 VALUES('alpha','abc');
|
||||
PRAGMA foreign_key_check(c19);
|
||||
}
|
||||
} {c19 1 p5 0}
|
||||
do_test fkey5-8.1 {
|
||||
db eval {
|
||||
DELETE FROM c19;
|
||||
INSERT INTO c19 VALUES('Alpha','abc');
|
||||
PRAGMA foreign_key_check(c19);
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-8.2 {
|
||||
db eval {
|
||||
INSERT INTO c20 VALUES('Alpha','abc');
|
||||
PRAGMA foreign_key_check(c20);
|
||||
}
|
||||
} {c20 1 p5 0}
|
||||
do_test fkey5-8.3 {
|
||||
db eval {
|
||||
DELETE FROM c20;
|
||||
INSERT INTO c20 VALUES('abc','Alpha');
|
||||
PRAGMA foreign_key_check(c20);
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-8.4 {
|
||||
db eval {
|
||||
INSERT INTO c21 VALUES('alpha','abc ');
|
||||
PRAGMA foreign_key_check(c21);
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-8.5 {
|
||||
db eval {
|
||||
DELETE FROM c21;
|
||||
INSERT INTO c19 VALUES('Alpha','abc');
|
||||
PRAGMA foreign_key_check(c21);
|
||||
}
|
||||
} {}
|
||||
do_test fkey5-8.6 {
|
||||
db eval {
|
||||
INSERT INTO c22 VALUES('Alpha','abc');
|
||||
PRAGMA foreign_key_check(c22);
|
||||
}
|
||||
} {c22 1 p6 0}
|
||||
do_test fkey5-8.7 {
|
||||
db eval {
|
||||
DELETE FROM c22;
|
||||
INSERT INTO c22 VALUES('abc ','ALPHA');
|
||||
PRAGMA foreign_key_check(c22);
|
||||
}
|
||||
} {}
|
||||
|
||||
|
||||
|
||||
finish_test
|
@ -29,6 +29,7 @@ do_malloc_test fkey_malloc-1 -sqlprep {
|
||||
INSERT INTO t2 VALUES('aaa');
|
||||
UPDATE t1 SET a = 'bbb';
|
||||
DELETE FROM t1;
|
||||
PRAGMA foreign_key_check;
|
||||
}
|
||||
|
||||
do_malloc_test fkey_malloc-2 -sqlprep {
|
||||
@ -128,5 +129,3 @@ do_malloc_test fkey_malloc-7 -sqlprep {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user