aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_utilcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r--src/backend/parser/parse_utilcmd.c62
1 files changed, 52 insertions, 10 deletions
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",