Skip to content

Commit 5fca910

Browse files
committed
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 cf8b7d3 commit 5fca910

File tree

7 files changed

+54
-56
lines changed

7 files changed

+54
-56
lines changed

src/backend/commands/tablecmds.c

+11-24
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

+21-1
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

+5-22
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

+6
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

+8-7
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

+1-1
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

+2-1
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)