MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
{
Relation attrrel;
- AttrNumber parent_attno;
- int parent_natts;
- TupleDesc tupleDesc;
- HeapTuple tuple;
- bool child_is_partition = false;
+ TupleDesc parent_desc;
attrrel = table_open(AttributeRelationId, RowExclusiveLock);
+ parent_desc = RelationGetDescr(parent_rel);
- tupleDesc = RelationGetDescr(parent_rel);
- parent_natts = tupleDesc->natts;
-
- /* If parent_rel is a partitioned table, child_rel must be a partition */
- if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
- child_is_partition = true;
-
- for (parent_attno = 1; parent_attno <= parent_natts; parent_attno++)
+ for (AttrNumber parent_attno = 1; parent_attno <= parent_desc->natts; parent_attno++)
{
- Form_pg_attribute attribute = TupleDescAttr(tupleDesc,
- parent_attno - 1);
- char *attributeName = NameStr(attribute->attname);
+ Form_pg_attribute parent_att = TupleDescAttr(parent_desc, parent_attno - 1);
+ char *parent_attname = NameStr(parent_att->attname);
+ HeapTuple tuple;
/* Ignore dropped columns in the parent. */
- if (attribute->attisdropped)
+ if (parent_att->attisdropped)
continue;
/* Find same column in child (matching on column name). */
- tuple = SearchSysCacheCopyAttName(RelationGetRelid(child_rel),
- attributeName);
+ tuple = SearchSysCacheCopyAttName(RelationGetRelid(child_rel), parent_attname);
if (HeapTupleIsValid(tuple))
{
- /* Check they are same type, typmod, and collation */
- Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
+ Form_pg_attribute child_att = (Form_pg_attribute) GETSTRUCT(tuple);
- if (attribute->atttypid != childatt->atttypid ||
- attribute->atttypmod != childatt->atttypmod)
+ if (parent_att->atttypid != child_att->atttypid ||
+ parent_att->atttypmod != child_att->atttypmod)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("child table \"%s\" has different type for column \"%s\"",
- RelationGetRelationName(child_rel),
- attributeName)));
+ RelationGetRelationName(child_rel), parent_attname)));
- if (attribute->attcollation != childatt->attcollation)
+ if (parent_att->attcollation != child_att->attcollation)
ereport(ERROR,
(errcode(ERRCODE_COLLATION_MISMATCH),
errmsg("child table \"%s\" has different collation for column \"%s\"",
- RelationGetRelationName(child_rel),
- attributeName)));
+ RelationGetRelationName(child_rel), parent_attname)));
/*
* If the parent has a not-null constraint that's not NO INHERIT,
*
* Other constraints are checked elsewhere.
*/
- if (attribute->attnotnull && !childatt->attnotnull)
+ if (parent_att->attnotnull && !child_att->attnotnull)
{
HeapTuple contup;
contup = findNotNullConstraintAttnum(RelationGetRelid(parent_rel),
- attribute->attnum);
+ parent_att->attnum);
if (HeapTupleIsValid(contup) &&
!((Form_pg_constraint) GETSTRUCT(contup))->connoinherit)
ereport(ERROR,
errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("column \"%s\" in child table must be marked NOT NULL",
- attributeName));
+ parent_attname));
}
/*
* Child column must be generated if and only if parent column is.
*/
- if (attribute->attgenerated && !childatt->attgenerated)
+ if (parent_att->attgenerated && !child_att->attgenerated)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("column \"%s\" in child table must be a generated column",
- attributeName)));
- if (childatt->attgenerated && !attribute->attgenerated)
+ errmsg("column \"%s\" in child table must be a generated column", parent_attname)));
+ if (child_att->attgenerated && !parent_att->attgenerated)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("column \"%s\" in child table must not be a generated column",
- attributeName)));
+ errmsg("column \"%s\" in child table must not be a generated column", parent_attname)));
/*
* OK, bump the child column's inheritance count. (If we fail
* later on, this change will just roll back.)
*/
- childatt->attinhcount++;
- if (childatt->attinhcount < 0)
+ child_att->attinhcount++;
+ if (child_att->attinhcount < 0)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
* is same in all partitions. (Note: there are only inherited
* attributes in partitions)
*/
- if (child_is_partition)
+ if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
- Assert(childatt->attinhcount == 1);
- childatt->attislocal = false;
+ Assert(child_att->attinhcount == 1);
+ child_att->attislocal = false;
}
CatalogTupleUpdate(attrrel, &tuple->t_self, tuple);
{
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("child table is missing column \"%s\"",
- attributeName)));
+ errmsg("child table is missing column \"%s\"", parent_attname)));
}
}
static void
MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
{
- Relation catalog_relation;
- TupleDesc tuple_desc;
+ Relation constraintrel;
SysScanDesc parent_scan;
ScanKeyData parent_key;
HeapTuple parent_tuple;
Oid parent_relid = RelationGetRelid(parent_rel);
- bool child_is_partition = false;
- catalog_relation = table_open(ConstraintRelationId, RowExclusiveLock);
- tuple_desc = RelationGetDescr(catalog_relation);
-
- /* If parent_rel is a partitioned table, child_rel must be a partition */
- if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
- child_is_partition = true;
+ constraintrel = table_open(ConstraintRelationId, RowExclusiveLock);
/* Outer loop scans through the parent's constraint definitions */
ScanKeyInit(&parent_key,
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(parent_relid));
- parent_scan = systable_beginscan(catalog_relation, ConstraintRelidTypidNameIndexId,
+ parent_scan = systable_beginscan(constraintrel, ConstraintRelidTypidNameIndexId,
true, NULL, 1, &parent_key);
while (HeapTupleIsValid(parent_tuple = systable_getnext(parent_scan)))
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(child_rel)));
- child_scan = systable_beginscan(catalog_relation, ConstraintRelidTypidNameIndexId,
+ child_scan = systable_beginscan(constraintrel, ConstraintRelidTypidNameIndexId,
true, NULL, 1, &child_key);
while (HeapTupleIsValid(child_tuple = systable_getnext(child_scan)))
* CHECK constraint are matched by name, NOT NULL ones by
* attribute number
*/
- if (child_con->contype == CONSTRAINT_CHECK &&
- strcmp(NameStr(parent_con->conname),
- NameStr(child_con->conname)) != 0)
- continue;
+ if (child_con->contype == CONSTRAINT_CHECK)
+ {
+ if (strcmp(NameStr(parent_con->conname),
+ NameStr(child_con->conname)) != 0)
+ continue;
+ }
else if (child_con->contype == CONSTRAINT_NOTNULL)
{
AttrNumber parent_attno = extractNotNullColumn(parent_tuple);
}
if (child_con->contype == CONSTRAINT_CHECK &&
- !constraints_equivalent(parent_tuple, child_tuple, tuple_desc))
+ !constraints_equivalent(parent_tuple, child_tuple, RelationGetDescr(constraintrel)))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("child table \"%s\" has different definition for check constraint \"%s\"",
- RelationGetRelationName(child_rel),
- NameStr(parent_con->conname))));
+ RelationGetRelationName(child_rel), NameStr(parent_con->conname))));
/*
* If the CHECK child constraint is "no inherit" then cannot
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"",
- NameStr(child_con->conname),
- RelationGetRelationName(child_rel))));
+ NameStr(child_con->conname), RelationGetRelationName(child_rel))));
/*
* If the child constraint is "not valid" then cannot merge with a
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"",
- NameStr(child_con->conname),
- RelationGetRelationName(child_rel))));
+ NameStr(child_con->conname), RelationGetRelationName(child_rel))));
/*
* OK, bump the child constraint's inheritance count. (If we fail
* inherited only once since it cannot have multiple parents and
* it is never considered local.
*/
- if (child_is_partition)
+ if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
Assert(child_con->coninhcount == 1);
child_con->conislocal = false;
}
- CatalogTupleUpdate(catalog_relation, &child_copy->t_self, child_copy);
+ CatalogTupleUpdate(constraintrel, &child_copy->t_self, child_copy);
heap_freetuple(child_copy);
found = true;
}
systable_endscan(parent_scan);
- table_close(catalog_relation, RowExclusiveLock);
+ table_close(constraintrel, RowExclusiveLock);
}
/*
List *connames;
List *nncolumns;
bool found;
- bool child_is_partition = false;
+ bool is_partitioning;
- /* If parent_rel is a partitioned table, child_rel must be a partition */
- if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
- child_is_partition = true;
+ is_partitioning = (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
found = DeleteInheritsTuple(RelationGetRelid(child_rel),
RelationGetRelid(parent_rel),
RelationGetRelationName(child_rel));
if (!found)
{
- if (child_is_partition)
+ if (is_partitioning)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation \"%s\" is not a partition of relation \"%s\"",
drop_parent_dependency(RelationGetRelid(child_rel),
RelationRelationId,
RelationGetRelid(parent_rel),
- child_dependency_type(child_is_partition));
+ child_dependency_type(is_partitioning));
/*
* Post alter hook of this inherits. Since object_access_hook doesn't take