git.postgresql.org Git - postgresql.git/commitdiff

git projects / postgresql.git / commitdiff
? search:
summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 0e86bad)
Fix MERGE with DO NOTHING actions into a partitioned table.
2025年3月29日 09:52:18 +0000 (09:52 +0000)
2025年3月29日 09:52:18 +0000 (09:52 +0000)
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


diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 105753cd2d17b8ede7f5e53b2b7fe8aa46ae7610..2fe21b7f2de737e0225b84a1f75d1792b1fa3867 100644 (file)
--- 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 56ef8815d2aed748367c1fea763765ef31abe602..1b7379c97a4fa3804e24a25faa99d26f5005e2a0 100644 (file)
--- 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 589943d63d62df8556f683f2f1b492fa0833eff5..a55c9696edc2f2b61d0a76e8b7839d11206c0e7a 100644 (file)
--- a/src/test/regress/expected/merge.out
+++ b/src/test/regress/expected/merge.out
@@ -1698,6 +1698,23 @@ SELECT * FROM pa_target ORDER BY tid;
14 | 140 | inserted by merge
(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
diff --git a/src/test/regress/sql/merge.sql b/src/test/regress/sql/merge.sql
index 61d76b7f8df8167e32e2568f3700145e57663ae1..d8e8f694b2c60067f246930f5e844b7af963d5d0 100644 (file)
--- 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
This is the main PostgreSQL git repository.
RSS Atom

AltStyle によって変換されたページ (->オリジナル) /