Fix bugs in RelationGetPartitionDispatchInfo.

The previous coding was not quite right for cases involving multiple
levels of partitioning.

Amit Langote
This commit is contained in:
Robert Haas 2016-12-13 11:29:08 -05:00
parent 4b9a98e154
commit a25665088d
1 changed files with 33 additions and 6 deletions

View File

@ -950,7 +950,8 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
*parted_rels; *parted_rels;
ListCell *lc; ListCell *lc;
int i, int i,
k; k,
offset;
/* /*
* Lock partitions and make a list of the partitioned ones to prepare * Lock partitions and make a list of the partitioned ones to prepare
@ -990,11 +991,19 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
*/ */
} }
/* Generate PartitionDispatch objects for all partitioned tables */ /*
* We want to create two arrays - one for leaf partitions and another for
* partitioned tables (including the root table and internal partitions).
* While we only create the latter here, leaf partition array of suitable
* objects (such as, ResultRelInfo) is created by the caller using the
* list of OIDs we return. Indexes into these arrays get assigned in a
* breadth-first manner, whereby partitions of any given level are placed
* consecutively in the respective arrays.
*/
pd = (PartitionDispatchData **) palloc(*num_parted * pd = (PartitionDispatchData **) palloc(*num_parted *
sizeof(PartitionDispatchData *)); sizeof(PartitionDispatchData *));
*leaf_part_oids = NIL; *leaf_part_oids = NIL;
i = k = 0; i = k = offset = 0;
foreach(lc, parted_rels) foreach(lc, parted_rels)
{ {
Relation partrel = lfirst(lc); Relation partrel = lfirst(lc);
@ -1010,6 +1019,16 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
pd[i]->partdesc = partdesc; pd[i]->partdesc = partdesc;
pd[i]->indexes = (int *) palloc(partdesc->nparts * sizeof(int)); pd[i]->indexes = (int *) palloc(partdesc->nparts * sizeof(int));
/*
* Indexes corresponding to the internal partitions are multiplied by
* -1 to distinguish them from those of leaf partitions. Encountering
* an index >= 0 means we found a leaf partition, which is immediately
* returned as the partition we are looking for. A negative index
* means we found a partitioned table, whose PartitionDispatch object
* is located at the above index multiplied back by -1. Using the
* PartitionDispatch object, search is continued further down the
* partition tree.
*/
m = 0; m = 0;
for (j = 0; j < partdesc->nparts; j++) for (j = 0; j < partdesc->nparts; j++)
{ {
@ -1023,14 +1042,22 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
else else
{ {
/* /*
* We can assign indexes this way because of the way * offset denotes the number of partitioned tables of upper
* parted_rels has been generated. * levels including those of the current level. Any partition
* of this table must belong to the next level and hence will
* be placed after the last partitioned table of this level.
*/ */
pd[i]->indexes[j] = -(i + 1 + m); pd[i]->indexes[j] = -(1 + offset + m);
m++; m++;
} }
} }
i++; i++;
/*
* This counts the number of partitioned tables at upper levels
* including those of the current level.
*/
offset += m;
} }
return pd; return pd;