BUG #19689: MERGE INSERT accepts a set-returning function during PREPARE but fails at EXECUTE

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: imchifan(at)163(dot)com
Subject: BUG #19689: MERGE INSERT accepts a set-returning function during PREPARE but fails at EXECUTE
Date: 2026-09-15 06:46:58
Message-ID: 19689-0a1b106035cd8a5b@postgresql.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 19689
Logged by: Qifan Liu
Email address: imchifan(at)163(dot)com
PostgreSQL version: 18.6
Operating system: Linux x86-64
Description:

Description
-----------
A set-returning function can be placed in the VALUES expression of a MERGE
WHEN NOT MATCHED INSERT action. PREPARE accepts the statement, but EXECUTE
fails with "set-valued function called in context that cannot accept a set"
and inserts no rows. This violates the analysis/execution contract: an
expression that the MERGE action cannot execute should be rejected while the
statement is analyzed, rather than being accepted into a prepared plan that
deterministically fails only when executed.

Impact: Applications can successfully prepare an unusable MERGE statement
and encounter a localized execution failure later. The statement inserts no
rows. This was reproduced consistently on all tested versions.

Steps to reproduce
------------------
```sql
CREATE TABLE merge_target (id integer);
CREATE TABLE merge_source (id integer);
INSERT INTO merge_source VALUES (1);

PREPARE merge_srf AS
MERGE INTO merge_target AS t
USING merge_source AS s
ON false
WHEN NOT MATCHED THEN
INSERT VALUES (generate_series(1, 2));

EXECUTE merge_srf;

SELECT count(*) AS rows_after_execution
FROM merge_target;
```

Actual result
-------------
```text
ERROR: set-valued function called in context that cannot accept a set

rows_after_execution
----------------------
0
(1 row)
```

Expected result
---------------
PREPARE should reject the set-returning function because a MERGE INSERT
action cannot execute that expression in this context. It should not create
a prepared statement that is accepted successfully and then
deterministically fails during EXECUTE.

Additional information
----------------------
The issue was reproduced on PostgreSQL 20devel, PostgreSQL 18.6, and
PostgreSQL 17.11. Inference: the MERGE INSERT action's specialized
expression handling does not propagate or enforce the restriction on
set-returning functions during analysis, leaving the executor to detect the
unsupported context.

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Alexandre Felipe 2026-09-15 06:57:32 Re: BUG #19687: ALTER SEQUENCE provokes error XX001 could not read blocks
Previous Message Andrey Rachitskiy 2026-09-15 04:26:02 Re: Detaching a child table makes an expression using it unrestorable