@@ -345,6 +345,8 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
345345AlterTableCmd * cmd ,LOCKMODE lockmode );
346346static void ATPostAlterTypeCleanup (List * * wqueue ,AlteredTableInfo * tab ,LOCKMODE lockmode );
347347static void ATPostAlterTypeParse (char * cmd ,List * * wqueue ,LOCKMODE lockmode );
348+ static void change_owner_fix_column_acls (Oid relationOid ,
349+ Oid oldOwnerId ,Oid newOwnerId );
348350static void change_owner_recurse_to_sequences (Oid relationOid ,
349351Oid newOwnerId ,LOCKMODE lockmode );
350352static void ATExecClusterOn (Relation rel ,const char * indexName ,LOCKMODE lockmode );
@@ -7530,6 +7532,14 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
75307532
75317533heap_freetuple (newtuple );
75327534
7535+ /*
7536+ * We must similarly update any per-column ACLs to reflect the new
7537+ * owner; for neatness reasons that's split out as a subroutine.
7538+ */
7539+ change_owner_fix_column_acls (relationOid ,
7540+ tuple_class -> relowner ,
7541+ newOwnerId );
7542+
75337543/*
75347544 * Update owner dependency reference, if any. A composite type has
75357545 * none, because it's tracked for the pg_type entry instead of here;
@@ -7586,6 +7596,71 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
75867596relation_close (target_rel ,NoLock );
75877597}
75887598
7599+ /*
7600+ * change_owner_fix_column_acls
7601+ *
7602+ * Helper function for ATExecChangeOwner. Scan the columns of the table
7603+ * and fix any non-null column ACLs to reflect the new owner.
7604+ */
7605+ static void
7606+ change_owner_fix_column_acls (Oid relationOid ,Oid oldOwnerId ,Oid newOwnerId )
7607+ {
7608+ Relation attRelation ;
7609+ SysScanDesc scan ;
7610+ ScanKeyData key [1 ];
7611+ HeapTuple attributeTuple ;
7612+
7613+ attRelation = heap_open (AttributeRelationId ,RowExclusiveLock );
7614+ ScanKeyInit (& key [0 ],
7615+ Anum_pg_attribute_attrelid ,
7616+ BTEqualStrategyNumber ,F_OIDEQ ,
7617+ ObjectIdGetDatum (relationOid ));
7618+ scan = systable_beginscan (attRelation ,AttributeRelidNumIndexId ,
7619+ true,SnapshotNow ,1 ,key );
7620+ while (HeapTupleIsValid (attributeTuple = systable_getnext (scan )))
7621+ {
7622+ Form_pg_attribute att = (Form_pg_attribute )GETSTRUCT (attributeTuple );
7623+ Datum repl_val [Natts_pg_attribute ];
7624+ bool repl_null [Natts_pg_attribute ];
7625+ bool repl_repl [Natts_pg_attribute ];
7626+ Acl * newAcl ;
7627+ Datum aclDatum ;
7628+ bool isNull ;
7629+ HeapTuple newtuple ;
7630+
7631+ /* Ignore dropped columns */
7632+ if (att -> attisdropped )
7633+ continue ;
7634+
7635+ aclDatum = heap_getattr (attributeTuple ,
7636+ Anum_pg_attribute_attacl ,
7637+ RelationGetDescr (attRelation ),
7638+ & isNull );
7639+ /* Null ACLs do not require changes */
7640+ if (isNull )
7641+ continue ;
7642+
7643+ memset (repl_null , false,sizeof (repl_null ));
7644+ memset (repl_repl , false,sizeof (repl_repl ));
7645+
7646+ newAcl = aclnewowner (DatumGetAclP (aclDatum ),
7647+ oldOwnerId ,newOwnerId );
7648+ repl_repl [Anum_pg_attribute_attacl - 1 ]= true;
7649+ repl_val [Anum_pg_attribute_attacl - 1 ]= PointerGetDatum (newAcl );
7650+
7651+ newtuple = heap_modify_tuple (attributeTuple ,
7652+ RelationGetDescr (attRelation ),
7653+ repl_val ,repl_null ,repl_repl );
7654+
7655+ simple_heap_update (attRelation ,& newtuple -> t_self ,newtuple );
7656+ CatalogUpdateIndexes (attRelation ,newtuple );
7657+
7658+ heap_freetuple (newtuple );
7659+ }
7660+ systable_endscan (scan );
7661+ heap_close (attRelation ,RowExclusiveLock );
7662+ }
7663+
75897664/*
75907665 * change_owner_recurse_to_sequences
75917666 *