diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2022-11-03 16:25:54 +0100 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2022-11-03 16:25:54 +0100 |
commit | 5fca91025e05f803140831953c09a36f08efcef5 (patch) | |
tree | 0c399e1a56dff2a58dc4e37503a03e97b4d5458a | |
parent | cf8b7d374ae10c8de389229ff924addc69e6f7df (diff) | |
download | postgresql-5fca91025e05f803140831953c09a36f08efcef5.tar.gz postgresql-5fca91025e05f803140831953c09a36f08efcef5.zip |
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 <japinli@hotmail.com>
Discussion: https://postgr.es/m/20221021093216.ffupd7epy2mytkux@alvherre.pgsql
-rw-r--r-- | src/backend/commands/tablecmds.c | 35 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 22 | ||||
-rw-r--r-- | src/backend/partitioning/partbounds.c | 27 | ||||
-rw-r--r-- | src/backend/utils/cache/partcache.c | 6 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 15 | ||||
-rw-r--r-- | src/include/partitioning/partbounds.h | 2 | ||||
-rw-r--r-- | src/include/utils/partcache.h | 3 |
7 files changed, 54 insertions, 56 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index bc90185da6b..140ecb0cbfa 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 737bd2d06d5..6ca23f88c4f 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 0823fa7b1db..29643fb4ab5 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 afa99c5d036..e32f4b96119 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 7e7ad3f7e47..7caff62af7f 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 1f5b706d831..a32fc6c149d 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 3394e1fcdba..c45fc3a3ac1 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 */ |