Skip to content

Commit 40a68b5

Browse files
alvherrepull[bot]
authored andcommitted
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
1 parent 7b834a0 commit 40a68b5

File tree

7 files changed

+54
-56
lines changed

7 files changed

+54
-56
lines changed

src/backend/commands/tablecmds.c

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -605,9 +605,10 @@ static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
605605
Oid oldRelOid, void *arg);
606606
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
607607
Oid oldrelid, void *arg);
608-
static PartitionSpec *transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy);
608+
static PartitionSpec *transformPartitionSpec(Relation rel, PartitionSpec *partspec);
609609
static void ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNumber *partattrs,
610-
List **partexprs, Oid *partopclass, Oid *partcollation, char strategy);
610+
List **partexprs, Oid *partopclass, Oid *partcollation,
611+
PartitionStrategy strategy);
611612
static void CreateInheritance(Relation child_rel, Relation parent_rel);
612613
static void RemoveInheritance(Relation child_rel, Relation parent_rel,
613614
bool expect_detached);
@@ -1122,7 +1123,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
11221123
if (partitioned)
11231124
{
11241125
ParseState *pstate;
1125-
char strategy;
11261126
int partnatts;
11271127
AttrNumber partattrs[PARTITION_MAX_KEYS];
11281128
Oid partopclass[PARTITION_MAX_KEYS];
@@ -1147,14 +1147,14 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
11471147
* and CHECK constraints, we could not have done the transformation
11481148
* earlier.
11491149
*/
1150-
stmt->partspec = transformPartitionSpec(rel, stmt->partspec,
1151-
&strategy);
1150+
stmt->partspec = transformPartitionSpec(rel, stmt->partspec);
11521151

11531152
ComputePartitionAttrs(pstate, rel, stmt->partspec->partParams,
11541153
partattrs, &partexprs, partopclass,
1155-
partcollation, strategy);
1154+
partcollation, stmt->partspec->strategy);
11561155

