Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc99ef18

Browse files
committed
Checks for ALTER TABLE ... SPLIT/MERGE PARTITIONS ... commands
Check that the target partition actually belongs to the parent table.Reported-by: Alexander LakhinDiscussion:https://postgr.es/m/cd842601-cf1a-9806-f7b7-d2509b93ba61%40gmail.comAuthor: Dmitry Koval
1 parentb1b13d2 commitc99ef18

File tree

6 files changed

+111
-21
lines changed

6 files changed

+111
-21
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21223,12 +21223,6 @@ ATExecSplitPartition(List **wqueue, AlteredTableInfo *tab, Relation rel,
2122321223
*/
2122421224
splitRel = table_openrv(cmd->name, AccessExclusiveLock);
2122521225

21226-
if (splitRel->rd_rel->relkind != RELKIND_RELATION)
21227-
ereport(ERROR,
21228-
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
21229-
errmsg("cannot split non-table partition \"%s\"",
21230-
RelationGetRelationName(splitRel))));
21231-
2123221226
splitRelOid = RelationGetRelid(splitRel);
2123321227

2123421228
/* Check descriptions of new partitions. */
@@ -21463,12 +21457,6 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel,
2146321457
*/
2146421458
mergingPartition = table_openrv(name, AccessExclusiveLock);
2146521459

21466-
if (mergingPartition->rd_rel->relkind != RELKIND_RELATION)
21467-
ereport(ERROR,
21468-
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
21469-
errmsg("cannot merge non-table partition \"%s\"",
21470-
RelationGetRelationName(mergingPartition))));
21471-
2147221460
/*
2147321461
* Checking that two partitions have the same name was before, in
2147421462
* function transformPartitionCmdForMerge().

‎src/backend/parser/parse_utilcmd.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include"catalog/heap.h"
3333
#include"catalog/index.h"
3434
#include"catalog/namespace.h"
35+
#include"catalog/partition.h"
3536
#include"catalog/pg_am.h"
3637
#include"catalog/pg_collation.h"
3738
#include"catalog/pg_constraint.h"
@@ -3415,6 +3416,39 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
34153416
}
34163417

34173418

3419+
/*
3420+
* checkPartition
3421+
*Check that partRelOid is an oid of partition of the parent table rel
3422+
*/
3423+
staticvoid
3424+
checkPartition(Relationrel,OidpartRelOid)
3425+
{
3426+
RelationpartRel;
3427+
3428+
partRel=relation_open(partRelOid,AccessShareLock);
3429+
3430+
if (partRel->rd_rel->relkind!=RELKIND_RELATION)
3431+
ereport(ERROR,
3432+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
3433+
errmsg("\"%s\" is not a table",
3434+
RelationGetRelationName(partRel))));
3435+
3436+
if (!partRel->rd_rel->relispartition)
3437+
ereport(ERROR,
3438+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
3439+
errmsg("\"%s\" is not a partition",
3440+
RelationGetRelationName(partRel))));
3441+
3442+
if (get_partition_parent(partRelOid, false)!=RelationGetRelid(rel))
3443+
ereport(ERROR,
3444+
(errcode(ERRCODE_UNDEFINED_TABLE),
3445+
errmsg("relation \"%s\" is not a partition of relation \"%s\"",
3446+
RelationGetRelationName(partRel),
3447+
RelationGetRelationName(rel))));
3448+
3449+
relation_close(partRel,AccessShareLock);
3450+
}
3451+
34183452
/*
34193453
* transformPartitionCmdForSplit
34203454
*Analyze the ALTER TABLLE ... SPLIT PARTITION command
@@ -3447,6 +3481,8 @@ transformPartitionCmdForSplit(CreateStmtContext *cxt, PartitionCmd *partcmd)
34473481

34483482
splitPartOid=RangeVarGetRelid(partcmd->name,NoLock, false);
34493483

3484+
checkPartition(parent,splitPartOid);
3485+
34503486
/* Then we should check partitions with transformed bounds. */
34513487
check_partitions_for_split(parent,splitPartOid,partcmd->name,partcmd->partlist,cxt->pstate);
34523488
}
@@ -3509,6 +3545,9 @@ transformPartitionCmdForMerge(CreateStmtContext *cxt, PartitionCmd *partcmd)
35093545
partOid=RangeVarGetRelid(name,NoLock, false);
35103546
if (partOid==defaultPartOid)
35113547
isDefaultPart= true;
3548+
3549+
checkPartition(parent,partOid);
3550+
35123551
partOids=lappend_oid(partOids,partOid);
35133552
}
35143553

