Skip to content

Commit 8d4cd3b

Browse files
committed
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
1 parent 8d48e84 commit 8d4cd3b

File tree

4 files changed

+34
-2
lines changed

4 files changed

+34
-2
lines changed

src/backend/executor/execPartition.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
873873
* reference and make copy for this relation, converting stuff that
874874
* references attribute numbers to match this relation's.
875875
*
876-
* This duplicates much of the logic in ExecInitMerge(), so something
876+
* This duplicates much of the logic in ExecInitMerge(), so if something
877877
* changes there, look here too.
878878
*/
879879
if (node && node->operation == CMD_MERGE)
@@ -944,6 +944,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
944944
NULL);
945945
break;
946946
case CMD_DELETE:
947+
case CMD_NOTHING:
948+
/* Nothing to do */
947949
break;
948950

949951
default:

src/backend/executor/nodeModifyTable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3443,7 +3443,7 @@ ExecInitMerge(ModifyTableState *mtstate, EState *estate)
34433443
case CMD_NOTHING:
34443444
break;
34453445
default:
3446-
elog(ERROR, "unknown operation");
3446+
elog(ERROR, "unknown action in MERGE WHEN clause");
34473447
break;
34483448
}
34493449
}

src/test/regress/expected/merge.out

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,6 +1698,23 @@ SELECT * FROM pa_target ORDER BY tid;
16981698
14 | 140 | inserted by merge
16991699
(14 rows)
17001700

1701+
ROLLBACK;
1702+
-- bug #18871: ExecInitPartitionInfo()'s handling of DO NOTHING actions
1703+
BEGIN;
1704+
TRUNCATE pa_target;
1705+
MERGE INTO pa_target t
1706+
USING (VALUES (10, 100)) AS s(sid, delta)
1707+
ON t.tid = s.sid
1708+
WHEN NOT MATCHED THEN
1709+
INSERT VALUES (1, 10, 'inserted by merge')
1710+
WHEN MATCHED THEN
1711+
DO NOTHING;
1712+
SELECT * FROM pa_target ORDER BY tid, val;
1713+
tid | balance | val
1714+
-----+---------+-------------------
1715+
1 | 10 | inserted by merge
1716+
(1 row)
1717+
17011718
ROLLBACK;
17021719
DROP TABLE pa_target CASCADE;
17031720
-- The target table is partitioned in the same way, but this time by attaching

src/test/regress/sql/merge.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,19 @@ SELECT merge_func();
10601060
SELECT * FROM pa_target ORDER BY tid;
10611061
ROLLBACK;
10621062

1063+
-- bug #18871: ExecInitPartitionInfo()'s handling of DO NOTHING actions
1064+
BEGIN;
1065+
TRUNCATE pa_target;
1066+
MERGE INTO pa_target t
1067+
USING (VALUES (10, 100)) AS s(sid, delta)
1068+
ON t.tid = s.sid
1069+
WHEN NOT MATCHED THEN
1070+
INSERT VALUES (1, 10, 'inserted by merge')
1071+
WHEN MATCHED THEN
1072+
DO NOTHING;
1073+
SELECT * FROM pa_target ORDER BY tid, val;
1074+
ROLLBACK;
1075+
10631076
DROP TABLE pa_target CASCADE;
10641077

10651078
-- The target table is partitioned in the same way, but this time by attaching

0 commit comments

Comments
 (0)