diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index afc7d18..ccb8fde 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -785,15 +785,14 @@ RelationBuildPartitionDesc(Relation rel) case PARTITION_STRAT_LIST: { ListInfo *listinfo; + int *mappings = (int *)palloc(sizeof(int) * nparts); + int next_index = 0; listinfo = (ListInfo *) palloc0(sizeof(ListInfo)); - /* - * Copy oids in the same order as they were found in the - * pg_inherits catalog - */ + /* Invalid mapping. */ for (i = 0; i < nparts; i++) - result->oids[i] = oids[i]; + mappings[i] = -1; /* Sort so that we can perform binary search over values */ qsort_arg(all_values, all_values_count, sizeof(ListValue *), @@ -801,23 +800,48 @@ RelationBuildPartitionDesc(Relation rel) listinfo->nvalues = all_values_count; listinfo->has_null = found_null_partition; - if (found_null_partition) - listinfo->null_index = null_partition_index; - else - listinfo->null_index = -1; listinfo->values = (Datum *) palloc0(all_values_count * sizeof(Datum)); listinfo->indexes = (int *) palloc0(all_values_count * sizeof(int)); + + /* + * While copying the indexes, adjust them so that they are same + * for any two partitioning schemes with the same lists. One + * way to achieve this is to assign indexes in the same order + * as the least values in the lists. + */ for (i = 0; i < all_values_count; i++) { listinfo->values[i] = datumCopy(all_values[i]->value, key->tcinfo->typbyval[0], key->tcinfo->typlen[0]); - listinfo->indexes[i] = all_values[i]->index; + + /* If this index has no mapping assign one. */ + if (mappings[all_values[i]->index] == -1) + mappings[all_values[i]->index] = next_index++; + + listinfo->indexes[i] = mappings[all_values[i]->index]; } + /* Assign a valid mapping to partition with NULLL values. */ + if (mappings[null_partition_index] == -1) + mappings[null_partition_index] = next_index++; + + /* All partitions get a valid mapping. */ + Assert(next_index == nparts); + + if (found_null_partition) + listinfo->null_index = mappings[null_partition_index]; + else + listinfo->null_index = -1; + + /* Re-arrange partition OIDs as per mappings. */ + for (i = 0; i < nparts; i++) + result->oids[i] = oids[mappings[i]]; + result->bounds->listinfo = listinfo; + pfree(mappings); break; } @@ -2273,7 +2297,6 @@ static bool equal_list_info(PartitionKey key, ListInfo *l1, ListInfo *l2, int n) { int i; - int *mapping; if (l1->nvalues != l2->nvalues) return false; @@ -2282,35 +2305,15 @@ equal_list_info(PartitionKey key, ListInfo *l1, ListInfo *l2, int n) return false; for (i = 0; i < l1->nvalues; i++) + { if (list_values_cmp(key, l1->values[i], l2->values[i])) return false; - /* - * Index start from one. A zero in nth slot means that partition n of - * the first collection has not yet been mapped with a partition from - * the second collection. - */ - mapping = (int *) palloc0((n + 1) * sizeof(int)); - for (i = 0; i < l1->nvalues; i++) - { - int l1_partno = l1->indexes[i] + 1, - l2_partno = l2->indexes[i] + 1; - - /* Encountered l1_partno for the first time, map to l2_partno */ - if (mapping[l1_partno] == 0) - mapping[l1_partno] = l2_partno; - /* - * Maintain that the mapping does not change, otherwise report - * inequality - */ - else if (mapping[l1_partno] != l2_partno) - return false; + /* Make sure that the indexes are "canonicalised. */ + Assert(l1->indexes[i] == l2->indexes[i]); } - /* Check that nulls are accepted in mapped partitions */ - Assert(l1->has_null || l1->null_index == -1); - Assert(l2->has_null || l2->null_index == -1); - if (l1->has_null && mapping[l1->null_index + 1] != l2->null_index + 1) + if (l1->null_index != l2->null_index); return false; return true;