@@ -357,6 +357,8 @@ static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMOD
357357static void ATPostAlterTypeParse (Oid oldId ,char * cmd ,
358358List * * wqueue ,LOCKMODE lockmode ,bool rewrite );
359359static void TryReuseIndex (Oid oldId ,IndexStmt * stmt );
360+ static void change_owner_fix_column_acls (Oid relationOid ,
361+ Oid oldOwnerId ,Oid newOwnerId );
360362static void change_owner_recurse_to_sequences (Oid relationOid ,
361363Oid newOwnerId ,LOCKMODE lockmode );
362364static void ATExecClusterOn (Relation rel ,const char * indexName ,LOCKMODE lockmode );
@@ -8008,6 +8010,14 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
80088010
80098011heap_freetuple (newtuple );
80108012
8013+ /*
8014+ * We must similarly update any per-column ACLs to reflect the new
8015+ * owner; for neatness reasons that's split out as a subroutine.
8016+ */
8017+ change_owner_fix_column_acls (relationOid ,
8018+ tuple_class -> relowner ,
8019+ newOwnerId );
8020+
80118021/*
80128022 * Update owner dependency reference, if any. A composite type has
80138023 * none, because it's tracked for the pg_type entry instead of here;
@@ -8064,6 +8074,71 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
80648074relation_close (target_rel ,NoLock );
80658075}
80668076
8077+ /*
8078+ * change_owner_fix_column_acls
8079+ *
8080+ * Helper function for ATExecChangeOwner. Scan the columns of the table
8081+ * and fix any non-null column ACLs to reflect the new owner.
8082+ */
8083+ static void
8084+ change_owner_fix_column_acls (Oid relationOid ,Oid oldOwnerId ,Oid newOwnerId )
8085+ {
8086+ Relation attRelation ;
8087+ SysScanDesc scan ;
8088+ ScanKeyData key [1 ];
8089+ HeapTuple attributeTuple ;
8090+
8091+ attRelation = heap_open (AttributeRelationId ,RowExclusiveLock );
8092+ ScanKeyInit (& key [0 ],
8093+ Anum_pg_attribute_attrelid ,
8094+ BTEqualStrategyNumber ,F_OIDEQ ,
8095+ ObjectIdGetDatum (relationOid ));
8096+ scan = systable_beginscan (attRelation ,AttributeRelidNumIndexId ,
8097+ true,SnapshotNow ,1 ,key );
8098+ while (HeapTupleIsValid (attributeTuple = systable_getnext (scan )))
8099+ {
8100+ Form_pg_attribute att = (Form_pg_attribute )GETSTRUCT (attributeTuple );
8101+ Datum repl_val [Natts_pg_attribute ];
8102+ bool repl_null [Natts_pg_attribute ];
8103+ bool repl_repl [Natts_pg_attribute ];
8104+ Acl * newAcl ;
8105+ Datum aclDatum ;
8106+ bool isNull ;
8107+ HeapTuple newtuple ;
8108+
8109+ /* Ignore dropped columns */
8110+ if (att -> attisdropped )
8111+ continue ;
8112+
8113+ aclDatum = heap_getattr (attributeTuple ,
8114+ Anum_pg_attribute_attacl ,
8115+ RelationGetDescr (attRelation ),
8116+ & isNull );
8117+ /* Null ACLs do not require changes */
8118+ if (isNull )
8119+ continue ;
8120+
8121+ memset (repl_null , false,sizeof (repl_null ));
8122+ memset (repl_repl , false,sizeof (repl_repl ));
8123+
8124+ newAcl = aclnewowner (DatumGetAclP (aclDatum ),
8125+ oldOwnerId ,newOwnerId );
8126+ repl_repl [Anum_pg_attribute_attacl - 1 ]= true;
8127+ repl_val [Anum_pg_attribute_attacl - 1 ]= PointerGetDatum (newAcl );
8128+
8129+ newtuple = heap_modify_tuple (attributeTuple ,
8130+ RelationGetDescr (attRelation ),
8131+ repl_val ,repl_null ,repl_repl );
8132+
8133+ simple_heap_update (attRelation ,& newtuple -> t_self ,newtuple );
8134+ CatalogUpdateIndexes (attRelation ,newtuple );
8135+
8136+ heap_freetuple (newtuple );
8137+ }
8138+ systable_endscan (scan );
8139+ heap_close (attRelation ,RowExclusiveLock );
8140+ }
8141+
80678142/*
80688143 * change_owner_recurse_to_sequences
80698144 *