From 587a9a2fcdfa7eec283679bbcf14a005f0e20a2c Mon Sep 17 00:00:00 2001
From: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Date: Wed, 29 Apr 2026 09:42:10 +0000
Subject: [PATCH v5 1/2] Fix errmsg issues in ALTER TABLE SPLIT/MERGE PARTITION

Apply review feedback for the SPLIT/MERGE PARTITION error messages:

* Use "cannot" instead of "can not".
* For SPLIT, use the requested form errmsg("cannot split partition
  \"%s\"", get_rel_name(splitPartOid)) so the errmsg names the old
  partition (consistent with the merge case naming the old partitions).
* Promote the duplicate secondary errmsg about an existing DEFAULT
  partition to errdetail.
* Capitalize and punctuate the errdetail and add the missing articles
  ("The lower bound ... to the upper bound ...").
* Distinguish the SPLIT and MERGE errhints by saying "old/new partition
  bounds" so the hints describe which partition bounds must be adjacent.
* Polish the DEFAULT-partition errhint wording.

Update the expected regression output to match.
---
 src/backend/commands/tablecmds.c              |  2 +-
 src/backend/parser/parse_utilcmd.c            | 12 +++---
 src/backend/partitioning/partbounds.c         | 19 +++++----
 src/test/regress/expected/partition_merge.out | 12 +++---
 src/test/regress/expected/partition_split.out | 39 ++++++++++---------
 5 files changed, 45 insertions(+), 39 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d8d7969bf30..88451c91448 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -23661,7 +23661,7 @@ SplitPartitionMoveRows(List **wqueue, Relation rel, Relation splitRel,
 			else
 				ereport(ERROR,
 						errcode(ERRCODE_CHECK_VIOLATION),
-						errmsg("can not find partition for split partition row"),
+						errmsg("cannot find partition for split partition row"),
 						errtable(splitRel));
 		}
 
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 37071502a9f..e27a558d7ad 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -3618,7 +3618,7 @@ transformPartitionCmdForSplit(CreateStmtContext *cxt, PartitionCmd *partcmd)
 						if (default_index != -1)
 							ereport(ERROR,
 									errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-									errmsg("DEFAULT partition should be one"),
+									errmsg("cannot specify more than one DEFAULT partition"),
 									parser_errposition(cxt->pstate, sps->name->location));
 
 						default_index = foreach_current_index(sps);
