@@ -923,13 +923,19 @@ RelationGetPartitionQual(Relation rel, bool recurse)
923923 return generate_partition_qual (rel , recurse );
924924}
925925
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 ) \
928931 do\
929932 {\
930933 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+ }\
933939 } while(0)
934940
935941/*
@@ -944,11 +950,13 @@ PartitionDispatch *
944950RelationGetPartitionDispatchInfo (Relation rel , int lockmode ,
945951 int * num_parted , List * * leaf_part_oids )
946952{
947- PartitionDesc rootpartdesc = RelationGetPartitionDesc (rel );
948953 PartitionDispatchData * * pd ;
949954 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 ;
952960 int i ,
953961 k ,
954962 offset ;
@@ -965,10 +973,13 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
965973 */
966974 * num_parted = 1 ;
967975 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 )
970980 {
971- Relation partrel = heap_open (lfirst_oid (lc ), lockmode );
981+ Relation partrel = heap_open (lfirst_oid (lc1 ), lockmode );
982+ Relation parent = lfirst (lc2 );
972983 PartitionDesc partdesc = RelationGetPartitionDesc (partrel );
973984
974985 /*
@@ -979,7 +990,8 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
979990 {
980991 (* num_parted )++ ;
981992 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 );
983995 }
984996 else
985997 heap_close (partrel , NoLock );
@@ -1004,10 +1016,12 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
10041016 sizeof (PartitionDispatchData * ));
10051017 * leaf_part_oids = NIL ;
10061018 i = k = offset = 0 ;
1007- foreach ( lc , parted_rels )
1019+ forboth ( lc1 , parted_rels , lc2 , parted_rel_parents )
10081020 {
1009- Relation partrel = lfirst (lc );
1021+ Relation partrel = lfirst (lc1 );
1022+ Relation parent = lfirst (lc2 );
10101023 PartitionKey partkey = RelationGetPartitionKey (partrel );
1024+ TupleDesc tupdesc = RelationGetDescr (partrel );
10111025 PartitionDesc partdesc = RelationGetPartitionDesc (partrel );
10121026 int j ,
10131027 m ;
@@ -1017,6 +1031,27 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
10171031 pd [i ]-> key = partkey ;
10181032 pd [i ]-> keystate = NIL ;
10191033 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+ }
10201055 pd [i ]-> indexes = (int * ) palloc (partdesc -> nparts * sizeof (int ));
10211056
10221057 /*
@@ -1610,6 +1645,8 @@ get_partition_for_tuple(PartitionDispatch *pd,
16101645 {
16111646 PartitionKey key = parent -> key ;
16121647 PartitionDesc partdesc = parent -> partdesc ;
1648+ TupleTableSlot * myslot = parent -> tupslot ;
1649+ TupleConversionMap * map = parent -> tupmap ;
16131650
16141651 /* Quick exit */
16151652 if (partdesc -> nparts == 0 )
@@ -1618,6 +1655,17 @@ get_partition_for_tuple(PartitionDispatch *pd,
16181655 return -1 ;
16191656 }
16201657
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+
16211669 /* Extract partition key from tuple */
16221670 FormPartitionKeyDatum (parent , slot , estate , values , isnull );
16231671
0 commit comments