diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/pg_constraint.c | 12 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 26 |
2 files changed, 33 insertions, 5 deletions
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 446b54b9ffa..698b493fc40 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -783,6 +783,12 @@ ConstraintSetParentConstraint(Oid childConstrId, Oid parentConstrId) constrForm = (Form_pg_constraint) GETSTRUCT(newtup); if (OidIsValid(parentConstrId)) { + /* don't allow setting parent for a constraint that already has one */ + Assert(constrForm->coninhcount == 0); + if (constrForm->conparentid != InvalidOid) + elog(ERROR, "constraint %u already has a parent constraint", + childConstrId); + constrForm->conislocal = false; constrForm->coninhcount++; constrForm->conparentid = parentConstrId; @@ -797,10 +803,12 @@ ConstraintSetParentConstraint(Oid childConstrId, Oid parentConstrId) else { constrForm->coninhcount--; - if (constrForm->coninhcount <= 0) - constrForm->conislocal = true; + constrForm->conislocal = true; constrForm->conparentid = InvalidOid; + /* Make sure there's no further inheritance. */ + Assert(constrForm->coninhcount == 0); + deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId, ConstraintRelationId, DEPENDENCY_INTERNAL_AUTO); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 887c19c3eff..e010586dd67 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -7243,6 +7243,7 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid pfeqoperators[INDEX_MAX_KEYS]; Oid ppeqoperators[INDEX_MAX_KEYS]; Oid ffeqoperators[INDEX_MAX_KEYS]; + bool connoinherit; int i; int numfks, numpks; @@ -7587,6 +7588,12 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, } /* + * FKs always inherit for partitioned tables, and never for legacy + * inheritance. + */ + connoinherit = rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE; + + /* * Record the FK constraint in pg_constraint. */ constrOid = CreateConstraintEntry(fkconstraint->conname, @@ -7616,7 +7623,7 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, NULL, true, /* islocal */ 0, /* inhcount */ - true, /* isnoinherit */ + connoinherit, /* conNoInherit */ false); /* is_internal */ ObjectAddressSet(address, ConstraintRelationId, constrOid); @@ -7937,7 +7944,7 @@ CloneFkReferencing(Relation pg_constraint, Relation parentRel, } systable_endscan(scan); - heap_close(trigrel, RowExclusiveLock); + table_close(trigrel, RowExclusiveLock); ConstraintSetParentConstraint(fk->conoid, parentConstrOid); CommandCounterIncrement(); @@ -9131,6 +9138,7 @@ ATExecDropConstraint(Relation rel, const char *constrName, HeapTuple tuple; bool found = false; bool is_no_inherit_constraint = false; + char contype; /* At top level, permission check was done in ATPrepCmd, else do it */ if (recursing) @@ -9171,6 +9179,7 @@ ATExecDropConstraint(Relation rel, const char *constrName, constrName, RelationGetRelationName(rel)))); is_no_inherit_constraint = con->connoinherit; + contype = con->contype; /* * If it's a foreign-key constraint, we'd better lock the referenced @@ -9179,7 +9188,7 @@ ATExecDropConstraint(Relation rel, const char *constrName, * that has unfired events). But we can/must skip that in the * self-referential case. */ - if (con->contype == CONSTRAINT_FOREIGN && + if (contype == CONSTRAINT_FOREIGN && con->confrelid != RelationGetRelid(rel)) { Relation frel; @@ -9224,6 +9233,17 @@ ATExecDropConstraint(Relation rel, const char *constrName, } /* + * For partitioned tables, non-CHECK inherited constraints are dropped via + * the dependency mechanism, so we're done here. + */ + if (contype != CONSTRAINT_CHECK && + rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + { + table_close(conrel, RowExclusiveLock); + return; + } + + /* * Propagate to children as appropriate. Unlike most other ALTER * routines, we have to do this one level of recursion at a time; we can't * use find_all_inheritors to do it in one pass. |