diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index be9fd49cd2e..eeaab2f4c9b 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -70,15 +70,12 @@ static int32 qsort_partition_list_value_cmp(const void *a, const void *b, 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, @@ -169,9 +166,9 @@ get_qual_from_partbound(Relation rel, Relation parent, * 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); @@ -199,13 +196,13 @@ partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping) 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", @@ -222,13 +219,12 @@ partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping) * 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; @@ -244,10 +240,9 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping) 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"); @@ -256,7 +251,6 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping) hbounds[i]->modulus = spec->modulus; hbounds[i]->remainder = spec->remainder; hbounds[i]->index = i; - i++; } /* Sort all the bounds in ascending order */ @@ -307,7 +301,8 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping) * 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; @@ -327,9 +322,9 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) 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) @@ -343,7 +338,6 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) if (spec->is_default) { default_index = i; - i++; continue; } @@ -374,8 +368,6 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) if (list_value) non_null_values = lappend(non_null_values, list_value); } - - i++; } ndatums = list_length(non_null_values); @@ -458,7 +450,7 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) } /* All partition must now have been assigned canonical indexes. */ - Assert(next_index == list_length(boundspecs)); + Assert(next_index == nparts); return boundinfo; } @@ -467,16 +459,15 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) * 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; @@ -493,10 +484,10 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping) 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; @@ -510,7 +501,7 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping) */ if (spec->is_default) { - default_index = i++; + default_index = i; continue; } @@ -518,7 +509,6 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping) upper = make_one_partition_rbound(key, i, spec->upperdatums, false); all_bounds[ndatums++] = lower; all_bounds[ndatums++] = upper; - i++; } Assert(ndatums == nparts * 2 || diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c index 7856b47cdd9..6db2c6f7831 100644 --- a/src/backend/utils/cache/partcache.c +++ b/src/backend/utils/cache/partcache.c @@ -255,28 +255,36 @@ void 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)) @@ -287,14 +295,16 @@ RelationBuildPartitionDesc(Relation rel) &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; @@ -304,12 +314,12 @@ RelationBuildPartitionDesc(Relation rel) 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", @@ -330,11 +340,7 @@ RelationBuildPartitionDesc(Relation rel) } /* 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); @@ -352,10 +358,10 @@ RelationBuildPartitionDesc(Relation rel) { 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); diff --git a/src/include/partitioning/partbounds.h b/src/include/partitioning/partbounds.h index 7a697d1c0a7..36fb584e23e 100644 --- a/src/include/partitioning/partbounds.h +++ b/src/include/partitioning/partbounds.h @@ -80,9 +80,8 @@ extern uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, Datum *values, bool *isnull); extern List *get_qual_from_partbound(Relation rel, Relation parent, PartitionBoundSpec *spec); -extern PartitionBoundInfo partition_bounds_create(List *boundspecs, - PartitionKey key, - int **mapping); +extern PartitionBoundInfo partition_bounds_create(PartitionBoundSpec **boundspecs, + int nparts, PartitionKey key, int **mapping); extern bool partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval, PartitionBoundInfo b1, PartitionBoundInfo b2);