@@ -923,13 +923,19 @@ RelationGetPartitionQual(Relation rel, bool recurse)
923
923
return generate_partition_qual (rel , recurse );
924
924
}
925
925
926
- /* Turn an array of OIDs with N elements into a list */
927
- #define OID_ARRAY_TO_LIST (arr , N , list ) \
926
+ /*
927
+ * Append OIDs of rel's partitions to the list 'partoids' and for each OID,
928
+ * append pointer rel to the list 'parents'.
929
+ */
930
+ #define APPEND_REL_PARTITION_OIDS (rel , partoids , parents ) \
928
931
do\
929
932
{\
930
933
int i;\
931
- for (i = 0; i < (N); i++)\
932
- (list) = lappend_oid((list), (arr)[i]);\
934
+ for (i = 0; i < (rel)->rd_partdesc->nparts; i++)\
935
+ {\
936
+ (partoids) = lappend_oid((partoids), (rel)->rd_partdesc->oids[i]);\
937
+ (parents) = lappend((parents), (rel));\
938
+ }\
933
939
} while(0)
934
940
935
941
/*
@@ -944,11 +950,13 @@ PartitionDispatch *
944
950
RelationGetPartitionDispatchInfo (Relation rel , int lockmode ,
945
951
int * num_parted , List * * leaf_part_oids )
946
952
{
947
- PartitionDesc rootpartdesc = RelationGetPartitionDesc (rel );
948
953
PartitionDispatchData * * pd ;
949
954
List * all_parts = NIL ,
950
- * parted_rels ;
951
- ListCell * lc ;
955
+ * all_parents = NIL ,
956
+ * parted_rels ,
957
+ * parted_rel_parents ;
958
+ ListCell * lc1 ,
959
+ * lc2 ;
952
960
int i ,
953
961
k ,
954
962
offset ;
@@ -965,10 +973,13 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
965
973
*/
966
974
* num_parted = 1 ;
967
975
parted_rels = list_make1 (rel );
968
- OID_ARRAY_TO_LIST (rootpartdesc -> oids , rootpartdesc -> nparts , all_parts );
969
- foreach (lc , all_parts )
976
+ /* Root partitioned table has no parent, so NULL for parent */
977
+ parted_rel_parents = list_make1 (NULL );
978
+ APPEND_REL_PARTITION_OIDS (rel , all_parts , all_parents );
979
+ forboth (lc1 , all_parts , lc2 , all_parents )
970
980
{
971
- Relation partrel = heap_open (lfirst_oid (lc ), lockmode );
981
+ Relation partrel = heap_open (lfirst_oid (lc1 ), lockmode );
982
+ Relation parent = lfirst (lc2 );
972
983
PartitionDesc partdesc = RelationGetPartitionDesc (partrel );
973
984
974
985
/*
@@ -979,7 +990,8 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
979
990
{
980
991
(* num_parted )++ ;
981
992
parted_rels = lappend (parted_rels , partrel );
982
- OID_ARRAY_TO_LIST (partdesc -> oids , partdesc -> nparts , all_parts );
993
+ parted_rel_parents = lappend (parted_rel_parents , parent );
994
+ APPEND_REL_PARTITION_OIDS (partrel , all_parts , all_parents );
983
995
}
984
996
else
985
997
heap_close (partrel , NoLock );
@@ -1004,10 +1016,12 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
1004
1016
sizeof (PartitionDispatchData * ));
1005
1017
* leaf_part_oids = NIL ;
1006
1018
i = k = offset = 0 ;
1007
- foreach ( lc , parted_rels )
1019
+ forboth ( lc1 , parted_rels , lc2 , parted_rel_parents )
1008
1020
{
1009
- Relation partrel = lfirst (lc );
1021
+ Relation partrel = lfirst (lc1 );
1022
+ Relation parent = lfirst (lc2 );
1010
1023
PartitionKey partkey = RelationGetPartitionKey (partrel );
1024
+ TupleDesc tupdesc = RelationGetDescr (partrel );
1011
1025
PartitionDesc partdesc = RelationGetPartitionDesc (partrel );
1012
1026
int j ,
1013
1027
m ;
@@ -1017,6 +1031,27 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
1017
1031
pd [i ]-> key = partkey ;
1018
1032
pd [i ]-> keystate = NIL ;
1019
1033
pd [i ]-> partdesc = partdesc ;
1034
+ if (parent != NULL )
1035
+ {
1036
+ /*
1037
+ * For every partitioned table other than root, we must store
1038
+ * a tuple table slot initialized with its tuple descriptor and
1039
+ * a tuple conversion map to convert a tuple from its parent's
1040
+ * rowtype to its own. That is to make sure that we are looking
1041
+ * at the correct row using the correct tuple descriptor when
1042
+ * computing its partition key for tuple routing.
1043
+ */
1044
+ pd [i ]-> tupslot = MakeSingleTupleTableSlot (tupdesc );
1045
+ pd [i ]-> tupmap = convert_tuples_by_name (RelationGetDescr (parent ),
1046
+ tupdesc ,
1047
+ gettext_noop ("could not convert row type" ));
1048
+ }
1049
+ else
1050
+ {
1051
+ /* Not required for the root partitioned table */
1052
+ pd [i ]-> tupslot = NULL ;
1053
+ pd [i ]-> tupmap = NULL ;
1054
+ }
1020
1055
pd [i ]-> indexes = (int * ) palloc (partdesc -> nparts * sizeof (int ));
1021
1056
1022
1057
/*
@@ -1610,6 +1645,8 @@ get_partition_for_tuple(PartitionDispatch *pd,
1610
1645
{
1611
1646
PartitionKey key = parent -> key ;
1612
1647
PartitionDesc partdesc = parent -> partdesc ;
1648
+ TupleTableSlot * myslot = parent -> tupslot ;
1649
+ TupleConversionMap * map = parent -> tupmap ;
1613
1650
1614
1651
/* Quick exit */
1615
1652
if (partdesc -> nparts == 0 )
@@ -1618,6 +1655,17 @@ get_partition_for_tuple(PartitionDispatch *pd,
1618
1655
return -1 ;
1619
1656
}
1620
1657
1658
+ if (myslot != NULL )
1659
+ {
1660
+ HeapTuple tuple = ExecFetchSlotTuple (slot );
1661
+
1662
+ ExecClearTuple (myslot );
1663
+ Assert (map != NULL );
1664
+ tuple = do_convert_tuple (tuple , map );
1665
+ ExecStoreTuple (tuple , myslot , InvalidBuffer , true);
1666
+ slot = myslot ;
1667
+ }
1668
+
1621
1669
/* Extract partition key from tuple */
1622
1670
FormPartitionKeyDatum (parent , slot , estate , values , isnull );
1623
1671
0 commit comments