diff options
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 62 |
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", |