Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1olpQ8-0001yO-Bh for pgsql-hackers@arkaria.postgresql.org; Fri, 21 Oct 2022 10:38:33 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1olpQ6-00038a-O9 for pgsql-hackers@arkaria.postgresql.org; Fri, 21 Oct 2022 10:38:30 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1olpQ6-00037j-3m for pgsql-hackers@lists.postgresql.org; Fri, 21 Oct 2022 10:38:30 +0000 Received: from wout1-smtp.messagingengine.com ([64.147.123.24]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1olpQ3-0001xg-B1 for pgsql-hackers@lists.postgresql.org; Fri, 21 Oct 2022 10:38:29 +0000 Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.west.internal (Postfix) with ESMTP id 1C27532004F8 for ; Fri, 21 Oct 2022 06:38:24 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Fri, 21 Oct 2022 06:38:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:date:feedback-id:feedback-id:from:from:in-reply-to :in-reply-to:message-id:mime-version:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; t=1666348703; x=1666435103; bh=D/yygqzD133ye pyXW+Du5NdSGp/H3YKV67PSsS9StO4=; b=UDjbr4rt5hmlRaBf/Bqt2HLeh9oJb aenxnfmSg8zUY6pF1vtQ5MiX2CzXZWRUwinJP+u2V/xH8TkaQeN4Wx2G8IDZaDjb nUPAO1buPy0ELonbgif2ZbCMPlqxO8Qa3B5Xwh5sNmO4d8ogb+OIyHg+ZxaSMNNg pKxJzjsJ+lMlZgSyJmoedigKch+kML93uzK+AAJ11DOZWp12ud9jwn9j6vPW/lIx 4Rbibjy1r0HK7acSWxHygkyYkRqiD35ucpyKtjt0puqaFnfKJ1h8Q8ArvGvGOzC0 mJKtO4LLvKfutz7CCaH1GScZhNmrEtYx6Yb6/qI67YBG3dinpy9fgA2ig== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrfeelkedgvdelucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfggtggugfgjsehmkeerredttdejnecuhfhrohhmpeetlhhvrghr ohcujfgvrhhrvghrrgcuoegrlhhvhhgvrhhrvgesrghlvhhhrdhnohdqihhprdhorhhgqe enucggtffrrghtthgvrhhnpeetvdfhteeuueekfefhfedugeffhfehhfdvleffleetkeeg geefhffggeekjedtudenucffohhmrghinhepvghnthgvrhhprhhishgvuggsrdgtohhmne cuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprghlvhhh vghrrhgvsegrlhhvhhdrnhhoqdhiphdrohhrgh X-ME-Proxy: Feedback-ID: ia2694551:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Fri, 21 Oct 2022 06:38:23 -0400 (EDT) Received: by perhan.alvh.no-ip.org (Postfix, from userid 1000) id 8833E7A; Fri, 21 Oct 2022 12:38:21 +0200 (CEST) Date: Fri, 21 Oct 2022 12:38:21 +0200 From: Alvaro Herrera To: Pg Hackers Subject: Re: parse partition strategy string in gram.y Message-ID: <20221021103821.amshtbitswqlb4yn@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="d4ylx4ich2eovwuz" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20221021093216.ffupd7epy2mytkux@alvherre.pgsql> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --d4ylx4ich2eovwuz Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit headerscheck fail, fixed here. -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/ #error "Operator lives in the wrong universe" ("Use of cookies in real-time system development", M. Gleixner, M. Mc Guire) --d4ylx4ich2eovwuz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v3-0001-have-gram.y-resolve-partition-strategy-names.patch" From c434020fc07616cdd13017135819083186d33256 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Thu, 20 Oct 2022 12:29:18 +0200 Subject: [PATCH v3] have gram.y resolve partition strategy names --- src/backend/commands/tablecmds.c | 35 +++++++++------------------ src/backend/parser/gram.y | 22 ++++++++++++++++- src/backend/partitioning/partbounds.c | 27 ++++----------------- src/backend/utils/cache/partcache.c | 6 +++++ src/include/nodes/parsenodes.h | 15 ++++++------ src/include/partitioning/partbounds.h | 2 +- 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 20135ef1b0..e07fd747f7 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 737bd2d06d..6ca23f88c4 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; @@ -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 * convert PUBLICATIONOBJ_CONTINUATION into appropriate PublicationObjSpecType. diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index 0823fa7b1d..29643fb4ab 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 afa99c5d03..8f3e411476 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_HASH && + key->strategy != PARTITION_STRATEGY_LIST && + key->strategy != PARTITION_STRATEGY_RANGE) + 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 633e7671b3..99cba300f3 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 1f5b706d83..9af4b1b5c7 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 3394e1fcdb..88b5bd7b2b 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 */ -- 2.30.2 --d4ylx4ich2eovwuz--