aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/tablecmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r--src/backend/commands/tablecmds.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 7ab3a511360..0866a680d7c 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -3017,8 +3017,15 @@ findAttrByName(const char *attributeName, List *schema)
* SetRelationHasSubclass
* Set the value of the relation's relhassubclass field in pg_class.
*
- * NOTE: caller must be holding an appropriate lock on the relation.
- * ShareUpdateExclusiveLock is sufficient.
+ * It's always safe to set this field to true, because all SQL commands are
+ * ready to see true and then find no children. On the other hand, commands
+ * generally assume zero children if this is false.
+ *
+ * Caller must hold any self-exclusive lock until end of transaction. If the
+ * new value is false, caller must have acquired that lock before reading the
+ * evidence that justified the false value. That way, it properly waits if
+ * another backend is simultaneously concluding no need to change the tuple
+ * (new and old values are true).
*
* NOTE: an important side-effect of this operation is that an SI invalidation
* message is sent out to all backends --- including me --- causing plans
@@ -3033,6 +3040,11 @@ SetRelationHasSubclass(Oid relationId, bool relhassubclass)
HeapTuple tuple;
Form_pg_class classtuple;
+ Assert(CheckRelationOidLockedByMe(relationId,
+ ShareUpdateExclusiveLock, false) ||
+ CheckRelationOidLockedByMe(relationId,
+ ShareRowExclusiveLock, true));
+
/*
* Fetch a modifiable copy of the tuple, modify it, update pg_class.
*/