Skip to content

Commit e8c9fd5

Browse files
committed
Allow ON UPDATE/DELETE SET DEFAULT plans to be cached.
Once upon a time, somebody was worried that cached RI plans wouldn't get remade with new default values after ALTER TABLE ... SET DEFAULT, so they didn't allow caching of plans for ON UPDATE/DELETE SET DEFAULT actions. That time is long gone, though (and even at the time I doubt this was the greatest hazard posed by ALTER TABLE...). So allow these triggers to cache their plans just like the others. The cache_plan argument to ri_PlanCheck is now vestigial, since there are no callers that don't pass "true"; but I left it alone in case there is any future need for it.
1 parent 03a5ba2 commit e8c9fd5

File tree

3 files changed

+65
-12
lines changed

3 files changed

+65
-12
lines changed

src/backend/utils/adt/ri_triggers.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,12 +2155,12 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
21552155
elog(ERROR, "SPI_connect failed");
21562156

21572157
/*
2158-
* Prepare a plan for the set default delete operation.
2159-
* Unfortunately we need to do it on every invocation because the
2160-
* default value could potentially change between calls.
2158+
* Fetch or prepare a saved plan for the set default delete
2159+
* operation
21612160
*/
21622161
ri_BuildQueryKey(&qkey, &riinfo, RI_PLAN_SETDEFAULT_DEL_DOUPDATE);
21632162

2163+
if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL)
21642164
{
21652165
StringInfoData querybuf;
21662166
StringInfoData qualbuf;
@@ -2207,9 +2207,9 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
22072207
}
22082208
appendStringInfoString(&querybuf, qualbuf.data);
22092209

2210-
/* Prepare the plan, don't save it */
2210+
/* Prepare and save the plan */
22112211
qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids,
2212-
&qkey, fk_rel, pk_rel, false);
2212+
&qkey, fk_rel, pk_rel, true);
22132213
}
22142214

22152215
/*
@@ -2239,7 +2239,7 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
22392239
return PointerGetDatum(NULL);
22402240

22412241
/*
2242-
* Handle MATCH PARTIAL set null delete.
2242+
* Handle MATCH PARTIAL set default delete.
22432243
*/
22442244
case FKCONSTR_MATCH_PARTIAL:
22452245
ereport(ERROR,
@@ -2348,12 +2348,12 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
23482348
elog(ERROR, "SPI_connect failed");
23492349

23502350
/*
2351-
* Prepare a plan for the set default delete operation.
2352-
* Unfortunately we need to do it on every invocation because the
2353-
* default value could potentially change between calls.
2351+
* Fetch or prepare a saved plan for the set default update
2352+
* operation
23542353
*/
23552354
ri_BuildQueryKey(&qkey, &riinfo, RI_PLAN_SETDEFAULT_UPD_DOUPDATE);
23562355

2356+
if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL)
23572357
{
23582358
StringInfoData querybuf;
23592359
StringInfoData qualbuf;
@@ -2400,9 +2400,9 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
24002400
}
24012401
appendStringInfoString(&querybuf, qualbuf.data);
24022402

2403-
/* Prepare the plan, don't save it */
2403+
/* Prepare and save the plan */
24042404
qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids,
2405-
&qkey, fk_rel, pk_rel, false);
2405+
&qkey, fk_rel, pk_rel, true);
24062406
}
24072407

24082408
/*
@@ -2432,7 +2432,7 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
24322432
return PointerGetDatum(NULL);
24332433

24342434
/*
2435-
* Handle MATCH PARTIAL set null delete.
2435+
* Handle MATCH PARTIAL set default update.
24362436
*/
24372437
case FKCONSTR_MATCH_PARTIAL:
24382438
ereport(ERROR,

src/test/regress/expected/foreign_key.out

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,3 +1319,39 @@ begin;
13191319
(2 rows)
13201320

13211321
commit;
1322+
--
1323+
-- Test that SET DEFAULT actions recognize updates to default values
1324+
--
1325+
create temp table defp (f1 int primary key);
1326+
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "defp_pkey" for table "defp"
1327+
create temp table defc (f1 int default 0
1328+
references defp on delete set default);
1329+
insert into defp values (0), (1), (2);
1330+
insert into defc values (2);
1331+
select * from defc;
1332+
f1
1333+
----
1334+
2
1335+
(1 row)
1336+
1337+
delete from defp where f1 = 2;
1338+
select * from defc;
1339+
f1
1340+
----
1341+
0
1342+
(1 row)
1343+
1344+
delete from defp where f1 = 0; -- fail
1345+
ERROR: update or delete on table "defp" violates foreign key constraint "defc_f1_fkey" on table "defc"
1346+
DETAIL: Key (f1)=(0) is still referenced from table "defc".
1347+
alter table defc alter column f1 set default 1;
1348+
delete from defp where f1 = 0;
1349+
select * from defc;
1350+
f1
1351+
----
1352+
1
1353+
(1 row)
1354+
1355+
delete from defp where f1 = 1; -- fail
1356+
ERROR: update or delete on table "defp" violates foreign key constraint "defc_f1_fkey" on table "defc"
1357+
DETAIL: Key (f1)=(1) is still referenced from table "defc".

src/test/regress/sql/foreign_key.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,3 +943,20 @@ begin;
943943
update selfref set a = 456 where a = 123;
944944
select a, b from selfref;
945945
commit;
946+
947+
--
948+
-- Test that SET DEFAULT actions recognize updates to default values
949+
--
950+
create temp table defp (f1 int primary key);
951+
create temp table defc (f1 int default 0
952+
references defp on delete set default);
953+
insert into defp values (0), (1), (2);
954+
insert into defc values (2);
955+
select * from defc;
956+
delete from defp where f1 = 2;
957+
select * from defc;
958+
delete from defp where f1 = 0; -- fail
959+
alter table defc alter column f1 set default 1;
960+
delete from defp where f1 = 0;
961+
select * from defc;
962+
delete from defp where f1 = 1; -- fail

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy