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
This commit is contained in:
Alvaro Herrera 2022-11-03 16:25:54 +01:00
parent cf8b7d374a
commit 5fca91025e
No known key found for this signature in database
GPG Key ID: 1C20ACB9D5C564AE
7 changed files with 54 additions and 56 deletions

View File

@ -605,9 +605,10 @@ static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
Oid oldRelOid, void *arg); Oid oldRelOid, void *arg);
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
Oid oldrelid, void *arg); 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, 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 CreateInheritance(Relation child_rel, Relation parent_rel);
static void RemoveInheritance(Relation child_rel, Relation parent_rel, static void RemoveInheritance(Relation child_rel, Relation parent_rel,
bool expect_detached); bool expect_detached);
@ -1122,7 +1123,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
if (partitioned) if (partitioned)
{ {
ParseState *pstate; ParseState *pstate;
char strategy;
int partnatts; int partnatts;
AttrNumber partattrs[PARTITION_MAX_KEYS]; AttrNumber partattrs[PARTITION_MAX_KEYS];
Oid partopclass[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 * and CHECK constraints, we could not have done the transformation
* earlier. * earlier.
*/ */
stmt->partspec = transformPartitionSpec(rel, stmt->partspec, stmt->partspec = transformPartitionSpec(rel, stmt->partspec);
&strategy);
ComputePartitionAttrs(pstate, rel, stmt->partspec->partParams, ComputePartitionAttrs(pstate, rel, stmt->partspec->partParams,
partattrs, &partexprs, partopclass, 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); partopclass, partcollation);
/* make it all visible */ /* make it all visible */
@ -17132,10 +17132,10 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
/* /*
* Transform any expressions present in the partition key * Transform any expressions present in the partition key
* *
* Returns a transformed PartitionSpec, as well as the strategy code * Returns a transformed PartitionSpec.
*/ */
static PartitionSpec * static PartitionSpec *
transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy) transformPartitionSpec(Relation rel, PartitionSpec *partspec)
{ {
PartitionSpec *newspec; PartitionSpec *newspec;
ParseState *pstate; ParseState *pstate;
@ -17148,21 +17148,8 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
newspec->partParams = NIL; newspec->partParams = NIL;
newspec->location = partspec->location; 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 */ /* Check valid number of columns for strategy */
if (*strategy == PARTITION_STRATEGY_LIST && if (partspec->strategy == PARTITION_STRATEGY_LIST &&
list_length(partspec->partParams) != 1) list_length(partspec->partParams) != 1)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@ -17208,7 +17195,7 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
static void static void
ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNumber *partattrs, ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNumber *partattrs,
List **partexprs, Oid *partopclass, Oid *partcollation, List **partexprs, Oid *partopclass, Oid *partcollation,
char strategy) PartitionStrategy strategy)
{ {
int attn; int attn;
ListCell *lc; ListCell *lc;

View File

@ -213,6 +213,7 @@ static void SplitColQualList(List *qualList,
static void processCASbits(int cas_bits, int location, const char *constrType, static void processCASbits(int cas_bits, int location, const char *constrType,
bool *deferrable, bool *initdeferred, bool *not_valid, bool *deferrable, bool *initdeferred, bool *not_valid,
bool *no_inherit, core_yyscan_t yyscanner); bool *no_inherit, core_yyscan_t yyscanner);
static PartitionStrategy parsePartitionStrategy(char *strategy);
static void preprocess_pubobj_list(List *pubobjspec_list, static void preprocess_pubobj_list(List *pubobjspec_list,
core_yyscan_t yyscanner); core_yyscan_t yyscanner);
static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
@ -4357,7 +4358,7 @@ PartitionSpec: PARTITION BY ColId '(' part_params ')'
{ {
PartitionSpec *n = makeNode(PartitionSpec); PartitionSpec *n = makeNode(PartitionSpec);
n->strategy = $3; n->strategy = parsePartitionStrategy($3);
n->partParams = $5; n->partParams = $5;
n->location = @1; n->location = @1;
@ -18414,6 +18415,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 * Process pubobjspec_list to check for errors in any of the objects and
* convert PUBLICATIONOBJ_CONTINUATION into appropriate PublicationObjSpecType. * convert PUBLICATIONOBJ_CONTINUATION into appropriate PublicationObjSpecType.

View File

@ -270,10 +270,6 @@ get_qual_from_partbound(Relation parent, PartitionBoundSpec *spec)
Assert(spec->strategy == PARTITION_STRATEGY_RANGE); Assert(spec->strategy == PARTITION_STRATEGY_RANGE);
my_qual = get_qual_for_range(parent, spec, false); my_qual = get_qual_for_range(parent, spec, false);
break; break;
default:
elog(ERROR, "unexpected partition strategy: %d",
(int) key->strategy);
} }
return my_qual; return my_qual;
@ -338,11 +334,6 @@ partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts,
case PARTITION_STRATEGY_RANGE: case PARTITION_STRATEGY_RANGE:
return create_range_bounds(boundspecs, nparts, key, mapping); return create_range_bounds(boundspecs, nparts, key, mapping);
default:
elog(ERROR, "unexpected partition strategy: %d",
(int) key->strategy);
break;
} }
Assert(false); Assert(false);
@ -1181,12 +1172,9 @@ partition_bounds_merge(int partnatts,
jointype, jointype,
outer_parts, outer_parts,
inner_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; return true;
break; break;
default: case PARTITION_STRATEGY_HASH:
/* HASH, or some other strategy */
break; break;
} }
@ -3241,10 +3228,6 @@ check_new_partition_bound(char *relname, Relation parent,
break; break;
} }
default:
elog(ERROR, "unexpected partition strategy: %d",
(int) key->strategy);
} }
if (overlap) if (overlap)
@ -3980,8 +3963,8 @@ make_partition_op_expr(PartitionKey key, int keynum,
key->partcollation[keynum]); key->partcollation[keynum]);
break; break;
default: case PARTITION_STRATEGY_HASH:
elog(ERROR, "invalid partitioning strategy"); Assert(false);
break; break;
} }

