Do not run ON UPDATE actions of a foreign key constraint unless at least one

column value really does change.

FossilOrigin-Name: 71ac8e28e55ff0250ebe2fe239159ce2458d9165
This commit is contained in:
drh 2009-09-23 03:01:58 +00:00
parent 6a2fe09387
commit 788536b165
3 changed files with 38 additions and 12 deletions

View File

@ -1,8 +1,8 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C Generalize\sthe\sIS\sand\sIS\sNOT\soperators\sso\sthat\stheir\sright-hand\sside\scan\sbe\nan\sarbitrary\sexpression\sand\snot\ssimple\sthe\sconstant\sNULL.\s\sThey\swork\slike\n=\sand\s<>\sexcept\sthat\sNULL\svalues\scompare\sequal\sto\sone\sanother\san\sunequal\sto\neverything\selse.
D 2009-09-23T02:29:37
C Do\snot\srun\sON\sUPDATE\sactions\sof\sa\sforeign\skey\sconstraint\sunless\sat\sleast\sone\ncolumn\svalue\sreally\sdoes\schange.
D 2009-09-23T03:01:59
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -119,7 +119,7 @@ F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638
F src/delete.c 15499f5d10047d38e68ce991b3f88cbddb6e0931
F src/expr.c 8a663240f374a5326ee157df3d27751f58b7676a
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
F src/fkey.c fa1ad144926a8536e23cbbf64c0e51b8f2fdd4bf
F src/fkey.c de296942345984960792f12ea4236a6bef2f800b
F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
@ -756,14 +756,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 3fc938c961fd7810594224b91a2d6e1ac9e48084
R d99ab25244fa05bd56d10d71bb3bee44
P 98853f6104076c50ea92175e17a3254bfbbd4619
R 827ec94cc2eb4c57959ec45f4b3d8098
U drh
Z 4608482892179163853473e1fbf42a31
Z ec752338f3000365feb24aa823e5d734
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFKuYgUoxKgR168RlERApeHAJ48L4oeCXw8ZV6ov3G5+bjNMfQIewCfX/Rc
qXj8iamFDJ6JXwF0VP/iAOI=
=lSDQ
iD8DBQFKuY+roxKgR168RlERAq1TAKCDsc87lQ7RxW/6hlefk/rm32wxUACdGuQz
1VFw5lE97EA4c5Tiy8ftXks=
=0G/k
-----END PGP SIGNATURE-----

View File

@ -1 +1 @@
98853f6104076c50ea92175e17a3254bfbbd4619
71ac8e28e55ff0250ebe2fe239159ce2458d9165

View File

@ -395,6 +395,7 @@ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){
TriggerStep *pStep = p->step_list;
sqlite3ExprDelete(dbMem, pStep->pWhere);
sqlite3ExprListDelete(dbMem, pStep->pExprList);
sqlite3ExprDelete(dbMem, p->pWhen);
sqlite3DbFree(dbMem, p);
}
}
@ -649,6 +650,7 @@ static Trigger *fkActionTrigger(
Expr *pWhere = 0; /* WHERE clause of trigger step */
ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */
int i; /* Iterator variable */
Expr *pWhen = 0; /* WHEN clause for the trigger */
if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
assert( aiCol || pFKey->nCol==1 );
@ -678,6 +680,25 @@ static Trigger *fkActionTrigger(
, 0);
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
/* For ON UPDATE, construct the next term of the WHEN clause.
** The final WHEN clause will be like this:
**
** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN)
*/
if( pChanges ){
pEq = sqlite3PExpr(pParse, TK_IS,
sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
0),
sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
0),
0);
pWhen = sqlite3ExprAnd(db, pWhen, pEq);
}
if( action!=OE_Cascade || pChanges ){
Expr *pNew;
if( action==OE_Cascade ){
@ -724,13 +745,18 @@ static Trigger *fkActionTrigger(
pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
if( pWhen ){
pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0);
pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
}
}
/* Re-enable the lookaside buffer, if it was disabled earlier. */
db->lookaside.bEnabled = enableLookaside;
sqlite3ExprDelete(pParse->db, pWhere);
sqlite3ExprListDelete(pParse->db, pList);
sqlite3ExprDelete(db, pWhere);
sqlite3ExprDelete(db, pWhen);
sqlite3ExprListDelete(db, pList);
if( db->mallocFailed==1 ){
fkTriggerDelete(db, pTrigger);
return 0;