@@ -1000,12 +1000,16 @@ get_partition_qual_relid(Oid relid)
10001000 * RelationGetPartitionDispatchInfo
10011001 *Returns information necessary to route tuples down a partition tree
10021002 *
1003- * All the partitions will be locked with lockmode, unless it is NoLock.
1004- * A list of the OIDs of all the leaf partitions of rel is returned in
1005- * *leaf_part_oids.
1003+ * The number of elements in the returned array (that is, the number of
1004+ * PartitionDispatch objects for the partitioned tables in the partition tree)
1005+ * is returned in *num_parted and a list of the OIDs of all the leaf
1006+ * partitions of rel is returned in *leaf_part_oids.
1007+ *
1008+ * All the relations in the partition tree (including 'rel') must have been
1009+ * locked (using at least the AccessShareLock) by the caller.
10061010 */
10071011PartitionDispatch *
1008- RelationGetPartitionDispatchInfo (Relation rel ,int lockmode ,
1012+ RelationGetPartitionDispatchInfo (Relation rel ,
10091013int * num_parted ,List * * leaf_part_oids )
10101014{
10111015PartitionDispatchData * * pd ;
@@ -1020,14 +1024,18 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
10201024offset ;
10211025
10221026/*
1023- * Lock partitions and make a list of the partitioned ones to prepare
1024- * their PartitionDispatch objects below.
1027+ * We rely on the relcache to traverse the partition tree to build both
1028+ * the leaf partition OIDs list and the array of PartitionDispatch objects
1029+ * for the partitioned tables in the tree. That means every partitioned
1030+ * table in the tree must be locked, which is fine since we require the
1031+ * caller to lock all the partitions anyway.
10251032 *
1026- * Cannot use find_all_inheritors() here, because then the order of OIDs
1027- * in parted_rels list would be unknown, which does not help, because we
1028- * assign indexes within individual PartitionDispatch in an order that is
1029- * predetermined (determined by the order of OIDs in individual partition
1030- * descriptors).
1033+ * For every partitioned table in the tree, starting with the root
1034+ * partitioned table, add its relcache entry to parted_rels, while also
1035+ * queuing its partitions (in the order in which they appear in the
1036+ * partition descriptor) to be looked at later in the same loop. This is
1037+ * a bit tricky but works because the foreach() macro doesn't fetch the
1038+ * next list element until the bottom of the loop.
10311039 */
10321040* num_parted = 1 ;
10331041parted_rels = list_make1 (rel );
@@ -1036,29 +1044,24 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
10361044APPEND_REL_PARTITION_OIDS (rel ,all_parts ,all_parents );
10371045forboth (lc1 ,all_parts ,lc2 ,all_parents )
10381046{
1039- Relation partrel = heap_open ( lfirst_oid (lc1 ), lockmode );
1047+ Oid partrelid = lfirst_oid (lc1 );
10401048Relation parent = lfirst (lc2 );
1041- PartitionDesc partdesc = RelationGetPartitionDesc (partrel );
10421049
1043- /*
1044- * If this partition is a partitioned table, add its children to the
1045- * end of the list, so that they are processed as well.
1046- */
1047- if (partdesc )
1050+ if (get_rel_relkind (partrelid )== RELKIND_PARTITIONED_TABLE )
10481051{
1052+ /*
1053+ * Already locked by the caller. Note that it is the
1054+ * responsibility of the caller to close the below relcache entry,
1055+ * once done using the information being collected here (for
1056+ * example, in ExecEndModifyTable).
1057+ */
1058+ Relation partrel = heap_open (partrelid ,NoLock );
1059+
10491060(* num_parted )++ ;
10501061parted_rels = lappend (parted_rels ,partrel );
10511062parted_rel_parents = lappend (parted_rel_parents ,parent );
10521063APPEND_REL_PARTITION_OIDS (partrel ,all_parts ,all_parents );
10531064}
1054- else
1055- heap_close (partrel ,NoLock );
1056-
1057- /*
1058- * We keep the partitioned ones open until we're done using the
1059- * information being collected here (for example, see
1060- * ExecEndModifyTable).
1061- */
10621065}
10631066
10641067/*