Avoid crash in ALTER TABLE not_partitioned DETACH PARTITION.

Amit Langote, reviewed and slightly changed by me.
This commit is contained in:
Robert Haas 2017-02-16 08:37:37 -05:00
parent 93e6e40574
commit 59407301a3
3 changed files with 25 additions and 14 deletions

View File

@ -133,7 +133,7 @@ static void transformConstraintAttrs(CreateStmtContext *cxt,
List *constraintList); List *constraintList);
static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column); static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
static void setSchemaName(char *context_schema, char **stmt_schema_name); static void setSchemaName(char *context_schema, char **stmt_schema_name);
static void transformAttachPartition(CreateStmtContext *cxt, PartitionCmd *cmd); static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd);
/* /*
@ -2654,12 +2654,12 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
} }
case AT_AttachPartition: case AT_AttachPartition:
case AT_DetachPartition:
{ {
PartitionCmd *partcmd = (PartitionCmd *) cmd->def; PartitionCmd *partcmd = (PartitionCmd *) cmd->def;
transformAttachPartition(&cxt, partcmd); transformPartitionCmd(&cxt, partcmd);
/* assign transformed value of the partition bound */
/* assign transformed values */
partcmd->bound = cxt.partbound; partcmd->bound = cxt.partbound;
} }
@ -3032,28 +3032,29 @@ setSchemaName(char *context_schema, char **stmt_schema_name)
} }
/* /*
* transformAttachPartition * transformPartitionCmd
* Analyze ATTACH PARTITION ... FOR VALUES ... * Analyze the ATTACH/DETACH PARTITION command
*
* In case of the ATTACH PARTITION command, cxt->partbound is set to the
* transformed value of cmd->bound.
*/ */
static void static void
transformAttachPartition(CreateStmtContext *cxt, PartitionCmd *cmd) transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd)
{ {
Relation parentRel = cxt->rel; Relation parentRel = cxt->rel;
/* /* the table must be partitioned */
* We are going to try to validate the partition bound specification
* against the partition key of rel, so it better have one.
*/
if (parentRel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) if (parentRel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("\"%s\" is not partitioned", errmsg("\"%s\" is not partitioned",
RelationGetRelationName(parentRel)))); RelationGetRelationName(parentRel))));
/* transform the values */ /* transform the partition bound, if any */
Assert(RelationGetPartitionKey(parentRel) != NULL); Assert(RelationGetPartitionKey(parentRel) != NULL);
cxt->partbound = transformPartitionBound(cxt->pstate, parentRel, if (cmd->bound != NULL)
cmd->bound); cxt->partbound = transformPartitionBound(cxt->pstate, parentRel,
cmd->bound);
} }
/* /*

View File

@ -3259,6 +3259,11 @@ DETAIL: "list_parted2" is already a child of "list_parted2".
-- --
-- DETACH PARTITION -- DETACH PARTITION
-- --
-- check that the table is partitioned at all
CREATE TABLE regular_table (a int);
ALTER TABLE regular_table DETACH PARTITION any_name;
ERROR: "regular_table" is not partitioned
DROP TABLE regular_table;
-- check that the partition being detached exists at all -- check that the partition being detached exists at all
ALTER TABLE list_parted2 DETACH PARTITION part_4; ALTER TABLE list_parted2 DETACH PARTITION part_4;
ERROR: relation "part_4" does not exist ERROR: relation "part_4" does not exist

View File

@ -2139,6 +2139,11 @@ ALTER TABLE list_parted2 ATTACH PARTITION list_parted2 FOR VALUES IN (0);
-- DETACH PARTITION -- DETACH PARTITION
-- --
-- check that the table is partitioned at all
CREATE TABLE regular_table (a int);
ALTER TABLE regular_table DETACH PARTITION any_name;
DROP TABLE regular_table;
-- check that the partition being detached exists at all -- check that the partition being detached exists at all
ALTER TABLE list_parted2 DETACH PARTITION part_4; ALTER TABLE list_parted2 DETACH PARTITION part_4;