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.c24
2 files changed, 32 insertions, 4 deletions
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 5720c652b2c..c0ae92c0052 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -792,6 +792,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;
@@ -806,10 +812,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 747acbd2b91..910e5deaa3f 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7336,6 +7336,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;
@@ -7680,6 +7681,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,
@@ -7710,7 +7717,7 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
NULL,
true, /* islocal */
0, /* inhcount */
- true, /* isnoinherit */
+ connoinherit, /* conNoInherit */
false); /* is_internal */
ObjectAddressSet(address, ConstraintRelationId, constrOid);
@@ -9230,6 +9237,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)
@@ -9270,6 +9278,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
@@ -9278,7 +9287,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;
@@ -9323,6 +9332,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)
+ {
+ heap_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.