提交 ed50049c 编写于 作者: B Bhuvnesh Chaudhary 提交者: Bhuvnesh

Disallow ALTER TABLE ADD CONSTRAINT USING INDEX on a partition root

ADD CONSTRAINT USING INDEX is a new feature which didn't existing for 4
or 5 branches. This is taken from upstream commit eb7ed3f3. With
partition tables, the changes are not propagated to the leaf partitions
if the operation is done on the root table, thus disallowed currently.

This introduces rel_is_interior_partition to determine if a relation is
an interior node in a partition hierarchy.
Co-authored-by: NSoumyadeep Chakraborty <sochakraborty@pivotal.io>
上级 3adad712
......@@ -575,6 +575,91 @@ rel_is_child_partition(Oid relid)
return result;
}
/*
* Is relid an interior node of a partitioning hierarchy?
*
* To determine if it is an interior node or not, we need to find the depth of
* our partition and check if there is at least one more level below us.
*
* Call only on entry database.
*/
bool
rel_is_interior_partition(Oid relid)
{
HeapTuple tuple;
Oid paroid = InvalidOid;
bool is_interior = false;
int mylevel = 0;
Relation partrulerel;
Relation partrel;
ScanKeyData scankey;
SysScanDesc sscan;
Oid partitioned_rel = InvalidOid; /* OID of the root table of
* the partition set */
/*
* Find the pg_partition_rule entry to see if this is a child at all and,
* if so, to locate the OID for the pg_partition entry.
*
* SELECT paroid FROM pg_partition_rule WHERE parchildrelid = :1
*/
partrulerel = heap_open(PartitionRuleRelationId, AccessShareLock);
ScanKeyInit(&scankey, Anum_pg_partition_rule_parchildrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
sscan = systable_beginscan(partrulerel, PartitionRuleParchildrelidIndexId, true,
NULL, 1, &scankey);
tuple = systable_getnext(sscan);
if (tuple)
paroid = ((Form_pg_partition_rule) GETSTRUCT(tuple))->paroid;
else
paroid = InvalidOid;
systable_endscan(sscan);
heap_close(partrulerel, AccessShareLock);
if (!OidIsValid(paroid))
return false;
tuple = SearchSysCache1(PARTOID, ObjectIdGetDatum(paroid));
Insist(HeapTupleIsValid(tuple));
mylevel = ((Form_pg_partition) GETSTRUCT(tuple))->parlevel;
partitioned_rel = ((Form_pg_partition) GETSTRUCT(tuple))->parrelid;
ReleaseSysCache(tuple);
/* SELECT * FROM pg_partition WHERE parrelid = :1 */
partrel = heap_open(PartitionRelationId, AccessShareLock);
ScanKeyInit(&scankey, Anum_pg_partition_parrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(partitioned_rel));
sscan = systable_beginscan(partrel, PartitionParrelidIndexId, true,
NULL, 1, &scankey);
while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
{
/* not interested in templates */
if (((Form_pg_partition) GETSTRUCT(tuple))->paristemplate == false)
{
int depth = ((Form_pg_partition) GETSTRUCT(tuple))->parlevel;
if (depth > mylevel)
{
is_interior = true;
break;
}
}
}
systable_endscan(sscan);
heap_close(partrel, AccessShareLock);
return is_interior;
}
/*
* Is relid a leaf node of a partitioning hierarchy? If no, it does not follow
* that it is the root.
......
......@@ -8813,6 +8813,18 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
Assert(OidIsValid(index_oid));
Assert(stmt->isconstraint);
/*
* Doing this on partitioned tables is not a simple feature to implement,
* so let's punt for now.
*/
Oid rel_id = RelationGetRelid(rel);
bool is_root_or_interior_partition = rel_is_partitioned(rel_id)
|| rel_is_interior_partition(rel_id);
if (Gp_role != GP_ROLE_EXECUTE && is_root_or_interior_partition)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables")));
indexRel = index_open(index_oid, AccessShareLock);
indexName = pstrdup(RelationGetRelationName(indexRel));
......
......@@ -80,6 +80,8 @@ extern bool rel_has_appendonly_partition(Oid relid);
extern bool rel_is_child_partition(Oid relid);
extern bool rel_is_interior_partition(Oid relid);
extern bool rel_is_leaf_partition(Oid relid);
extern bool rel_partitioning_is_uniform(Oid rootOid);
......
......@@ -969,3 +969,19 @@ create table parttab_x (a int4, b int4) distributed by (b);
alter table parttab exchange partition for (1) with table parttab_x;
alter table parttab alter partition for (1) exchange partition for (1) with table parttab_x;
-- add constraint using index is forbidden on root and interior partitioned tables
create table root_part(a int, b int)
partition by range(b)
subpartition by list(b)
subpartition template (subpartition leaf values (1))
(partition interior start(1) end(2) every(1));
-- disallowed on root partitions
create unique index on root_part(a, b);
alter table root_part add primary key using index root_part_a_b_idx ;
-- disallowed on interior partitions
create unique index on root_part_1_prt_interior(a, b);
alter table root_part_1_prt_interior add primary key using index root_part_1_prt_interior_a_b_idx1 ;
-- allowed on leaf partitions
create unique index on root_part_1_prt_interior_2_prt_leaf(a, b);
alter table root_part_1_prt_interior_2_prt_leaf add primary key using index root_part_1_prt_interior_2_prt_leaf_a_b_idx2;
drop table root_part;
......@@ -2954,3 +2954,21 @@ alter table parttab exchange partition for (1) with table parttab_x;
ERROR: distribution policy for "parttab_x" must be the same as that for "parttab"
alter table parttab alter partition for (1) exchange partition for (1) with table parttab_x;
ERROR: distribution policy for "parttab_x" must be the same as that for "parttab"
-- add constraint using index is forbidden on root and interior partitioned tables
create table root_part(a int, b int)
partition by range(b)
subpartition by list(b)
subpartition template (subpartition leaf values (1))
(partition interior start(1) end(2) every(1));
-- disallowed on root partitions
create unique index on root_part(a, b);
alter table root_part add primary key using index root_part_a_b_idx ;
ERROR: ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables
-- disallowed on interior partitions
create unique index on root_part_1_prt_interior(a, b);
alter table root_part_1_prt_interior add primary key using index root_part_1_prt_interior_a_b_idx1 ;
ERROR: ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables
-- allowed on leaf partitions
create unique index on root_part_1_prt_interior_2_prt_leaf(a, b);
alter table root_part_1_prt_interior_2_prt_leaf add primary key using index root_part_1_prt_interior_2_prt_leaf_a_b_idx2;
drop table root_part;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册