From: drh Date: Mon, 17 Dec 2012 18:43:02 +0000 (+0000) Subject: "PRAGMA foreign_key_check" with no argument checks the foreign keys on all X-Git-Tag: version-3.7.16~93^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=613028b34e97c841a15e23074c7ccaaef0d4e435;p=thirdparty%2Fsqlite.git "PRAGMA foreign_key_check" with no argument checks the foreign keys on all tables. FossilOrigin-Name: 57d47423a65d183cb1efcb95b28cb143e788b953 --- diff --git a/manifest b/manifest index 239a8f55d8..40430b8c8a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sissue\swith\schild\skeys\sthat\sare\snot\sINTEGER\sPRIMARY\sKEY\nreferencing\sINTEGER\sPRIMARY\sKEY\sin\sthe\sparent. -D 2012-12-17T18:05:54.523 +C "PRAGMA\sforeign_key_check"\swith\sno\sargument\schecks\sthe\sforeign\skeys\son\sall\ntables. +D 2012-12-17T18:43:02.925 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 690d441a758cbffd13e814dc2724a721a6ebd400 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,7 +168,7 @@ F src/parse.y c2b4a6454ad77299b1443e2c483a560a9f16e724 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9 -F src/pragma.c 599af02bcc13c8f41a6670a19185119ffae18e6d +F src/pragma.c b98dfe89b961d41be6d502d23adf18ed02dbb410 F src/prepare.c 931ad0d852a0df48f79adcba6ce79ca5f475625c F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 @@ -1025,7 +1025,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 01c980e9bbdf82e0b37667b6403c19ed8c73ee62 -R abb2e93db46b538d88f02500430c7bfd +P 603b695bf094b9da905f877a13dcb134463db92a +R 838d64421c46ea50daf2c57db5adcb2d U drh -Z 4013a6f2f3fe7fcef30b92f6b8b3c386 +Z f327b298aa59d7b1bf00c17e68686c2c diff --git a/manifest.uuid b/manifest.uuid index f929e33227..a607adedca 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -603b695bf094b9da905f877a13dcb134463db92a \ No newline at end of file +57d47423a65d183cb1efcb95b28cb143e788b953 \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index fbd556526a..d65f4cd101 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1115,33 +1115,51 @@ void sqlite3Pragma( #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( 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 */ 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); + regResult = pParse->nMem+1; + pParse->nMem += 3; + regKey = ++pParse->nMem; + regRow = ++pParse->nMem; + v = sqlite3GetVdbe(pParse); + sqlite3VdbeSetNumCols(v, 3); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, 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->pFKey==0 ) continue; + 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; - aiCols = 0; - x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); if( x==0 ){ if( pIdx==0 ){ sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); @@ -1151,62 +1169,52 @@ void sqlite3Pragma( sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); } }else{ + k = 0; 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 ){ - int iKey = pFK->aCol[0].iFrom; - if( iKey>=0 && 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); + if( pFK ) break; + if( pParse->nTabnTab = 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; + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); + assert( x==0 ); + addrOk = sqlite3VdbeMakeLabel(v); + if( pIdx==0 ){ + int iKey = pFK->aCol[0].iFrom; + if( iKey>=0 && 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{ - for(j=0; jnCol; 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); + 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; jnCol; j++){ + sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, pFK->aCol[j].iFrom, + regRow+j); + sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); } - 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); + 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_Next, 0, addrTop+1); - sqlite3VdbeJumpHere(v, addrTop); + sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); + sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+2); + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 3); + sqlite3VdbeResolveLabel(v, addrOk); } + sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); + sqlite3VdbeJumpHere(v, addrTop); } }else #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */