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.
This commit is contained in:
Tom Lane 2012-06-18 19:37:23 -04:00
parent 03a5ba24b0
commit e8c9fd5fdf
3 changed files with 65 additions and 12 deletions

View File

@ -2155,12 +2155,12 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
elog(ERROR, "SPI_connect failed");
/*
* Prepare a plan for the set default delete operation.
* Unfortunately we need to do it on every invocation because the
* default value could potentially change between calls.
* Fetch or prepare a saved plan for the set default delete
* operation
*/
ri_BuildQueryKey(&qkey, &riinfo, RI_PLAN_SETDEFAULT_DEL_DOUPDATE);
if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL)
{
StringInfoData querybuf;
StringInfoData qualbuf;
@ -2207,9 +2207,9 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
}
appendStringInfoString(&querybuf, qualbuf.data);
/* Prepare the plan, don't save it */
/* Prepare and save the plan */
qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids,
&qkey, fk_rel, pk_rel, false);
&qkey, fk_rel, pk_rel, true);
}
/*
@ -2239,7 +2239,7 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
return PointerGetDatum(NULL);
/*
* Handle MATCH PARTIAL set null delete.
* Handle MATCH PARTIAL set default delete.
*/
case FKCONSTR_MATCH_PARTIAL:
ereport(ERROR,
@ -2348,12 +2348,12 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
elog(ERROR, "SPI_connect failed");
/*
* Prepare a plan for the set default delete operation.
* Unfortunately we need to do it on every invocation because the
* default value could potentially change between calls.
* Fetch or prepare a saved plan for the set default update
* operation
*/
ri_BuildQueryKey(&qkey, &riinfo, RI_PLAN_SETDEFAULT_UPD_DOUPDATE);
if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL)
{
StringInfoData querybuf;
StringInfoData qualbuf;
@ -2400,9 +2400,9 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
}
appendStringInfoString(&querybuf, qualbuf.data);
/* Prepare the plan, don't save it */
/* Prepare and save the plan */
qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids,
&qkey, fk_rel, pk_rel, false);
&qkey, fk_rel, pk_rel, true);
}
/*
@ -2432,7 +2432,7 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
return PointerGetDatum(NULL);
/*
* Handle MATCH PARTIAL set null delete.
* Handle MATCH PARTIAL set default update.
*/
case FKCONSTR_MATCH_PARTIAL:
ereport(ERROR,

View File

@ -1319,3 +1319,39 @@ begin;
(2 rows)
commit;
--
-- Test that SET DEFAULT actions recognize updates to default values
--
create temp table defp (f1 int primary key);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "defp_pkey" for table "defp"
create temp table defc (f1 int default 0
references defp on delete set default);
insert into defp values (0), (1), (2);
insert into defc values (2);
select * from defc;
f1
----
2
(1 row)
delete from defp where f1 = 2;
select * from defc;
f1
----
0
(1 row)
delete from defp where f1 = 0; -- fail
ERROR: update or delete on table "defp" violates foreign key constraint "defc_f1_fkey" on table "defc"
DETAIL: Key (f1)=(0) is still referenced from table "defc".
alter table defc alter column f1 set default 1;
delete from defp where f1 = 0;
select * from defc;
f1
----
1
(1 row)
delete from defp where f1 = 1; -- fail
ERROR: update or delete on table "defp" violates foreign key constraint "defc_f1_fkey" on table "defc"
DETAIL: Key (f1)=(1) is still referenced from table "defc".

View File

@ -943,3 +943,20 @@ begin;
update selfref set a = 456 where a = 123;
select a, b from selfref;
commit;
--
-- Test that SET DEFAULT actions recognize updates to default values
--
create temp table defp (f1 int primary key);
create temp table defc (f1 int default 0
references defp on delete set default);
insert into defp values (0), (1), (2);
insert into defc values (2);
select * from defc;
delete from defp where f1 = 2;
select * from defc;
delete from defp where f1 = 0; -- fail
alter table defc alter column f1 set default 1;
delete from defp where f1 = 0;
select * from defc;
delete from defp where f1 = 1; -- fail