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:
parent
03a5ba24b0
commit
e8c9fd5fdf
|
@ -2155,12 +2155,12 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
|
||||||
elog(ERROR, "SPI_connect failed");
|
elog(ERROR, "SPI_connect failed");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare a plan for the set default delete operation.
|
* Fetch or prepare a saved plan for the set default delete
|
||||||
* Unfortunately we need to do it on every invocation because the
|
* operation
|
||||||
* default value could potentially change between calls.
|
|
||||||
*/
|
*/
|
||||||
ri_BuildQueryKey(&qkey, &riinfo, RI_PLAN_SETDEFAULT_DEL_DOUPDATE);
|
ri_BuildQueryKey(&qkey, &riinfo, RI_PLAN_SETDEFAULT_DEL_DOUPDATE);
|
||||||
|
|
||||||
|
if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL)
|
||||||
{
|
{
|
||||||
StringInfoData querybuf;
|
StringInfoData querybuf;
|
||||||
StringInfoData qualbuf;
|
StringInfoData qualbuf;
|
||||||
|
@ -2207,9 +2207,9 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
|
||||||
}
|
}
|
||||||
appendStringInfoString(&querybuf, qualbuf.data);
|
appendStringInfoString(&querybuf, qualbuf.data);
|
||||||
|
|
||||||
/* Prepare the plan, don't save it */
|
/* Prepare and save the plan */
|
||||||
qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids,
|
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);
|
return PointerGetDatum(NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle MATCH PARTIAL set null delete.
|
* Handle MATCH PARTIAL set default delete.
|
||||||
*/
|
*/
|
||||||
case FKCONSTR_MATCH_PARTIAL:
|
case FKCONSTR_MATCH_PARTIAL:
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
|
@ -2348,12 +2348,12 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
|
||||||
elog(ERROR, "SPI_connect failed");
|
elog(ERROR, "SPI_connect failed");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare a plan for the set default delete operation.
|
* Fetch or prepare a saved plan for the set default update
|
||||||
* Unfortunately we need to do it on every invocation because the
|
* operation
|
||||||
* default value could potentially change between calls.
|
|
||||||
*/
|
*/
|
||||||
ri_BuildQueryKey(&qkey, &riinfo, RI_PLAN_SETDEFAULT_UPD_DOUPDATE);
|
ri_BuildQueryKey(&qkey, &riinfo, RI_PLAN_SETDEFAULT_UPD_DOUPDATE);
|
||||||
|
|
||||||
|
if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL)
|
||||||
{
|
{
|
||||||
StringInfoData querybuf;
|
StringInfoData querybuf;
|
||||||
StringInfoData qualbuf;
|
StringInfoData qualbuf;
|
||||||
|
@ -2400,9 +2400,9 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
|
||||||
}
|
}
|
||||||
appendStringInfoString(&querybuf, qualbuf.data);
|
appendStringInfoString(&querybuf, qualbuf.data);
|
||||||
|
|
||||||
/* Prepare the plan, don't save it */
|
/* Prepare and save the plan */
|
||||||
qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids,
|
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);
|
return PointerGetDatum(NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle MATCH PARTIAL set null delete.
|
* Handle MATCH PARTIAL set default update.
|
||||||
*/
|
*/
|
||||||
case FKCONSTR_MATCH_PARTIAL:
|
case FKCONSTR_MATCH_PARTIAL:
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
|
|
|
@ -1319,3 +1319,39 @@ begin;
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
commit;
|
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".
|
||||||
|
|
|
@ -943,3 +943,20 @@ begin;
|
||||||
update selfref set a = 456 where a = 123;
|
update selfref set a = 456 where a = 123;
|
||||||
select a, b from selfref;
|
select a, b from selfref;
|
||||||
commit;
|
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
|
||||||
|
|
Loading…
Reference in New Issue