aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/tablecmds.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c21a309f04f..eab570a8675 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5681,14 +5681,10 @@ ATSimpleRecursion(List **wqueue, Relation rel,
AlterTableUtilityContext *context)
{
/*
- * Propagate to children if desired. Only plain tables, foreign tables
- * and partitioned tables have children, so no need to search for other
- * relkinds.
+ * Propagate to children, if desired and if there are (or might be) any
+ * children.
*/
- if (recurse &&
- (rel->rd_rel->relkind == RELKIND_RELATION ||
- rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
- rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
+ if (recurse && rel->rd_rel->relhassubclass)
{
Oid relid = RelationGetRelid(rel);
ListCell *child;
@@ -6699,6 +6695,41 @@ ATPrepSetNotNull(List **wqueue, Relation rel,
return;
/*
+ * If the target column is already marked NOT NULL, we can skip recursing
+ * to children, because their columns should already be marked NOT NULL as
+ * well. But there's no point in checking here unless the relation has
+ * some children; else we can just wait till execution to check. (If it
+ * does have children, however, this can save taking per-child locks
+ * unnecessarily. This greatly improves concurrency in some parallel
+ * restore scenarios.)
+ *
+ * Unfortunately, we can only apply this optimization to partitioned
+ * tables, because traditional inheritance doesn't enforce that child
+ * columns be NOT NULL when their parent is. (That's a bug that should
+ * get fixed someday.)
+ */
+ if (rel->rd_rel->relhassubclass &&
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ HeapTuple tuple;
+ bool attnotnull;
+
+ tuple = SearchSysCacheAttName(RelationGetRelid(rel), cmd->name);
+
+ /* Might as well throw the error now, if name is bad */
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ cmd->name, RelationGetRelationName(rel))));
+
+ attnotnull = ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull;
+ ReleaseSysCache(tuple);
+ if (attnotnull)
+ return;
+ }
+
+ /*
* If we have ALTER TABLE ONLY ... SET NOT NULL on a partitioned table,
* apply ALTER TABLE ... CHECK NOT NULL to every child. Otherwise, use
* normal recursion logic.