diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 38 | ||||
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 62 |
2 files changed, 89 insertions, 11 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 1fcdb25142f..ee7a89045c3 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -269,6 +269,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); PartitionElem *partelem; PartitionSpec *partspec; PartitionBoundSpec *partboundspec; + SinglePartitionSpec *singlepartspec; RoleSpec *rolespec; PublicationObjSpec *publicationobjectspec; struct SelectLimit *selectlimit; @@ -646,6 +647,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <partelem> part_elem %type <list> part_params %type <partboundspec> PartitionBoundSpec +%type <singlepartspec> SinglePartitionSpec +%type <list> partitions_list %type <list> hash_partbound %type <defelt> hash_partbound_elem @@ -777,7 +780,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); SAVEPOINT SCALAR SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHOW - SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SOURCE SQL_P STABLE STANDALONE_P + SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SPLIT SOURCE SQL_P STABLE STANDALONE_P START STATEMENT STATISTICS STDIN STDOUT STORAGE STORED STRICT_P STRING_P STRIP_P SUBSCRIPTION SUBSTRING SUPPORT SYMMETRIC SYSID SYSTEM_P SYSTEM_USER @@ -2307,6 +2310,23 @@ alter_table_cmds: | alter_table_cmds ',' alter_table_cmd { $$ = lappend($1, $3); } ; +partitions_list: + SinglePartitionSpec { $$ = list_make1($1); } + | partitions_list ',' SinglePartitionSpec { $$ = lappend($1, $3); } + ; + +SinglePartitionSpec: + PARTITION qualified_name PartitionBoundSpec + { + SinglePartitionSpec *n = makeNode(SinglePartitionSpec); + + n->name = $2; + n->bound = $3; + + $$ = n; + } + ; + partition_cmd: /* ALTER TABLE <name> ATTACH PARTITION <table_name> FOR VALUES */ ATTACH PARTITION qualified_name PartitionBoundSpec @@ -2351,6 +2371,20 @@ partition_cmd: n->def = (Node *) cmd; $$ = (Node *) n; } + /* ALTER TABLE <name> SPLIT PARTITION <partition_name> INTO () */ + | SPLIT PARTITION qualified_name INTO '(' partitions_list ')' + { + AlterTableCmd *n = makeNode(AlterTableCmd); + PartitionCmd *cmd = makeNode(PartitionCmd); + + n->subtype = AT_SplitPartition; + cmd->name = $3; + cmd->bound = NULL; + cmd->partlist = $6; + cmd->concurrent = false; + n->def = (Node *) cmd; + $$ = (Node *) n; + } /* ALTER TABLE <name> MERGE PARTITIONS () INTO <partition_name> */ | MERGE PARTITIONS '(' qualified_name_list ')' INTO qualified_name { @@ -17756,6 +17790,7 @@ unreserved_keyword: | SKIP | SNAPSHOT | SOURCE + | SPLIT | SQL_P | STABLE | STANDALONE_P @@ -18393,6 +18428,7 @@ bare_label_keyword: | SNAPSHOT | SOME | SOURCE + | SPLIT | SQL_P | STABLE | STANDALONE_P diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 48a23c7ca42..88a4a41186a 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -136,7 +136,7 @@ static void transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList); static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column); static void setSchemaName(const char *context_schema, char **stmt_schema_name); -static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd); +static void transformPartitionCmd(CreateStmtContext *cxt, PartitionBoundSpec *bound); static List *transformPartitionRangeBounds(ParseState *pstate, List *blist, Relation parent); static void validateInfiniteBounds(ParseState *pstate, List *blist); @@ -3416,6 +3416,43 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString, /* + * transformPartitionCmdForSplit + * Analyze the ALTER TABLLE ... SPLIT PARTITION command + * + * For each new partition sps->bound is set to the transformed value of bound. + * Does checks for bounds of new partitions. + */ +static void +transformPartitionCmdForSplit(CreateStmtContext *cxt, PartitionCmd *partcmd) +{ + Relation parent = cxt->rel; + Oid splitPartOid; + ListCell *listptr; + + if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("\"%s\" is not a partitioned table", RelationGetRelationName(parent)))); + + /* Transform partition bounds for all partitions in the list: */ + foreach(listptr, partcmd->partlist) + { + SinglePartitionSpec *sps = (SinglePartitionSpec *) lfirst(listptr); + + cxt->partbound = NULL; + transformPartitionCmd(cxt, sps->bound); + /* Assign transformed value of the partition bound. */ + sps->bound = cxt->partbound; + } + + splitPartOid = RangeVarGetRelid(partcmd->name, NoLock, false); + + /* Then we should check partitions with transformed bounds. */ + check_partitions_for_split(parent, splitPartOid, partcmd->name, partcmd->partlist, cxt->pstate); +} + + +/* * transformPartitionCmdForMerge * Analyze the ALTER TABLLE ... MERGE PARTITIONS command * @@ -3751,7 +3788,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, { PartitionCmd *partcmd = (PartitionCmd *) cmd->def; - transformPartitionCmd(&cxt, partcmd); + transformPartitionCmd(&cxt, partcmd->bound); /* assign transformed value of the partition bound */ partcmd->bound = cxt.partbound; } @@ -3759,6 +3796,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, newcmds = lappend(newcmds, cmd); break; + case AT_SplitPartition: case AT_MergePartitions: { PartitionCmd *partcmd = (PartitionCmd *) cmd->def; @@ -3767,7 +3805,11 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("list of new partitions should contains at least two items"))); - transformPartitionCmdForMerge(&cxt, partcmd); + + if (cmd->subtype == AT_SplitPartition) + transformPartitionCmdForSplit(&cxt, partcmd); + else + transformPartitionCmdForMerge(&cxt, partcmd); newcmds = lappend(newcmds, cmd); break; } @@ -4172,13 +4214,13 @@ setSchemaName(const char *context_schema, char **stmt_schema_name) /* * transformPartitionCmd - * Analyze the ATTACH/DETACH PARTITION command + * Analyze the ATTACH/DETACH/SPLIT PARTITION command * - * In case of the ATTACH PARTITION command, cxt->partbound is set to the - * transformed value of cmd->bound. + * In case of the ATTACH/SPLIT PARTITION command, cxt->partbound is set to the + * transformed value of bound. */ static void -transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd) +transformPartitionCmd(CreateStmtContext *cxt, PartitionBoundSpec *bound) { Relation parentRel = cxt->rel; @@ -4187,9 +4229,9 @@ transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd) case RELKIND_PARTITIONED_TABLE: /* transform the partition bound, if any */ Assert(RelationGetPartitionKey(parentRel) != NULL); - if (cmd->bound != NULL) + if (bound != NULL) cxt->partbound = transformPartitionBound(cxt->pstate, parentRel, - cmd->bound); + bound); break; case RELKIND_PARTITIONED_INDEX: @@ -4197,7 +4239,7 @@ transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd) * A partitioned index cannot have a partition bound set. ALTER * INDEX prevents that with its grammar, but not ALTER TABLE. */ - if (cmd->bound != NULL) + if (bound != NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("\"%s\" is not a partitioned table", |