@@ -316,6 +316,8 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
316
316
const char * colName , TypeName * typeName );
317
317
static void ATPostAlterTypeCleanup (List * * wqueue , AlteredTableInfo * tab );
318
318
static void ATPostAlterTypeParse (char * cmd , List * * wqueue );
319
+ static void change_owner_fix_column_acls (Oid relationOid ,
320
+ Oid oldOwnerId , Oid newOwnerId );
319
321
static void change_owner_recurse_to_sequences (Oid relationOid ,
320
322
Oid newOwnerId );
321
323
static void ATExecClusterOn (Relation rel , const char * indexName );
@@ -6644,6 +6646,14 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing)
6644
6646
6645
6647
heap_freetuple (newtuple );
6646
6648
6649
+ /*
6650
+ * We must similarly update any per-column ACLs to reflect the new
6651
+ * owner; for neatness reasons that's split out as a subroutine.
6652
+ */
6653
+ change_owner_fix_column_acls (relationOid ,
6654
+ tuple_class -> relowner ,
6655
+ newOwnerId );
6656
+
6647
6657
/*
6648
6658
* Update owner dependency reference, if any. A composite type has
6649
6659
* none, because it's tracked for the pg_type entry instead of here;
@@ -6700,6 +6710,71 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing)
6700
6710
relation_close (target_rel , NoLock );
6701
6711
}
6702
6712
6713
+ /*
6714
+ * change_owner_fix_column_acls
6715
+ *
6716
+ * Helper function for ATExecChangeOwner. Scan the columns of the table
6717
+ * and fix any non-null column ACLs to reflect the new owner.
6718
+ */
6719
+ static void
6720
+ change_owner_fix_column_acls (Oid relationOid , Oid oldOwnerId , Oid newOwnerId )
6721
+ {
6722
+ Relation attRelation ;
6723
+ SysScanDesc scan ;
6724
+ ScanKeyData key [1 ];
6725
+ HeapTuple attributeTuple ;
6726
+
6727
+ attRelation = heap_open (AttributeRelationId , RowExclusiveLock );
6728
+ ScanKeyInit (& key [0 ],
6729
+ Anum_pg_attribute_attrelid ,
6730
+ BTEqualStrategyNumber , F_OIDEQ ,
6731
+ ObjectIdGetDatum (relationOid ));
6732
+ scan = systable_beginscan (attRelation , AttributeRelidNumIndexId ,
6733
+ true, SnapshotNow , 1 , key );
6734
+ while (HeapTupleIsValid (attributeTuple = systable_getnext (scan )))
6735
+ {
6736
+ Form_pg_attribute att = (Form_pg_attribute ) GETSTRUCT (attributeTuple );
6737
+ Datum repl_val [Natts_pg_attribute ];
6738
+ bool repl_null [Natts_pg_attribute ];
6739
+ bool repl_repl [Natts_pg_attribute ];
6740
+ Acl * newAcl ;
6741
+ Datum aclDatum ;
6742
+ bool isNull ;
6743
+ HeapTuple newtuple ;
6744
+
6745
+ /* Ignore dropped columns */
6746
+ if (att -> attisdropped )
6747
+ continue ;
6748
+
6749
+ aclDatum = heap_getattr (attributeTuple ,
6750
+ Anum_pg_attribute_attacl ,
6751
+ RelationGetDescr (attRelation ),
6752
+ & isNull );
6753
+ /* Null ACLs do not require changes */
6754
+ if (isNull )
6755
+ continue ;
6756
+
6757
+ memset (repl_null , false, sizeof (repl_null ));
6758
+ memset (repl_repl , false, sizeof (repl_repl ));
6759
+
6760
+ newAcl = aclnewowner (DatumGetAclP (aclDatum ),
6761
+ oldOwnerId , newOwnerId );
6762
+ repl_repl [Anum_pg_attribute_attacl - 1 ] = true;
6763
+ repl_val [Anum_pg_attribute_attacl - 1 ] = PointerGetDatum (newAcl );
6764
+
6765
+ newtuple = heap_modify_tuple (attributeTuple ,
6766
+ RelationGetDescr (attRelation ),
6767
+ repl_val , repl_null , repl_repl );
6768
+
6769
+ simple_heap_update (attRelation , & newtuple -> t_self , newtuple );
6770
+ CatalogUpdateIndexes (attRelation , newtuple );
6771
+
6772
+ heap_freetuple (newtuple );
6773
+ }
6774
+ systable_endscan (scan );
6775
+ heap_close (attRelation , RowExclusiveLock );
6776
+ }
6777
+
6703
6778
/*
6704
6779
* change_owner_recurse_to_sequences
6705
6780
*
0 commit comments