mirror of
https://github.com/postgres/postgres.git
synced 2025-04-20 00:42:27 +03:00
Fix things so that updatable views work with partitioned tables.
Previously, ExecInitModifyTable was missing handling for WITH CHECK OPTION, and view_query_is_auto_updatable was missing handling for RELKIND_PARTITIONED_TABLE. Amit Langote, reviewed by me.
This commit is contained in:
parent
132488bfee
commit
587cda35ca
@ -1777,6 +1777,46 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build WITH CHECK OPTION constraints for each leaf partition rel.
|
||||||
|
* Note that we didn't build the withCheckOptionList for each partition
|
||||||
|
* within the planner, but simple translation of the varattnos for each
|
||||||
|
* partition will suffice. This only occurs for the INSERT case;
|
||||||
|
* UPDATE/DELETE cases are handled above.
|
||||||
|
*/
|
||||||
|
if (node->withCheckOptionLists != NIL && mtstate->mt_num_partitions > 0)
|
||||||
|
{
|
||||||
|
List *wcoList;
|
||||||
|
|
||||||
|
Assert(operation == CMD_INSERT);
|
||||||
|
resultRelInfo = mtstate->mt_partitions;
|
||||||
|
wcoList = linitial(node->withCheckOptionLists);
|
||||||
|
for (i = 0; i < mtstate->mt_num_partitions; i++)
|
||||||
|
{
|
||||||
|
Relation partrel = resultRelInfo->ri_RelationDesc;
|
||||||
|
List *mapped_wcoList;
|
||||||
|
List *wcoExprs = NIL;
|
||||||
|
ListCell *ll;
|
||||||
|
|
||||||
|
/* varno = node->nominalRelation */
|
||||||
|
mapped_wcoList = map_partition_varattnos(wcoList,
|
||||||
|
node->nominalRelation,
|
||||||
|
partrel, rel);
|
||||||
|
foreach(ll, mapped_wcoList)
|
||||||
|
{
|
||||||
|
WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
|
||||||
|
ExprState *wcoExpr = ExecInitExpr((Expr *) wco->qual,
|
||||||
|
mtstate->mt_plans[i]);
|
||||||
|
|
||||||
|
wcoExprs = lappend(wcoExprs, wcoExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
resultRelInfo->ri_WithCheckOptions = mapped_wcoList;
|
||||||
|
resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
|
||||||
|
resultRelInfo++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize RETURNING projections if needed.
|
* Initialize RETURNING projections if needed.
|
||||||
*/
|
*/
|
||||||
|
@ -2249,7 +2249,8 @@ view_query_is_auto_updatable(Query *viewquery, bool check_cols)
|
|||||||
if (base_rte->rtekind != RTE_RELATION ||
|
if (base_rte->rtekind != RTE_RELATION ||
|
||||||
(base_rte->relkind != RELKIND_RELATION &&
|
(base_rte->relkind != RELKIND_RELATION &&
|
||||||
base_rte->relkind != RELKIND_FOREIGN_TABLE &&
|
base_rte->relkind != RELKIND_FOREIGN_TABLE &&
|
||||||
base_rte->relkind != RELKIND_VIEW))
|
base_rte->relkind != RELKIND_VIEW &&
|
||||||
|
base_rte->relkind != RELKIND_PARTITIONED_TABLE))
|
||||||
return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
|
return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
|
||||||
|
|
||||||
if (base_rte->tablesample)
|
if (base_rte->tablesample)
|
||||||
|
@ -2367,3 +2367,27 @@ ERROR: new row violates check option for view "v1"
|
|||||||
DETAIL: Failing row contains (-1, invalid).
|
DETAIL: Failing row contains (-1, invalid).
|
||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
-- check that an auto-updatable view on a partitioned table works correctly
|
||||||
|
create table p (a int, b int) partition by range (a, b);
|
||||||
|
create table p1 (b int not null, a int not null) partition by range (b);
|
||||||
|
create table p11 (like p1);
|
||||||
|
alter table p11 drop a;
|
||||||
|
alter table p11 add a int;
|
||||||
|
alter table p11 drop a;
|
||||||
|
alter table p11 add a int not null;
|
||||||
|
alter table p1 attach partition p11 for values from (2) to (5);
|
||||||
|
alter table p attach partition p1 for values from (1, 2) to (1, 10);
|
||||||
|
create view pv as select * from p;
|
||||||
|
insert into pv values (1, 2);
|
||||||
|
select tableoid::regclass, * from p;
|
||||||
|
tableoid | a | b
|
||||||
|
----------+---+---
|
||||||
|
p11 | 1 | 2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
create view pv_wco as select * from p where a = 0 with check option;
|
||||||
|
insert into pv_wco values (1, 2);
|
||||||
|
ERROR: new row violates check option for view "pv_wco"
|
||||||
|
DETAIL: Failing row contains (2, 1).
|
||||||
|
drop view pv, pv_wco;
|
||||||
|
drop table p, p1, p11;
|
||||||
|
@ -1112,3 +1112,22 @@ INSERT INTO v1 VALUES (-1, 'invalid'); -- should fail
|
|||||||
|
|
||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
-- check that an auto-updatable view on a partitioned table works correctly
|
||||||
|
create table p (a int, b int) partition by range (a, b);
|
||||||
|
create table p1 (b int not null, a int not null) partition by range (b);
|
||||||
|
create table p11 (like p1);
|
||||||
|
alter table p11 drop a;
|
||||||
|
alter table p11 add a int;
|
||||||
|
alter table p11 drop a;
|
||||||
|
alter table p11 add a int not null;
|
||||||
|
alter table p1 attach partition p11 for values from (2) to (5);
|
||||||
|
alter table p attach partition p1 for values from (1, 2) to (1, 10);
|
||||||
|
|
||||||
|
create view pv as select * from p;
|
||||||
|
insert into pv values (1, 2);
|
||||||
|
select tableoid::regclass, * from p;
|
||||||
|
create view pv_wco as select * from p where a = 0 with check option;
|
||||||
|
insert into pv_wco values (1, 2);
|
||||||
|
drop view pv, pv_wco;
|
||||||
|
drop table p, p1, p11;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user