From bd50a926ef04a175dfa8a35aba05a7cda6c016b8 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 3 Nov 2013 02:27:58 +0000 Subject: [PATCH] Improved comments on foreign key logic. FossilOrigin-Name: 1315d9109c7105f4a62bb2d43ca6948d41245129 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/build.c | 4 ++-- src/fkey.c | 32 +++++++++++++++++--------------- src/sqliteInt.h | 29 +++++++++++++++++++---------- 5 files changed, 47 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index 603ef68ad6..9c0e62b6e4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sSynopsis\son\sregister\scomparison\soperators.\s\sFix\sa\sbug\son\sthe\nconstraint\scheck\sgenerator. -D 2013-11-02T22:29:34.665 +C Improved\scomments\son\sforeign\skey\slogic. +D 2013-11-03T02:27:58.561 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,7 +168,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 509722ce305471b626d3401c0631a808fd33237b F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0 -F src/build.c 113a23bc6f8cf81dd03c984ef0460cca89c48f2e +F src/build.c 21727e787a763e2a9981297eff7945374eaffc19 F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c @@ -176,7 +176,7 @@ F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c 605be39dc72a56768a55ee7245d92774ed7ae343 F src/expr.c ecc2b98eb75fe5533cfdfcca6b04cfe5f0c6001f F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 8dc2b14dd93cd991629ce98e02bc4a5a181f7146 +F src/fkey.c df809cab5485c16ab146cc13246afd41900ece84 F src/func.c 2c47b65e6e00e3e9374942f28254faf8adafe398 F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 @@ -223,7 +223,7 @@ F src/shell.c 03d8d9b4052430343ff30d646334621f980f1202 F src/sqlite.h.in 547a44dd4ff4d975e92a645ea2d609e543a83d0f F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 7cc1b32804563f26cf44a4a48ad370490c8f737c +F src/sqliteInt.h 0d272caa9b943c7e20b9c9924c6d793aece6ee0d F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1130,7 +1130,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 39e32187b66405e00dbd44685f6cdd269c90f5e5 -R 58e9f12157086c3e22220529477830cd +P a7a18b65fa34dfdf6117fa21db3e576f96876617 +R c871a047a9d8bb37aa43632b24cb0302 U drh -Z 72d46f91118ca7659eef125e3fbe4980 +Z 938c2bb15557c0ae50def104b2712b1c diff --git a/manifest.uuid b/manifest.uuid index 58d0d3a8af..677a3fb241 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a7a18b65fa34dfdf6117fa21db3e576f96876617 \ No newline at end of file +1315d9109c7105f4a62bb2d43ca6948d41245129 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 5562641937..5554c40dbe 100644 --- a/src/build.c +++ b/src/build.c @@ -2466,8 +2466,8 @@ exit_drop_table: ** currently under construction. pFromCol determines which columns ** in the current table point to the foreign key. If pFromCol==0 then ** connect the key to the last column inserted. pTo is the name of -** the table referred to. pToCol is a list of tables in the other -** pTo table that the foreign key points to. flags contains all +** the table referred to (a.k.a the "parent" table). pToCol is a list +** of tables in the parent pTo table. flags contains all ** information about the conflict resolution algorithms specified ** in the ON DELETE, ON UPDATE and ON INSERT clauses. ** diff --git a/src/fkey.c b/src/fkey.c index fc39d2fea4..c78f8c3e5e 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -475,12 +475,12 @@ static void fkLookupParent( */ static void fkScanChildren( Parse *pParse, /* Parse context */ - SrcList *pSrc, /* SrcList containing the table to scan */ - Table *pTab, - Index *pIdx, /* Foreign key index */ - FKey *pFKey, /* Foreign key relationship */ + SrcList *pSrc, /* The child table to be scanned */ + Table *pTab, /* The parent table */ + Index *pIdx, /* Index on parent covering the foreign key */ + FKey *pFKey, /* The foreign key linking pSrc to pTab */ int *aiCol, /* Map from pIdx cols to child table cols */ - int regData, /* Referenced table data starts here */ + int regData, /* Parent row data starts here */ int nIncr /* Amount to increment deferred counter by */ ){ sqlite3 *db = pParse->db; /* Database handle */ @@ -491,7 +491,9 @@ static void fkScanChildren( int iFkIfZero = 0; /* Address of OP_FkIfZero */ Vdbe *v = sqlite3GetVdbe(pParse); - assert( !pIdx || pIdx->pTable==pTab ); + assert( pIdx==0 || pIdx->pTable==pTab ); + assert( pIdx==0 || pIdx->nKeyCol==pFKey->nCol ); + assert( pIdx!=0 || pFKey->nCol==1 ); if( nIncr<0 ){ iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0); @@ -545,7 +547,7 @@ static void fkScanChildren( ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE ** clause, where $rowid is the rowid of the row being deleted. */ if( pTab==pFKey->pFrom && nIncr>0 && HasRowid(pTab) /*FIXME*/ ){ - Expr *pEq; /* Expression (pLeft = pRight) */ + Expr *pNe; /* Expression (pLeft != pRight) */ Expr *pLeft; /* Value from parent table row */ Expr *pRight; /* Column ref to child table */ pLeft = sqlite3Expr(db, TK_REGISTER, 0); @@ -556,8 +558,8 @@ static void fkScanChildren( pRight->iTable = pSrc->a[0].iCursor; pRight->iColumn = -1; } - pEq = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0); - pWhere = sqlite3ExprAnd(db, pWhere, pEq); + pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0); + pWhere = sqlite3ExprAnd(db, pWhere, pNe); } /* Resolve the references in the WHERE clause. */ @@ -587,8 +589,8 @@ static void fkScanChildren( } /* -** This function returns a pointer to the head of a linked list of FK -** constraints for which table pTab is the parent table. For example, +** This function returns a linked list of FKey objects (connected by +** FKey.pNextTo) holding all children of table pTab. For example, ** given the following schema: ** ** CREATE TABLE t1(a PRIMARY KEY); @@ -890,7 +892,8 @@ void sqlite3FkCheck( sqlite3DbFree(db, aiFree); } - /* Loop through all the foreign key constraints that refer to this table */ + /* Loop through all the foreign key constraints that refer to this table. + ** (the "child" constraints) */ for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ Index *pIdx = 0; /* Foreign key index for pFKey */ SrcList *pSrc; @@ -915,9 +918,8 @@ void sqlite3FkCheck( } assert( aiCol || pFKey->nCol==1 ); - /* Create a SrcList structure containing a single table (the table - ** the foreign key that refers to this table is attached to). This - ** is required for the sqlite3WhereXXX() interface. */ + /* Create a SrcList structure containing the child table. We need the + ** child table as a SrcList for sqlite3WhereBegin() */ pSrc = sqlite3SrcListAppend(db, 0, 0, 0); if( pSrc ){ struct SrcList_item *pItem = pSrc->a; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8890cbeaf4..43a82b7393 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1451,26 +1451,35 @@ struct Table { ** ); ** ** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". +** Equivalent names: +** +** from-table == child-table +** to-table == parent-table ** ** Each REFERENCES clause generates an instance of the following structure ** which is attached to the from-table. The to-table need not exist when ** the from-table is created. The existence of the to-table is not checked. +** +** The list of all parents for child Table X is held at X.pFKey. +** +** A list of all children for a table named Z (which might not even exist) +** is held in Schema.fkeyHash with a hash key of Z. */ struct FKey { Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */ - FKey *pNextFrom; /* Next foreign key in pFrom */ + FKey *pNextFrom; /* Next FKey with the same in pFrom. Next parent of pFrom */ char *zTo; /* Name of table that the key points to (aka: Parent) */ - FKey *pNextTo; /* Next foreign key on table named zTo */ - FKey *pPrevTo; /* Previous foreign key on table named zTo */ + FKey *pNextTo; /* Next with the same zTo. Next child of zTo. */ + FKey *pPrevTo; /* Previous with the same zTo */ int nCol; /* Number of columns in this key */ /* EV: R-30323-21917 */ - u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ - u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */ - Trigger *apTrigger[2]; /* Triggers for aAction[] actions */ - struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ - int iFrom; /* Index of column in pFrom */ - char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ - } aCol[1]; /* One entry for each of nCol column s */ + u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ + u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */ + Trigger *apTrigger[2];/* Triggers for aAction[] actions */ + struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ + int iFrom; /* Index of column in pFrom */ + char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */ + } aCol[1]; /* One entry for each of nCol columns */ }; /*