summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2022-11-03 15:25:54 +0000
committerAlvaro Herrera2022-11-03 15:25:54 +0000
commit5fca91025e05f803140831953c09a36f08efcef5 (patch)
tree0c399e1a56dff2a58dc4e37503a03e97b4d5458a
parentcf8b7d374ae10c8de389229ff924addc69e6f7df (diff)
Resolve partition strategy during early parsing
This has little practical value, but there's no reason to let the partition strategy names travel through DDL as strings. Reviewed-by: Japin Li <[email protected]> Discussion: https://postgr.es/m/[email protected]
-rw-r--r--src/backend/commands/tablecmds.c35
-rw-r--r--src/backend/parser/gram.y22
-rw-r--r--src/backend/partitioning/partbounds.c27
-rw-r--r--src/backend/utils/cache/partcache.c6
-rw-r--r--src/include/nodes/parsenodes.h15
-rw-r--r--src/include/partitioning/partbounds.h2
-rw-r--r--src/include/utils/partcache.h3
7 files changed, 54 insertions, 56 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index bc90185da6..140ecb0cbf 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -605,9 +605,10 @@ static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
Oid oldRelOid, void *arg);
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
Oid oldrelid, void *arg);
-static PartitionSpec *transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy);
+static PartitionSpec *transformPartitionSpec(Relation rel, PartitionSpec *partspec);
static void ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNumber *partattrs,
- List **partexprs, Oid *partopclass, Oid *partcollation, char strategy);
+ List **partexprs, Oid *partopclass, Oid *partcollation,
+ PartitionStrategy strategy);
static void CreateInheritance(Relation child_rel, Relation parent_rel);
static void RemoveInheritance(Relation child_rel, Relation parent_rel,
bool expect_detached);
@@ -1122,7 +1123,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
if (partitioned)
{
ParseState *pstate;
- char strategy;
int partnatts;
AttrNumber partattrs[PARTITION_MAX_KEYS];
Oid partopclass[PARTITION_MAX_KEYS];
@@ -1147,14 +1147,14 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
* and CHECK constraints, we could not have done the transformation
* earlier.
*/
- stmt->partspec = transformPartitionSpec(rel, stmt->partspec,
- &strategy);
+ stmt->partspec = transformPartitionSpec(rel, stmt->partspec);
ComputePartitionAttrs(pstate, rel, stmt->partspec->partParams,
partattrs, &partexprs, partopclass,
- partcollation, strategy);
+ partcollation, stmt->partspec->strategy);
- StorePartitionKey(rel, strategy, partnatts, partattrs, partexprs,
+ StorePartitionKey(rel, stmt->partspec->strategy, partnatts, partattrs,
+ partexprs,
partopclass, partcollation);
/* make it all visible */
@@ -17132,10 +17132,10 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
/*
* Transform any expressions present in the partition key
*
- * Returns a transformed PartitionSpec, as well as the strategy code
+ * Returns a transformed PartitionSpec.
*/
static PartitionSpec *
-transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
+transformPartitionSpec(Relation rel, PartitionSpec *partspec)
{
PartitionSpec *newspec;
ParseState *pstate;
@@ -17148,21 +17148,8 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
newspec->partParams = NIL;
newspec->location = partspec->location;
- /* Parse partitioning strategy name */
- if (pg_strcasecmp(partspec->strategy, "hash") == 0)
- *strategy = PARTITION_STRATEGY_HASH;
- else if (pg_strcasecmp(partspec->strategy, "list") == 0)
- *strategy = PARTITION_STRATEGY_LIST;
- else if (pg_strcasecmp(partspec->strategy, "range") == 0)
- *strategy = PARTITION_STRATEGY_RANGE;
- else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unrecognized partitioning strategy \"%s\"",
- partspec->strategy)));
-
/* Check valid number of columns for strategy */
- if (*strategy == PARTITION_STRATEGY_LIST &&
+ if (partspec->strategy == PARTITION_STRATEGY_LIST &&
list_length(partspec->partParams) != 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@@ -17208,7 +17195,7 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
static void
ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNumber *partattrs,
List **partexprs, Oid *partopclass, Oid *partcollation,
- char strategy)
+ PartitionStrategy strategy)
{
int attn;
ListCell *lc;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 737bd2d06d..6ca23f88c4 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -213,6 +213,7 @@ static void SplitColQualList(List *qualList,
static void processCASbits(int cas_bits, int location, const char *constrType,
bool *deferrable, bool *initdeferred, bool *not_valid,
bool *no_inherit, core_yyscan_t yyscanner);
+static PartitionStrategy parsePartitionStrategy(char *strategy);
static void preprocess_pubobj_list(List *pubobjspec_list,
core_yyscan_t yyscanner);
static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
@@ -4357,7 +4358,7 @@ PartitionSpec: PARTITION BY ColId '(' part_params ')'
{
PartitionSpec *n = makeNode(PartitionSpec);
- n->strategy = $3;
+ n->strategy = parsePartitionStrategy($3);
n->partParams = $5;
n->location = @1;
@@ -18415,6 +18416,25 @@ processCASbits(int cas_bits, int location, const char *constrType,
}
/*
+ * Parse a user-supplied partition strategy string into parse node
+ * PartitionStrategy representation, or die trying.
+ */
+static PartitionStrategy
+parsePartitionStrategy(char *strategy)
+{
+ if (pg_strcasecmp(strategy, "list") == 0)
+ return PARTITION_STRATEGY_LIST;
+ else if (pg_strcasecmp(strategy, "range") == 0)
+ return PARTITION_STRATEGY_RANGE;
+ else if (pg_strcasecmp(strategy, "hash") == 0)
+ return PARTITION_STRATEGY_HASH;
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unrecognized partitioning strategy \"%s\"",
+ strategy)));
+}
+
+/*
* Process pubobjspec_list to check for errors in any of the objects and
* convert PUBLICATIONOBJ_CONTINUATION into appropriate PublicationObjSpecType.
*/
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 0823fa7b1d..29643fb4ab 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -270,10 +270,6 @@ get_qual_from_partbound(Relation parent, PartitionBoundSpec *spec)
Assert(spec->strategy == PARTITION_STRATEGY_RANGE);
my_qual = get_qual_for_range(parent, spec, false);
break;
-
- default:
- elog(ERROR, "unexpected partition strategy: %d",
- (int) key->strategy);
}
return my_qual;
@@ -338,11 +334,6 @@ partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts,
case PARTITION_STRATEGY_RANGE:
return create_range_bounds(boundspecs, nparts, key, mapping);
-
- default:
- elog(ERROR, "unexpected partition strategy: %d",
- (int) key->strategy);
- break;
}
Assert(false);
@@ -1181,12 +1172,9 @@ partition_bounds_merge(int partnatts,
jointype,
outer_parts,
inner_parts);
-
- default:
- elog(ERROR, "unexpected partition strategy: %d",
- (int) outer_rel->boundinfo->strategy);
- return NULL; /* keep compiler quiet */
}
+
+ return NULL;
}
/*
@@ -2892,8 +2880,7 @@ partitions_are_ordered(PartitionBoundInfo boundinfo, Bitmapset *live_parts)
return true;
break;
- default:
- /* HASH, or some other strategy */
+ case PARTITION_STRATEGY_HASH:
break;
}
@@ -3241,10 +3228,6 @@ check_new_partition_bound(char *relname, Relation parent,
break;
}
-
- default:
- elog(ERROR, "unexpected partition strategy: %d",
- (int) key->strategy);
}
if (overlap)
@@ -3980,8 +3963,8 @@ make_partition_op_expr(PartitionKey key, int keynum,
key->partcollation[keynum]);
break;
- default:
- elog(ERROR, "invalid partitioning strategy");
+ case PARTITION_STRATEGY_HASH:
+ Assert(false);
break;
}
diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c
index afa99c5d03..e32f4b9611 100644
--- a/src/backend/utils/cache/partcache.c
+++ b/src/backend/utils/cache/partcache.c
@@ -115,6 +115,12 @@ RelationBuildPartitionKey(Relation relation)
key->strategy = form->partstrat;
key->partnatts = form->partnatts;
+ /* Validate partition strategy code */
+ if (key->strategy != PARTITION_STRATEGY_LIST &&
+ key->strategy != PARTITION_STRATEGY_RANGE &&
+ key->strategy != PARTITION_STRATEGY_HASH)
+ elog(ERROR, "invalid partition strategy \"%c\"", key->strategy);
+
/*
* We can rely on the first variable-length attribute being mapped to the
* relevant field of the catalog's C struct, because all previous
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 7e7ad3f7e4..7caff62af7 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -827,6 +827,13 @@ typedef struct PartitionElem
int location; /* token location, or -1 if unknown */
} PartitionElem;
+typedef enum PartitionStrategy
+{
+ PARTITION_STRATEGY_LIST = 'l',
+ PARTITION_STRATEGY_RANGE = 'r',
+ PARTITION_STRATEGY_HASH = 'h'
+} PartitionStrategy;
+
/*
* PartitionSpec - parse-time representation of a partition key specification
*
@@ -835,17 +842,11 @@ typedef struct PartitionElem
typedef struct PartitionSpec
{
NodeTag type;
- char *strategy; /* partitioning strategy ('hash', 'list' or
- * 'range') */
+ PartitionStrategy strategy;
List *partParams; /* List of PartitionElems */
int location; /* token location, or -1 if unknown */
} PartitionSpec;
-/* Internal codes for partitioning strategies */
-#define PARTITION_STRATEGY_HASH 'h'
-#define PARTITION_STRATEGY_LIST 'l'
-#define PARTITION_STRATEGY_RANGE 'r'
-
/*
* PartitionBoundSpec - a partition bound specification
*
diff --git a/src/include/partitioning/partbounds.h b/src/include/partitioning/partbounds.h
index 1f5b706d83..a32fc6c149 100644
--- a/src/include/partitioning/partbounds.h
+++ b/src/include/partitioning/partbounds.h
@@ -78,7 +78,7 @@ struct RelOptInfo; /* avoid including pathnodes.h here */
*/
typedef struct PartitionBoundInfoData
{
- char strategy; /* hash, list or range? */
+ PartitionStrategy strategy; /* hash, list or range? */
int ndatums; /* Length of the datums[] array */
Datum **datums;
PartitionRangeDatumKind **kind; /* The kind of each range bound datum;
diff --git a/src/include/utils/partcache.h b/src/include/utils/partcache.h
index 3394e1fcdb..c45fc3a3ac 100644
--- a/src/include/utils/partcache.h
+++ b/src/include/utils/partcache.h
@@ -13,6 +13,7 @@
#include "access/attnum.h"
#include "fmgr.h"
+#include "nodes/parsenodes.h"
#include "nodes/pg_list.h"
#include "nodes/primnodes.h"
#include "partitioning/partdefs.h"
@@ -23,7 +24,7 @@
*/
typedef struct PartitionKeyData
{
- char strategy; /* partitioning strategy */
+ PartitionStrategy strategy; /* partitioning strategy */
int16 partnatts; /* number of columns in the partition key */
AttrNumber *partattrs; /* attribute numbers of columns in the
* partition key or 0 if it's an expr */