static void ATPostAlterTypeParse(Oid oldId, char *cmd,
List **wqueue, LOCKMODE lockmode, bool rewrite);
static void TryReuseIndex(Oid oldId, IndexStmt *stmt);
+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);
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;
relation_close(target_rel, NoLock);
}
+/*
+ * 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
*