@@ -345,6 +345,8 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
345
345
AlterTableCmd * cmd ,LOCKMODE lockmode );
346
346
static void ATPostAlterTypeCleanup (List * * wqueue ,AlteredTableInfo * tab ,LOCKMODE lockmode );
347
347
static void ATPostAlterTypeParse (char * cmd ,List * * wqueue ,LOCKMODE lockmode );
348
+ static void change_owner_fix_column_acls (Oid relationOid ,
349
+ Oid oldOwnerId ,Oid newOwnerId );
348
350
static void change_owner_recurse_to_sequences (Oid relationOid ,
349
351
Oid newOwnerId ,LOCKMODE lockmode );
350
352
static void ATExecClusterOn (Relation rel ,const char * indexName ,LOCKMODE lockmode );
@@ -7530,6 +7532,14 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
7530
7532
7531
7533
heap_freetuple (newtuple );
7532
7534
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
+
7533
7543
/*
7534
7544
* Update owner dependency reference, if any. A composite type has
7535
7545
* 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
7586
7596
relation_close (target_rel ,NoLock );
7587
7597
}
7588
7598
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
+
7589
7664
/*
7590
7665
* change_owner_recurse_to_sequences
7591
7666
*