‎src/test/regress/expected/partition_merge.out

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_fe
2525
ERROR: partition with name "sales_feb2022" already used
2626
LINE 1: ...e MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_feb2...
2727
^
28-
-- ERROR:cannot merge non-table partition "sales_apr2022"
28+
-- ERROR:"sales_apr2022" is not a table
2929
ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_apr2022) INTO sales_feb_mar_apr2022;
30-
ERROR:cannot merge non-table partition "sales_apr2022"
30+
ERROR:"sales_apr2022" is not a table
3131
-- ERROR: invalid partitions order, partition "sales_mar2022" can not be merged
3232
-- (space between sections sales_jan2022 and sales_mar2022)
3333
ALTER TABLE sales_range MERGE PARTITIONS (sales_jan2022, sales_mar2022) INTO sales_jan_mar2022;
@@ -590,12 +590,12 @@ CREATE TABLE sales_nord2 PARTITION OF sales_list2 FOR VALUES IN ('Oslo', 'St. Pe
590590
CREATE TABLE sales_others2 PARTITION OF sales_list2 DEFAULT;
591591
CREATE TABLE sales_external (LIKE sales_list);
592592
CREATE TABLE sales_external2 (vch VARCHAR(5));
593-
-- ERROR:partition bound for relation"sales_external" isnull
593+
-- ERROR: "sales_external" isnot a partition
594594
ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_external) INTO sales_all;
595-
ERROR:partition bound for relation"sales_external" isnull
596-
-- ERROR:partition bound for relation"sales_external2" isnull
595+
ERROR: "sales_external" isnot a partition
596+
-- ERROR: "sales_external2" isnot a partition
597597
ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_external2) INTO sales_all;
598-
ERROR:partition bound for relation"sales_external2" isnull
598+
ERROR: "sales_external2" isnot a partition
599599
-- ERROR: relation "sales_nord2" is not a partition of relation "sales_list"
600600
ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_nord2, sales_east) INTO sales_all;
601601
ERROR: relation "sales_nord2" is not a partition of relation "sales_list"
@@ -729,4 +729,21 @@ SELECT * FROM sales_list WHERE salesman_name = 'Ivanov';
729729
RESET enable_seqscan;
730730
DROP TABLE sales_list;
731731
--
732+
-- Try to MERGE partitions of another table.
733+
--
734+
CREATE TABLE t1 (i int, a int, b int, c int) PARTITION BY RANGE (a, b);
735+
CREATE TABLE t1p1 PARTITION OF t1 FOR VALUES FROM (1, 1) TO (1, 2);
736+
CREATE TABLE t2 (i int, t text) PARTITION BY RANGE (t);
737+
CREATE TABLE t2pa PARTITION OF t2 FOR VALUES FROM ('A') TO ('C');
738+
CREATE TABLE t3 (i int, t text);
739+
-- ERROR: relation "t1p1" is not a partition of relation "t2"
740+
ALTER TABLE t2 MERGE PARTITIONS (t1p1, t2pa) INTO t2p;
741+
ERROR: relation "t1p1" is not a partition of relation "t2"
742+
-- ERROR: "t3" is not a partition
743+
ALTER TABLE t2 MERGE PARTITIONS (t2pa, t3) INTO t2p;
744+
ERROR: "t3" is not a partition
745+
DROP TABLE t3;
746+
DROP TABLE t2;
747+
DROP TABLE t1;
748+
--
732749
DROP SCHEMA partitions_merge_schema;

‎src/test/regress/expected/partition_split.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,4 +1414,17 @@ SELECT * FROM sales_others;
14141414

