void *arg);
static int32 qsort_partition_rbound_cmp(const void *a, const void *b,
void *arg);
-static PartitionBoundInfo create_hash_bounds(List *boundspecs,
- PartitionKey key,
- int **mapping);
-static PartitionBoundInfo create_list_bounds(List *boundspecs,
- PartitionKey key,
- int **mapping);
-static PartitionBoundInfo create_range_bounds(List *boundspecs,
- PartitionKey key,
- int **mapping);
+static PartitionBoundInfo create_hash_bounds(PartitionBoundSpec **boundspecs,
+ int nparts, PartitionKey key, int **mapping);
+static PartitionBoundInfo create_list_bounds(PartitionBoundSpec **boundspecs,
+ int nparts, PartitionKey key, int **mapping);
+static PartitionBoundInfo create_range_bounds(PartitionBoundSpec **boundspecs,
+ int nparts, PartitionKey key, int **mapping);
static PartitionRangeBound *make_one_partition_rbound(PartitionKey key, int index,
List *datums, bool lower);
static int32 partition_hbound_cmp(int modulus1, int remainder1, int modulus2,
* current memory context.
*/
PartitionBoundInfo
-partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping)
+partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts,
+ PartitionKey key, int **mapping)
{
- int nparts = list_length(boundspecs);
int i;
Assert(nparts > 0);
switch (key->strategy)
{
case PARTITION_STRATEGY_HASH:
- return create_hash_bounds(boundspecs, key, mapping);
+ return create_hash_bounds(boundspecs, nparts, key, mapping);
case PARTITION_STRATEGY_LIST:
- return create_list_bounds(boundspecs, key, mapping);
+ return create_list_bounds(boundspecs, nparts, key, mapping);
case PARTITION_STRATEGY_RANGE:
- return create_range_bounds(boundspecs, key, mapping);
+ return create_range_bounds(boundspecs, nparts, key, mapping);
default:
elog(ERROR, "unexpected partition strategy: %d",
* Create a PartitionBoundInfo for a hash partitioned table
*/
static PartitionBoundInfo
-create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping)
+create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
+ PartitionKey key, int **mapping)
{
PartitionBoundInfo boundinfo;
PartitionHashBound **hbounds = NULL;
- ListCell *cell;
- int i,
- nparts = list_length(boundspecs);
+ int i;
int ndatums = 0;
int greatest_modulus;
palloc(nparts * sizeof(PartitionHashBound *));
/* Convert from node to the internal representation */
- i = 0;
- foreach(cell, boundspecs)
+ for (i = 0; i < nparts; i++)
{
- PartitionBoundSpec *spec = castNode(PartitionBoundSpec, lfirst(cell));
+ PartitionBoundSpec *spec = boundspecs[i];
if (spec->strategy != PARTITION_STRATEGY_HASH)
elog(ERROR, "invalid strategy in partition bound spec");
hbounds[i]->modulus = spec->modulus;
hbounds[i]->remainder = spec->remainder;
hbounds[i]->index = i;
- i++;
}
/* Sort all the bounds in ascending order */
* Create a PartitionBoundInfo for a list partitioned table
*/
static PartitionBoundInfo
-create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
+create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
+ PartitionKey key, int **mapping)
{
PartitionBoundInfo boundinfo;
PartitionListValue **all_values = NULL;
boundinfo->default_index = -1;
/* Create a unified list of non-null values across all partitions. */
- foreach(cell, boundspecs)
+ for (i = 0; i < nparts; i++)
{
- PartitionBoundSpec *spec = castNode(PartitionBoundSpec, lfirst(cell));
+ PartitionBoundSpec *spec = boundspecs[i];
ListCell *c;
if (spec->strategy != PARTITION_STRATEGY_LIST)
if (spec->is_default)
{
default_index = i;
- i++;
continue;
}
if (list_value)
non_null_values = lappend(non_null_values, list_value);
}
-
- i++;
}
ndatums = list_length(non_null_values);
}
/* All partition must now have been assigned canonical indexes. */
- Assert(next_index == list_length(boundspecs));
+ Assert(next_index == nparts);
return boundinfo;
}
* Create a PartitionBoundInfo for a range partitioned table
*/
static PartitionBoundInfo
-create_range_bounds(List *boundspecs, PartitionKey key, int **mapping)
+create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
+ PartitionKey key, int **mapping)
{
PartitionBoundInfo boundinfo;
PartitionRangeBound **rbounds = NULL;
PartitionRangeBound **all_bounds,
*prev;
- ListCell *cell;
int i,
- k,
- nparts = list_length(boundspecs);
+ k;
int ndatums = 0;
int default_index = -1;
int next_index = 0;
palloc0(2 * nparts * sizeof(PartitionRangeBound *));
/* Create a unified list of range bounds across all the partitions. */
- i = ndatums = 0;
- foreach(cell, boundspecs)
+ ndatums = 0;
+ for (i = 0; i < nparts; i++)
{
- PartitionBoundSpec *spec = castNode(PartitionBoundSpec, lfirst(cell));
+ PartitionBoundSpec *spec = boundspecs[i];
PartitionRangeBound *lower,
*upper;
*/
if (spec->is_default)
{
- default_index = i++;
+ default_index = i;
continue;
}
upper = make_one_partition_rbound(key, i, spec->upperdatums, false);
all_bounds[ndatums++] = lower;
all_bounds[ndatums++] = upper;
- i++;
}
Assert(ndatums == nparts * 2 ||
RelationBuildPartitionDesc(Relation rel)
{
PartitionDesc partdesc;
- PartitionBoundInfo boundinfo;
+ PartitionBoundInfo boundinfo = NULL;
List *inhoids;
- List *boundspecs = NIL;
+ PartitionBoundSpec **boundspecs = NULL;
+ Oid *oids = NULL;
ListCell *cell;
int i,
nparts;
PartitionKey key = RelationGetPartitionKey(rel);
MemoryContext oldcxt;
- Oid *oids_orig;
int *mapping;
/* Get partition oids from pg_inherits */
inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock);
+ nparts = list_length(inhoids);
- /* Collect bound spec nodes in a list */
+ if (nparts > 0)
+ {
+ oids = palloc(nparts * sizeof(Oid));
+ boundspecs = palloc(nparts * sizeof(PartitionBoundSpec *));
+ }
+
+ /* Collect bound spec nodes for each partition */
+ i = 0;
foreach(cell, inhoids)
{
Oid inhrelid = lfirst_oid(cell);
HeapTuple tuple;
Datum datum;
bool isnull;
- Node *boundspec;
+ PartitionBoundSpec *boundspec;
tuple = SearchSysCache1(RELOID, inhrelid);
if (!HeapTupleIsValid(tuple))
&isnull);
if (isnull)
elog(ERROR, "null relpartbound for relation %u", inhrelid);
- boundspec = (Node *) stringToNode(TextDatumGetCString(datum));
+ boundspec = stringToNode(TextDatumGetCString(datum));
+ if (!IsA(boundspec, PartitionBoundSpec))
+ elog(ERROR, "invalid relpartbound for relation %u", inhrelid);
/*
* Sanity check: If the PartitionBoundSpec says this is the default
* partition, its OID should correspond to whatever's stored in
* pg_partitioned_table.partdefid; if not, the catalog is corrupt.
*/
- if (castNode(PartitionBoundSpec, boundspec)->is_default)
+ if (boundspec->is_default)
{
Oid partdefid;
inhrelid, partdefid);
}
- boundspecs = lappend(boundspecs, boundspec);
+ oids[i] = inhrelid;
+ boundspecs[i] = boundspec;
+ ++i;
ReleaseSysCache(tuple);
}
- nparts = list_length(boundspecs);
-
/* Now build the actual relcache partition descriptor */
rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
"partition descriptor",
}
/* First create PartitionBoundInfo */
- boundinfo = partition_bounds_create(boundspecs, key, &mapping);
- oids_orig = (Oid *) palloc(sizeof(Oid) * partdesc->nparts);
- i = 0;
- foreach(cell, inhoids)
- oids_orig[i++] = lfirst_oid(cell);
+ boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
/* Now copy boundinfo and oids into partdesc. */
oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
{
int index = mapping[i];
- partdesc->oids[index] = oids_orig[i];
+ partdesc->oids[index] = oids[i];
/* Record if the partition is a leaf partition */
partdesc->is_leaf[index] =
- (get_rel_relkind(oids_orig[i]) != RELKIND_PARTITIONED_TABLE);
+ (get_rel_relkind(oids[i]) != RELKIND_PARTITIONED_TABLE);
}
MemoryContextSwitchTo(oldcxt);