0002-Fix-cross-partition-merge-fail.patch

text/plain

Filename: 0002-Fix-cross-partition-merge-fail.patch
Type: text/plain
Part: 0
Message: Re: BUG #18871: Cross-partition MERGE fails with unclear internal error

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch 0002
File+
src/backend/executor/execPartition.c 1 0
src/backend/executor/nodeModifyTable.c 4 0
src/test/regress/expected/partition_prune.out 28 0
src/test/regress/sql/partition_prune.sql 14 0
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 84ccd7d457d..8d1e3c0624f 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -956,6 +956,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
 												  NULL);
 					break;
 				case CMD_DELETE:
+				case CMD_NOTHING:
 					break;
 
 				default:
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 87c820276a8..381847cfdf3 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -3712,6 +3712,10 @@ ExecInitMerge(ModifyTableState *mtstate, EState *estate)
 				lappend(resultRelInfo->ri_MergeActions[action->matchKind],
 						action_state);
 
+			/*
+			 * ExecInitPartitionInfo() duplicates much of the logic here, so if
+			 * you change something here, look there, too.
+			 */
 			switch (action->commandType)
 			{
 				case CMD_INSERT:
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index 0bf35260b46..2f3e5db8252 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -4694,6 +4694,34 @@ table part_abc_view;
  2 | c | t
 (2 rows)
 
+rollback;
+-- Cross-partition merge
+begin;
+explain (costs off)
+merge into part_abc_view pt
+using (select 3 as a) as q on pt.a = q.a
+WHEN NOT MATCHED THEN INSERT VALUES (1, 2)
+WHEN MATCHED THEN DO NOTHING;
+              QUERY PLAN              
+--------------------------------------
+ Merge on part_abc
+   ->  Nested Loop Left Join
+         ->  Result
+         ->  Result
+               One-Time Filter: false
+(5 rows)
+
+merge into part_abc_view pt
+using (select 3 as a) as q on pt.a = q.a
+WHEN NOT MATCHED THEN INSERT VALUES (1, 2)
+WHEN MATCHED THEN DO NOTHING;
+table part_abc_view;
+ a | b | c 
+---+---+---
+ 1 | 2 | 
+ 2 | c | t
+(2 rows)
+
 rollback;
 -- A case with multiple ModifyTable nodes.
 begin;
diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql
index f6db9479f54..339c8d9a4e8 100644
--- a/src/test/regress/sql/partition_prune.sql
+++ b/src/test/regress/sql/partition_prune.sql
@@ -1413,6 +1413,20 @@ when not matched then insert values (1, 'd', false) returning pt.a;
 table part_abc_view;
 rollback;
 
+-- Cross-partition merge
+begin;
+explain (costs off)
+merge into part_abc_view pt
+using (select 3 as a) as q on pt.a = q.a
+WHEN NOT MATCHED THEN INSERT VALUES (1, 2)
+WHEN MATCHED THEN DO NOTHING;
+merge into part_abc_view pt
+using (select 3 as a) as q on pt.a = q.a
+WHEN NOT MATCHED THEN INSERT VALUES (1, 2)
+WHEN MATCHED THEN DO NOTHING;
+table part_abc_view;
+rollback;
+
 -- A case with multiple ModifyTable nodes.
 begin;
 create table part_abc_log (action text, a int, b text, c bool);