canonical_partition_indexes.patch
invalid/octet-stream
Filename: canonical_partition_indexes.patch
Type: invalid/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/partition.c | 38 | 35 |
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;