View File

@ -115,6 +115,12 @@ RelationBuildPartitionKey(Relation relation)
key->strategy = form->partstrat; key->strategy = form->partstrat;
key->partnatts = form->partnatts; 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 * We can rely on the first variable-length attribute being mapped to the
* relevant field of the catalog's C struct, because all previous * relevant field of the catalog's C struct, because all previous

View File

@ -827,6 +827,13 @@ typedef struct PartitionElem
int location; /* token location, or -1 if unknown */ int location; /* token location, or -1 if unknown */
} PartitionElem; } 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 * PartitionSpec - parse-time representation of a partition key specification
* *
@ -835,17 +842,11 @@ typedef struct PartitionElem
typedef struct PartitionSpec typedef struct PartitionSpec
{ {
NodeTag type; NodeTag type;
char *strategy; /* partitioning strategy ('hash', 'list' or PartitionStrategy strategy;
* 'range') */
List *partParams; /* List of PartitionElems */ List *partParams; /* List of PartitionElems */
int location; /* token location, or -1 if unknown */ int location; /* token location, or -1 if unknown */
} PartitionSpec; } 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 * PartitionBoundSpec - a partition bound specification
* *

View File

@ -78,7 +78,7 @@ struct RelOptInfo; /* avoid including pathnodes.h here */
*/ */
typedef struct PartitionBoundInfoData typedef struct PartitionBoundInfoData
{ {
char strategy; /* hash, list or range? */ PartitionStrategy strategy; /* hash, list or range? */
int ndatums; /* Length of the datums[] array */ int ndatums; /* Length of the datums[] array */
Datum **datums; Datum **datums;
PartitionRangeDatumKind **kind; /* The kind of each range bound datum; PartitionRangeDatumKind **kind; /* The kind of each range bound datum;

View File

@ -13,6 +13,7 @@
#include "access/attnum.h" #include "access/attnum.h"
#include "fmgr.h" #include "fmgr.h"
#include "nodes/parsenodes.h"
#include "nodes/pg_list.h" #include "nodes/pg_list.h"
#include "nodes/primnodes.h" #include "nodes/primnodes.h"
#include "partitioning/partdefs.h" #include "partitioning/partdefs.h"
@ -23,7 +24,7 @@
*/ */
typedef struct PartitionKeyData typedef struct PartitionKeyData
{ {
char strategy; /* partitioning strategy */ PartitionStrategy strategy; /* partitioning strategy */
int16 partnatts; /* number of columns in the partition key */ int16 partnatts; /* number of columns in the partition key */
AttrNumber *partattrs; /* attribute numbers of columns in the AttrNumber *partattrs; /* attribute numbers of columns in the
* partition key or 0 if it's an expr */ * partition key or 0 if it's an expr */