1157-
StorePartitionKey(rel, strategy, partnatts, partattrs, partexprs,
1156+
StorePartitionKey(rel, stmt->partspec->strategy, partnatts, partattrs,
1157+
partexprs,
11581158
partopclass, partcollation);
11591159

11601160
/* make it all visible */
@@ -17132,10 +17132,10 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
1713217132
/*
1713317133
* Transform any expressions present in the partition key
1713417134
*
17135-
* Returns a transformed PartitionSpec, as well as the strategy code
17135+
* Returns a transformed PartitionSpec.
1713617136
*/
1713717137
static PartitionSpec *
17138-
transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
17138+
transformPartitionSpec(Relation rel, PartitionSpec *partspec)
1713917139
{
1714017140
PartitionSpec *newspec;
1714117141
ParseState *pstate;
@@ -17148,21 +17148,8 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
1714817148
newspec->partParams = NIL;
1714917149
newspec->location = partspec->location;
1715017150

17151-
/* Parse partitioning strategy name */
17152-
if (pg_strcasecmp(partspec->strategy, "hash") == 0)
17153-
*strategy = PARTITION_STRATEGY_HASH;
17154-
else if (pg_strcasecmp(partspec->strategy, "list") == 0)
17155-
*strategy = PARTITION_STRATEGY_LIST;
17156-
else if (pg_strcasecmp(partspec->strategy, "range") == 0)
17157-
*strategy = PARTITION_STRATEGY_RANGE;
17158-
else
17159-
ereport(ERROR,
17160-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
17161-
errmsg("unrecognized partitioning strategy \"%s\"",
17162-
partspec->strategy)));
17163-
1716417151
/* Check valid number of columns for strategy */
17165-
if (*strategy == PARTITION_STRATEGY_LIST &&
17152+
if (partspec->strategy == PARTITION_STRATEGY_LIST &&
1716617153
list_length(partspec->partParams) != 1)
1716717154
ereport(ERROR,
1716817155
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@@ -17208,7 +17195,7 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
1720817195
static void
1720917196
ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNumber *partattrs,
1721017197
List **partexprs, Oid *partopclass, Oid *partcollation,
17211-
char strategy)
17198+
PartitionStrategy strategy)
1721217199
{
1721317200
int attn;
1721417201
ListCell *lc;

src/backend/parser/gram.y

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ static void SplitColQualList(List *qualList,
213213
static void processCASbits(int cas_bits, int location, const char *constrType,
214214
bool *deferrable, bool *initdeferred, bool *not_valid,
215215
bool *no_inherit, core_yyscan_t yyscanner);
216+
static PartitionStrategy parsePartitionStrategy(char *strategy);
216217
static void preprocess_pubobj_list(List *pubobjspec_list,
217218
core_yyscan_t yyscanner);
218219
static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
@@ -4357,7 +4358,7 @@ PartitionSpec: PARTITION BY ColId '(' part_params ')'
43574358
{
43584359
PartitionSpec *n = makeNode(PartitionSpec);
43594360

4360-
n->strategy = $3;
4361+
n->strategy = parsePartitionStrategy($3);
43614362
n->partParams = $5;
43624363
n->location = @1;
43634364

@@ -18414,6 +18415,25 @@ processCASbits(int cas_bits, int location, const char *constrType,
1841418415
}
1841518416
}
1841618417

18418+
/*
18419+
* Parse a user-supplied partition strategy string into parse node
18420+
* PartitionStrategy representation, or die trying.
18421+
*/
18422+
static PartitionStrategy
18423+
parsePartitionStrategy(char *strategy)
18424+
{
18425+
if (pg_strcasecmp(strategy, "list") == 0)
18426+
return PARTITION_STRATEGY_LIST;
18427+
else if (pg_strcasecmp(strategy, "range") == 0)
18428+
return PARTITION_STRATEGY_RANGE;
18429+
else if (pg_strcasecmp(strategy, "hash") == 0)
18430+
return PARTITION_STRATEGY_HASH;
18431+
ereport(ERROR,
18432+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
18433+
errmsg("unrecognized partitioning strategy \"%s\"",
18434+
strategy)));
18435+
}
18436+
1841718437
/*
1841818438
* Process pubobjspec_list to check for errors in any of the objects and
1841918439
* convert PUBLICATIONOBJ_CONTINUATION into appropriate PublicationObjSpecType.

src/backend/partitioning/partbounds.c

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,6 @@ get_qual_from_partbound(Relation parent, PartitionBoundSpec *spec)
270270
Assert(spec->strategy == PARTITION_STRATEGY_RANGE);
271271
my_qual = get_qual_for_range(parent, spec, false);
272272
break;
273-
274-
default:
275-
elog(ERROR, "unexpected partition strategy: %d",
276-
(int) key->strategy);
277273
}
278274

279275
return my_qual;
@@ -338,11 +334,6 @@ partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts,
338334

339335
case PARTITION_STRATEGY_RANGE:
340336
return create_range_bounds(boundspecs, nparts, key, mapping);
341-
342-
default:
343-
elog(ERROR, "unexpected partition strategy: %d",
344-
(int) key->strategy);
345-
break;
346337
}
347338

348339
Assert(false);
@@ -1181,12 +1172,9 @@ partition_bounds_merge(int partnatts,
11811172
jointype,
11821173
outer_parts,
11831174
inner_parts);
1184-
1185-
default:
1186-
elog(ERROR, "unexpected partition strategy: %d",
1187-
(int) outer_rel->boundinfo->strategy);
1188-
return NULL; /* keep compiler quiet */
11891175
}
1176+
1177+
return NULL;
11901178
}
11911179

11921180
/*
@@ -2892,8 +2880,7 @@ partitions_are_ordered(PartitionBoundInfo boundinfo, Bitmapset *live_parts)
28922880
return true;
28932881

28942882
break;
2895-
default:
2896-
/* HASH, or some other strategy */
2883+
case PARTITION_STRATEGY_HASH:
28972884
break;
28982885
}
28992886

