PartitionKey key, int **mapping)
{
PartitionBoundInfo boundinfo;
- PartitionHashBound **hbounds = NULL;
+ PartitionHashBound *hbounds;
int i;
- int ndatums = 0;
int greatest_modulus;
+ Datum *boundDatums;
boundinfo = (PartitionBoundInfoData *)
palloc0(sizeof(PartitionBoundInfoData));
boundinfo->null_index = -1;
boundinfo->default_index = -1;
- ndatums = nparts;
- hbounds = (PartitionHashBound **)
- palloc(nparts * sizeof(PartitionHashBound *));
+ hbounds = (PartitionHashBound *)
+ palloc(nparts * sizeof(PartitionHashBound));
/* Convert from node to the internal representation */
for (i = 0; i < nparts; i++)
if (spec->strategy != PARTITION_STRATEGY_HASH)
elog(ERROR, "invalid strategy in partition bound spec");
- hbounds[i] = (PartitionHashBound *) palloc(sizeof(PartitionHashBound));
- hbounds[i]->modulus = spec->modulus;
- hbounds[i]->remainder = spec->remainder;
- hbounds[i]->index = i;
+ hbounds[i].modulus = spec->modulus;
+ hbounds[i].remainder = spec->remainder;
+ hbounds[i].index = i;
}
/* Sort all the bounds in ascending order */
- qsort(hbounds, nparts, sizeof(PartitionHashBound *),
+ qsort(hbounds, nparts, sizeof(PartitionHashBound),
qsort_partition_hbound_cmp);
/* After sorting, moduli are now stored in ascending order. */
- greatest_modulus = hbounds[ndatums - 1]->modulus;
+ greatest_modulus = hbounds[nparts - 1].modulus;
- boundinfo->ndatums = ndatums;
- boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
+ boundinfo->ndatums = nparts;
+ boundinfo->datums = (Datum **) palloc0(nparts * sizeof(Datum *));
+ boundinfo->kind = NULL;
boundinfo->nindexes = greatest_modulus;
boundinfo->indexes = (int *) palloc(greatest_modulus * sizeof(int));
for (i = 0; i < greatest_modulus; i++)
boundinfo->indexes[i] = -1;
+ /*
+ * In the loop below, to save from allocating a series of small datum
+ * arrays, here we just allocate a single array and below we'll just
+ * assign a portion of this array per partition.
+ */
+ boundDatums = (Datum *) palloc(nparts * 2 * sizeof(Datum));
+
/*
* For hash partitioning, there are as many datums (modulus and remainder
* pairs) as there are partitions. Indexes are simply values ranging from
*/
for (i = 0; i < nparts; i++)
{
- int modulus = hbounds[i]->modulus;
- int remainder = hbounds[i]->remainder;
+ int modulus = hbounds[i].modulus;
+ int remainder = hbounds[i].remainder;
- boundinfo->datums[i] = (Datum *) palloc(2 * sizeof(Datum));
+ boundinfo->datums[i] = &boundDatums[i * 2];
boundinfo->datums[i][0] = Int32GetDatum(modulus);
boundinfo->datums[i][1] = Int32GetDatum(remainder);
remainder += modulus;
}
- (*mapping)[hbounds[i]->index] = i;
- pfree(hbounds[i]);
+ (*mapping)[hbounds[i].index] = i;
}
pfree(hbounds);
return boundinfo;
}
+/*
+ * get_non_null_list_datum_count
+ * Counts the number of non-null Datums in each partition.
+ */
+static int
+get_non_null_list_datum_count(PartitionBoundSpec **boundspecs, int nparts)
+{
+ int i;
+ int count = 0;
+
+ for (i = 0; i < nparts; i++)
+ {
+ ListCell *lc;
+
+ foreach(lc, boundspecs[i]->listdatums)
+ {
+ Const *val = castNode(Const, lfirst(lc));
+
+ if (!val->constisnull)
+ count++;
+ }
+ }
+
+ return count;
+}
+
/*
* create_list_bounds
* Create a PartitionBoundInfo for a list partitioned table
PartitionKey key, int **mapping)
{
PartitionBoundInfo boundinfo;
- PartitionListValue **all_values = NULL;
- ListCell *cell;
- int i = 0;
- int ndatums = 0;
+ PartitionListValue *all_values;
+ int i;
+ int j;
+ int ndatums;
int next_index = 0;
int default_index = -1;
int null_index = -1;
- List *non_null_values = NIL;
+ Datum *boundDatums;
boundinfo = (PartitionBoundInfoData *)
palloc0(sizeof(PartitionBoundInfoData));
boundinfo->null_index = -1;
boundinfo->default_index = -1;
+ ndatums = get_non_null_list_datum_count(boundspecs, nparts);
+ all_values = (PartitionListValue *)
+ palloc(ndatums * sizeof(PartitionListValue));
+
/* Create a unified list of non-null values across all partitions. */
- for (i = 0; i < nparts; i++)
+ for (j = 0, i = 0; i < nparts; i++)
{
PartitionBoundSpec *spec = boundspecs[i];
ListCell *c;
foreach(c, spec->listdatums)
{
Const *val = castNode(Const, lfirst(c));
- PartitionListValue *list_value = NULL;
if (!val->constisnull)
{
- list_value = (PartitionListValue *)
- palloc0(sizeof(PartitionListValue));
- list_value->index = i;
- list_value->value = val->constvalue;
+ all_values[j].index = i;
+ all_values[j].value = val->constvalue;
+ j++;
}
else
{
elog(ERROR, "found null more than once");
null_index = i;
}
-
- if (list_value)
- non_null_values = lappend(non_null_values, list_value);
}
}
- ndatums = list_length(non_null_values);
-
- /*
- * Collect all list values in one array. Alongside the value, we also save
- * the index of partition the value comes from.
- */
- all_values = (PartitionListValue **)
- palloc(ndatums * sizeof(PartitionListValue *));
- i = 0;
- foreach(cell, non_null_values)
- {
- PartitionListValue *src = lfirst(cell);
-
- all_values[i] = (PartitionListValue *)
- palloc(sizeof(PartitionListValue));
- all_values[i]->value = src->value;
- all_values[i]->index = src->index;
- i++;
- }
+ /* ensure we found a Datum for every slot in the all_values array */
+ Assert(j == ndatums);
- qsort_arg(all_values, ndatums, sizeof(PartitionListValue *),
+ qsort_arg(all_values, ndatums, sizeof(PartitionListValue),
qsort_partition_list_value_cmp, (void *) key);
boundinfo->ndatums = ndatums;
boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
+ boundinfo->kind = NULL;
boundinfo->nindexes = ndatums;
boundinfo->indexes = (int *) palloc(ndatums * sizeof(int));
+ /*
+ * In the loop below, to save from allocating a series of small datum
+ * arrays, here we just allocate a single array and below we'll just
+ * assign a portion of this array per datum.
+ */
+ boundDatums = (Datum *) palloc(ndatums * sizeof(Datum));
+
/*
* Copy values. Canonical indexes are values ranging from 0 to (nparts -
* 1) assigned to each partition such that all datums of a given partition
*/
for (i = 0; i < ndatums; i++)
{
- int orig_index = all_values[i]->index;
+ int orig_index = all_values[i].index;
- boundinfo->datums[i] = (Datum *) palloc(sizeof(Datum));
- boundinfo->datums[i][0] = datumCopy(all_values[i]->value,
+ boundinfo->datums[i] = &boundDatums[i];
+ boundinfo->datums[i][0] = datumCopy(all_values[i].value,
key->parttypbyval[0],
key->parttyplen[0]);
boundinfo->indexes[i] = (*mapping)[orig_index];
}
+ pfree(all_values);
+
/*
* Set the canonical value for null_index, if any.
*
PartitionRangeBound **all_bounds,
*prev;
int i,
- k;
+ k,
+ partnatts;
int ndatums = 0;
int default_index = -1;
int next_index = 0;
+ Datum *boundDatums;
+ PartitionRangeDatumKind *boundKinds;
boundinfo = (PartitionBoundInfoData *)
palloc0(sizeof(PartitionBoundInfoData));
prev = cur;
}
+ pfree(all_bounds);
+
/* Update ndatums to hold the count of distinct datums. */
ndatums = k;
boundinfo->nindexes = ndatums + 1;
boundinfo->indexes = (int *) palloc((ndatums + 1) * sizeof(int));
+ /*
+ * In the loop below, to save from allocating a series of small arrays,
+ * here we just allocate a single array for Datums and another for
+ * PartitionRangeDatumKinds, below we'll just assign a portion of these
+ * arrays in each loop.
+ */
+ partnatts = key->partnatts;
+ boundDatums = (Datum *) palloc(ndatums * partnatts * sizeof(Datum));
+ boundKinds = (PartitionRangeDatumKind *) palloc(ndatums * partnatts *
+ sizeof(PartitionRangeDatumKind));
+
for (i = 0; i < ndatums; i++)
{
int j;
- boundinfo->datums[i] = (Datum *) palloc(key->partnatts *
- sizeof(Datum));
- boundinfo->kind[i] = (PartitionRangeDatumKind *)
- palloc(key->partnatts *
- sizeof(PartitionRangeDatumKind));
- for (j = 0; j < key->partnatts; j++)
+ boundinfo->datums[i] = &boundDatums[i * partnatts];
+ boundinfo->kind[i] = &boundKinds[i * partnatts];
+ for (j = 0; j < partnatts; j++)
{
if (rbounds[i]->kind[j] == PARTITION_RANGE_DATUM_VALUE)
boundinfo->datums[i][j] =
}
}
+ pfree(rbounds);
+
/* Set the canonical value for default_index, if any. */
if (default_index != -1)
{
int partnatts;
bool hash_part;
int natts;
+ Datum *boundDatums;
dest = (PartitionBoundInfo) palloc(sizeof(PartitionBoundInfoData));
if (src->kind != NULL)
{
+ PartitionRangeDatumKind *boundKinds;
+
+ /* only RANGE partition should have a non-NULL kind */
+ Assert(key->strategy == PARTITION_STRATEGY_RANGE);
+
dest->kind = (PartitionRangeDatumKind **) palloc(ndatums *
sizeof(PartitionRangeDatumKind *));
+
+ /*
+ * In the loop below, to save from allocating a series of small arrays
+ * for storing the PartitionRangeDatumKind, we allocate a single chunk
+ * here and use a smaller portion of it for each datum.
+ */
+ boundKinds = (PartitionRangeDatumKind *) palloc(ndatums * partnatts *
+ sizeof(PartitionRangeDatumKind));
+
for (i = 0; i < ndatums; i++)
{
- dest->kind[i] = (PartitionRangeDatumKind *) palloc(partnatts *
- sizeof(PartitionRangeDatumKind));
-
+ dest->kind[i] = &boundKinds[i * partnatts];
memcpy(dest->kind[i], src->kind[i],
- sizeof(PartitionRangeDatumKind) * key->partnatts);
+ sizeof(PartitionRangeDatumKind) * partnatts);
}
}
else
*/
hash_part = (key->strategy == PARTITION_STRATEGY_HASH);
natts = hash_part ? 2 : partnatts;
+ boundDatums = palloc(ndatums * natts * sizeof(Datum));
for (i = 0; i < ndatums; i++)
{
int j;
- dest->datums[i] = (Datum *) palloc(sizeof(Datum) * natts);
+ dest->datums[i] = &boundDatums[i * natts];
for (j = 0; j < natts; j++)
{
static int32
qsort_partition_hbound_cmp(const void *a, const void *b)
{
- PartitionHashBound *h1 = (*(PartitionHashBound *const *) a);
- PartitionHashBound *h2 = (*(PartitionHashBound *const *) b);
+ PartitionHashBound *const h1 = (PartitionHashBound *const) a;
+ PartitionHashBound *const h2 = (PartitionHashBound *const) b;
return partition_hbound_cmp(h1->modulus, h1->remainder,
h2->modulus, h2->remainder);
static int32
qsort_partition_list_value_cmp(const void *a, const void *b, void *arg)
{
- Datum val1 = (*(PartitionListValue *const *) a)->value,
- val2 = (*(PartitionListValue *const *) b)->value;
+ Datum val1 = ((PartitionListValue *const) a)->value,
+ val2 = ((PartitionListValue *const) b)->value;
PartitionKey key = (PartitionKey) arg;
return DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0],