Skip to content

Commit 2530367

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 8afec4e commit 2530367

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
@@ -872,7 +872,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
872872
* reference and make copy for this relation, converting stuff that
873873
* references attribute numbers to match this relation's.
874874
*
875-
* This duplicates much of the logic in ExecInitMerge(), so something
875+
* This duplicates much of the logic in ExecInitMerge(), so if something
876876
* changes there, look here too.
877877
*/
878878
if (node && node->operation == CMD_MERGE)
@@ -952,6 +952,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
952952
NULL);
953953
break;
954954
case CMD_DELETE:
955+
case CMD_NOTHING:
956+
/* Nothing to do */
955957
break;
956958

957959
default:

src/backend/executor/nodeModifyTable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3600,7 +3600,7 @@ ExecInitMerge(ModifyTableState *mtstate, EState *estate)
36003600
case CMD_NOTHING:
36013601
break;
36023602
default:
3603-
elog(ERROR, "unknown operation");
3603+
elog(ERROR, "unknown action in MERGE WHEN clause");
36043604
break;
36053605
}
36063606
}

src/test/regress/expected/merge.out

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,23 @@ SELECT * FROM pa_target ORDER BY tid;
20582058
15 | 1500 | initial
20592059
(8 rows)
20602060

2061+
ROLLBACK;
2062+
-- bug #18871: ExecInitPartitionInfo()'s handling of DO NOTHING actions
2063+
BEGIN;
2064+
TRUNCATE pa_target;
2065+
MERGE INTO pa_target t
2066+
USING (VALUES (10, 100)) AS s(sid, delta)
2067+
ON t.tid = s.sid
2068+
WHEN NOT MATCHED THEN
2069+
INSERT VALUES (1, 10, 'inserted by merge')
2070+
WHEN MATCHED THEN
2071+
DO NOTHING;
2072+
SELECT * FROM pa_target ORDER BY tid, val;
2073+
tid | balance | val
2074+
-----+---------+-------------------
2075+
1 | 10 | inserted by merge
2076+
(1 row)
2077+
20612078
ROLLBACK;
20622079
DROP TABLE pa_target CASCADE;
20632080
-- 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
@@ -1269,6 +1269,19 @@ MERGE INTO pa_target t
12691269
SELECT * FROM pa_target ORDER BY tid;
12701270
ROLLBACK;
12711271

1272+
-- bug #18871: ExecInitPartitionInfo()'s handling of DO NOTHING actions
1273+
BEGIN;
1274+
TRUNCATE pa_target;
1275+
MERGE INTO pa_target t
1276+
USING (VALUES (10, 100)) AS s(sid, delta)
1277+
ON t.tid = s.sid
1278+
WHEN NOT MATCHED THEN
1279+
INSERT VALUES (1, 10, 'inserted by merge')
1280+
WHEN MATCHED THEN
1281+
DO NOTHING;
1282+
SELECT * FROM pa_target ORDER BY tid, val;
1283+
ROLLBACK;
1284+
12721285
DROP TABLE pa_target CASCADE;
12731286

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

0 commit comments

Comments
 (0)