@@ -669,6 +669,7 @@ create_single_partition_internal(Oid parent_relid,
669669 List * create_stmts ;
670670 ListCell * lc ;
671671
672+ /* Current user and security context */
672673 Oid save_userid ;
673674 int save_sec_context ;
674675 bool need_priv_escalation = !superuser (); /* we might be a SU */
@@ -861,21 +862,29 @@ create_table_using_stmt(CreateStmt *create_stmt, Oid relowner)
861862static void
862863copy_acl_privileges (Oid parent_relid , Oid partition_relid )
863864{
864- Relation pg_class_rel ;
865+ Relation pg_class_rel ,
866+ pg_attribute_rel ;
865867
866- TupleDesc pg_class_desc ;
868+ TupleDesc pg_class_desc ,
869+ pg_attribute_desc ;
867870
868871 HeapTuple htup ;
869-
870- ScanKeyData skey ;
872+ ScanKeyData skey [2 ];
871873 SysScanDesc scan ;
872874
873875 Datum acl_datum ;
874876 bool acl_null ;
875877
878+ Snapshot snapshot ;
879+
876880 pg_class_rel = heap_open (RelationRelationId , RowExclusiveLock );
881+ pg_attribute_rel = heap_open (AttributeRelationId , RowExclusiveLock );
882+
883+ /* Get most recent snapshot */
884+ snapshot = RegisterSnapshot (GetLatestSnapshot ());
877885
878886 pg_class_desc = RelationGetDescr (pg_class_rel );
887+ pg_attribute_desc = RelationGetDescr (pg_attribute_rel );
879888
880889 htup = SearchSysCache1 (RELOID , ObjectIdGetDatum (parent_relid ));
881890 if (!HeapTupleIsValid (htup ))
@@ -886,21 +895,25 @@ copy_acl_privileges(Oid parent_relid, Oid partition_relid)
886895
887896 /* Copy datum if it's not NULL */
888897 if (!acl_null )
889- acl_datum = datumCopy (acl_datum ,
890- pg_class_desc -> attrs [Anum_pg_class_relacl - 1 ]-> attbyval ,
891- pg_class_desc -> attrs [Anum_pg_class_relacl - 1 ]-> attlen );
898+ {
899+ Form_pg_attribute acl_column ;
900+
901+ acl_column = pg_class_desc -> attrs [Anum_pg_class_relacl - 1 ];
902+
903+ acl_datum = datumCopy (acl_datum , acl_column -> attbyval , acl_column -> attlen );
904+ }
892905
893906 /* Release 'htup' */
894907 ReleaseSysCache (htup );
895908
896909 /* Search for 'partition_relid' */
897- ScanKeyInit (& skey ,
910+ ScanKeyInit (& skey [ 0 ] ,
898911 ObjectIdAttributeNumber ,
899912 BTEqualStrategyNumber , F_OIDEQ ,
900913 ObjectIdGetDatum (partition_relid ));
901914
902- scan = systable_beginscan (pg_class_rel , ClassOidIndexId , true,
903- GetLatestSnapshot (), 1 , & skey );
915+ scan = systable_beginscan (pg_class_rel , ClassOidIndexId ,
916+ true, snapshot , 1 , skey );
904917
905918 /* There should be exactly one tuple (our child) */
906919 if (HeapTupleIsValid (htup = systable_getnext (scan )))
@@ -918,8 +931,7 @@ copy_acl_privileges(Oid parent_relid, Oid partition_relid)
918931 replaces [Anum_pg_class_relacl - 1 ] = true;
919932
920933 /* Build new tuple with parent's ACL */
921- htup = heap_modify_tuple (htup , RelationGetDescr (pg_class_rel ),
922- values , nulls , replaces );
934+ htup = heap_modify_tuple (htup , pg_class_desc , values , nulls , replaces );
923935
924936 /* Update child's tuple */
925937 simple_heap_update (pg_class_rel , & iptr , htup );
@@ -930,7 +942,106 @@ copy_acl_privileges(Oid parent_relid, Oid partition_relid)
930942
931943 systable_endscan (scan );
932944
945+
946+ /* Search for 'parent_relid's columns */
947+ ScanKeyInit (& skey [0 ],
948+ Anum_pg_attribute_attrelid ,
949+ BTEqualStrategyNumber , F_OIDEQ ,
950+ ObjectIdGetDatum (parent_relid ));
951+
952+ /* Consider only user-defined columns (>0) */
953+ ScanKeyInit (& skey [1 ],
954+ Anum_pg_attribute_attnum ,
955+ BTEqualStrategyNumber , F_INT2GT ,
956+ Int16GetDatum (InvalidAttrNumber ));
957+
958+ scan = systable_beginscan (pg_attribute_rel ,
959+ AttributeRelidNumIndexId ,
960+ true, snapshot , 2 , skey );
961+
962+ /* Go through the list of parent's columns */
963+ while (HeapTupleIsValid (htup = systable_getnext (scan )))
964+ {
965+ ScanKeyData subskey [2 ];
966+ SysScanDesc subscan ;
967+ HeapTuple subhtup ;
968+
969+ AttrNumber cur_attnum ;
970+ bool cur_attnum_null ;
971+
972+ /* Get parent column's ACL */
973+ acl_datum = heap_getattr (htup , Anum_pg_attribute_attacl ,
974+ pg_attribute_desc , & acl_null );
975+
976+ /* Copy datum if it's not NULL */
977+ if (!acl_null )
978+ {
979+ Form_pg_attribute acl_column ;
980+
981+ acl_column = pg_attribute_desc -> attrs [Anum_pg_attribute_attacl - 1 ];
982+
983+ acl_datum = datumCopy (acl_datum ,
984+ acl_column -> attbyval ,
985+ acl_column -> attlen );
986+ }
987+
988+ /* Fetch number of current column */
989+ cur_attnum = DatumGetInt16 (heap_getattr (htup , Anum_pg_attribute_attnum ,
990+ pg_attribute_desc , & cur_attnum_null ));
991+ Assert (cur_attnum_null == false); /* must not be NULL! */
992+
993+ /* Search for 'partition_relid' */
994+ ScanKeyInit (& subskey [0 ],
995+ Anum_pg_attribute_attrelid ,
996+ BTEqualStrategyNumber , F_OIDEQ ,
997+ ObjectIdGetDatum (partition_relid ));
998+
999+ /* Search for 'partition_relid's columns */
1000+ ScanKeyInit (& subskey [1 ],
1001+ Anum_pg_attribute_attnum ,
1002+ BTEqualStrategyNumber , F_INT2EQ ,
1003+ Int16GetDatum (cur_attnum ));
1004+
1005+ subscan = systable_beginscan (pg_attribute_rel ,
1006+ AttributeRelidNumIndexId ,
1007+ true, snapshot , 2 , subskey );
1008+
1009+ /* There should be exactly one tuple (our child's column) */
1010+ if (HeapTupleIsValid (subhtup = systable_getnext (subscan )))
1011+ {
1012+ ItemPointerData iptr ;
1013+ Datum values [Natts_pg_attribute ] = { (Datum ) 0 };
1014+ bool nulls [Natts_pg_attribute ] = { false };
1015+ bool replaces [Natts_pg_attribute ] = { false };
1016+
1017+ /* Copy ItemPointer of this tuple */
1018+ iptr = subhtup -> t_self ;
1019+
1020+ values [Anum_pg_attribute_attacl - 1 ] = acl_datum ; /* ACL array */
1021+ nulls [Anum_pg_attribute_attacl - 1 ] = acl_null ; /* do we have ACL? */
1022+ replaces [Anum_pg_attribute_attacl - 1 ] = true;
1023+
1024+ /* Build new tuple with parent's ACL */
1025+ subhtup = heap_modify_tuple (subhtup , pg_attribute_desc ,
1026+ values , nulls , replaces );
1027+
1028+ /* Update child's tuple */
1029+ simple_heap_update (pg_attribute_rel , & iptr , subhtup );
1030+
1031+ /* Don't forget to update indexes */
1032+ CatalogUpdateIndexes (pg_attribute_rel , subhtup );
1033+ }
1034+
1035+ systable_endscan (subscan );
1036+ }
1037+
1038+ systable_endscan (scan );
1039+
1040+ /* Don't forget to free snapshot */
1041+ UnregisterSnapshot (snapshot );
1042+
9331043 heap_close (pg_class_rel , RowExclusiveLock );
1044+ heap_close (pg_attribute_rel , RowExclusiveLock );
9341045}
9351046
9361047/* Copy foreign keys of parent table */
0 commit comments