@@ -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
*
0 commit comments