aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/pg_constraint.c12
-rw-r--r--src/backend/commands/tablecmds.c26
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.