summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDean Rasheed <dean.a.rasheed@gmail.com>2025-03-29 09:52:18 +0000
committerDean Rasheed <dean.a.rasheed@gmail.com>2025-03-29 09:52:18 +0000
commit14a33d3f0ae6dcbe9b91d33f64b795c2aef6a870 (patch)
tree20f1861efa70fbcca348ded79000dee1ff004d7b
parent0e86bad380997b3b6d39191df31ad7c1945ab389 (diff)
Fix MERGE with DO NOTHING actions into a partitioned table.
ExecInitPartitionInfo() duplicates much of the logic in ExecInitMerge(), except that it failed to handle DO NOTHING actions. This would cause an "unknown action in MERGE WHEN clause" error if a MERGE with any DO NOTHING actions attempted to insert into a partition not already initialised by ExecInitModifyTable(). Bug: #18871 Reported-by: Alexander Lakhin <exclusion@gmail.com> Author: Tender Wang <tndrwang@gmail.com> Reviewed-by: Gurjeet Singh <gurjeet@singh.im> Discussion: https://postgr.es/m/18871-b44e3c96de3bd2e8%40postgresql.org Backpatch-through: 15
-rw-r--r--src/backend/executor/execPartition.c4
-rw-r--r--src/backend/executor/nodeModifyTable.c2
-rw-r--r--src/test/regress/expected/merge.out17
-rw-r--r--src/test/regress/sql/merge.sql13
4 files changed, 34 insertions, 2 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 105753cd2d1..2fe21b7f2de 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -871,7 +871,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
* reference and make copy for this relation, converting stuff that
* references attribute numbers to match this relation's.
*
- * This duplicates much of the logic in ExecInitMerge(), so something
+ * This duplicates much of the logic in ExecInitMerge(), so if something
* changes there, look here too.
*/
if (node && node->operation == CMD_MERGE)
@@ -941,6 +941,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
NULL);
break;
case CMD_DELETE:
+ case CMD_NOTHING:
+ /* Nothing to do */
break;
default:
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 56ef8815d2a..1b7379c97a4 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -3424,7 +3424,7 @@ ExecInitMerge(ModifyTableState *mtstate, EState *estate)
case CMD_NOTHING:
break;
default:
- elog(ERROR, "unknown operation");
+ elog(ERROR, "unknown action in MERGE WHEN clause");
break;
}
}
diff --git a/src/test/regress/expected/merge.out b/src/test/regress/expected/merge.out
index 589943d63d6..a55c9696edc 100644
--- a/src/test/regress/expected/merge.out
+++ b/src/test/regress/expected/merge.out
@@ -1699,6 +1699,23 @@ SELECT * FROM pa_target ORDER BY tid;
(14 rows)
ROLLBACK;
+-- bug #18871: ExecInitPartitionInfo()'s handling of DO NOTHING actions
+BEGIN;
+TRUNCATE pa_target;
+MERGE INTO pa_target t
+ USING (VALUES (10, 100)) AS s(sid, delta)
+ ON t.tid = s.sid
+ WHEN NOT MATCHED THEN
+ INSERT VALUES (1, 10, 'inserted by merge')
+ WHEN MATCHED THEN
+ DO NOTHING;
+SELECT * FROM pa_target ORDER BY tid, val;
+ tid | balance | val
+-----+---------+-------------------
+ 1 | 10 | inserted by merge
+(1 row)
+
+ROLLBACK;
DROP TABLE pa_target CASCADE;
-- The target table is partitioned in the same way, but this time by attaching
-- partitions which have columns in different order, dropped columns etc.
diff --git a/src/test/regress/sql/merge.sql b/src/test/regress/sql/merge.sql
index 61d76b7f8df..d8e8f694b2c 100644
--- a/src/test/regress/sql/merge.sql
+++ b/src/test/regress/sql/merge.sql
@@ -1060,6 +1060,19 @@ SELECT merge_func();
SELECT * FROM pa_target ORDER BY tid;
ROLLBACK;
+-- bug #18871: ExecInitPartitionInfo()'s handling of DO NOTHING actions
+BEGIN;
+TRUNCATE pa_target;
+MERGE INTO pa_target t
+ USING (VALUES (10, 100)) AS s(sid, delta)
+ ON t.tid = s.sid
+ WHEN NOT MATCHED THEN
+ INSERT VALUES (1, 10, 'inserted by merge')
+ WHEN MATCHED THEN
+ DO NOTHING;
+SELECT * FROM pa_target ORDER BY tid, val;
+ROLLBACK;
+
DROP TABLE pa_target CASCADE;
-- The target table is partitioned in the same way, but this time by attaching