Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a problem with "ON DELETE RESTRICT" and "ON UPDATE RESTRICT" foreign keys in attached databases scanning child tables in the wrong schema. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
04d5b637f087520cd58211505f9b5c08 |
User & Date: | dan 2022-04-16 15:46:23 |
Context
2022-04-16
| ||
17:53 | Make shell auto-column work with lots of columns when log() is missing. (check-in: 82366436 user: larrybr tags: trunk) | |
15:46 | Fix a problem with "ON DELETE RESTRICT" and "ON UPDATE RESTRICT" foreign keys in attached databases scanning child tables in the wrong schema. (check-in: 04d5b637 user: dan tags: trunk) | |
2022-04-14
| ||
19:48 | Cherry pick subroutine indentation improvements and the hardening of OP_Gosub from the right-join branch back into trunk. (check-in: 12645f10 user: drh tags: trunk) | |
Changes
Changes to src/fkey.c.
︙ | ︙ | |||
530 531 532 533 534 535 536 | ** The code generated by this function scans through the rows in the child ** table that correspond to the parent table row being deleted or inserted. ** For each child row found, one of the following actions is taken: ** ** Operation | FK type | Action taken ** -------------------------------------------------------------------------- ** DELETE immediate Increment the "immediate constraint counter". | < < < < | 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | ** The code generated by this function scans through the rows in the child ** table that correspond to the parent table row being deleted or inserted. ** For each child row found, one of the following actions is taken: ** ** Operation | FK type | Action taken ** -------------------------------------------------------------------------- ** DELETE immediate Increment the "immediate constraint counter". ** ** INSERT immediate Decrement the "immediate constraint counter". ** ** DELETE deferred Increment the "deferred constraint counter". ** ** INSERT deferred Decrement the "deferred constraint counter". ** ** These operations are identified in the comment at the top of this file ** (fkey.c) as "I.2" and "D.2". */ static void fkScanChildren( |
︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 | ** compiled on table pTab, which is the parent table of foreign-key pFKey. ** If the current operation is an UPDATE, then the pChanges parameter is ** passed a pointer to the list of columns being modified. If it is a ** DELETE, pChanges is passed a NULL pointer. ** ** It returns a pointer to a Trigger structure containing a trigger ** equivalent to the ON UPDATE or ON DELETE action specified by pFKey. | | | | | 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 | ** compiled on table pTab, which is the parent table of foreign-key pFKey. ** If the current operation is an UPDATE, then the pChanges parameter is ** passed a pointer to the list of columns being modified. If it is a ** DELETE, pChanges is passed a NULL pointer. ** ** It returns a pointer to a Trigger structure containing a trigger ** equivalent to the ON UPDATE or ON DELETE action specified by pFKey. ** If the action is "NO ACTION" then a NULL pointer is returned (these actions ** require no special handling by the triggers sub-system, code for them is ** created by fkScanChildren()). ** ** For example, if pFKey is the foreign key and pTab is table "p" in ** the following schema: ** ** CREATE TABLE p(pk PRIMARY KEY); ** CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE); ** |
︙ | ︙ | |||
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 | } sqlite3DbFree(db, aiCol); zFrom = pFKey->pFrom->zName; nFrom = sqlite3Strlen30(zFrom); if( action==OE_Restrict ){ Token tFrom; Expr *pRaise; tFrom.z = zFrom; tFrom.n = nFrom; pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed"); if( pRaise ){ pRaise->affExpr = OE_Abort; } pSelect = sqlite3SelectNew(pParse, sqlite3ExprListAppend(pParse, 0, pRaise), | > > > > > | | 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 | } sqlite3DbFree(db, aiCol); zFrom = pFKey->pFrom->zName; nFrom = sqlite3Strlen30(zFrom); if( action==OE_Restrict ){ int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); Token tFrom; Token tDb; Expr *pRaise; tFrom.z = zFrom; tFrom.n = nFrom; tDb.z = db->aDb[iDb].zDbSName; tDb.n = sqlite3Strlen30(tDb.z); pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed"); if( pRaise ){ pRaise->affExpr = OE_Abort; } pSelect = sqlite3SelectNew(pParse, sqlite3ExprListAppend(pParse, 0, pRaise), sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom), pWhere, 0, 0, 0, 0, 0 ); pWhere = 0; } /* Disable lookaside memory allocation */ |
︙ | ︙ |
Changes to test/fkey8.test.
︙ | ︙ | |||
223 224 225 226 227 228 229 230 231 | INSERT INTO child VALUES(456); UPDATE parent SET p = '456' WHERE p=1200; COMMIT; } do_execsql_test 5.3 { PRAGMA integrity_check; } {ok} finish_test | > > > > > > > > > > > > > > > > > > > > > > | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | INSERT INTO child VALUES(456); UPDATE parent SET p = '456' WHERE p=1200; COMMIT; } do_execsql_test 5.3 { PRAGMA integrity_check; } {ok} #------------------------------------------------------------------------- reset_db forcedelete test.db2 do_execsql_test 6.1 { PRAGMA foreign_keys = on; CREATE TABLE c1(b); INSERT INTO c1 VALUES(123); } do_execsql_test 6.2 { ATTACH 'test.db2' AS aux; CREATE TABLE aux.p1(a INTEGER PRIMARY KEY); CREATE TABLE aux.c1(b REFERENCES p1(a) ON DELETE RESTRICT); INSERT INTO aux.p1 VALUES(123); } do_execsql_test 6.3 { DELETE FROM aux.p1 WHERE a=123; } finish_test |