mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-06 15:49:35 +03:00
Prototype for PRAGMA that checks all foreign key constraints on a table.
FossilOrigin-Name: 01c980e9bbdf82e0b37667b6403c19ed8c73ee62
This commit is contained in:
19
manifest
19
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Optimize\sIN\soperators\sin\sthe\sWHERE\sclause\sof\squeries\susing\svirtual\stables.
|
C Prototype\sfor\sPRAGMA\sthat\schecks\sall\sforeign\skey\sconstraints\son\sa\stable.
|
||||||
D 2012-12-14T17:54:38.979
|
D 2012-12-17T16:46:37.634
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 690d441a758cbffd13e814dc2724a721a6ebd400
|
F Makefile.in 690d441a758cbffd13e814dc2724a721a6ebd400
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -132,7 +132,7 @@ F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
|||||||
F src/delete.c 9b8d308979114991e5dc7cee958316e07186941d
|
F src/delete.c 9b8d308979114991e5dc7cee958316e07186941d
|
||||||
F src/expr.c 0e41d66d868b37dbc0e041c342e0036fad27e705
|
F src/expr.c 0e41d66d868b37dbc0e041c342e0036fad27e705
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c dcb7c37a4bf526ded7b24a01a60fe071bcd160a2
|
F src/fkey.c 21fb59849f5ce409d82736a34c1c21612d029e59
|
||||||
F src/func.c 8147799b048065a1590805be464d05b4913e652c
|
F src/func.c 8147799b048065a1590805be464d05b4913e652c
|
||||||
F src/global.c e59ecd2c553ad0d4bfbc84ca71231336f8993a7a
|
F src/global.c e59ecd2c553ad0d4bfbc84ca71231336f8993a7a
|
||||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||||
@@ -168,7 +168,7 @@ F src/parse.y c2b4a6454ad77299b1443e2c483a560a9f16e724
|
|||||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||||
F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
|
F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
|
||||||
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
|
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
|
||||||
F src/pragma.c 015723c48072781d2740e310ab04dc92956b76d1
|
F src/pragma.c 52adf60a59ee30717ffc24d5dffbf8305e2b0532
|
||||||
F src/prepare.c 931ad0d852a0df48f79adcba6ce79ca5f475625c
|
F src/prepare.c 931ad0d852a0df48f79adcba6ce79ca5f475625c
|
||||||
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
|
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
|
||||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||||
@@ -179,7 +179,7 @@ F src/shell.c e392dd1ccbb77cc1d75a8367a89b473c24bea019
|
|||||||
F src/sqlite.h.in 39cc33bb08897c748fe3383c29ccf56585704177
|
F src/sqlite.h.in 39cc33bb08897c748fe3383c29ccf56585704177
|
||||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||||
F src/sqliteInt.h d1f0866c69d94fe018a32f78c31a043e3fc0d0de
|
F src/sqliteInt.h fed3071c8d1b7ccfe37f509def6ea5421988577c
|
||||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||||
F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
|
F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
@@ -1025,7 +1025,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||||
P 52e755943f87354febe214e5dc3b423a1e38ba80 d2fb7619b063b329b6d7ba9a16a7290e5d868f23
|
P 3d65c70343196b8f69c5293e7703839846fade85
|
||||||
R fea13d1ea2e8500bc200a6665b5fa212
|
R d2dffba8202bff8058b0bdfbf2948311
|
||||||
|
T *branch * foreign-key-check
|
||||||
|
T *sym-foreign-key-check *
|
||||||
|
T -sym-trunk *
|
||||||
U drh
|
U drh
|
||||||
Z 55c2c2e92a55016f5394cb88b53de07c
|
Z c27ac5b11b52c35a742b54038f8a6374
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
3d65c70343196b8f69c5293e7703839846fade85
|
01c980e9bbdf82e0b37667b6403c19ed8c73ee62
|
||||||
12
src/fkey.c
12
src/fkey.c
@@ -142,7 +142,7 @@
|
|||||||
** A foreign key constraint requires that the key columns in the parent
|
** A foreign key constraint requires that the key columns in the parent
|
||||||
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
|
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
|
||||||
** Given that pParent is the parent table for foreign key constraint pFKey,
|
** 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
|
** 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
|
** 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
|
** into pParse. If an OOM error occurs, non-zero is returned and the
|
||||||
** pParse->db->mallocFailed flag is set.
|
** pParse->db->mallocFailed flag is set.
|
||||||
*/
|
*/
|
||||||
static int locateFkeyIndex(
|
int sqlite3FkLocateIndex(
|
||||||
Parse *pParse, /* Parse context to store any error in */
|
Parse *pParse, /* Parse context to store any error in */
|
||||||
Table *pParent, /* Parent table of FK constraint pFKey */
|
Table *pParent, /* Parent table of FK constraint pFKey */
|
||||||
FKey *pFKey, /* Foreign key to find index for */
|
FKey *pFKey, /* Foreign key to find index for */
|
||||||
@@ -736,7 +736,7 @@ void sqlite3FkCheck(
|
|||||||
}else{
|
}else{
|
||||||
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
|
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) );
|
assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
|
||||||
if( !isIgnoreErrors || db->mallocFailed ) return;
|
if( !isIgnoreErrors || db->mallocFailed ) return;
|
||||||
if( pTo==0 ){
|
if( pTo==0 ){
|
||||||
@@ -816,7 +816,7 @@ void sqlite3FkCheck(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
|
if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
|
||||||
if( !isIgnoreErrors || db->mallocFailed ) return;
|
if( !isIgnoreErrors || db->mallocFailed ) return;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -871,7 +871,7 @@ u32 sqlite3FkOldmask(
|
|||||||
}
|
}
|
||||||
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
|
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
|
||||||
Index *pIdx = 0;
|
Index *pIdx = 0;
|
||||||
locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
|
sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
|
||||||
if( pIdx ){
|
if( pIdx ){
|
||||||
for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
|
for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
|
||||||
}
|
}
|
||||||
@@ -997,7 +997,7 @@ static Trigger *fkActionTrigger(
|
|||||||
int i; /* Iterator variable */
|
int i; /* Iterator variable */
|
||||||
Expr *pWhen = 0; /* WHEN clause for the trigger */
|
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 );
|
assert( aiCol || pFKey->nCol==1 );
|
||||||
|
|
||||||
for(i=0; i<pFKey->nCol; i++){
|
for(i=0; i<pFKey->nCol; i++){
|
||||||
|
|||||||
92
src/pragma.c
92
src/pragma.c
@@ -1114,6 +1114,98 @@ void sqlite3Pragma(
|
|||||||
}else
|
}else
|
||||||
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
|
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
||||||
|
if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 && zRight ){
|
||||||
|
FKey *pFK;
|
||||||
|
Table *pTab;
|
||||||
|
Table *pParent;
|
||||||
|
Index *pIdx;
|
||||||
|
int i, j;
|
||||||
|
int x;
|
||||||
|
int *aiCols;
|
||||||
|
|
||||||
|
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||||
|
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
|
||||||
|
if( pTab && pTab->pFKey ){
|
||||||
|
int regResult;
|
||||||
|
int regRow;
|
||||||
|
int regKey;
|
||||||
|
v = sqlite3GetVdbe(pParse);
|
||||||
|
sqlite3VdbeSetNumCols(v, 2);
|
||||||
|
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "fkid", SQLITE_STATIC);
|
||||||
|
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
|
||||||
|
sqlite3CodeVerifySchema(pParse, iDb);
|
||||||
|
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
|
||||||
|
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||||
|
pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
|
||||||
|
if( pParent==0 ) break;
|
||||||
|
pIdx = 0;
|
||||||
|
aiCols = 0;
|
||||||
|
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
|
||||||
|
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{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sqlite3DbFree(db, aiCols);
|
||||||
|
}
|
||||||
|
pParse->nTab = i;
|
||||||
|
if( pFK==0 ){
|
||||||
|
int addrTop;
|
||||||
|
int addrOk;
|
||||||
|
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
|
||||||
|
regResult = pParse->nMem+1;
|
||||||
|
pParse->nMem += 2;
|
||||||
|
regRow = pParse->nMem+1;
|
||||||
|
pParse->nMem += pTab->nCol;
|
||||||
|
regKey = ++pParse->nMem;
|
||||||
|
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 ){
|
||||||
|
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, pFK->aCol[0].iFrom,
|
||||||
|
regRow);
|
||||||
|
sqlite3VdbeAddOp1(v, OP_MustBeInt, regRow);
|
||||||
|
sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
|
||||||
|
x = sqlite3VdbeCurrentAddr(v);
|
||||||
|
sqlite3VdbeJumpHere(v, x-2);
|
||||||
|
sqlite3VdbeJumpHere(v, x-3);
|
||||||
|
}else{
|
||||||
|
for(j=0; j<pFK->nCol; j++){
|
||||||
|
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, pFK->aCol[j].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);
|
||||||
|
}
|
||||||
|
sqlite3DbFree(db, aiCols);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 2);
|
||||||
|
sqlite3VdbeResolveLabel(v, addrOk);
|
||||||
|
}
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
|
||||||
|
sqlite3VdbeJumpHere(v, addrTop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
|
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
|
||||||
if( zRight ){
|
if( zRight ){
|
||||||
|
|||||||
@@ -3209,8 +3209,10 @@ const char *sqlite3JournalModename(int);
|
|||||||
#endif
|
#endif
|
||||||
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
||||||
void sqlite3FkDelete(sqlite3 *, Table*);
|
void sqlite3FkDelete(sqlite3 *, Table*);
|
||||||
|
int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
|
||||||
#else
|
#else
|
||||||
#define sqlite3FkDelete(a,b)
|
#define sqlite3FkDelete(a,b)
|
||||||
|
#define sqlite3FkLocateIndex(a,b,c,d,e)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user