@@ -3645,9 +3645,9 @@ transformPartitionCmdForSplit(CreateStmtContext *cxt, PartitionCmd *partcmd)
 	if (isSplitPartDefault && default_index == -1)
 		ereport(ERROR,
 				errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-				errmsg("can not split DEFAULT partition \"%s\"",
+				errmsg("cannot split DEFAULT partition \"%s\"",
 					   get_rel_name(splitPartOid)),
-				errhint("To split DEFAULT partition one of the new partition must be DEFAULT."),
+				errhint("To split a DEFAULT partition, one of the new partitions must be DEFAULT."),
 				parser_errposition(cxt->pstate, ((SinglePartitionSpec *) linitial(splitlist))->name->location));
 
 	/*
@@ -3662,10 +3662,10 @@ transformPartitionCmdForSplit(CreateStmtContext *cxt, PartitionCmd *partcmd)
 
 		ereport(ERROR,
 				errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-				errmsg("can not split non-DEFAULT partition \"%s\"",
+				errmsg("cannot split non-DEFAULT partition \"%s\"",
 					   get_rel_name(splitPartOid)),
-				errmsg("new partition cannot be DEFAULT because DEFAULT partition \"%s\" already exists",
-					   get_rel_name(defaultPartOid)),
+				errdetail("New partition cannot be DEFAULT because DEFAULT partition \"%s\" already exists.",
+					  get_rel_name(defaultPartOid)),
 				parser_errposition(cxt->pstate, spsDef->name->location));
 	}
 
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 05250eda472..5891f14396e 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -4992,6 +4992,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
  * defaultPart:		true if one of the new partitions is DEFAULT
  * is_merge:		true indicates the operation is MERGE PARTITIONS;
  * 					false indicates the operation is SPLIT PARTITION.
+ * splitPartOid:	OID of the partition being split (only used when
+ * 					is_merge is false)
  * pstate:			pointer to ParseState struct for determining error position
  */
 static void
@@ -5002,6 +5004,7 @@ check_two_partitions_bounds_range(Relation parent,
 								  PartitionBoundSpec *second_bound,
 								  bool defaultPart,
 								  bool is_merge,
+								  Oid splitPartOid,
 								  ParseState *pstate)
 {
 	PartitionKey key = RelationGetPartitionKey(parent);
@@ -5030,20 +5033,20 @@ check_two_partitions_bounds_range(Relation parent,
 		if (is_merge)
 			ereport(ERROR,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-					errmsg("can not merge partition \"%s\" together with partition \"%s\"",
+					errmsg("cannot merge partition \"%s\" together with partition \"%s\"",
 						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errdetail("The lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
-					errhint("ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent."),
+					errhint("ALTER TABLE ... MERGE PARTITIONS requires the old partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
 		else
 			ereport(ERROR,
 					errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-					errmsg("can not split to partition \"%s\" together with partition \"%s\"",
-						   second_name->relname, first_name->relname),
-					errdetail("lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
+					errmsg("cannot split partition \"%s\"",
+						   get_rel_name(splitPartOid)),
+					errdetail("The lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\".",
 							  second_name->relname, first_name->relname),
-					errhint("ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent."),
+					errhint("ALTER TABLE ... SPLIT PARTITION requires the new partition bounds to be adjacent."),
 					parser_errposition(pstate, datum->location));
 	}
 }
@@ -5148,6 +5151,7 @@ calculate_partition_bound_for_merge(Relation parent,
 													  (PartitionBoundSpec *) list_nth(bounds, index),
 													  false,
 													  true,
+													  InvalidOid,
 													  pstate);
 				}
 
@@ -5851,6 +5855,7 @@ check_partitions_for_split(Relation parent,
 											  sps->name, sps->bound,
 											  createDefaultPart,
 											  false,
+											  splitPartOid,
 											  pstate);
 
 		spsPrev = sps;
diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out
index 883110e25d9..d941046eb28 100644
--- a/src/test/regress/expected/partition_merge.out
+++ b/src/test/regress/expected/partition_merge.out
@@ -34,16 +34,16 @@ HINT:  ALTER TABLE ... MERGE PARTITIONS can only merge partitions don't have sub
 -- DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022"
 -- (space between sections sales_jan2022 and sales_mar2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_jan2022, sales_mar2022) INTO sales_jan_mar2022;
-ERROR:  can not merge partition "sales_mar2022" together with partition "sales_jan2022"
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022"
-HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
+ERROR:  cannot merge partition "sales_mar2022" together with partition "sales_jan2022"
+DETAIL:  The lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_jan2022".
+HINT:  ALTER TABLE ... MERGE PARTITIONS requires the old partition bounds to be adjacent.
 -- ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
 -- DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
 -- (space between sections sales_dec2021 and sales_jan2022)
 ALTER TABLE sales_range MERGE PARTITIONS (sales_dec2021, sales_jan2022, sales_feb2022) INTO sales_dec_jan_feb2022;
-ERROR:  can not merge partition "sales_jan2022" together with partition "sales_dec2021"
-DETAIL:  lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021"
-HINT:  ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent.
+ERROR:  cannot merge partition "sales_jan2022" together with partition "sales_dec2021"
+DETAIL:  The lower bound of partition "sales_jan2022" is not equal to the upper bound of partition "sales_dec2021".
+HINT:  ALTER TABLE ... MERGE PARTITIONS requires the old partition bounds to be adjacent.
 -- ERROR:  partition with name "sales_feb2022" is already used
 ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, partitions_merge_schema.sales_feb2022) INTO sales_feb_mar_apr2022;
 ERROR:  partition with name "sales_feb2022" is already used
diff --git a/src/test/regress/expected/partition_split.out b/src/test/regress/expected/partition_split.out
index 43ca299648e..d00c0cc074e 100644
--- a/src/test/regress/expected/partition_split.out
+++ b/src/test/regress/expected/partition_split.out
@@ -106,11 +106,11 @@ ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO
   (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'),
    PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO ('2022-04-01'),
    PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'));
-ERROR:  can not split to partition "sales_mar2022" together with partition "sales_feb2022"
+ERROR:  cannot split partition "sales_feb_mar_apr2022"
 LINE 3:    PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022"
-HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
+DETAIL:  The lower bound of partition "sales_mar2022" is not equal to the upper bound of partition "sales_feb2022".
+HINT:  ALTER TABLE ... SPLIT PARTITION requires the new partition bounds to be adjacent.
 -- Tests for spaces between partitions, them should be executed without DEFAULT partition
 ALTER TABLE sales_range DETACH PARTITION sales_others;
 -- ERROR:  lower bound of partition "sales_feb2022" is not equal to lower bound of split partition "sales_feb_mar_apr2022"
@@ -467,11 +467,11 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
    PARTITION sales_error FOR VALUES FROM ('2021-12-30') TO ('2022-02-01'),
    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'),
    PARTITION sales_others DEFAULT);
-ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
+ERROR:  cannot split partition "sales_others"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-30') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
-HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
+DETAIL:  The lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
+HINT:  ALTER TABLE ... SPLIT PARTITION requires the new partition bounds to be adjacent.
 -- sales_error intersects with sales_feb2022 (upper bound)
 -- ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
 ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
@@ -479,11 +479,11 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
    PARTITION sales_error FOR VALUES FROM ('2022-01-01') TO ('2022-02-02'),
    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'),
    PARTITION sales_others DEFAULT);
-ERROR:  can not split to partition "sales_feb2022" together with partition "sales_error"
+ERROR:  cannot split partition "sales_others"
 LINE 4:    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO...
                                                     ^
-DETAIL:  lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error"
-HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
+DETAIL:  The lower bound of partition "sales_feb2022" is not equal to the upper bound of partition "sales_error".
+HINT:  ALTER TABLE ... SPLIT PARTITION requires the new partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (inside bound)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
@@ -491,11 +491,11 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
    PARTITION sales_error FOR VALUES FROM ('2021-12-10') TO ('2021-12-20'),
    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'),
    PARTITION sales_others DEFAULT);
-ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
+ERROR:  cannot split partition "sales_others"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-10') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
-HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
+DETAIL:  The lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
+HINT:  ALTER TABLE ... SPLIT PARTITION requires the new partition bounds to be adjacent.
 -- sales_error intersects with sales_dec2021 (exactly the same bounds)
 -- ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
 ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
@@ -503,21 +503,21 @@ ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
    PARTITION sales_error FOR VALUES FROM ('2021-12-01') TO ('2022-01-01'),
    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'),
    PARTITION sales_others DEFAULT);
-ERROR:  can not split to partition "sales_error" together with partition "sales_dec2021"
+ERROR:  cannot split partition "sales_others"
 LINE 3:    PARTITION sales_error FOR VALUES FROM ('2021-12-01') TO (...
                                                   ^
-DETAIL:  lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021"
-HINT:  ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent.
+DETAIL:  The lower bound of partition "sales_error" is not equal to the upper bound of partition "sales_dec2021".
+HINT:  ALTER TABLE ... SPLIT PARTITION requires the new partition bounds to be adjacent.
 -- ERROR:  can not split DEFAULT partition "sales_others"
 -- HINT:  To split DEFAULT partition one of the new partition must be DEFAULT.
 ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
   (PARTITION sales_dec2021 FOR VALUES FROM ('2021-12-01') TO ('2022-01-01'),
    PARTITION sales_jan2022 FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'),
    PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'));
-ERROR:  can not split DEFAULT partition "sales_others"
+ERROR:  cannot split DEFAULT partition "sales_others"
 LINE 2:   (PARTITION sales_dec2021 FOR VALUES FROM ('2021-12-01') TO...
                      ^
-HINT:  To split DEFAULT partition one of the new partition must be DEFAULT.
+HINT:  To split a DEFAULT partition, one of the new partitions must be DEFAULT.
 -- no error: bounds of sales_noerror are between sales_dec2021 and sales_feb2022
 ALTER TABLE sales_range SPLIT PARTITION sales_others INTO
   (PARTITION sales_dec2021 FOR VALUES FROM ('2021-12-01') TO ('2022-01-01'),
@@ -895,9 +895,10 @@ ALTER TABLE sales_list SPLIT PARTITION sales_all INTO
    PARTITION sales_east FOR VALUES IN ('Beijing', 'Delhi', 'Vladivostok'),
    PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv'),
    PARTITION sales_others2 DEFAULT);
-ERROR:  new partition cannot be DEFAULT because DEFAULT partition "sales_others" already exists
+ERROR:  cannot split non-DEFAULT partition "sales_all"
 LINE 5:    PARTITION sales_others2 DEFAULT);
                      ^
+DETAIL:  New partition cannot be DEFAULT because DEFAULT partition "sales_others" already exists.
 DROP TABLE sales_list;
 -- Test for non-symbolic comparison of values (numeric values '0' and '0.0' are equal).
 CREATE TABLE t (a numeric) PARTITION BY LIST (a);
@@ -941,7 +942,7 @@ ALTER TABLE sales_list SPLIT PARTITION sales_all INTO
    PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv'),
    PARTITION sales_others DEFAULT,
    PARTITION sales_others2 DEFAULT);
-ERROR:  DEFAULT partition should be one
+ERROR:  cannot specify more than one DEFAULT partition
 LINE 6:    PARTITION sales_others2 DEFAULT);
                      ^
 DROP TABLE sales_list;
-- 
2.43.0