@@ -3241,10 +3228,6 @@ check_new_partition_bound(char *relname, Relation parent,
32413228

32423229
break;
32433230
}
3244-
3245-
default:
3246-
elog(ERROR, "unexpected partition strategy: %d",
3247-
(int) key->strategy);
32483231
}
32493232

32503233
if (overlap)
@@ -3980,8 +3963,8 @@ make_partition_op_expr(PartitionKey key, int keynum,
39803963
key->partcollation[keynum]);
39813964
break;
39823965

3983-
default:
3984-
elog(ERROR, "invalid partitioning strategy");
3966+
case PARTITION_STRATEGY_HASH:
3967+
Assert(false);
39853968
break;
39863969
}
39873970

src/backend/utils/cache/partcache.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ RelationBuildPartitionKey(Relation relation)
115115
key->strategy = form->partstrat;
116116
key->partnatts = form->partnatts;
117117

118+
/* Validate partition strategy code */
119+
if (key->strategy != PARTITION_STRATEGY_LIST &&
120+
key->strategy != PARTITION_STRATEGY_RANGE &&
121+
key->strategy != PARTITION_STRATEGY_HASH)
122+
elog(ERROR, "invalid partition strategy \"%c\"", key->strategy);
123+
118124
/*
119125
* We can rely on the first variable-length attribute being mapped to the
120126
* relevant field of the catalog's C struct, because all previous

src/include/nodes/parsenodes.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,13 @@ typedef struct PartitionElem
827827
int location; /* token location, or -1 if unknown */
828828
} PartitionElem;
829829

830+
typedef enum PartitionStrategy
831+
{
832+
PARTITION_STRATEGY_LIST = 'l',
833+
PARTITION_STRATEGY_RANGE = 'r',
834+
PARTITION_STRATEGY_HASH = 'h'
835+
} PartitionStrategy;
836+
830837
/*
831838
* PartitionSpec - parse-time representation of a partition key specification
832839
*
@@ -835,17 +842,11 @@ typedef struct PartitionElem
835842
typedef struct PartitionSpec
836843
{
837844
NodeTag type;
838-
char *strategy; /* partitioning strategy ('hash', 'list' or
839-
* 'range') */
845+
PartitionStrategy strategy;
840846
List *partParams; /* List of PartitionElems */
841847
int location; /* token location, or -1 if unknown */
842848
} PartitionSpec;
843849

844-
/* Internal codes for partitioning strategies */
845-
#define PARTITION_STRATEGY_HASH 'h'
846-
#define PARTITION_STRATEGY_LIST 'l'
847-
#define PARTITION_STRATEGY_RANGE 'r'
848-
849850
/*
850851
* PartitionBoundSpec - a partition bound specification
851852
*

src/include/partitioning/partbounds.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ struct RelOptInfo; /* avoid including pathnodes.h here */
7878
*/
7979
typedef struct PartitionBoundInfoData
8080
{
81-
char strategy; /* hash, list or range? */
81+
PartitionStrategy strategy; /* hash, list or range? */
8282
int ndatums; /* Length of the datums[] array */
8383
Datum **datums;
8484
PartitionRangeDatumKind **kind; /* The kind of each range bound datum;

src/include/utils/partcache.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "access/attnum.h"
1515
#include "fmgr.h"
16+
#include "nodes/parsenodes.h"
1617
#include "nodes/pg_list.h"
1718
#include "nodes/primnodes.h"
1819
#include "partitioning/partdefs.h"
@@ -23,7 +24,7 @@
2324
*/
2425
typedef struct PartitionKeyData
2526
{
26-
char strategy; /* partitioning strategy */
27+
PartitionStrategy strategy; /* partitioning strategy */
2728
int16 partnatts; /* number of columns in the partition key */
2829
AttrNumber *partattrs; /* attribute numbers of columns in the
2930
* partition key or 0 if it's an expr */

0 commit comments

Comments
 (0)