15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code. In place of 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing: 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** May you do good and not evil. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** May you find forgiveness for yourself and forgive others. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** May you share freely, never taking more than you give. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)************************************************************************* 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This file contains code used by the compiler to add foreign key 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** support to compiled SQL statements. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqliteInt.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_FOREIGN_KEY 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_TRIGGER 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Deferred and Immediate FKs 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** -------------------------- 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Foreign keys in SQLite come in two flavours: deferred and immediate. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If an immediate foreign key constraint is violated, SQLITE_CONSTRAINT 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is returned and the current statement transaction rolled back. If a 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** deferred foreign key constraint is violated, no action is taken 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** immediately. However if the application attempts to commit the 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transaction before fixing the constraint violation, the attempt fails. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Deferred constraints are implemented using a simple counter associated 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** with the database handle. The counter is set to zero each time a 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** database transaction is opened. Each time a statement is executed 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that causes a foreign key violation, the counter is incremented. Each 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** time a statement is executed that removes an existing violation from 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the database, the counter is decremented. When the transaction is 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** committed, the commit fails if the current value of the counter is 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** greater than zero. This scheme has two big drawbacks: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** * When a commit fails due to a deferred foreign key constraint, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** there is no way to tell which foreign constraint is not satisfied, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or which row it is not satisfied for. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** * If the database contains foreign key violations when the 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transaction is opened, this may cause the mechanism to malfunction. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Despite these problems, this approach is adopted as it seems simpler 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** than the alternatives. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** INSERT operations: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** I.1) For each FK for which the table is the child table, search 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the parent table for a match. If none is found increment the 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** constraint counter. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** I.2) For each FK for which the table is the parent table, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** search the child table for rows that correspond to the new 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** row in the parent table. Decrement the counter for each row 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** found (as the constraint is now satisfied). 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** DELETE operations: 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** D.1) For each FK for which the table is the child table, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** search the parent table for a row that corresponds to the 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** deleted row in the child table. If such a row is not found, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** decrement the counter. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** D.2) For each FK for which the table is the parent table, search 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the child table for rows that correspond to the deleted row 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in the parent table. For each found increment the counter. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** UPDATE operations: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An UPDATE command requires that all 4 steps above are taken, but only 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for FK constraints for which the affected columns are actually 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** modified (values must be compared at runtime). 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This simplifies the implementation a bit. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For the purposes of immediate FK constraints, the OR REPLACE conflict 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** resolution is considered to delete rows before the new row is inserted. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If a delete caused by OR REPLACE violates an FK constraint, an exception 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is thrown, even if the FK constraint would be satisfied after the new 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** row is inserted. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Immediate constraints are usually handled similarly. The only difference 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is that the counter used is stored as part of each individual statement 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** object (struct Vdbe). If, after the statement has run, its immediate 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** constraint counter is greater than zero, it returns SQLITE_CONSTRAINT 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and the statement transaction is rolled back. An exception is an INSERT 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** statement that inserts a single row only (no triggers). In this case, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** instead of using a counter, an exception is thrown immediately if the 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** INSERT violates a foreign key constraint. This is necessary as such 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** an INSERT does not open a statement transaction. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** TODO: How should dropping a table be handled? How should renaming a 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table be handled? 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Query API Notes 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** --------------- 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Before coding an UPDATE or DELETE row operation, the code-generator 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for those two operations needs to know whether or not the operation 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** requires any FK processing and, if so, which columns of the original 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** row are required by the FK processing VDBE code (i.e. if FKs were 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** implemented using triggers, which of the old.* columns would be 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** accessed). No information is required by the code-generator before 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** coding an INSERT operation. The functions used by the UPDATE/DELETE 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** generation code to query for this information are: 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3FkRequired() - Test to see if FK processing is required. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3FkOldmask() - Query for the set of required old.* columns. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Externally accessible module functions 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** -------------------------------------- 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3FkCheck() - Check for foreign key violations. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3FkActions() - Code triggers for ON UPDATE/ON DELETE actions. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3FkDelete() - Delete an FKey structure. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** VDBE Calling Convention 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ----------------------- 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Example: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For the following INSERT statement: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** CREATE TABLE t1(a, b INTEGER PRIMARY KEY, c); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** INSERT INTO t1 VALUES(1, 2, 3.1); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register (x): 2 (type integer) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register (x+1): 1 (type integer) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register (x+2): NULL (type NULL) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register (x+3): 3.1 (type real) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A foreign key constraint requires that the key columns in the parent 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Given that pParent is the parent table for foreign key constraint pFKey, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** search the schema a unique index on the parent key columns. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If successful, zero is returned. If the parent key is an INTEGER PRIMARY 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set to point to the unique index. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the parent key consists of a single column (the foreign key constraint 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is not a composite foreign key), output variable *paiCol is set to NULL. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Otherwise, it is set to point to an allocated array of size N, where 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** N is the number of columns in the parent key. The first element of the 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** array is the index of the child table column that is mapped by the FK 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** constraint to the parent table column stored in the left-most column 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of index *ppIdx. The second element of the array is the index of the 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** child table column that corresponds to the second left-most column of 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** *ppIdx, and so on. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the required index cannot be found, either because: 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1) The named parent key columns do not exist, or 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2) The named parent key columns do exist, but are not subject to a 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** UNIQUE or PRIMARY KEY constraint, or 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 3) No parent key columns were provided explicitly as part of the 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** foreign key definition, and the parent table does not have a 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** PRIMARY KEY, or 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 4) No parent key columns were provided explicitly as part of the 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** foreign key definition, and the PRIMARY KEY of the parent table 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** consists of a a different number of columns to the child key in 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the child table. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** then non-zero is returned, and a "foreign key mismatch" error loaded 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** into pParse. If an OOM error occurs, non-zero is returned and the 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** pParse->db->mallocFailed flag is set. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int locateFkeyIndex( 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Parse *pParse, /* Parse context to store any error in */ 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Table *pParent, /* Parent table of FK constraint pFKey */ 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *pFKey, /* Foreign key to find index for */ 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Index **ppIdx, /* OUT: Unique index on parent table */ 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int **paiCol /* OUT: Map of index columns in pFKey */ 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Index *pIdx = 0; /* Value to return via *ppIdx */ 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *aiCol = 0; /* Value to return via *paiCol */ 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nCol = pFKey->nCol; /* Number of columns in parent key */ 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zKey = pFKey->aCol[0].zCol; /* Name of left-most parent key column */ 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The caller is responsible for zeroing output parameters. */ 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( ppIdx && *ppIdx==0 ); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( !paiCol || *paiCol==0 ); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pParse ); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If this is a non-composite (single column) foreign key, check if it 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** and *paiCol set to zero and return early. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Otherwise, for a composite foreign key (more than one column), allocate 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** space for the aiCol array (returned via output parameter *paiCol). 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Non-composite foreign keys do not require the aiCol array. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nCol==1 ){ 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The FK maps to the IPK if any of the following are true: 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** mapped to the primary key of table pParent, or 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 2) The FK is explicitly mapped to a column declared as INTEGER 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** PRIMARY KEY. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pParent->iPKey>=0 ){ 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !zKey ) return 0; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else if( paiCol ){ 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( nCol>1 ); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aiCol = (int *)sqlite3DbMallocRaw(pParse->db, nCol*sizeof(int)); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !aiCol ) return 1; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *paiCol = aiCol; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){ 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** of columns. If each indexed column corresponds to a foreign key 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** column of pFKey, then this index is a winner. */ 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zKey==0 ){ 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If zKey is NULL, then this foreign key is implicitly mapped to 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** identified by the test (Index.autoIndex==2). */ 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pIdx->autoIndex==2 ){ 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( aiCol ){ 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If zKey is non-NULL, then this foreign key was declared to 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** map to an explicit list of columns in table pParent. Check if this 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** index matches those columns. Also, check that the index uses 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the default collation sequences for each column. */ 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i, j; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<nCol; i++){ 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */ 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zDfltColl; /* Def. collation for column */ 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zIdxCol; /* Name of indexed column */ 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the index uses a collation sequence that is different from 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the default collation sequence for the column, this index is 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** unusable. Bail out early in this case. */ 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zDfltColl = pParent->aCol[iCol].zColl; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !zDfltColl ){ 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zDfltColl = "BINARY"; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zIdxCol = pParent->aCol[iCol].zName; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(j=0; j<nCol; j++){ 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){ 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( j==nCol ) break; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( i==nCol ) break; /* pIdx is usable */ 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !pIdx ){ 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !pParse->disableTriggers ){ 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ErrorMsg(pParse, "foreign key mismatch"); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3DbFree(pParse->db, aiCol); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ppIdx = pIdx; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called when a row is inserted into or deleted from the 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** child table of foreign key constraint pFKey. If an SQL UPDATE is executed 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on the child table of pFKey, this function is invoked twice for each row 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** affected - once to "delete" the old row, and then again to "insert" the 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** new row. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Each time it is called, this function generates VDBE code to locate the 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** row in the parent table that corresponds to the row being inserted into 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or deleted from the child table. If the parent row can be found, no 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** special action is taken. Otherwise, if the parent row can *not* be 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** found in the parent table: 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Operation | FK type | Action taken 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** -------------------------------------------------------------------------- 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** INSERT immediate Increment the "immediate constraint counter". 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** DELETE immediate Decrement the "immediate constraint counter". 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** INSERT deferred Increment the "deferred constraint counter". 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** DELETE deferred Decrement the "deferred constraint counter". 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** These operations are identified in the comment at the top of this file 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (fkey.c) as "I.1" and "D.1". 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void fkLookupParent( 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Parse *pParse, /* Parse context */ 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iDb, /* Index of database housing pTab */ 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Table *pTab, /* Parent table of FK pFKey */ 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Index *pIdx, /* Unique index on parent key columns in pTab */ 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *pFKey, /* Foreign key constraint */ 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *aiCol, /* Map from parent key columns to child table columns */ 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int regData, /* Address of array containing child table row */ 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nIncr, /* Increment constraint counter by this */ 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isIgnore /* If true, pretend pTab contains all NULL values */ 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; /* Iterator variable */ 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Vdbe *v = sqlite3GetVdbe(pParse); /* Vdbe to add code to */ 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iCur = pParse->nTab - 1; /* Cursor number to use */ 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */ 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If nIncr is less than zero, then check at runtime if there are any 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** outstanding constraints to resolve. If there are not, there is no need 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** to check if deleting this row resolves any outstanding violations. 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Check if any of the key columns in the child table row are NULL. If 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** any are, then the constraint is considered satisfied. No need to 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** search for a matching row in the parent table. */ 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nIncr<0 ){ 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<pFKey->nCol; i++){ 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iReg = aiCol[i] + regData + 1; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isIgnore==0 ){ 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pIdx==0 ){ 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** column of the parent table (table pTab). */ 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iMustBeInt; /* Address of MustBeInt instruction */ 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int regTemp = sqlite3GetTempReg(pParse); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Invoke MustBeInt to coerce the child key value to an integer (i.e. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** apply the affinity of the parent key). If this fails, then there 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** is no matching parent key. Before using MustBeInt, make a copy of 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the value. Otherwise, the value inserted into the child key column 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** will have INTEGER affinity applied to it, which may not be correct. */ 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the parent table is the same as the child table, and we are about 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** to increment the constraint-counter (i.e. this is an INSERT operation), 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** then check if the row being inserted matches itself. If so, do not 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** increment the constraint-counter. */ 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pTab==pFKey->pFrom && nIncr==1 ){ 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeJumpHere(v, iMustBeInt); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ReleaseTempReg(pParse, regTemp); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nCol = pFKey->nCol; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int regTemp = sqlite3GetTempRange(pParse, nCol); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int regRec = sqlite3GetTempReg(pParse); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<nCol; i++){ 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the parent table is the same as the child table, and we are about 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** to increment the constraint-counter (i.e. this is an INSERT operation), 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** then check if the row being inserted matches itself. If so, do not 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** increment the constraint-counter. */ 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pTab==pFKey->pFrom && nIncr==1 ){ 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<nCol; i++){ 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iChild = aiCol[i]+1+regData; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iParent = pIdx->aiColumn[i]+1+regData; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ReleaseTempReg(pParse, regRec); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ReleaseTempRange(pParse, regTemp, nCol); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Special case: If this is an INSERT statement that will insert exactly 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** one row into the table, raise a constraint immediately instead of 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** incrementing a counter. This is necessary as the VM code is being 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** generated for will not open a statement transaction. */ 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( nIncr==1 ); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3HaltConstraint( 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pParse, OE_Abort, "foreign key constraint failed", P4_STATIC 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nIncr>0 && pFKey->isDeferred==0 ){ 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ParseToplevel(pParse)->mayAbort = 1; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeResolveLabel(v, iOk); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp1(v, OP_Close, iCur); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called to generate code executed when a row is deleted 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** from the parent table of foreign key constraint pFKey and, if pFKey is 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** deferred, when a row is inserted into the same table. When generating 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** code for an SQL UPDATE operation, this function may be called twice - 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** once to "delete" the old row and once to "insert" the new row. 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The code generated by this function scans through the rows in the child 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table that correspond to the parent table row being deleted or inserted. 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For each child row found, one of the following actions is taken: 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Operation | FK type | Action taken 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** -------------------------------------------------------------------------- 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** DELETE immediate Increment the "immediate constraint counter". 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Or, if the ON (UPDATE|DELETE) action is RESTRICT, 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** throw a "foreign key constraint failed" exception. 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** INSERT immediate Decrement the "immediate constraint counter". 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** DELETE deferred Increment the "deferred constraint counter". 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Or, if the ON (UPDATE|DELETE) action is RESTRICT, 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** throw a "foreign key constraint failed" exception. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** INSERT deferred Decrement the "deferred constraint counter". 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** These operations are identified in the comment at the top of this file 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (fkey.c) as "I.2" and "D.2". 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void fkScanChildren( 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Parse *pParse, /* Parse context */ 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SrcList *pSrc, /* SrcList containing the table to scan */ 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Table *pTab, 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Index *pIdx, /* Foreign key index */ 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *pFKey, /* Foreign key relationship */ 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *aiCol, /* Map from pIdx cols to child table cols */ 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int regData, /* Referenced table data starts here */ 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nIncr /* Amount to increment deferred counter by */ 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3 *db = pParse->db; /* Database handle */ 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; /* Iterator variable */ 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pWhere = 0; /* WHERE clause to scan with */ 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NameContext sNameContext; /* Context used to resolve WHERE clause */ 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WhereInfo *pWInfo; /* Context used by sqlite3WhereXXX() */ 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iFkIfZero = 0; /* Address of OP_FkIfZero */ 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Vdbe *v = sqlite3GetVdbe(pParse); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( !pIdx || pIdx->pTable==pTab ); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nIncr<0 ){ 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Create an Expr object representing an SQL expression like: 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** <parent-key1> = <child-key1> AND <parent-key2> = <child-key2> ... 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** The collation sequence used for the comparison should be that of 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the parent key columns. The affinity of the parent key column should 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** be applied to each child key value before the comparison takes place. 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<pFKey->nCol; i++){ 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pLeft; /* Value from parent table row */ 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pRight; /* Column ref to child table */ 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pEq; /* Expression (pLeft = pRight) */ 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iCol; /* Index of column in child table */ 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zCol; /* Name of column in child table */ 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pLeft = sqlite3Expr(db, TK_REGISTER, 0); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pLeft ){ 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set the collation sequence and affinity of the LHS of each TK_EQ 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** expression to the parent key column defaults. */ 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pIdx ){ 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Column *pCol; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iCol = pIdx->aiColumn[i]; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pCol = &pTab->aCol[iCol]; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pTab->iPKey==iCol ) iCol = -1; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pLeft->iTable = regData+iCol+1; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pLeft->affinity = pCol->affinity; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pLeft->iTable = regData; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pLeft->affinity = SQLITE_AFF_INTEGER; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( iCol>=0 ); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zCol = pFKey->pFrom->aCol[iCol].zName; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pRight = sqlite3Expr(db, TK_ID, zCol); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pWhere = sqlite3ExprAnd(db, pWhere, pEq); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the child table is the same as the parent table, and this scan 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** is taking place as part of a DELETE operation (operation D.2), omit the 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** clause, where $rowid is the rowid of the row being deleted. */ 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pTab==pFKey->pFrom && nIncr>0 ){ 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pEq; /* Expression (pLeft = pRight) */ 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pLeft; /* Value from parent table row */ 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pRight; /* Column ref to child table */ 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pLeft = sqlite3Expr(db, TK_REGISTER, 0); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pRight = sqlite3Expr(db, TK_COLUMN, 0); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pLeft && pRight ){ 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pLeft->iTable = regData; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pLeft->affinity = SQLITE_AFF_INTEGER; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pRight->iTable = pSrc->a[0].iCursor; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pRight->iColumn = -1; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pEq = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pWhere = sqlite3ExprAnd(db, pWhere, pEq); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Resolve the references in the WHERE clause. */ 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&sNameContext, 0, sizeof(NameContext)); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sNameContext.pSrcList = pSrc; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sNameContext.pParse = pParse; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ResolveExprNames(&sNameContext, pWhere); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Create VDBE to loop through the entries in pSrc that match the WHERE 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** clause. If the constraint is not deferred, throw an exception for 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** each row found. Otherwise, for deferred constraints, increment the 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** deferred constraint counter by nIncr for each row selected. */ 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nIncr>0 && pFKey->isDeferred==0 ){ 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ParseToplevel(pParse)->mayAbort = 1; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pWInfo ){ 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3WhereEnd(pWInfo); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Clean up the WHERE clause constructed above. */ 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ExprDelete(db, pWhere); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( iFkIfZero ){ 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeJumpHere(v, iFkIfZero); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function returns a pointer to the head of a linked list of FK 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** constraints for which table pTab is the parent table. For example, 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** given the following schema: 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** CREATE TABLE t1(a PRIMARY KEY); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** CREATE TABLE t2(b REFERENCES t1(a); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Calling this function with table "t1" as an argument returns a pointer 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to the FKey structure representing the foreign key constraint on table 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** "t2". Calling this function with "t2" as the argument would return a 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** NULL pointer (as there are no FK constraints for which t2 is the parent 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table). 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FKey *sqlite3FkReferences(Table *pTab){ 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nName = sqlite3Strlen30(pTab->zName); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The second argument is a Trigger structure allocated by the 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** fkActionTrigger() routine. This function deletes the Trigger structure 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and all of its sub-components. 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The Trigger structure or any of its sub-components may be allocated from 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the lookaside buffer belonging to database handle dbMem. 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( p ){ 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TriggerStep *pStep = p->step_list; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ExprDelete(dbMem, pStep->pWhere); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ExprListDelete(dbMem, pStep->pExprList); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3SelectDelete(dbMem, pStep->pSelect); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ExprDelete(dbMem, p->pWhen); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3DbFree(dbMem, p); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called to generate code that runs when table pTab is 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** being dropped from the database. The SrcList passed as the second argument 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to this function contains a single entry guaranteed to resolve to 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table pTab. 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Normally, no code is required. However, if either 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (a) The table is the parent table of a FK constraint, or 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (b) The table is the child table of a deferred FK constraint and it is 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** determined at runtime that there are outstanding deferred FK 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** constraint violations in the database, 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** then the equivalent of "DELETE FROM <tbl>" is executed before dropping 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the table from the database. Triggers are disabled while running this 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** DELETE, but foreign key actions are not. 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3 *db = pParse->db; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){ 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iSkip = 0; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Vdbe *v = sqlite3GetVdbe(pParse); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( v ); /* VDBE has already been allocated */ 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sqlite3FkReferences(pTab)==0 ){ 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Search for a deferred foreign key constraint for which this table 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** is the child table. If one cannot be found, return without 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** generating any VDBE code. If one can be found, then jump over 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the entire DELETE if there are no outstanding deferred constraints 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** when this statement is run. */ 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *p; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(p=pTab->pFKey; p; p=p->pNextFrom){ 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( p->isDeferred ) break; 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !p ) return; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iSkip = sqlite3VdbeMakeLabel(v); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pParse->disableTriggers = 1; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pParse->disableTriggers = 0; 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the DELETE has generated immediate foreign key constraint 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** violations, halt the VDBE and return an error at this point, before 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** any modifications to the schema are made. This is because statement 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** transactions are not able to rollback schema changes. */ 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3HaltConstraint( 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pParse, OE_Abort, "foreign key constraint failed", P4_STATIC 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( iSkip ){ 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3VdbeResolveLabel(v, iSkip); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called when inserting, deleting or updating a row of 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table pTab to generate VDBE code to perform foreign key constraint 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** processing for the operation. 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For a DELETE operation, parameter regOld is passed the index of the 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** first register in an array of (pTab->nCol+1) registers containing the 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** rowid of the row being deleted, followed by each of the column values 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the row being deleted, from left to right. Parameter regNew is passed 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** zero in this case. 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For an INSERT operation, regOld is passed zero and regNew is passed the 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** first register of an array of (pTab->nCol+1) registers containing the new 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** row data. 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For an UPDATE operation, this function is called twice. Once before 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the original record is deleted from the table using the calling convention 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** described for DELETE. Then again after the original record is deleted 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** but before the new record is inserted using the INSERT convention. 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void sqlite3FkCheck( 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Parse *pParse, /* Parse context */ 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Table *pTab, /* Row is being deleted from this table */ 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int regOld, /* Previous row data is stored here */ 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int regNew /* New row data is stored here */ 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3 *db = pParse->db; /* Database handle */ 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *pFKey; /* Used to iterate through FKs */ 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iDb; /* Index of database containing pTab */ 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zDb; /* Name of database containing pTab */ 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isIgnoreErrors = pParse->disableTriggers; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Exactly one of regOld and regNew should be non-zero. */ 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( (regOld==0)!=(regNew==0) ); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If foreign-keys are disabled, this function is a no-op. */ 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (db->flags&SQLITE_ForeignKeys)==0 ) return; 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iDb = sqlite3SchemaToIndex(db, pTab->pSchema); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zDb = db->aDb[iDb].zName; 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Loop through all the foreign key constraints for which pTab is the 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** child table (the table that the foreign key definition is part of). */ 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Table *pTo; /* Parent table of foreign key pFKey */ 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Index *pIdx = 0; /* Index on key columns in pTo */ 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *aiFree = 0; 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *aiCol; 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iCol; 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isIgnore = 0; 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Find the parent table of this foreign key. Also find a unique index 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** on the parent key columns in the parent table. If either of these 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** schema items cannot be located, set an error in pParse and return 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** early. */ 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pParse->disableTriggers ){ 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pTo = sqlite3FindTable(db, pFKey->zTo, zDb); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !isIgnoreErrors || db->mallocFailed ) return; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFKey->nCol==1 || (aiFree && pIdx) ); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( aiFree ){ 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aiCol = aiFree; 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iCol = pFKey->aCol[0].iFrom; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aiCol = &iCol; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<pFKey->nCol; i++){ 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( aiCol[i]==pTab->iPKey ){ 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aiCol[i] = -1; 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_AUTHORIZATION 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Request permission to read the parent key columns. If the 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** authorization callback returns SQLITE_IGNORE, behave as if any 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** values read from the parent table are NULL. */ 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( db->xAuth ){ 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rcauth; 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isIgnore = (rcauth==SQLITE_IGNORE); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Take a shared-cache advisory read-lock on the parent table. Allocate 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** a cursor to use to search the unique index on the parent key columns 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** in the parent table. */ 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pParse->nTab++; 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( regOld!=0 ){ 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* A row is being removed from the child table. Search for the parent. 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** If the parent does not exist, removing the child row resolves an 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** outstanding foreign key constraint violation. */ 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore); 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( regNew!=0 ){ 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* A row is being added to the child table. If a parent row cannot 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** be found, adding the child row has violated the FK constraint. */ 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore); 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3DbFree(db, aiFree); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Loop through all the foreign key constraints that refer to this table */ 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Index *pIdx = 0; /* Foreign key index for pFKey */ 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SrcList *pSrc; 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *aiCol = 0; 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( regOld==0 && regNew!=0 ); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Inserting a single row into a parent table cannot cause an immediate 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** foreign key violation. So do nothing in this case. */ 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !isIgnoreErrors || db->mallocFailed ) return; 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( aiCol || pFKey->nCol==1 ); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Create a SrcList structure containing a single table (the table 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the foreign key that refers to this table is attached to). This 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** is required for the sqlite3WhereXXX() interface. */ 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pSrc = sqlite3SrcListAppend(db, 0, 0, 0); 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pSrc ){ 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct SrcList_item *pItem = pSrc->a; 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pItem->pTab = pFKey->pFrom; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pItem->zName = pFKey->pFrom->zName; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pItem->pTab->nRef++; 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pItem->iCursor = pParse->nTab++; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( regNew!=0 ){ 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( regOld!=0 ){ 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If there is a RESTRICT action configured for the current operation 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** on the parent table of this FK, then throw an exception 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** immediately if the FK constraint is violated, even if this is a 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** deferred trigger. That's what RESTRICT means. To defer checking 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the constraint, the FK should specify NO ACTION (represented 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** using OE_None). NO ACTION is the default. */ 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pItem->zName = 0; 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3SrcListDelete(db, pSrc); 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3DbFree(db, aiCol); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x))) 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called before generating code to update or delete a 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** row contained in table pTab. 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)u32 sqlite3FkOldmask( 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Parse *pParse, /* Parse context */ 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Table *pTab /* Table being modified */ 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 mask = 0; 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pParse->db->flags&SQLITE_ForeignKeys ){ 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *p; 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(p=pTab->pFKey; p; p=p->pNextFrom){ 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Index *pIdx = 0; 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) locateFkeyIndex(pParse, pTab, p, &pIdx, 0); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pIdx ){ 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mask; 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called before generating code to update or delete a 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** row contained in table pTab. If the operation is a DELETE, then 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** parameter aChange is passed a NULL value. For an UPDATE, aChange points 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to an array of size N, where N is the number of columns in table pTab. 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the i'th column is not modified by the UPDATE, then the corresponding 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** entry in the aChange[] array is set to -1. If the column is modified, 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the value is 0 or greater. Parameter chngRowid is set to true if the 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** UPDATE statement modifies the rowid fields of the table. 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If any foreign key processing will be required, this function returns 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** true. If there is no foreign key related processing, this function 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returns false. 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3FkRequired( 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Parse *pParse, /* Parse context */ 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Table *pTab, /* Table being modified */ 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *aChange, /* Non-NULL for UPDATE operations */ 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int chngRowid /* True for UPDATE that affects rowid */ 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pParse->db->flags&SQLITE_ForeignKeys ){ 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !aChange ){ 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* A DELETE operation. Foreign key processing is required if the 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** table in question is either the child or parent table for any 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** foreign key constraint. */ 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (sqlite3FkReferences(pTab) || pTab->pFKey); 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This is an UPDATE. Foreign key processing is only required if the 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** operation modifies one or more child or parent key columns. */ 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *p; 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check if any child key columns are being modified. */ 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(p=pTab->pFKey; p; p=p->pNextFrom){ 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<p->nCol; i++){ 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iChildKey = p->aCol[i].iFrom; 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( aChange[iChildKey]>=0 ) return 1; 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( iChildKey==pTab->iPKey && chngRowid ) return 1; 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check if any parent key columns are being modified. */ 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<p->nCol; i++){ 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zKey = p->aCol[i].zCol; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iKey; 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(iKey=0; iKey<pTab->nCol; iKey++){ 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Column *pCol = &pTab->aCol[iKey]; 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey) : pCol->isPrimKey) ){ 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( aChange[iKey]>=0 ) return 1; 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( iKey==pTab->iPKey && chngRowid ) return 1; 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called when an UPDATE or DELETE operation is being 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** compiled on table pTab, which is the parent table of foreign-key pFKey. 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the current operation is an UPDATE, then the pChanges parameter is 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** passed a pointer to the list of columns being modified. If it is a 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** DELETE, pChanges is passed a NULL pointer. 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** It returns a pointer to a Trigger structure containing a trigger 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** equivalent to the ON UPDATE or ON DELETE action specified by pFKey. 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returned (these actions require no special handling by the triggers 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sub-system, code for them is created by fkScanChildren()). 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For example, if pFKey is the foreign key and pTab is table "p" in 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the following schema: 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** CREATE TABLE p(pk PRIMARY KEY); 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** then the returned trigger structure is equivalent to: 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** CREATE TRIGGER ... DELETE ON p BEGIN 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** DELETE FROM c WHERE ck = old.pk; 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** END; 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The returned pointer is cached as part of the foreign key object. It 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is eventually freed along with the rest of the foreign key object by 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3FkDelete(). 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Trigger *fkActionTrigger( 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Parse *pParse, /* Parse context */ 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Table *pTab, /* Table being updated or deleted from */ 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *pFKey, /* Foreign key to get action for */ 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprList *pChanges /* Change-list for UPDATE, NULL for DELETE */ 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3 *db = pParse->db; /* Database handle */ 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int action; /* One of OE_None, OE_Cascade etc. */ 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Trigger *pTrigger; /* Trigger definition to return */ 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iAction = (pChanges!=0); /* 1 for UPDATE, 0 for DELETE */ 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) action = pFKey->aAction[iAction]; 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pTrigger = pFKey->apTrigger[iAction]; 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( action!=OE_None && !pTrigger ){ 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 enableLookaside; /* Copy of db->lookaside.bEnabled */ 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char const *zFrom; /* Name of child table */ 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nFrom; /* Length in bytes of zFrom */ 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Index *pIdx = 0; /* Parent key index for this FK */ 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *aiCol = 0; /* child table cols -> parent key cols */ 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TriggerStep *pStep = 0; /* First (only) step of trigger program */ 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pWhere = 0; /* WHERE clause of trigger step */ 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; /* Iterator variable */ 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pWhen = 0; /* WHEN clause for the trigger */ 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( aiCol || pFKey->nCol==1 ); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<pFKey->nCol; i++){ 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Token tOld = { "old", 3 }; /* Literal "old" token */ 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Token tNew = { "new", 3 }; /* Literal "new" token */ 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Token tFromCol; /* Name of column in child table */ 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Token tToCol; /* Name of column in parent table */ 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iFromCol; /* Idx of column in child table */ 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pEq; /* tFromCol = OLD.tToCol */ 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( iFromCol>=0 ); 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid"; 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tToCol.n = sqlite3Strlen30(tToCol.z); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tFromCol.n = sqlite3Strlen30(tFromCol.z); 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Create the expression "OLD.zToCol = zFromCol". It is important 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** that the "OLD.zToCol" term is on the LHS of the = operator, so 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** that the affinity and collation sequence associated with the 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** parent table are used for the comparison. */ 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pEq = sqlite3PExpr(pParse, TK_EQ, 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_DOT, 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , 0), 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , 0); 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pWhere = sqlite3ExprAnd(db, pWhere, pEq); 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* For ON UPDATE, construct the next term of the WHEN clause. 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** The final WHEN clause will be like this: 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pChanges ){ 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pEq = sqlite3PExpr(pParse, TK_IS, 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_DOT, 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0), 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_DOT, 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0), 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0); 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pWhen = sqlite3ExprAnd(db, pWhen, pEq); 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){ 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pNew; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( action==OE_Cascade ){ 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pNew = sqlite3PExpr(pParse, TK_DOT, 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , 0); 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else if( action==OE_SetDflt ){ 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pDflt ){ 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pNew = sqlite3ExprDup(db, pDflt, 0); 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pList = sqlite3ExprListAppend(pParse, pList, pNew); 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ExprListSetName(pParse, pList, &tFromCol, 0); 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3DbFree(db, aiCol); 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zFrom = pFKey->pFrom->zName; 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nFrom = sqlite3Strlen30(zFrom); 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( action==OE_Restrict ){ 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Token tFrom; 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *pRaise; 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tFrom.z = zFrom; 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tFrom.n = nFrom; 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pRaise = sqlite3Expr(db, TK_RAISE, "foreign key constraint failed"); 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pRaise ){ 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pRaise->affinity = OE_Abort; 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pSelect = sqlite3SelectNew(pParse, 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ExprListAppend(pParse, 0, pRaise), 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3SrcListAppend(db, 0, &tFrom, 0), 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pWhere, 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pWhere = 0; 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Disable lookaside memory allocation */ 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enableLookaside = db->lookaside.bEnabled; 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db->lookaside.bEnabled = 0; 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pTrigger = (Trigger *)sqlite3DbMallocZero(db, 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(Trigger) + /* struct Trigger */ 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(TriggerStep) + /* Single step in trigger program */ 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nFrom + 1 /* Space for pStep->target.z */ 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pTrigger ){ 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep->target.z = (char *)&pStep[1]; 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep->target.n = nFrom; 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy((char *)pStep->target.z, zFrom, nFrom); 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pWhen ){ 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0); 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Re-enable the lookaside buffer, if it was disabled earlier. */ 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db->lookaside.bEnabled = enableLookaside; 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ExprDelete(db, pWhere); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ExprDelete(db, pWhen); 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3ExprListDelete(db, pList); 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3SelectDelete(db, pSelect); 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( db->mallocFailed==1 ){ 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fkTriggerDelete(db, pTrigger); 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch( action ){ 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case OE_Restrict: 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep->op = TK_SELECT; 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case OE_Cascade: 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !pChanges ){ 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep->op = TK_DELETE; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep->op = TK_UPDATE; 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pStep->pTrig = pTrigger; 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pTrigger->pSchema = pTab->pSchema; 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pTrigger->pTabSchema = pTab->pSchema; 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFKey->apTrigger[iAction] = pTrigger; 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pTrigger->op = (pChanges ? TK_UPDATE : TK_DELETE); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pTrigger; 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called when deleting or updating a row to implement 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** any required CASCADE, SET NULL or SET DEFAULT actions. 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void sqlite3FkActions( 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Parse *pParse, /* Parse context */ 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Table *pTab, /* Table being updated or deleted from */ 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */ 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int regOld /* Address of array containing old row */ 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If foreign-key support is enabled, iterate through all FKs that 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** refer to table pTab. If there is an action associated with the FK 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** for this operation (either update or delete), invoke the associated 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** trigger sub-program. */ 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pParse->db->flags&SQLITE_ForeignKeys ){ 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *pFKey; /* Iterator variable */ 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Trigger *pAction = fkActionTrigger(pParse, pTab, pFKey, pChanges); 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pAction ){ 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3CodeRowTriggerDirect(pParse, pAction, pTab, regOld, OE_Abort, 0); 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* ifndef SQLITE_OMIT_TRIGGER */ 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Free all memory associated with foreign key definitions attached to 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** hash table. 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void sqlite3FkDelete(sqlite3 *db, Table *pTab){ 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *pFKey; /* Iterator variable */ 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FKey *pNext; /* Copy of pFKey->pNextFrom */ 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){ 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Remove the FK from the fkeyHash hash table. */ 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !db || db->pnBytesFreed==0 ){ 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pFKey->pPrevTo ){ 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFKey->pPrevTo->pNextTo = pFKey->pNextTo; 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *p = (void *)pFKey->pNextTo; 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), p); 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pFKey->pNextTo ){ 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* EV: R-30323-21917 Each foreign key constraint in SQLite is 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** classified as either immediate or deferred. 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 ); 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Delete any triggers created to implement actions for this FK. */ 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_TRIGGER 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fkTriggerDelete(db, pFKey->apTrigger[0]); 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fkTriggerDelete(db, pFKey->apTrigger[1]); 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pNext = pFKey->pNextFrom; 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3DbFree(db, pFKey); 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */ 1190