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.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f679d619d7d..8f569ed0bd6 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -345,6 +345,8 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
AlterTableCmd *cmd, LOCKMODE lockmode);
static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode);
static void ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode);
+static void change_owner_fix_column_acls(Oid relationOid,
+ Oid oldOwnerId, Oid newOwnerId);
static void change_owner_recurse_to_sequences(Oid relationOid,
Oid newOwnerId, LOCKMODE lockmode);
static void ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode);
@@ -7531,6 +7533,14 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
heap_freetuple(newtuple);
/*
+ * We must similarly update any per-column ACLs to reflect the new
+ * owner; for neatness reasons that's split out as a subroutine.
+ */
+ change_owner_fix_column_acls(relationOid,
+ tuple_class->relowner,
+ newOwnerId);
+
+ /*
* Update owner dependency reference, if any. A composite type has
* none, because it's tracked for the pg_type entry instead of here;
* indexes and TOAST tables don't have their own entries either.
@@ -7587,6 +7597,71 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
}
/*
+ * change_owner_fix_column_acls
+ *
+ * Helper function for ATExecChangeOwner. Scan the columns of the table
+ * and fix any non-null column ACLs to reflect the new owner.
+ */
+static void
+change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId)
+{
+ Relation attRelation;
+ SysScanDesc scan;
+ ScanKeyData key[1];
+ HeapTuple attributeTuple;
+
+ attRelation = heap_open(AttributeRelationId, RowExclusiveLock);
+ ScanKeyInit(&key[0],
+ Anum_pg_attribute_attrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relationOid));
+ scan = systable_beginscan(attRelation, AttributeRelidNumIndexId,
+ true, SnapshotNow, 1, key);
+ while (HeapTupleIsValid(attributeTuple = systable_getnext(scan)))
+ {
+ Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple);
+ Datum repl_val[Natts_pg_attribute];
+ bool repl_null[Natts_pg_attribute];
+ bool repl_repl[Natts_pg_attribute];
+ Acl *newAcl;
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple newtuple;
+
+ /* Ignore dropped columns */
+ if (att->attisdropped)
+ continue;
+
+ aclDatum = heap_getattr(attributeTuple,
+ Anum_pg_attribute_attacl,
+ RelationGetDescr(attRelation),
+ &isNull);
+ /* Null ACLs do not require changes */
+ if (isNull)
+ continue;
+
+ memset(repl_null, false, sizeof(repl_null));
+ memset(repl_repl, false, sizeof(repl_repl));
+
+ newAcl = aclnewowner(DatumGetAclP(aclDatum),
+ oldOwnerId, newOwnerId);
+ repl_repl[Anum_pg_attribute_attacl - 1] = true;
+ repl_val[Anum_pg_attribute_attacl - 1] = PointerGetDatum(newAcl);
+
+ newtuple = heap_modify_tuple(attributeTuple,
+ RelationGetDescr(attRelation),
+ repl_val, repl_null, repl_repl);
+
+ simple_heap_update(attRelation, &newtuple->t_self, newtuple);
+ CatalogUpdateIndexes(attRelation, newtuple);
+
+ heap_freetuple(newtuple);
+ }
+ systable_endscan(scan);
+ heap_close(attRelation, RowExclusiveLock);
+}
+
+/*
* change_owner_recurse_to_sequences
*
* Helper function for ATExecChangeOwner. Examines pg_depend searching