14151415
DROP TABLE sales_range;
14161416
--
1417+
-- Try to SPLIT partition of another table.
1418+
--
1419+
CREATE TABLE t1(i int, t text) PARTITION BY LIST (t);
1420+
CREATE TABLE t1pa PARTITION OF t1 FOR VALUES IN ('A');
1421+
CREATE TABLE t2 (i int, t text) PARTITION BY RANGE (t);
1422+
-- ERROR: relation "t1pa" is not a partition of relation "t2"
1423+
ALTER TABLE t2 SPLIT PARTITION t1pa INTO
1424+
(PARTITION t2a FOR VALUES FROM ('A') TO ('B'),
1425+
PARTITION t2b FOR VALUES FROM ('B') TO ('C'));
1426+
ERROR: relation "t1pa" is not a partition of relation "t2"
1427+
DROP TABLE t2;
1428+
DROP TABLE t1;
1429+
--
14171430
DROP SCHEMA partition_split_schema;

‎src/test/regress/sql/partition_merge.sql

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ CREATE TABLE sales_others PARTITION OF sales_range DEFAULT;
2828

2929
-- ERROR: partition with name "sales_feb2022" already used
3030
ALTERTABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_feb2022) INTO sales_feb_mar_apr2022;
31-
-- ERROR:cannot merge non-table partition "sales_apr2022"
31+
-- ERROR:"sales_apr2022" is not a table
3232
ALTERTABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_apr2022) INTO sales_feb_mar_apr2022;
3333
-- ERROR: invalid partitions order, partition "sales_mar2022" can not be merged
3434
-- (space between sections sales_jan2022 and sales_mar2022)
@@ -350,9 +350,9 @@ CREATE TABLE sales_others2 PARTITION OF sales_list2 DEFAULT;
350350
CREATETABLEsales_external (LIKE sales_list);
351351
CREATETABLEsales_external2 (vchVARCHAR(5));
352352

353-
-- ERROR:partition bound for relation"sales_external" isnull
353+
-- ERROR: "sales_external" isnot a partition
354354
ALTERTABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_external) INTO sales_all;
355-
-- ERROR:partition bound for relation"sales_external2" isnull
355+
-- ERROR: "sales_external2" isnot a partition
356356
ALTERTABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_external2) INTO sales_all;
357357
-- ERROR: relation "sales_nord2" is not a partition of relation "sales_list"
358358
ALTERTABLE sales_list MERGE PARTITIONS (sales_west, sales_nord2, sales_east) INTO sales_all;
@@ -426,5 +426,23 @@ RESET enable_seqscan;
426426

427427
DROPTABLE sales_list;
428428

429+
--
430+
-- Try to MERGE partitions of another table.
431+
--
432+
CREATETABLEt1 (iint, aint, bint, cint) PARTITION BY RANGE (a, b);
433+
CREATETABLEt1p1 PARTITION OF t1 FORVALUESFROM (1,1) TO (1,2);
434+
CREATETABLEt2 (iint, ttext) PARTITION BY RANGE (t);
435+
CREATETABLEt2pa PARTITION OF t2 FORVALUESFROM ('A') TO ('C');
436+
CREATETABLEt3 (iint, ttext);
437+
438+
-- ERROR: relation "t1p1" is not a partition of relation "t2"
439+
ALTERTABLE t2 MERGE PARTITIONS (t1p1, t2pa) INTO t2p;
440+
-- ERROR: "t3" is not a partition
441+
ALTERTABLE t2 MERGE PARTITIONS (t2pa, t3) INTO t2p;
442+
443+
DROPTABLE t3;
444+
DROPTABLE t2;
445+
DROPTABLE t1;
446+
429447
--
430448
DROPSCHEMA partitions_merge_schema;

‎src/test/regress/sql/partition_split.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,5 +829,20 @@ SELECT * FROM sales_others;
829829

830830
DROPTABLE sales_range;
831831

832+
--
833+
-- Try to SPLIT partition of another table.
834+
--
835+
CREATETABLEt1(iint, ttext) PARTITION BY LIST (t);
836+
CREATETABLEt1pa PARTITION OF t1 FORVALUESIN ('A');
837+
CREATETABLEt2 (iint, ttext) PARTITION BY RANGE (t);
838+
839+
-- ERROR: relation "t1pa" is not a partition of relation "t2"
840+
ALTERTABLE t2 SPLIT PARTITION t1pa INTO
841+
(PARTITION t2a FORVALUESFROM ('A') TO ('B'),
842+
PARTITION t2b FORVALUESFROM ('B') TO ('C'));
843+
844+
DROPTABLE t2;
845+
DROPTABLE t1;
846+
832847
--
833848
DROPSCHEMA partition_split_schema;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp