summaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y38
-rw-r--r--src/backend/parser/parse_utilcmd.c62
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",