mirror of
https://github.com/postgres/postgres.git
synced 2025-05-21 00:02:53 -04:00
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:
parent
cf8b7d374a
commit
5fca91025e
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
src/backend/utils/cache/partcache.c
vendored
6
src/backend/utils/cache/partcache.c
vendored
@ -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
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user