public inbox for [email protected]
help / color / mirror / Atom feedBUG #19484: Segmentation fault triggered by FDW
32+ messages / 8 participants
[nested] [flat]
* BUG #19484: Segmentation fault triggered by FDW
@ 2026-05-18 06:38 PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: PG Bug reporting form @ 2026-05-18 06:38 UTC (permalink / raw)
To: [email protected]; +Cc: [email protected]
The following bug has been logged on the website:
Bug reference: 19484
Logged by: Chi Zhang
Email address: [email protected]
PostgreSQL version: 18.4
Operating system: Ubuntu 24.04
Description:
Hi,
I found the following test case triggers a segmentation fault:
```
\set ON_ERROR_STOP on
CREATE EXTENSION postgres_fdw;
CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (
host '/path/to/pg_socket',
port '5432',
dbname :'dbname'
);
CREATE USER MAPPING FOR postgres SERVER loopback
OPTIONS (user 'postgres');
CREATE SCHEMA r;
CREATE TABLE r.remote_p2 (a int NOT NULL, b int);
CREATE TABLE pt (a int NOT NULL, b int) PARTITION BY LIST (a);
CREATE TABLE pt_p1 PARTITION OF pt FOR VALUES IN (1);
CREATE FOREIGN TABLE pt_p2 PARTITION OF pt FOR VALUES IN (2)
SERVER loopback
OPTIONS (schema_name 'r', table_name 'remote_p2');
INSERT INTO pt_p1 VALUES (1, 10);
INSERT INTO r.remote_p2 VALUES (2, 20);
SET plan_cache_mode = force_generic_plan;
PREPARE upd(int) AS
UPDATE pt
SET b = b + 1
WHERE a = $1
RETURNING tableoid::regclass, a, b;
EXPLAIN (costs off) EXECUTE upd(2);
EXECUTE upd(2);
SELECT * FROM r.remote_p2 ORDER BY a;
```
This is the log:
```
2026-05-18 13:40:41.888 CST [21729] LOG: database system is ready to accept
connections
2026-05-18 13:41:03.317 CST [21932] LOG: unexpected EOF on client
connection with an open transaction
2026-05-18 13:41:03.317 CST [21729] LOG: client backend (PID 21931) was
terminated by signal 11: Segmentation fault
2026-05-18 13:41:03.317 CST [21729] DETAIL: Failed process was running:
EXECUTE upd(2);
2026-05-18 13:41:03.317 CST [21729] LOG: terminating any other active
server processes
2026-05-18 13:41:03.319 CST [21729] LOG: all server processes terminated;
reinitializing
2026-05-18 13:41:03.345 CST [21936] LOG: database system was interrupted;
last known up at 2026-05-18 13:40:41 CST
2026-05-18 13:41:03.509 CST [21936] LOG: database system was not properly
shut down; automatic recovery in progress
2026-05-18 13:41:03.513 CST [21936] LOG: redo starts at 0/98371040
2026-05-18 13:41:03.531 CST [21936] LOG: invalid record length at
0/987B6E68: expected at least 24, got 0
2026-05-18 13:41:03.531 CST [21936] LOG: redo done at 0/987B6E40 system
usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.01 s
2026-05-18 13:41:03.537 CST [21937] LOG: checkpoint starting:
end-of-recovery fast wait
2026-05-18 13:41:03.654 CST [21937] LOG: checkpoint complete:
end-of-recovery fast wait: wrote 975 buffers (6.0%), wrote 3 SLRU buffers; 0
WAL file(s) added, 0 removed, 0
recycled; write=0.081 s, sync=0.030 s, total=0.121 s; sync files=325,
longest=0.005 s, average=0.001 s; distance=4375 kB, estimate=4375 kB;
lsn=0/987B6E68, redo lsn=0/987B6E68
2026-05-18 13:41:03.660 CST [21729] LOG: database system is ready to
accept connections
```
I built the Postgres from source code
901ed9b352b41f034e17bc540725082a488fce31 of github commit.
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
@ 2026-05-20 12:37 ` Ayush Tiwari <[email protected]>
2026-05-20 17:46 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
0 siblings, 2 replies; 32+ messages in thread
From: Ayush Tiwari @ 2026-05-20 12:37 UTC (permalink / raw)
To: [email protected]; [email protected]; Etsuro Fujita <[email protected]>
Hi,
On Wed, 20 May 2026 at 03:59, PG Bug reporting form <[email protected]>
wrote:
> The following bug has been logged on the website:
>
> Bug reference: 19484
> Logged by: Chi Zhang
> Email address: [email protected]
> PostgreSQL version: 18.4
> Operating system: Ubuntu 24.04
> Description:
>
> Hi,
>
> I found the following test case triggers a segmentation fault:
>
> ```
> \set ON_ERROR_STOP on
>
> CREATE EXTENSION postgres_fdw;
>
> CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw
> OPTIONS (
> host '/path/to/pg_socket',
> port '5432',
> dbname :'dbname'
> );
>
> CREATE USER MAPPING FOR postgres SERVER loopback
> OPTIONS (user 'postgres');
>
> CREATE SCHEMA r;
> CREATE TABLE r.remote_p2 (a int NOT NULL, b int);
>
> CREATE TABLE pt (a int NOT NULL, b int) PARTITION BY LIST (a);
> CREATE TABLE pt_p1 PARTITION OF pt FOR VALUES IN (1);
> CREATE FOREIGN TABLE pt_p2 PARTITION OF pt FOR VALUES IN (2)
> SERVER loopback
> OPTIONS (schema_name 'r', table_name 'remote_p2');
>
> INSERT INTO pt_p1 VALUES (1, 10);
> INSERT INTO r.remote_p2 VALUES (2, 20);
>
> SET plan_cache_mode = force_generic_plan;
>
> PREPARE upd(int) AS
> UPDATE pt
> SET b = b + 1
> WHERE a = $1
> RETURNING tableoid::regclass, a, b;
>
> EXPLAIN (costs off) EXECUTE upd(2);
> EXECUTE upd(2);
> SELECT * FROM r.remote_p2 ORDER BY a;
>
Thanks for the very precise repro, that made this easy to track down.
I reproduced the crash on master. The plan EXPLAIN under
force_generic_plan shows runtime pruning is in effect:
Update on pt
Foreign Update on pt_p2 pt_2
-> Append
Subplans Removed: 1
-> Foreign Update on pt_p2 pt_2
The SEGV happens inside postgresBeginForeignModify() because
ExecInitModifyTable() builds re-indexed "kept" copies of several
parallel per-result-relation lists after dropping pruned relations -
withCheckOptionLists, returningLists, updateColnosLists,
mergeActionLists and mergeJoinConditions, however two members were
missed:
- node->fdwPrivLists, read with list_nth(node->fdwPrivLists, i) when
BeginForeignModify() is called, and
- node->fdwDirectModifyPlans, checked with bms_is_member(i, ...) when
setting ri_usesFdwDirectModify.
Both were still indexed against the original (pre-pruning) positions
while the surrounding loop's "i" is now the kept position. When the
foreign partition's kept-index no longer matched its original index,
BeginForeignModify() got the wrong fdw_private and crashed.
Attached patch builds re-indexed kept copies for these two arrays in
the same loop as the other parallel lists, and uses them at the two
call sites.
Regards,
Ayush
Attachments:
[application/octet-stream] v1-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu.patch (7.3K, ../../CAJTYsWXY9C3B-7NZw72OKen2L2rZt=c-t6=kjTJzgj=ZaNPe8g@mail.gmail.com/3-v1-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu.patch)
download | inline diff:
From 1bcf981c29f54b77a07c25a7b3eb06d90164bd8a Mon Sep 17 00:00:00 2001
From: Ayush Tiwari <[email protected]>
Date: Wed, 20 May 2026 05:06:57 +0000
Subject: [PATCH v1] Re-index ModifyTable FDW arrays when pruning result
relations
ExecInitModifyTable() copies parallel per-result-relation lists from
the plan node into a new "kept" set after dropping pruned result
relations. That re-indexing was already done for withCheckOptionLists,
returningLists, updateColnosLists, mergeActionLists and
mergeJoinConditions, but two members were missed:
* node->fdwPrivLists, indexed by list_nth() when calling
BeginForeignModify(), and
* node->fdwDirectModifyPlans, indexed by bms_is_member() when setting
ri_usesFdwDirectModify.
Both were still read using the *kept* loop variable i against the
*original* (pre-pruning) indexing, so on a partitioned UPDATE/DELETE
that uses a generic plan (PREPARE/EXECUTE under plan_cache_mode =
force_generic_plan) and runtime partition pruning, a foreign partition
whose original index no longer matched its kept position caused
BeginForeignModify() to receive the wrong fdw_private and segfault
inside the FDW.
Build re-indexed kept copies for these two arrays in the same loop as
the other parallel lists and use them at the call sites. Add a
postgres_fdw regression case using PREPARE/EXECUTE under
force_generic_plan that exercises the failing path.
Reported-by: Chi Zhang <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
.../postgres_fdw/expected/postgres_fdw.out | 26 +++++++++++++++++++
contrib/postgres_fdw/sql/postgres_fdw.sql | 22 ++++++++++++++++
src/backend/executor/nodeModifyTable.c | 18 +++++++++++--
3 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index e90289e4ab1..872d871a675 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -9337,6 +9337,32 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 21
+(1 row)
+
+deallocate fdw_part_upd;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index dfc58beb0d2..c80aaf1c1b4 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -2723,6 +2723,28 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+deallocate fdw_part_upd;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
+
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 478cb01783c..f69060cb5ab 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -5108,6 +5108,9 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
List *resultRelations = NIL;
List *withCheckOptionLists = NIL;
List *returningLists = NIL;
+ /* fdwPrivLists/fdwDirectModifyPlans are re-indexed to match resultRelations */
+ List *fdwPrivLists = NIL;
+ Bitmapset *fdwDirectModifyPlans = NULL;
List *updateColnosLists = NIL;
List *mergeActionLists = NIL;
List *mergeJoinConditions = NIL;
@@ -5153,6 +5156,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (keep_rel)
{
+ int new_index = list_length(resultRelations);
+
resultRelations = lappend_int(resultRelations, rti);
if (node->withCheckOptionLists)
{
@@ -5170,6 +5175,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
returningLists = lappend(returningLists, returningList);
}
+ if (node->fdwPrivLists)
+ {
+ List *fdwPrivList = (List *) list_nth(node->fdwPrivLists, i);
+
+ fdwPrivLists = lappend(fdwPrivLists, fdwPrivList);
+ }
+ if (bms_is_member(i, node->fdwDirectModifyPlans))
+ fdwDirectModifyPlans = bms_add_member(fdwDirectModifyPlans,
+ new_index);
if (node->updateColnosLists)
{
List *updateColnosList = list_nth(node->updateColnosLists, i);
@@ -5291,7 +5305,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/* Initialize the usesFdwDirectModify flag */
resultRelInfo->ri_usesFdwDirectModify =
- bms_is_member(i, node->fdwDirectModifyPlans);
+ bms_is_member(i, fdwDirectModifyPlans);
/*
* Verify result relation is a valid target for the current operation
@@ -5320,7 +5334,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
resultRelInfo->ri_FdwRoutine != NULL &&
resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
+ List *fdw_private = (List *) list_nth(fdwPrivLists, i);
resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
resultRelInfo,
--
2.43.0
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
@ 2026-05-20 17:46 ` Etsuro Fujita <[email protected]>
1 sibling, 0 replies; 32+ messages in thread
From: Etsuro Fujita @ 2026-05-20 17:46 UTC (permalink / raw)
To: Ayush Tiwari <[email protected]>; +Cc: [email protected]; [email protected]
Hi,
On Wed, May 20, 2026 at 5:37 AM Ayush Tiwari
<[email protected]> wrote:
> On Wed, 20 May 2026 at 03:59, PG Bug reporting form <[email protected]> wrote:
>> I found the following test case triggers a segmentation fault:
[snip]
> Thanks for the very precise repro, that made this easy to track down.
>
> I reproduced the crash on master. The plan EXPLAIN under
> force_generic_plan shows runtime pruning is in effect:
>
> Update on pt
> Foreign Update on pt_p2 pt_2
> -> Append
> Subplans Removed: 1
> -> Foreign Update on pt_p2 pt_2
>
> The SEGV happens inside postgresBeginForeignModify() because
> ExecInitModifyTable() builds re-indexed "kept" copies of several
> parallel per-result-relation lists after dropping pruned relations -
> withCheckOptionLists, returningLists, updateColnosLists,
> mergeActionLists and mergeJoinConditions, however two members were
> missed:
>
> - node->fdwPrivLists, read with list_nth(node->fdwPrivLists, i) when
> BeginForeignModify() is called, and
> - node->fdwDirectModifyPlans, checked with bms_is_member(i, ...) when
> setting ri_usesFdwDirectModify.
>
> Both were still indexed against the original (pre-pruning) positions
> while the surrounding loop's "i" is now the kept position. When the
> foreign partition's kept-index no longer matched its original index,
> BeginForeignModify() got the wrong fdw_private and crashed.
>
> Attached patch builds re-indexed kept copies for these two arrays in
> the same loop as the other parallel lists, and uses them at the two
> call sites.
Thanks Chi for the report, and Ayush for the analysis and patch! Will review.
Best regards,
Etsuro Fujita
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
@ 2026-05-22 20:56 ` Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
1 sibling, 1 reply; 32+ messages in thread
From: Matheus Alcantara @ 2026-05-22 20:56 UTC (permalink / raw)
To: Ayush Tiwari <[email protected]>; [email protected]; [email protected]; Etsuro Fujita <[email protected]>
On Wed May 20, 2026 at 9:37 AM -03, Ayush Tiwari wrote:
> I reproduced the crash on master. The plan EXPLAIN under
> force_generic_plan shows runtime pruning is in effect:
>
> Update on pt
> Foreign Update on pt_p2 pt_2
> -> Append
> Subplans Removed: 1
> -> Foreign Update on pt_p2 pt_2
>
> The SEGV happens inside postgresBeginForeignModify() because
> ExecInitModifyTable() builds re-indexed "kept" copies of several
> parallel per-result-relation lists after dropping pruned relations -
> withCheckOptionLists, returningLists, updateColnosLists,
> mergeActionLists and mergeJoinConditions, however two members were
> missed:
>
> - node->fdwPrivLists, read with list_nth(node->fdwPrivLists, i) when
> BeginForeignModify() is called, and
> - node->fdwDirectModifyPlans, checked with bms_is_member(i, ...) when
> setting ri_usesFdwDirectModify.
>
> Both were still indexed against the original (pre-pruning) positions
> while the surrounding loop's "i" is now the kept position. When the
> foreign partition's kept-index no longer matched its original index,
> BeginForeignModify() got the wrong fdw_private and crashed.
>
> Attached patch builds re-indexed kept copies for these two arrays in
> the same loop as the other parallel lists, and uses them at the two
> call sites.
>
Hi, thanks for the patch. This issue started on version 18 by commit
cbc127917e0.
The patch fixes the issue and it make sense to me. One a minor comment
is that I think pg_indent is needed on nodeModifyTable.c
--
Matheus Alcantara
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
@ 2026-05-30 06:18 ` Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Rafia Sabih @ 2026-05-30 06:18 UTC (permalink / raw)
To: Matheus Alcantara <[email protected]>; +Cc: Ayush Tiwari <[email protected]>; [email protected]; [email protected]; Etsuro Fujita <[email protected]>
On Fri, 22 May 2026 at 22:56, Matheus Alcantara <[email protected]>
wrote:
> On Wed May 20, 2026 at 9:37 AM -03, Ayush Tiwari wrote:
> > I reproduced the crash on master. The plan EXPLAIN under
> > force_generic_plan shows runtime pruning is in effect:
> >
> > Update on pt
> > Foreign Update on pt_p2 pt_2
> > -> Append
> > Subplans Removed: 1
> > -> Foreign Update on pt_p2 pt_2
> >
> > The SEGV happens inside postgresBeginForeignModify() because
> > ExecInitModifyTable() builds re-indexed "kept" copies of several
> > parallel per-result-relation lists after dropping pruned relations -
> > withCheckOptionLists, returningLists, updateColnosLists,
> > mergeActionLists and mergeJoinConditions, however two members were
> > missed:
> >
> > - node->fdwPrivLists, read with list_nth(node->fdwPrivLists, i) when
> > BeginForeignModify() is called, and
> > - node->fdwDirectModifyPlans, checked with bms_is_member(i, ...) when
> > setting ri_usesFdwDirectModify.
> >
> > Both were still indexed against the original (pre-pruning) positions
> > while the surrounding loop's "i" is now the kept position. When the
> > foreign partition's kept-index no longer matched its original index,
> > BeginForeignModify() got the wrong fdw_private and crashed.
> >
> > Attached patch builds re-indexed kept copies for these two arrays in
> > the same loop as the other parallel lists, and uses them at the two
> > call sites.
> >
>
A good catch. However there is one issue that remains here,
in show_modifytable_info still is using the old index here fdw_private =
(List *) list_nth(node->fdwPrivLists, j) i.e. the one before pruning.
In fact I found a scenario where it is causing crash, try this
create table fdw_part_update2 (a int not null, b int) partition by list (a);
create table fdw_part_update2_p1 partition of fdw_part_update2 for values
in (1);
create table fdw_part_update2_remote (a int not null, b int);
create foreign table fdw_part_update2_p2 partition of fdw_part_update2
for values in (2)
server loopback options (table_name 'fdw_part_update2_remote');
insert into fdw_part_update2_p1 values (1, 10);
insert into fdw_part_update2_remote values (2, 20);
set plan_cache_mode = force_generic_plan;
prepare fdw_part_upd2(int) as
update fdw_part_update2 set b = b + random()::int * 0 + 1 where a = $1
returning tableoid::regclass, a, b;
execute fdw_part_upd2(2);
explain (analyze, verbose, costs off, timing off, summary off)
execute fdw_part_upd2(2);
Please find the attached file for the patch to fix this. This patch applies
over the earlier patch (given by Ayush) in this thread.
>
> Hi, thanks for the patch. This issue started on version 18 by commit
> cbc127917e0.
>
> The patch fixes the issue and it make sense to me. One a minor comment
> is that I think pg_indent is needed on nodeModifyTable.c
>
> --
> Matheus Alcantara
> EDB: https://www.enterprisedb.com
>
>
>
--
Regards,
Rafia Sabih
CYBERTEC PostgreSQL International GmbH
Attachments:
[application/octet-stream] 0001-Fix-show_modifytable_info.patch (5.7K, ../../CA+FpmFc10Dtnr9dr=xqK2cNYQ4-1VuOyvOT7-eqXPmiQJoyPew@mail.gmail.com/3-0001-Fix-show_modifytable_info.patch)
download | inline diff:
From 984ff4240463ae8627e734351afa4f9d131162dd Mon Sep 17 00:00:00 2001
From: Rafia Sabih <[email protected]>
Date: Sat, 30 May 2026 08:11:35 +0200
Subject: [PATCH] Fix show_modifytable_info()
show_modifytable_info() in explain.c reads the plan-indexed
node->fdwPrivLists using the post-pruning executor index j,
producing an out-of-bounds access when calling
ExplainForeignModify on a non-direct-modify FDW relation.
Fix by saving the re-indexed list to mtstate->fdwPrivLists (new field
in ModifyTableState) and reading from there in explain.c.
---
.../postgres_fdw/expected/postgres_fdw.out | 25 +++++++++++++++++++
contrib/postgres_fdw/sql/postgres_fdw.sql | 7 ++++++
src/backend/commands/explain.c | 2 +-
src/backend/executor/nodeModifyTable.c | 3 ++-
src/include/nodes/execnodes.h | 3 ++-
5 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 872d871a675..5f5cb78ee65 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -9360,6 +9360,31 @@ execute fdw_part_upd(2);
(1 row)
deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 22
+(1 row)
+
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+ QUERY PLAN
+--------------------------------------------------------------------------------------------------------------------------------------------------------
+ Update on public.fdw_part_update (actual rows=1.00 loops=1)
+ Output: (fdw_part_update_1.tableoid)::regclass, fdw_part_update_1.a, fdw_part_update_1.b
+ Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ Remote SQL: UPDATE public.fdw_part_update_remote SET b = $2 WHERE ctid = $1 RETURNING a, b
+ -> Append (actual rows=1.00 loops=1)
+ Subplans Removed: 1
+ -> Foreign Scan on public.fdw_part_update_p2 fdw_part_update_2 (actual rows=1.00 loops=1)
+ Output: ((fdw_part_update_2.b + ((random())::integer * 0)) + 1), fdw_part_update_2.tableoid, fdw_part_update_2.ctid, fdw_part_update_2.*
+ Remote SQL: SELECT a, b, ctid FROM public.fdw_part_update_remote WHERE ((a = $1::integer)) FOR UPDATE
+(9 rows)
+
+deallocate fdw_part_upd2;
reset plan_cache_mode;
drop table fdw_part_update;
drop table fdw_part_update_remote;
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index c80aaf1c1b4..dc135573a21 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -2741,6 +2741,13 @@ prepare fdw_part_upd(int) as
returning tableoid::regclass, a, b;
execute fdw_part_upd(2);
deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+deallocate fdw_part_upd2;
reset plan_cache_mode;
drop table fdw_part_update;
drop table fdw_part_update_remote;
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 112c17b0d64..92326291129 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4821,7 +4821,7 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ List *fdw_private = (List *) list_nth(mtstate->fdwPrivLists, j);
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index f69060cb5ab..a66509465b9 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -5109,7 +5109,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
List *withCheckOptionLists = NIL;
List *returningLists = NIL;
/* fdwPrivLists/fdwDirectModifyPlans are re-indexed to match resultRelations */
- List *fdwPrivLists = NIL;
+ List *fdwPrivLists = NIL;
Bitmapset *fdwDirectModifyPlans = NULL;
List *updateColnosLists = NIL;
List *mergeActionLists = NIL;
@@ -5230,6 +5230,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
+ mtstate->fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 13359180d25..7b33d4d0410 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1444,7 +1444,8 @@ typedef struct ModifyTableState
bool mt_done; /* are we done? */
int mt_nrels; /* number of entries in resultRelInfo[] */
ResultRelInfo *resultRelInfo; /* info about target relation(s) */
-
+ /* Re-indexed fdw private data lists, aligned with resultRelInfo[] after pruning */
+ List *fdwPrivLists;
/*
* Target relation mentioned in the original statement, used to fire
* statement-level triggers and as the root for tuple routing. (This
--
2.39.5 (Apple Git-154)
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
@ 2026-06-09 15:10 ` Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Matheus Alcantara @ 2026-06-09 15:10 UTC (permalink / raw)
To: Rafia Sabih <[email protected]>; +Cc: Ayush Tiwari <[email protected]>; [email protected]; [email protected]; Etsuro Fujita <[email protected]>
On Sat May 30, 2026 at 3:18 AM -03, Rafia Sabih wrote:
> A good catch. However there is one issue that remains here,
> in show_modifytable_info still is using the old index here fdw_private =
> (List *) list_nth(node->fdwPrivLists, j) i.e. the one before pruning.
> In fact I found a scenario where it is causing crash, try this
>
> create table fdw_part_update2 (a int not null, b int) partition by list (a);
> create table fdw_part_update2_p1 partition of fdw_part_update2 for values
> in (1);
> create table fdw_part_update2_remote (a int not null, b int);
> create foreign table fdw_part_update2_p2 partition of fdw_part_update2
> for values in (2)
> server loopback options (table_name 'fdw_part_update2_remote');
> insert into fdw_part_update2_p1 values (1, 10);
> insert into fdw_part_update2_remote values (2, 20);
> set plan_cache_mode = force_generic_plan;
> prepare fdw_part_upd2(int) as
> update fdw_part_update2 set b = b + random()::int * 0 + 1 where a = $1
> returning tableoid::regclass, a, b;
> execute fdw_part_upd2(2);
> explain (analyze, verbose, costs off, timing off, summary off)
> execute fdw_part_upd2(2);
>
> Please find the attached file for the patch to fix this. This patch applies
> over the earlier patch (given by Ayush) in this thread.
>
Thanks for catching this, Rafia. The fix is correct —
show_modifytable_info() was indeed still reading from node->fdwPrivLists
using the post-pruning index j, which causes an out-of-bounds access
when partitions are pruned.
I think both patches should be squashed into a single one since they fix
the same underlying issue. I've done this locally and also ran pg_indent
over the result. Attached is the combined patch.
One minor naming observation: the new fdwPrivLists field in
ModifyTableState doesn't follow the mt_ prefix convention used by the
other re-indexed lists (mt_updateColnosLists, mt_mergeActionLists,
mt_mergeJoinConditions). Should we rename it to mt_fdwPrivLists for
consistency?
--
Matheus Alcantara
EDB: https://www.enterprisedb.com
From 4020e86e2ec85b6fd58397b5f4f467d1baf5ad87 Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <[email protected]>
Date: Tue, 9 Jun 2026 11:55:34 -0300
Subject: [PATCH] Re-index ModifyTable FDW arrays when pruning result relations
ExecInitModifyTable() copies parallel per-result-relation lists from
the plan node into a new "kept" set after dropping pruned result
relations. That re-indexing was already done for withCheckOptionLists,
returningLists, updateColnosLists, mergeActionLists and
mergeJoinConditions, but fdwPrivLists and fdwDirectModifyPlans were missed.
Additionally, show_modifytable_info() in explain.c was reading the
plan-indexed node->fdwPrivLists using the post-pruning executor index,
causing out-of-bounds access. Fix by saving the re-indexed list to
mtstate->fdwPrivLists and reading from there.
Author: Ayush Tiwari <[email protected]>
Author: Rafia Sabih <[email protected]>
Co-authored-by: Matheus Alcantara <[email protected]>
Reported-by: Chi Zhang <[email protected]>
Discussion: https://www.postgresql.org/message-id/19484-a3cb82c8cde3c8fa%40postgresql.org
---
.../postgres_fdw/expected/postgres_fdw.out | 51 +++++++++++++++++++
contrib/postgres_fdw/sql/postgres_fdw.sql | 29 +++++++++++
src/backend/commands/explain.c | 2 +-
src/backend/executor/nodeModifyTable.c | 23 ++++++++-
src/include/nodes/execnodes.h | 6 +++
5 files changed, 108 insertions(+), 3 deletions(-)
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index e90289e4ab1..5f5cb78ee65 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -9337,6 +9337,57 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 21
+(1 row)
+
+deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 22
+(1 row)
+
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+ QUERY PLAN
+--------------------------------------------------------------------------------------------------------------------------------------------------------
+ Update on public.fdw_part_update (actual rows=1.00 loops=1)
+ Output: (fdw_part_update_1.tableoid)::regclass, fdw_part_update_1.a, fdw_part_update_1.b
+ Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ Remote SQL: UPDATE public.fdw_part_update_remote SET b = $2 WHERE ctid = $1 RETURNING a, b
+ -> Append (actual rows=1.00 loops=1)
+ Subplans Removed: 1
+ -> Foreign Scan on public.fdw_part_update_p2 fdw_part_update_2 (actual rows=1.00 loops=1)
+ Output: ((fdw_part_update_2.b + ((random())::integer * 0)) + 1), fdw_part_update_2.tableoid, fdw_part_update_2.ctid, fdw_part_update_2.*
+ Remote SQL: SELECT a, b, ctid FROM public.fdw_part_update_remote WHERE ((a = $1::integer)) FOR UPDATE
+(9 rows)
+
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index dfc58beb0d2..dc135573a21 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -2723,6 +2723,35 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
+
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 112c17b0d64..3e43c97896e 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4821,7 +4821,7 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ List *fdw_private = (List *) list_nth(mtstate->fdwPrivLists, j);
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 33a6735f08d..a631c345c5e 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -5105,6 +5105,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
List *resultRelations = NIL;
List *withCheckOptionLists = NIL;
List *returningLists = NIL;
+
+ /*
+ * fdwPrivLists/fdwDirectModifyPlans are re-indexed to match
+ * resultRelations
+ */
+ List *fdwPrivLists = NIL;
+ Bitmapset *fdwDirectModifyPlans = NULL;
List *updateColnosLists = NIL;
List *mergeActionLists = NIL;
List *mergeJoinConditions = NIL;
@@ -5150,6 +5157,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (keep_rel)
{
+ int new_index = list_length(resultRelations);
+
resultRelations = lappend_int(resultRelations, rti);
if (node->withCheckOptionLists)
{
@@ -5167,6 +5176,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
returningLists = lappend(returningLists, returningList);
}
+ if (node->fdwPrivLists)
+ {
+ List *fdwPrivList = (List *) list_nth(node->fdwPrivLists, i);
+
+ fdwPrivLists = lappend(fdwPrivLists, fdwPrivList);
+ }
+ if (bms_is_member(i, node->fdwDirectModifyPlans))
+ fdwDirectModifyPlans = bms_add_member(fdwDirectModifyPlans,
+ new_index);
if (node->updateColnosLists)
{
List *updateColnosList = list_nth(node->updateColnosLists, i);
@@ -5213,6 +5231,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
+ mtstate->fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
@@ -5288,7 +5307,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/* Initialize the usesFdwDirectModify flag */
resultRelInfo->ri_usesFdwDirectModify =
- bms_is_member(i, node->fdwDirectModifyPlans);
+ bms_is_member(i, fdwDirectModifyPlans);
/*
* Verify result relation is a valid target for the current operation
@@ -5317,7 +5336,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
resultRelInfo->ri_FdwRoutine != NULL &&
resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
+ List *fdw_private = (List *) list_nth(fdwPrivLists, i);
resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
resultRelInfo,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 53c138310db..f64c2cc5f34 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
int mt_nrels; /* number of entries in resultRelInfo[] */
ResultRelInfo *resultRelInfo; /* info about target relation(s) */
+ /*
+ * Re-indexed fdw private data lists, aligned with resultRelInfo[] after
+ * pruning
+ */
+ List *fdwPrivLists;
+
/*
* Target relation mentioned in the original statement, used to fire
* statement-level triggers and as the root for tuple routing. (This
--
2.50.1 (Apple Git-155)
Attachments:
[text/plain] 0001-Re-index-ModifyTable-FDW-arrays-when-pruning-result-.patch (10.3K, ../../[email protected]/2-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-result-.patch)
download | inline diff:
From 4020e86e2ec85b6fd58397b5f4f467d1baf5ad87 Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <[email protected]>
Date: Tue, 9 Jun 2026 11:55:34 -0300
Subject: [PATCH] Re-index ModifyTable FDW arrays when pruning result relations
ExecInitModifyTable() copies parallel per-result-relation lists from
the plan node into a new "kept" set after dropping pruned result
relations. That re-indexing was already done for withCheckOptionLists,
returningLists, updateColnosLists, mergeActionLists and
mergeJoinConditions, but fdwPrivLists and fdwDirectModifyPlans were missed.
Additionally, show_modifytable_info() in explain.c was reading the
plan-indexed node->fdwPrivLists using the post-pruning executor index,
causing out-of-bounds access. Fix by saving the re-indexed list to
mtstate->fdwPrivLists and reading from there.
Author: Ayush Tiwari <[email protected]>
Author: Rafia Sabih <[email protected]>
Co-authored-by: Matheus Alcantara <[email protected]>
Reported-by: Chi Zhang <[email protected]>
Discussion: https://www.postgresql.org/message-id/19484-a3cb82c8cde3c8fa%40postgresql.org
---
.../postgres_fdw/expected/postgres_fdw.out | 51 +++++++++++++++++++
contrib/postgres_fdw/sql/postgres_fdw.sql | 29 +++++++++++
src/backend/commands/explain.c | 2 +-
src/backend/executor/nodeModifyTable.c | 23 ++++++++-
src/include/nodes/execnodes.h | 6 +++
5 files changed, 108 insertions(+), 3 deletions(-)
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index e90289e4ab1..5f5cb78ee65 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -9337,6 +9337,57 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 21
+(1 row)
+
+deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 22
+(1 row)
+
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+ QUERY PLAN
+--------------------------------------------------------------------------------------------------------------------------------------------------------
+ Update on public.fdw_part_update (actual rows=1.00 loops=1)
+ Output: (fdw_part_update_1.tableoid)::regclass, fdw_part_update_1.a, fdw_part_update_1.b
+ Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ Remote SQL: UPDATE public.fdw_part_update_remote SET b = $2 WHERE ctid = $1 RETURNING a, b
+ -> Append (actual rows=1.00 loops=1)
+ Subplans Removed: 1
+ -> Foreign Scan on public.fdw_part_update_p2 fdw_part_update_2 (actual rows=1.00 loops=1)
+ Output: ((fdw_part_update_2.b + ((random())::integer * 0)) + 1), fdw_part_update_2.tableoid, fdw_part_update_2.ctid, fdw_part_update_2.*
+ Remote SQL: SELECT a, b, ctid FROM public.fdw_part_update_remote WHERE ((a = $1::integer)) FOR UPDATE
+(9 rows)
+
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index dfc58beb0d2..dc135573a21 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -2723,6 +2723,35 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
+
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 112c17b0d64..3e43c97896e 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4821,7 +4821,7 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ List *fdw_private = (List *) list_nth(mtstate->fdwPrivLists, j);
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 33a6735f08d..a631c345c5e 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -5105,6 +5105,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
List *resultRelations = NIL;
List *withCheckOptionLists = NIL;
List *returningLists = NIL;
+
+ /*
+ * fdwPrivLists/fdwDirectModifyPlans are re-indexed to match
+ * resultRelations
+ */
+ List *fdwPrivLists = NIL;
+ Bitmapset *fdwDirectModifyPlans = NULL;
List *updateColnosLists = NIL;
List *mergeActionLists = NIL;
List *mergeJoinConditions = NIL;
@@ -5150,6 +5157,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (keep_rel)
{
+ int new_index = list_length(resultRelations);
+
resultRelations = lappend_int(resultRelations, rti);
if (node->withCheckOptionLists)
{
@@ -5167,6 +5176,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
returningLists = lappend(returningLists, returningList);
}
+ if (node->fdwPrivLists)
+ {
+ List *fdwPrivList = (List *) list_nth(node->fdwPrivLists, i);
+
+ fdwPrivLists = lappend(fdwPrivLists, fdwPrivList);
+ }
+ if (bms_is_member(i, node->fdwDirectModifyPlans))
+ fdwDirectModifyPlans = bms_add_member(fdwDirectModifyPlans,
+ new_index);
if (node->updateColnosLists)
{
List *updateColnosList = list_nth(node->updateColnosLists, i);
@@ -5213,6 +5231,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
+ mtstate->fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
@@ -5288,7 +5307,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/* Initialize the usesFdwDirectModify flag */
resultRelInfo->ri_usesFdwDirectModify =
- bms_is_member(i, node->fdwDirectModifyPlans);
+ bms_is_member(i, fdwDirectModifyPlans);
/*
* Verify result relation is a valid target for the current operation
@@ -5317,7 +5336,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
resultRelInfo->ri_FdwRoutine != NULL &&
resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
+ List *fdw_private = (List *) list_nth(fdwPrivLists, i);
resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
resultRelInfo,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 53c138310db..f64c2cc5f34 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
int mt_nrels; /* number of entries in resultRelInfo[] */
ResultRelInfo *resultRelInfo; /* info about target relation(s) */
+ /*
+ * Re-indexed fdw private data lists, aligned with resultRelInfo[] after
+ * pruning
+ */
+ List *fdwPrivLists;
+
/*
* Target relation mentioned in the original statement, used to fire
* statement-level triggers and as the root for tuple routing. (This
--
2.50.1 (Apple Git-155)
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
@ 2026-06-10 05:15 ` Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Ayush Tiwari @ 2026-06-10 05:15 UTC (permalink / raw)
To: Matheus Alcantara <[email protected]>; +Cc: Rafia Sabih <[email protected]>; [email protected]; [email protected]; Etsuro Fujita <[email protected]>
Hi,
On Tue, 9 Jun 2026 at 20:40, Matheus Alcantara <[email protected]>
wrote:
>
> I think both patches should be squashed into a single one since they fix
> the same underlying issue. I've done this locally and also ran pg_indent
> over the result. Attached is the combined patch.
>
Thanks for this!
> One minor naming observation: the new fdwPrivLists field in
> ModifyTableState doesn't follow the mt_ prefix convention used by the
> other re-indexed lists (mt_updateColnosLists, mt_mergeActionLists,
> mt_mergeJoinConditions). Should we rename it to mt_fdwPrivLists for
> consistency?
>
I think yes, it makes sense to rename it.
Regards,
Ayush
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
@ 2026-06-10 11:08 ` Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Matheus Alcantara @ 2026-06-10 11:08 UTC (permalink / raw)
To: Ayush Tiwari <[email protected]>; +Cc: Rafia Sabih <[email protected]>; [email protected]; [email protected]; Etsuro Fujita <[email protected]>; Amit Langote <[email protected]>
On Wed Jun 10, 2026 at 2:15 AM -03, Ayush Tiwari wrote:
>> One minor naming observation: the new fdwPrivLists field in
>> ModifyTableState doesn't follow the mt_ prefix convention used by the
>> other re-indexed lists (mt_updateColnosLists, mt_mergeActionLists,
>> mt_mergeJoinConditions). Should we rename it to mt_fdwPrivLists for
>> consistency?
>>
>
> I think yes, it makes sense to rename it.
>
Attached v2 renamed, thanks.
(Also CC Amit on this since he committed cbc127917e0 which I believe
that is when the issue started)
--
Matheus Alcantara
EDB: https://www.enterprisedb.com
From 971d185cf4bfb75d0459f2c7848e6b77afa2ee85 Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <[email protected]>
Date: Tue, 9 Jun 2026 11:55:34 -0300
Subject: [PATCH v2] Re-index ModifyTable FDW arrays when pruning result
relations
ExecInitModifyTable() copies parallel per-result-relation lists from
the plan node into a new "kept" set after dropping pruned result
relations. That re-indexing was already done for withCheckOptionLists,
returningLists, updateColnosLists, mergeActionLists and
mergeJoinConditions, but fdwPrivLists and fdwDirectModifyPlans were missed.
Additionally, show_modifytable_info() in explain.c was reading the
plan-indexed node->fdwPrivLists using the post-pruning executor index,
causing out-of-bounds access. Fix by saving the re-indexed list to
mtstate->mt_fdwPrivLists and reading from there.
Author: Ayush Tiwari <[email protected]>
Author: Rafia Sabih <[email protected]>
Co-authored-by: Matheus Alcantara <[email protected]>
Reviewed-by: Ayush Tiwari <[email protected]>
Reported-by: Chi Zhang <[email protected]>
Discussion: https://www.postgresql.org/message-id/19484-a3cb82c8cde3c8fa%40postgresql.org
---
.../postgres_fdw/expected/postgres_fdw.out | 51 +++++++++++++++++++
contrib/postgres_fdw/sql/postgres_fdw.sql | 29 +++++++++++
src/backend/commands/explain.c | 2 +-
src/backend/executor/nodeModifyTable.c | 23 ++++++++-
src/include/nodes/execnodes.h | 6 +++
5 files changed, 108 insertions(+), 3 deletions(-)
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index e90289e4ab1..5f5cb78ee65 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -9337,6 +9337,57 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 21
+(1 row)
+
+deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 22
+(1 row)
+
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+ QUERY PLAN
+--------------------------------------------------------------------------------------------------------------------------------------------------------
+ Update on public.fdw_part_update (actual rows=1.00 loops=1)
+ Output: (fdw_part_update_1.tableoid)::regclass, fdw_part_update_1.a, fdw_part_update_1.b
+ Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ Remote SQL: UPDATE public.fdw_part_update_remote SET b = $2 WHERE ctid = $1 RETURNING a, b
+ -> Append (actual rows=1.00 loops=1)
+ Subplans Removed: 1
+ -> Foreign Scan on public.fdw_part_update_p2 fdw_part_update_2 (actual rows=1.00 loops=1)
+ Output: ((fdw_part_update_2.b + ((random())::integer * 0)) + 1), fdw_part_update_2.tableoid, fdw_part_update_2.ctid, fdw_part_update_2.*
+ Remote SQL: SELECT a, b, ctid FROM public.fdw_part_update_remote WHERE ((a = $1::integer)) FOR UPDATE
+(9 rows)
+
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index dfc58beb0d2..dc135573a21 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -2723,6 +2723,35 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
+
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 112c17b0d64..a40d03d35f3 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4821,7 +4821,7 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ List *fdw_private = (List *) list_nth(mtstate->mt_fdwPrivLists, j);
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 33a6735f08d..feea28214d4 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -5105,6 +5105,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
List *resultRelations = NIL;
List *withCheckOptionLists = NIL;
List *returningLists = NIL;
+
+ /*
+ * fdwPrivLists/fdwDirectModifyPlans are re-indexed to match
+ * resultRelations
+ */
+ List *fdwPrivLists = NIL;
+ Bitmapset *fdwDirectModifyPlans = NULL;
List *updateColnosLists = NIL;
List *mergeActionLists = NIL;
List *mergeJoinConditions = NIL;
@@ -5150,6 +5157,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (keep_rel)
{
+ int new_index = list_length(resultRelations);
+
resultRelations = lappend_int(resultRelations, rti);
if (node->withCheckOptionLists)
{
@@ -5167,6 +5176,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
returningLists = lappend(returningLists, returningList);
}
+ if (node->fdwPrivLists)
+ {
+ List *fdwPrivList = (List *) list_nth(node->fdwPrivLists, i);
+
+ fdwPrivLists = lappend(fdwPrivLists, fdwPrivList);
+ }
+ if (bms_is_member(i, node->fdwDirectModifyPlans))
+ fdwDirectModifyPlans = bms_add_member(fdwDirectModifyPlans,
+ new_index);
if (node->updateColnosLists)
{
List *updateColnosList = list_nth(node->updateColnosLists, i);
@@ -5213,6 +5231,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
+ mtstate->mt_fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
@@ -5288,7 +5307,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/* Initialize the usesFdwDirectModify flag */
resultRelInfo->ri_usesFdwDirectModify =
- bms_is_member(i, node->fdwDirectModifyPlans);
+ bms_is_member(i, fdwDirectModifyPlans);
/*
* Verify result relation is a valid target for the current operation
@@ -5317,7 +5336,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
resultRelInfo->ri_FdwRoutine != NULL &&
resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
+ List *fdw_private = (List *) list_nth(fdwPrivLists, i);
resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
resultRelInfo,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 53c138310db..5871383961f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
int mt_nrels; /* number of entries in resultRelInfo[] */
ResultRelInfo *resultRelInfo; /* info about target relation(s) */
+ /*
+ * Re-indexed fdw private data lists, aligned with resultRelInfo[] after
+ * pruning
+ */
+ List *mt_fdwPrivLists;
+
/*
* Target relation mentioned in the original statement, used to fire
* statement-level triggers and as the root for tuple routing. (This
--
2.50.1 (Apple Git-155)
Attachments:
[text/plain] v2-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu.patch (10.4K, ../../[email protected]/2-v2-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu.patch)
download | inline diff:
From 971d185cf4bfb75d0459f2c7848e6b77afa2ee85 Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <[email protected]>
Date: Tue, 9 Jun 2026 11:55:34 -0300
Subject: [PATCH v2] Re-index ModifyTable FDW arrays when pruning result
relations
ExecInitModifyTable() copies parallel per-result-relation lists from
the plan node into a new "kept" set after dropping pruned result
relations. That re-indexing was already done for withCheckOptionLists,
returningLists, updateColnosLists, mergeActionLists and
mergeJoinConditions, but fdwPrivLists and fdwDirectModifyPlans were missed.
Additionally, show_modifytable_info() in explain.c was reading the
plan-indexed node->fdwPrivLists using the post-pruning executor index,
causing out-of-bounds access. Fix by saving the re-indexed list to
mtstate->mt_fdwPrivLists and reading from there.
Author: Ayush Tiwari <[email protected]>
Author: Rafia Sabih <[email protected]>
Co-authored-by: Matheus Alcantara <[email protected]>
Reviewed-by: Ayush Tiwari <[email protected]>
Reported-by: Chi Zhang <[email protected]>
Discussion: https://www.postgresql.org/message-id/19484-a3cb82c8cde3c8fa%40postgresql.org
---
.../postgres_fdw/expected/postgres_fdw.out | 51 +++++++++++++++++++
contrib/postgres_fdw/sql/postgres_fdw.sql | 29 +++++++++++
src/backend/commands/explain.c | 2 +-
src/backend/executor/nodeModifyTable.c | 23 ++++++++-
src/include/nodes/execnodes.h | 6 +++
5 files changed, 108 insertions(+), 3 deletions(-)
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index e90289e4ab1..5f5cb78ee65 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -9337,6 +9337,57 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 21
+(1 row)
+
+deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 22
+(1 row)
+
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+ QUERY PLAN
+--------------------------------------------------------------------------------------------------------------------------------------------------------
+ Update on public.fdw_part_update (actual rows=1.00 loops=1)
+ Output: (fdw_part_update_1.tableoid)::regclass, fdw_part_update_1.a, fdw_part_update_1.b
+ Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ Remote SQL: UPDATE public.fdw_part_update_remote SET b = $2 WHERE ctid = $1 RETURNING a, b
+ -> Append (actual rows=1.00 loops=1)
+ Subplans Removed: 1
+ -> Foreign Scan on public.fdw_part_update_p2 fdw_part_update_2 (actual rows=1.00 loops=1)
+ Output: ((fdw_part_update_2.b + ((random())::integer * 0)) + 1), fdw_part_update_2.tableoid, fdw_part_update_2.ctid, fdw_part_update_2.*
+ Remote SQL: SELECT a, b, ctid FROM public.fdw_part_update_remote WHERE ((a = $1::integer)) FOR UPDATE
+(9 rows)
+
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index dfc58beb0d2..dc135573a21 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -2723,6 +2723,35 @@ select tableoid::regclass, * FROM locp;
-- The executor should not let unexercised FDWs shut down
update utrtest set a = 1 where b = 'foo';
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd(2);
+deallocate fdw_part_upd;
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
+
-- Test that remote triggers work with update tuple routing
create trigger loct_br_insert_trigger before insert on loct
for each row execute procedure br_insert_trigfunc();
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 112c17b0d64..a40d03d35f3 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4821,7 +4821,7 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ List *fdw_private = (List *) list_nth(mtstate->mt_fdwPrivLists, j);
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 33a6735f08d..feea28214d4 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -5105,6 +5105,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
List *resultRelations = NIL;
List *withCheckOptionLists = NIL;
List *returningLists = NIL;
+
+ /*
+ * fdwPrivLists/fdwDirectModifyPlans are re-indexed to match
+ * resultRelations
+ */
+ List *fdwPrivLists = NIL;
+ Bitmapset *fdwDirectModifyPlans = NULL;
List *updateColnosLists = NIL;
List *mergeActionLists = NIL;
List *mergeJoinConditions = NIL;
@@ -5150,6 +5157,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (keep_rel)
{
+ int new_index = list_length(resultRelations);
+
resultRelations = lappend_int(resultRelations, rti);
if (node->withCheckOptionLists)
{
@@ -5167,6 +5176,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
returningLists = lappend(returningLists, returningList);
}
+ if (node->fdwPrivLists)
+ {
+ List *fdwPrivList = (List *) list_nth(node->fdwPrivLists, i);
+
+ fdwPrivLists = lappend(fdwPrivLists, fdwPrivList);
+ }
+ if (bms_is_member(i, node->fdwDirectModifyPlans))
+ fdwDirectModifyPlans = bms_add_member(fdwDirectModifyPlans,
+ new_index);
if (node->updateColnosLists)
{
List *updateColnosList = list_nth(node->updateColnosLists, i);
@@ -5213,6 +5231,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
+ mtstate->mt_fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
@@ -5288,7 +5307,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/* Initialize the usesFdwDirectModify flag */
resultRelInfo->ri_usesFdwDirectModify =
- bms_is_member(i, node->fdwDirectModifyPlans);
+ bms_is_member(i, fdwDirectModifyPlans);
/*
* Verify result relation is a valid target for the current operation
@@ -5317,7 +5336,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
resultRelInfo->ri_FdwRoutine != NULL &&
resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
+ List *fdw_private = (List *) list_nth(fdwPrivLists, i);
resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
resultRelInfo,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 53c138310db..5871383961f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
int mt_nrels; /* number of entries in resultRelInfo[] */
ResultRelInfo *resultRelInfo; /* info about target relation(s) */
+ /*
+ * Re-indexed fdw private data lists, aligned with resultRelInfo[] after
+ * pruning
+ */
+ List *mt_fdwPrivLists;
+
/*
* Target relation mentioned in the original statement, used to fire
* statement-level triggers and as the root for tuple routing. (This
--
2.50.1 (Apple Git-155)
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
@ 2026-06-10 13:09 ` Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-10 13:09 UTC (permalink / raw)
To: Matheus Alcantara <[email protected]>; +Cc: Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Etsuro Fujita <[email protected]>; Amit Langote <[email protected]>
Hi Matheus,
On Wed, Jun 10, 2026 at 8:09 PM Matheus Alcantara
<[email protected]> wrote:
>
> On Wed Jun 10, 2026 at 2:15 AM -03, Ayush Tiwari wrote:
> >> One minor naming observation: the new fdwPrivLists field in
> >> ModifyTableState doesn't follow the mt_ prefix convention used by the
> >> other re-indexed lists (mt_updateColnosLists, mt_mergeActionLists,
> >> mt_mergeJoinConditions). Should we rename it to mt_fdwPrivLists for
> >> consistency?
> >>
> >
> > I think yes, it makes sense to rename it.
> >
>
> Attached v2 renamed, thanks.
>
> (Also CC Amit on this since he committed cbc127917e0 which I believe
> that is when the issue started)
Thanks for adding me. I'll take a look at this early next week.
--
Thanks, Amit Langote
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-10 13:27 ` Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-10 13:27 UTC (permalink / raw)
To: Matheus Alcantara <[email protected]>; +Cc: Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Etsuro Fujita <[email protected]>; Amit Langote <[email protected]>
On Wed, Jun 10, 2026 at 10:09 PM Amit Langote <[email protected]> wrote:
> On Wed, Jun 10, 2026 at 8:09 PM Matheus Alcantara
> <[email protected]> wrote:
> > On Wed Jun 10, 2026 at 2:15 AM -03, Ayush Tiwari wrote:
> > >> One minor naming observation: the new fdwPrivLists field in
> > >> ModifyTableState doesn't follow the mt_ prefix convention used by the
> > >> other re-indexed lists (mt_updateColnosLists, mt_mergeActionLists,
> > >> mt_mergeJoinConditions). Should we rename it to mt_fdwPrivLists for
> > >> consistency?
> > >>
> > >
> > > I think yes, it makes sense to rename it.
> > >
> >
> > Attached v2 renamed, thanks.
> >
> > (Also CC Amit on this since he committed cbc127917e0 which I believe
> > that is when the issue started)
>
> Thanks for adding me. I'll take a look at this early next week.
I looked, and the patch seems straightforward enough.
Before committing it, I'd like to wait briefly to see if Fujita-san
has any thoughts on the FDW-side concerns, since he has already chimed
in on the thread.
--
Thanks, Amit Langote
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-11 10:40 ` Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Etsuro Fujita @ 2026-06-11 10:40 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Amit-san,
On Wed, Jun 10, 2026 at 10:27 PM Amit Langote <[email protected]> wrote:
> Before committing it, I'd like to wait briefly to see if Fujita-san
> has any thoughts on the FDW-side concerns, since he has already chimed
> in on the thread.
I'll review the patch as early as I can next week, but if you want to
commit it quickly, please go ahead.
Thanks!
Best regards,
Etsuro Fujita
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
@ 2026-06-11 10:44 ` Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-11 10:44 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Hi Fujita-san,
On Thu, Jun 11, 2026 at 7:41 PM Etsuro Fujita <[email protected]> wrote:
>
> Amit-san,
>
> On Wed, Jun 10, 2026 at 10:27 PM Amit Langote <[email protected]> wrote:
> > Before committing it, I'd like to wait briefly to see if Fujita-san
> > has any thoughts on the FDW-side concerns, since he has already chimed
> > in on the thread.
>
> I'll review the patch as early as I can next week, but if you want to
> commit it quickly, please go ahead.
No problem; I'll hold off.
--
Thanks, Amit Langote
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-18 09:15 ` Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-18 09:15 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Fujita-san,
On Thu, Jun 11, 2026 at 7:44 PM Amit Langote <[email protected]> wrote:
>
> Hi Fujita-san,
>
> On Thu, Jun 11, 2026 at 7:41 PM Etsuro Fujita <[email protected]> wrote:
> >
> > Amit-san,
> >
> > On Wed, Jun 10, 2026 at 10:27 PM Amit Langote <[email protected]> wrote:
> > > Before committing it, I'd like to wait briefly to see if Fujita-san
> > > has any thoughts on the FDW-side concerns, since he has already chimed
> > > in on the thread.
> >
> > I'll review the patch as early as I can next week, but if you want to
> > commit it quickly, please go ahead.
>
> No problem; I'll hold off.
A small clarification on this one: the patch makes no changes to
postgres_fdw code, only adds a regression test. The bug, which I
introduced, is in how nodeModifyTable.c supplies fdw_private from the
pruned/validated fdwPrivLists in ModifyTableState rather than the
original list in ModifyTable, so the postgres_fdw side itself is
unchanged. The substantive change is the executor re-indexing.
Still holding off on committing per our exchange, but no rush given
you may want to prioritize the v19 open items. Happy to go ahead
whenever, or wait for your comments.
--
Thanks, Amit Langote
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-18 10:50 ` Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Etsuro Fujita @ 2026-06-18 10:50 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Amit-san,
On Thu, Jun 18, 2026 at 6:16 PM Amit Langote <[email protected]> wrote:
> A small clarification on this one: the patch makes no changes to
> postgres_fdw code, only adds a regression test. The bug, which I
> introduced, is in how nodeModifyTable.c supplies fdw_private from the
> pruned/validated fdwPrivLists in ModifyTableState rather than the
> original list in ModifyTable, so the postgres_fdw side itself is
> unchanged. The substantive change is the executor re-indexing.
Thanks for the clarification!
> Still holding off on committing per our exchange, but no rush given
> you may want to prioritize the v19 open items. Happy to go ahead
> whenever, or wait for your comments.
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
@ 2026-06-18 10:55 ` Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Etsuro Fujita @ 2026-06-18 10:55 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Sorry, I accidentally sent this before I finished writing.
On Thu, Jun 18, 2026 at 7:50 PM Etsuro Fujita <[email protected]> wrote:
>
> Amit-san,
>
> On Thu, Jun 18, 2026 at 6:16 PM Amit Langote <[email protected]> wrote:
> > A small clarification on this one: the patch makes no changes to
> > postgres_fdw code, only adds a regression test. The bug, which I
> > introduced, is in how nodeModifyTable.c supplies fdw_private from the
> > pruned/validated fdwPrivLists in ModifyTableState rather than the
> > original list in ModifyTable, so the postgres_fdw side itself is
> > unchanged. The substantive change is the executor re-indexing.
>
> Thanks for the clarification!
>
> > Still holding off on committing per our exchange, but no rush given
> > you may want to prioritize the v19 open items. Happy to go ahead
> > whenever, or wait for your comments.
Actually, I've just started reviewing the patch. I'll let you know
the results (if any) by tomorrow. Thanks for the consideration as
well.
Best regards,
Etsuro Fujita
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
@ 2026-06-18 10:57 ` Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-18 10:57 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
On Thu, Jun 18, 2026 at 19:55 Etsuro Fujita <[email protected]> wrote:
> Sorry, I accidentally sent this before I finished writing.
>
> On Thu, Jun 18, 2026 at 7:50 PM Etsuro Fujita <[email protected]>
> wrote:
> >
> > Amit-san,
> >
> > On Thu, Jun 18, 2026 at 6:16 PM Amit Langote <[email protected]>
> wrote:
> > > A small clarification on this one: the patch makes no changes to
> > > postgres_fdw code, only adds a regression test. The bug, which I
> > > introduced, is in how nodeModifyTable.c supplies fdw_private from the
> > > pruned/validated fdwPrivLists in ModifyTableState rather than the
> > > original list in ModifyTable, so the postgres_fdw side itself is
> > > unchanged. The substantive change is the executor re-indexing.
> >
> > Thanks for the clarification!
> >
> > > Still holding off on committing per our exchange, but no rush given
> > > you may want to prioritize the v19 open items. Happy to go ahead
> > > whenever, or wait for your comments.
>
> Actually, I've just started reviewing the patch. I'll let you know
> the results (if any) by tomorrow. Thanks for the consideration as
> well.
Ah, thanks for the heads up.
- Amit
>
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-19 11:59 ` Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Etsuro Fujita @ 2026-06-19 11:59 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Amit-san,
On Thu, Jun 18, 2026 at 7:57 PM Amit Langote <[email protected]> wrote:
> On Thu, Jun 18, 2026 at 19:55 Etsuro Fujita <[email protected]> wrote:
>> Actually, I've just started reviewing the patch. I'll let you know
>> the results (if any) by tomorrow.
> Ah, thanks for the heads up.
Here are my review comments:
@@ -5167,6 +5176,15 @@ ExecInitModifyTable(ModifyTable *node, EState
*estate, int eflags)
returningLists = lappend(returningLists, returningList);
}
+ if (node->fdwPrivLists)
+ {
+ List *fdwPrivList = (List *)
list_nth(node->fdwPrivLists, i);
+
+ fdwPrivLists = lappend(fdwPrivLists, fdwPrivList);
+ }
As node->fdwPrivLists is always created, the if-test is useless, so I
removed it like the attached. Also, this is nitpicking but, in the
attached I moved a comment added above
("fdwPrivLists/fdwDirectModifyPlans are re-indexed to match
resultRelations") to a more appropriate place, and did some minor
editorialization.
+-- Runtime pruning of result relations must keep ModifyTable's per-relation
+-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
+-- resultRelations. Otherwise BeginForeignModify() reads the wrong
+-- fdw_private and segfaults.
This comment isn't 100% correct, because this issue happens with
DirectModify as well. I think we could expand the comment to mention
that as well, but the comment is already too much/detailed IMO; I
don't think we add such a comment for a test case, so how about
simplifying the comment like this: "Test that direct modify and
foreign modify work with runtime pruning of result relations (bug
#19484)"
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+execute fdw_part_upd2(2);
+explain (analyze, verbose, costs off, timing off, summary off)
+ execute fdw_part_upd2(2);
I think it's expensive to do explain with the analyze option enabled,
just for conforming the plan. To save cycles, I removed the option.
(As the test case for DirectModify was missing the explain test, I
added it, for consistency.) The test cases are placed in the "test
tuple routing for foreign-table partitions" section, but they are
basic ones to test writable foreign tables, so I moved them to the
"test writable foreign table stuff" section.
@@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
int mt_nrels; /* number of entries in resultRelInfo[] */
ResultRelInfo *resultRelInfo; /* info about target relation(s) */
+ /*
+ * Re-indexed fdw private data lists, aligned with resultRelInfo[] after
+ * pruning
+ */
+ List *mt_fdwPrivLists;
For v18, I think we should put this at the end of the ModifyTableState
struct, to avoid ABI breakage.
That's it. Sorry for the delay.
Best regards,
Etsuro Fujita
Attachments:
[application/octet-stream] v2-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu-efujita.patch (9.1K, ../../CAPmGK15nR_pePb9QAMViq+AGuWeJSqPnLTJVLsr96aU2TFmcmw@mail.gmail.com/2-v2-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu-efujita.patch)
download | inline diff:
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index e90289e4ab1..13853b8b720 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -7197,6 +7197,70 @@ RESET enable_material;
DROP FOREIGN TABLE remt2;
DROP TABLE loct1;
DROP TABLE loct2;
+-- Test that direct modify and foreign modify work with runtime pruning of
+-- result relations (bug #19484)
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+-- Check DirectModify case
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+explain (verbose, costs off)
+ execute fdw_part_upd(2);
+ QUERY PLAN
+-------------------------------------------------------------------------------------------------------------------------
+ Update on public.fdw_part_update
+ Output: (fdw_part_update_1.tableoid)::regclass, fdw_part_update_1.a, fdw_part_update_1.b
+ Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ -> Append
+ Subplans Removed: 1
+ -> Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ Remote SQL: UPDATE public.fdw_part_update_remote SET b = (b + 1) WHERE ((a = $1::integer)) RETURNING a, b
+(7 rows)
+
+execute fdw_part_upd(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 21
+(1 row)
+
+deallocate fdw_part_upd;
+-- Check ForeignModify case
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+explain (verbose, costs off)
+ execute fdw_part_upd2(2);
+ QUERY PLAN
+--------------------------------------------------------------------------------------------------------------------------------------------------------
+ Update on public.fdw_part_update
+ Output: (fdw_part_update_1.tableoid)::regclass, fdw_part_update_1.a, fdw_part_update_1.b
+ Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ Remote SQL: UPDATE public.fdw_part_update_remote SET b = $2 WHERE ctid = $1 RETURNING a, b
+ -> Append
+ Subplans Removed: 1
+ -> Foreign Scan on public.fdw_part_update_p2 fdw_part_update_2
+ Output: ((fdw_part_update_2.b + ((random())::integer * 0)) + 1), fdw_part_update_2.tableoid, fdw_part_update_2.ctid, fdw_part_update_2.*
+ Remote SQL: SELECT a, b, ctid FROM public.fdw_part_update_remote WHERE ((a = $1::integer)) FOR UPDATE
+(9 rows)
+
+execute fdw_part_upd2(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 22
+(1 row)
+
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
-- ===================================================================
-- test check constraints
-- ===================================================================
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index dfc58beb0d2..697c4a92e2d 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -1778,6 +1778,40 @@ DROP FOREIGN TABLE remt2;
DROP TABLE loct1;
DROP TABLE loct2;
+-- Test that direct modify and foreign modify work with runtime pruning of
+-- result relations (bug #19484)
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+
+-- Check DirectModify case
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+explain (verbose, costs off)
+ execute fdw_part_upd(2);
+execute fdw_part_upd(2);
+deallocate fdw_part_upd;
+
+-- Check ForeignModify case
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+explain (verbose, costs off)
+ execute fdw_part_upd2(2);
+execute fdw_part_upd2(2);
+deallocate fdw_part_upd2;
+
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
+
-- ===================================================================
-- test check constraints
-- ===================================================================
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 112c17b0d64..a40d03d35f3 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4821,7 +4821,7 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ List *fdw_private = (List *) list_nth(mtstate->mt_fdwPrivLists, j);
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 33a6735f08d..846dc516b43 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -5108,6 +5108,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
List *updateColnosLists = NIL;
List *mergeActionLists = NIL;
List *mergeJoinConditions = NIL;
+ List *fdwPrivLists = NIL;
+ Bitmapset *fdwDirectModifyPlans = NULL;
ResultRelInfo *resultRelInfo;
List *arowmarks;
ListCell *l;
@@ -5150,6 +5152,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (keep_rel)
{
+ List *fdwPrivList = (List *) list_nth(node->fdwPrivLists, i);
+
resultRelations = lappend_int(resultRelations, rti);
if (node->withCheckOptionLists)
{
@@ -5185,6 +5189,19 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mergeJoinConditions = lappend(mergeJoinConditions, mergeJoinCondition);
}
+
+ /*
+ * fdwPrivLists/fdwDirectModifyPlans are re-indexed to match
+ * resultRelations
+ */
+ fdwPrivLists = lappend(fdwPrivLists, fdwPrivList);
+ if (bms_is_member(i, node->fdwDirectModifyPlans))
+ {
+ int new_index = list_length(resultRelations) - 1;
+
+ fdwDirectModifyPlans = bms_add_member(fdwDirectModifyPlans,
+ new_index);
+ }
}
i++;
}
@@ -5213,6 +5230,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
+ mtstate->mt_fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
@@ -5288,7 +5306,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/* Initialize the usesFdwDirectModify flag */
resultRelInfo->ri_usesFdwDirectModify =
- bms_is_member(i, node->fdwDirectModifyPlans);
+ bms_is_member(i, fdwDirectModifyPlans);
/*
* Verify result relation is a valid target for the current operation
@@ -5317,7 +5335,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
resultRelInfo->ri_FdwRoutine != NULL &&
resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
+ List *fdw_private = (List *) list_nth(fdwPrivLists, i);
resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
resultRelInfo,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 53c138310db..5871383961f 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
int mt_nrels; /* number of entries in resultRelInfo[] */
ResultRelInfo *resultRelInfo; /* info about target relation(s) */
+ /*
+ * Re-indexed fdw private data lists, aligned with resultRelInfo[] after
+ * pruning
+ */
+ List *mt_fdwPrivLists;
+
/*
* Target relation mentioned in the original statement, used to fire
* statement-level triggers and as the root for tuple routing. (This
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
@ 2026-06-22 08:28 ` Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-22 08:28 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Fujita-san,
On Fri, Jun 19, 2026 at 8:59 PM Etsuro Fujita <[email protected]> wrote:
> On Thu, Jun 18, 2026 at 7:57 PM Amit Langote <[email protected]> wrote:
> > On Thu, Jun 18, 2026 at 19:55 Etsuro Fujita <[email protected]> wrote:
> >> Actually, I've just started reviewing the patch. I'll let you know
> >> the results (if any) by tomorrow.
>
> > Ah, thanks for the heads up.
>
> Here are my review comments:
Thanks a lot for the review.
> @@ -5167,6 +5176,15 @@ ExecInitModifyTable(ModifyTable *node, EState
> *estate, int eflags)
>
> returningLists = lappend(returningLists, returningList);
> }
> + if (node->fdwPrivLists)
> + {
> + List *fdwPrivList = (List *)
> list_nth(node->fdwPrivLists, i);
> +
> + fdwPrivLists = lappend(fdwPrivLists, fdwPrivList);
> + }
>
> As node->fdwPrivLists is always created, the if-test is useless, so I
> removed it like the attached. Also, this is nitpicking but, in the
> attached I moved a comment added above
> ("fdwPrivLists/fdwDirectModifyPlans are re-indexed to match
> resultRelations") to a more appropriate place, and did some minor
> editorialization.
Looks good.
> +-- Runtime pruning of result relations must keep ModifyTable's per-relation
> +-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
> +-- resultRelations. Otherwise BeginForeignModify() reads the wrong
> +-- fdw_private and segfaults.
>
> This comment isn't 100% correct, because this issue happens with
> DirectModify as well. I think we could expand the comment to mention
> that as well, but the comment is already too much/detailed IMO; I
> don't think we add such a comment for a test case, so how about
> simplifying the comment like this: "Test that direct modify and
> foreign modify work with runtime pruning of result relations (bug
> #19484)"
I agree that the details shouldn't leak into test code and have been
trying to follow that principle. Also, bug numbers shouldn't be
mentioned because one can always use `git blame` to find them.
However, since different committers have different styles, I'm fine
with it; kept in the attached updated patch.
> +prepare fdw_part_upd2(int) as
> + update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
> + returning tableoid::regclass, a, b;
> +execute fdw_part_upd2(2);
> +explain (analyze, verbose, costs off, timing off, summary off)
> + execute fdw_part_upd2(2);
>
> I think it's expensive to do explain with the analyze option enabled,
> just for conforming the plan. To save cycles, I removed the option.
> (As the test case for DirectModify was missing the explain test, I
> added it, for consistency.) The test cases are placed in the "test
> tuple routing for foreign-table partitions" section, but they are
> basic ones to test writable foreign tables, so I moved them to the
> "test writable foreign table stuff" section.
Sounds good.
> @@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
> int mt_nrels; /* number of entries in resultRelInfo[] */
> ResultRelInfo *resultRelInfo; /* info about target relation(s) */
>
> + /*
> + * Re-indexed fdw private data lists, aligned with resultRelInfo[] after
> + * pruning
> + */
> + List *mt_fdwPrivLists;
>
> For v18, I think we should put this at the end of the ModifyTableState
> struct, to avoid ABI breakage.
Good point on ABI. Rather than placing it differently per branch, how
about putting mt_fdwPrivLists at the end of the struct alongside
mt_updateColnosLists/mt_mergeActionLists/mt_mergeJoinConditions, which
are the same kind of unpruned-filtered lists? That keeps it ABI-safe
and lets master and 18 share an identical change. I'd fold it into
their existing comment too.
> That's it. Sorry for the delay.
No problem.
Updated patch attached.
--
Thanks, Amit Langote
Attachments:
[application/octet-stream] v3-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu.patch (11.3K, ../../CA+HiwqFT0VDOCAdN1bcVZTOF0oBbR4kzLF-OwEcgPOf01me-Kw@mail.gmail.com/2-v3-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu.patch)
download | inline diff:
From ec941e96354e39517a8dd82eb64e8673ffef310c Mon Sep 17 00:00:00 2001
From: Amit Langote <[email protected]>
Date: Mon, 22 Jun 2026 17:21:45 +0900
Subject: [PATCH v3] Re-index ModifyTable FDW arrays when pruning result
relations
ExecInitModifyTable() rebuilds the per-result-relation lists after
dropping result relations removed by initial runtime pruning. The
re-indexing was done for withCheckOptionLists, returningLists,
updateColnosLists, mergeActionLists and mergeJoinConditions, but
fdwPrivLists and fdwDirectModifyPlans were missed. As a result, a
kept foreign result relation could be handed the wrong fdw_private,
or ri_usesFdwDirectModify could be set from the wrong plan index,
leading to wrong behavior or a crash in BeginForeignModify() and in
the direct-modify path.
show_modifytable_info() had the same problem: it indexed the
plan-ordered node->fdwPrivLists with the post-pruning executor
position, so once initial pruning removed a result relation it
could read a different relation's fdw_private (often a NIL entry),
producing wrong EXPLAIN output or a crash.
Fix by re-indexing fdwPrivLists and fdwDirectModifyPlans alongside
the other lists, saving the re-indexed private lists in
ModifyTableState.mt_fdwPrivLists and reading from there in both
nodeModifyTable.c and explain.c.
Reported-by: Chi Zhang <[email protected]>
Author: Ayush Tiwari <[email protected]>
Author: Rafia Sabih <[email protected]>
Reviewed-by: Matheus Alcantara <[email protected]>
Reviewed-by: Etsuro Fujita <[email protected]>
Discussion: https://postgr.es/m/19484-a3cb82c8cde3c8fa%40postgresql.org
Backpatch-through: 18
---
.../postgres_fdw/expected/postgres_fdw.out | 64 +++++++++++++++++++
contrib/postgres_fdw/sql/postgres_fdw.sql | 34 ++++++++++
src/backend/commands/explain.c | 2 +-
src/backend/executor/nodeModifyTable.c | 22 ++++++-
src/include/nodes/execnodes.h | 8 ++-
5 files changed, 124 insertions(+), 6 deletions(-)
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index abfc84f8860..be455710c9b 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -7132,6 +7132,70 @@ RESET enable_material;
DROP FOREIGN TABLE remt2;
DROP TABLE loct1;
DROP TABLE loct2;
+-- Test that direct modify and foreign modify work with runtime pruning of
+-- result relations (bug #19484)
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+-- Check DirectModify case
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+explain (verbose, costs off)
+ execute fdw_part_upd(2);
+ QUERY PLAN
+-------------------------------------------------------------------------------------------------------------------------
+ Update on public.fdw_part_update
+ Output: (fdw_part_update_1.tableoid)::regclass, fdw_part_update_1.a, fdw_part_update_1.b
+ Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ -> Append
+ Subplans Removed: 1
+ -> Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ Remote SQL: UPDATE public.fdw_part_update_remote SET b = (b + 1) WHERE ((a = $1::integer)) RETURNING a, b
+(7 rows)
+
+execute fdw_part_upd(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 21
+(1 row)
+
+deallocate fdw_part_upd;
+-- Check ForeignModify case
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+explain (verbose, costs off)
+ execute fdw_part_upd2(2);
+ QUERY PLAN
+--------------------------------------------------------------------------------------------------------------------------------------------------------
+ Update on public.fdw_part_update
+ Output: (fdw_part_update_1.tableoid)::regclass, fdw_part_update_1.a, fdw_part_update_1.b
+ Foreign Update on public.fdw_part_update_p2 fdw_part_update_2
+ Remote SQL: UPDATE public.fdw_part_update_remote SET b = $2 WHERE ctid = $1 RETURNING a, b
+ -> Append
+ Subplans Removed: 1
+ -> Foreign Scan on public.fdw_part_update_p2 fdw_part_update_2
+ Output: ((fdw_part_update_2.b + ((random())::integer * 0)) + 1), fdw_part_update_2.tableoid, fdw_part_update_2.ctid, fdw_part_update_2.*
+ Remote SQL: SELECT a, b, ctid FROM public.fdw_part_update_remote WHERE ((a = $1::integer)) FOR UPDATE
+(9 rows)
+
+execute fdw_part_upd2(2);
+ tableoid | a | b
+--------------------+---+----
+ fdw_part_update_p2 | 2 | 22
+(1 row)
+
+deallocate fdw_part_upd2;
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
-- ===================================================================
-- test check constraints
-- ===================================================================
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index f03c5aab4d9..7d2bd6700bc 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -1732,6 +1732,40 @@ DROP FOREIGN TABLE remt2;
DROP TABLE loct1;
DROP TABLE loct2;
+-- Test that direct modify and foreign modify work with runtime pruning of
+-- result relations (bug #19484)
+create table fdw_part_update (a int not null, b int) partition by list (a);
+create table fdw_part_update_p1 partition of fdw_part_update for values in (1);
+create table fdw_part_update_remote (a int not null, b int);
+create foreign table fdw_part_update_p2 partition of fdw_part_update
+ for values in (2)
+ server loopback options (table_name 'fdw_part_update_remote');
+insert into fdw_part_update_p1 values (1, 10);
+insert into fdw_part_update_remote values (2, 20);
+set plan_cache_mode = force_generic_plan;
+
+-- Check DirectModify case
+prepare fdw_part_upd(int) as
+ update fdw_part_update set b = b + 1 where a = $1
+ returning tableoid::regclass, a, b;
+explain (verbose, costs off)
+ execute fdw_part_upd(2);
+execute fdw_part_upd(2);
+deallocate fdw_part_upd;
+
+-- Check ForeignModify case
+prepare fdw_part_upd2(int) as
+ update fdw_part_update set b = b + random()::int * 0 + 1 where a = $1
+ returning tableoid::regclass, a, b;
+explain (verbose, costs off)
+ execute fdw_part_upd2(2);
+execute fdw_part_upd2(2);
+deallocate fdw_part_upd2;
+
+reset plan_cache_mode;
+drop table fdw_part_update;
+drop table fdw_part_update_remote;
+
-- ===================================================================
-- test check constraints
-- ===================================================================
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 7e2792ead71..6d2624e75b8 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4609,7 +4609,7 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ List *fdw_private = (List *) list_nth(mtstate->mt_fdwPrivLists, j);
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index ea8ed94a764..cac30666663 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -4647,6 +4647,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
List *updateColnosLists = NIL;
List *mergeActionLists = NIL;
List *mergeJoinConditions = NIL;
+ List *fdwPrivLists = NIL;
+ Bitmapset *fdwDirectModifyPlans = NULL;
ResultRelInfo *resultRelInfo;
List *arowmarks;
ListCell *l;
@@ -4689,6 +4691,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (keep_rel)
{
+ List *fdwPrivList = (List *) list_nth(node->fdwPrivLists, i);
+
resultRelations = lappend_int(resultRelations, rti);
if (node->withCheckOptionLists)
{
@@ -4724,6 +4728,19 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mergeJoinConditions = lappend(mergeJoinConditions, mergeJoinCondition);
}
+
+ /*
+ * fdwPrivLists/fdwDirectModifyPlans are re-indexed to match
+ * resultRelations
+ */
+ fdwPrivLists = lappend(fdwPrivLists, fdwPrivList);
+ if (bms_is_member(i, node->fdwDirectModifyPlans))
+ {
+ int new_index = list_length(resultRelations) - 1;
+
+ fdwDirectModifyPlans = bms_add_member(fdwDirectModifyPlans,
+ new_index);
+ }
}
i++;
}
@@ -4753,6 +4770,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
+ mtstate->mt_fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
@@ -4828,7 +4846,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/* Initialize the usesFdwDirectModify flag */
resultRelInfo->ri_usesFdwDirectModify =
- bms_is_member(i, node->fdwDirectModifyPlans);
+ bms_is_member(i, fdwDirectModifyPlans);
/*
* Verify result relation is a valid target for the current operation
@@ -4857,7 +4875,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
resultRelInfo->ri_FdwRoutine != NULL &&
resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
+ List *fdw_private = (List *) list_nth(fdwPrivLists, i);
resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
resultRelInfo,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 409e172bfb6..6677a03caab 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1453,13 +1453,15 @@ typedef struct ModifyTableState
double mt_merge_deleted;
/*
- * Lists of valid updateColnosLists, mergeActionLists, and
- * mergeJoinConditions. These contain only entries for unpruned
- * relations, filtered from the corresponding lists in ModifyTable.
+ * Lists of valid updateColnosLists, mergeActionLists,
+ * mergeJoinConditions, and fdwPrivLists. These contain only entries for
+ * unpruned relations, filtered from the corresponding lists in
+ * ModifyTable.
*/
List *mt_updateColnosLists;
List *mt_mergeActionLists;
List *mt_mergeJoinConditions;
+ List *mt_fdwPrivLists;
} ModifyTableState;
/* ----------------
--
2.47.3
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-23 08:27 ` Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Etsuro Fujita @ 2026-06-23 08:27 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Amit-san,
On Mon, Jun 22, 2026 at 5:28 PM Amit Langote <[email protected]> wrote:
> On Fri, Jun 19, 2026 at 8:59 PM Etsuro Fujita <[email protected]> wrote:
> > +-- Runtime pruning of result relations must keep ModifyTable's per-relation
> > +-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
> > +-- resultRelations. Otherwise BeginForeignModify() reads the wrong
> > +-- fdw_private and segfaults.
> >
> > This comment isn't 100% correct, because this issue happens with
> > DirectModify as well. I think we could expand the comment to mention
> > that as well, but the comment is already too much/detailed IMO; I
> > don't think we add such a comment for a test case, so how about
> > simplifying the comment like this: "Test that direct modify and
> > foreign modify work with runtime pruning of result relations (bug
> > #19484)"
>
> I agree that the details shouldn't leak into test code and have been
> trying to follow that principle. Also, bug numbers shouldn't be
> mentioned because one can always use `git blame` to find them.
> However, since different committers have different styles, I'm fine
> with it; kept in the attached updated patch.
Thanks!
> > @@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
> > int mt_nrels; /* number of entries in resultRelInfo[] */
> > ResultRelInfo *resultRelInfo; /* info about target relation(s) */
> >
> > + /*
> > + * Re-indexed fdw private data lists, aligned with resultRelInfo[] after
> > + * pruning
> > + */
> > + List *mt_fdwPrivLists;
> >
> > For v18, I think we should put this at the end of the ModifyTableState
> > struct, to avoid ABI breakage.
>
> Good point on ABI. Rather than placing it differently per branch, how
> about putting mt_fdwPrivLists at the end of the struct alongside
> mt_updateColnosLists/mt_mergeActionLists/mt_mergeJoinConditions, which
> are the same kind of unpruned-filtered lists? That keeps it ABI-safe
> and lets master and 18 share an identical change. I'd fold it into
> their existing comment too.
That's a good idea! So +1
> Updated patch attached.
LGTM.
Best regards,
Etsuro Fujita
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
@ 2026-06-24 00:00 ` Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-24 00:00 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
On Tue, Jun 23, 2026 at 5:27 PM Etsuro Fujita <[email protected]> wrote:
> On Mon, Jun 22, 2026 at 5:28 PM Amit Langote <[email protected]> wrote:
> > On Fri, Jun 19, 2026 at 8:59 PM Etsuro Fujita <[email protected]> wrote:
>
> > > +-- Runtime pruning of result relations must keep ModifyTable's per-relation
> > > +-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the kept
> > > +-- resultRelations. Otherwise BeginForeignModify() reads the wrong
> > > +-- fdw_private and segfaults.
> > >
> > > This comment isn't 100% correct, because this issue happens with
> > > DirectModify as well. I think we could expand the comment to mention
> > > that as well, but the comment is already too much/detailed IMO; I
> > > don't think we add such a comment for a test case, so how about
> > > simplifying the comment like this: "Test that direct modify and
> > > foreign modify work with runtime pruning of result relations (bug
> > > #19484)"
> >
> > I agree that the details shouldn't leak into test code and have been
> > trying to follow that principle. Also, bug numbers shouldn't be
> > mentioned because one can always use `git blame` to find them.
> > However, since different committers have different styles, I'm fine
> > with it; kept in the attached updated patch.
>
> Thanks!
>
> > > @@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
> > > int mt_nrels; /* number of entries in resultRelInfo[] */
> > > ResultRelInfo *resultRelInfo; /* info about target relation(s) */
> > >
> > > + /*
> > > + * Re-indexed fdw private data lists, aligned with resultRelInfo[] after
> > > + * pruning
> > > + */
> > > + List *mt_fdwPrivLists;
> > >
> > > For v18, I think we should put this at the end of the ModifyTableState
> > > struct, to avoid ABI breakage.
> >
> > Good point on ABI. Rather than placing it differently per branch, how
> > about putting mt_fdwPrivLists at the end of the struct alongside
> > mt_updateColnosLists/mt_mergeActionLists/mt_mergeJoinConditions, which
> > are the same kind of unpruned-filtered lists? That keeps it ABI-safe
> > and lets master and 18 share an identical change. I'd fold it into
> > their existing comment too.
>
> That's a good idea! So +1
>
> > Updated patch attached.
>
> LGTM.
Pushed, thanks for checking.
--
Thanks, Amit Langote
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-24 01:43 ` Amit Langote <[email protected]>
2026-06-24 01:53 ` Re: BUG #19484: Segmentation fault triggered by FDW Tom Lane <[email protected]>
2026-06-24 02:23 ` Re: BUG #19484: Segmentation fault triggered by FDW Richard Guo <[email protected]>
0 siblings, 2 replies; 32+ messages in thread
From: Amit Langote @ 2026-06-24 01:43 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
On Wed, Jun 24, 2026 at 9:00 Amit Langote <[email protected]> wrote:
> On Tue, Jun 23, 2026 at 5:27 PM Etsuro Fujita <[email protected]>
> wrote:
> > On Mon, Jun 22, 2026 at 5:28 PM Amit Langote <[email protected]>
> wrote:
> > > On Fri, Jun 19, 2026 at 8:59 PM Etsuro Fujita <[email protected]>
> wrote:
> >
> > > > +-- Runtime pruning of result relations must keep ModifyTable's
> per-relation
> > > > +-- FDW arrays (fdwPrivLists, fdwDirectModifyPlans) aligned with the
> kept
> > > > +-- resultRelations. Otherwise BeginForeignModify() reads the wrong
> > > > +-- fdw_private and segfaults.
> > > >
> > > > This comment isn't 100% correct, because this issue happens with
> > > > DirectModify as well. I think we could expand the comment to mention
> > > > that as well, but the comment is already too much/detailed IMO; I
> > > > don't think we add such a comment for a test case, so how about
> > > > simplifying the comment like this: "Test that direct modify and
> > > > foreign modify work with runtime pruning of result relations (bug
> > > > #19484)"
> > >
> > > I agree that the details shouldn't leak into test code and have been
> > > trying to follow that principle. Also, bug numbers shouldn't be
> > > mentioned because one can always use `git blame` to find them.
> > > However, since different committers have different styles, I'm fine
> > > with it; kept in the attached updated patch.
> >
> > Thanks!
> >
> > > > @@ -1446,6 +1446,12 @@ typedef struct ModifyTableState
> > > > int mt_nrels; /* number of entries in
> resultRelInfo[] */
> > > > ResultRelInfo *resultRelInfo; /* info about target relation(s)
> */
> > > >
> > > > + /*
> > > > + * Re-indexed fdw private data lists, aligned with
> resultRelInfo[] after
> > > > + * pruning
> > > > + */
> > > > + List *mt_fdwPrivLists;
> > > >
> > > > For v18, I think we should put this at the end of the
> ModifyTableState
> > > > struct, to avoid ABI breakage.
> > >
> > > Good point on ABI. Rather than placing it differently per branch, how
> > > about putting mt_fdwPrivLists at the end of the struct alongside
> > > mt_updateColnosLists/mt_mergeActionLists/mt_mergeJoinConditions, which
> > > are the same kind of unpruned-filtered lists? That keeps it ABI-safe
> > > and lets master and 18 share an identical change. I'd fold it into
> > > their existing comment too.
> >
> > That's a good idea! So +1
> >
> > > Updated patch attached.
> >
> > LGTM.
>
> Pushed, thanks for checking.
crake is now red on REL_18:
https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=crake&dt=2026-06-24%2000%3A02%3A03
It reports sizeof(ModifyTableState) grew by 8 bytes.
That’s from adding mt_fdwPrivLists at the end of the struct. Placing it
last keeps existing field offsets stable, which is what extensions reading
the node rely on, but it does grow the struct, which is what the checker
flags. I believe we’ve added trailing struct members in back branches
before for exactly this reason. Is a flagged sizeof increase acceptable
here under that precedent, or do we now want to avoid any flagged ABI
change on a back branch?
If we’d rather avoid it, I have a no-field alternative for REL_18:
show_modifytable_info() is the only reader of the re-indexed list, and it
can recompute the mapping from node->resultRelations and
node->fdwPrivLists, both plan-ordered and untouched by pruning. master
would keep the field as committed, so the branches would differ slightly.
I’m inclined toward the no-field version for REL_18 to keep the farm green,
unless someone would rather keep the same code in both branches and accept
the size change. I’ll hold off briefly for any thoughts before doing that.
- Amit
>
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-24 01:53 ` Tom Lane <[email protected]>
2026-06-24 03:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
1 sibling, 1 reply; 32+ messages in thread
From: Tom Lane @ 2026-06-24 01:53 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Etsuro Fujita <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Amit Langote <[email protected]> writes:
> crake is now red on REL_18:
> https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=crake&dt=2026-06-24%2000%3A02%3A03
> It reports sizeof(ModifyTableState) grew by 8 bytes.
> That’s from adding mt_fdwPrivLists at the end of the struct. Placing it
> last keeps existing field offsets stable, which is what extensions reading
> the node rely on, but it does grow the struct, which is what the checker
> flags. I believe we’ve added trailing struct members in back branches
> before for exactly this reason. Is a flagged sizeof increase acceptable
> here under that precedent, or do we now want to avoid any flagged ABI
> change on a back branch?
I don't believe that the addition of ABI checking was meant to change
our back-patching policies, just to make sure we don't make
unintentional ABI changes. As you say, we've added trailing fields
before. The critical question is whether it's likely that any
extensions create their own ModifyTableState nodes (and might make
them too small and/or fail to fill the new field correctly).
I was about to say that that seems unlikely to me, but a check of
Debian Code Search immediately found pg_rewrite doing it. So yeah,
looks like we'd better adopt the no-ABI-break solution.
regards, tom lane
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:53 ` Re: BUG #19484: Segmentation fault triggered by FDW Tom Lane <[email protected]>
@ 2026-06-24 03:50 ` Amit Langote <[email protected]>
0 siblings, 0 replies; 32+ messages in thread
From: Amit Langote @ 2026-06-24 03:50 UTC (permalink / raw)
To: Tom Lane <[email protected]>; +Cc: Etsuro Fujita <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
On Wed, Jun 24, 2026 at 10:53 AM Tom Lane <[email protected]> wrote:
> Amit Langote <[email protected]> writes:
> > crake is now red on REL_18:
> > https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=crake&dt=2026-06-24%2000%3A02%3A03
>
> > It reports sizeof(ModifyTableState) grew by 8 bytes.
>
> > That’s from adding mt_fdwPrivLists at the end of the struct. Placing it
> > last keeps existing field offsets stable, which is what extensions reading
> > the node rely on, but it does grow the struct, which is what the checker
> > flags. I believe we’ve added trailing struct members in back branches
> > before for exactly this reason. Is a flagged sizeof increase acceptable
> > here under that precedent, or do we now want to avoid any flagged ABI
> > change on a back branch?
>
> I don't believe that the addition of ABI checking was meant to change
> our back-patching policies, just to make sure we don't make
> unintentional ABI changes. As you say, we've added trailing fields
> before. The critical question is whether it's likely that any
> extensions create their own ModifyTableState nodes (and might make
> them too small and/or fail to fill the new field correctly).
>
> I was about to say that that seems unlikely to me, but a check of
> Debian Code Search immediately found pg_rewrite doing it. So yeah,
> looks like we'd better adopt the no-ABI-break solution.
Ah, ok, will post the patch to do so in the REL_18_STABLE branch.
Thanks for the comment.
--
Thanks, Amit Langote
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-24 02:23 ` Richard Guo <[email protected]>
2026-06-24 04:25 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
1 sibling, 1 reply; 32+ messages in thread
From: Richard Guo @ 2026-06-24 02:23 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Etsuro Fujita <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
On Wed, Jun 24, 2026 at 10:43 AM Amit Langote <[email protected]> wrote:
> If we’d rather avoid it, I have a no-field alternative for REL_18: show_modifytable_info() is the only reader of the re-indexed list, and it can recompute the mapping from node->resultRelations and node->fdwPrivLists, both plan-ordered and untouched by pruning.
This sounds like a nice solution. Since show_modifytable_info() is
only used for EXPLAIN, I guess the recompute overhead on the
re-indexed list should be fine.
- Richard
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 02:23 ` Re: BUG #19484: Segmentation fault triggered by FDW Richard Guo <[email protected]>
@ 2026-06-24 04:25 ` Amit Langote <[email protected]>
2026-06-24 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-24 04:25 UTC (permalink / raw)
To: Richard Guo <[email protected]>; +Cc: Etsuro Fujita <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
On Wed, Jun 24, 2026 at 11:23 AM Richard Guo <[email protected]> wrote:
> On Wed, Jun 24, 2026 at 10:43 AM Amit Langote <[email protected]> wrote:
> > If we’d rather avoid it, I have a no-field alternative for REL_18: show_modifytable_info() is the only reader of the re-indexed list, and it can recompute the mapping from node->resultRelations and node->fdwPrivLists, both plan-ordered and untouched by pruning.
>
> This sounds like a nice solution. Since show_modifytable_info() is
> only used for EXPLAIN, I guess the recompute overhead on the
> re-indexed list should be fine.
Thanks for chiming in, here is the patch to do so.
--
Thanks, Amit Langote
Attachments:
[application/octet-stream] v1-0001-Avoid-ABI-break-in-ModifyTableState-from-the-FDW-.patch (4.2K, ../../CA+HiwqEbqW_957S9UAEoZJ5aYyBF_Bp+ON+6thQNCySxSwv+Fg@mail.gmail.com/2-v1-0001-Avoid-ABI-break-in-ModifyTableState-from-the-FDW-.patch)
download | inline diff:
From 32c4b647ec492a20b159c546a24a021a45360c6b Mon Sep 17 00:00:00 2001
From: Amit Langote <[email protected]>
Date: Wed, 24 Jun 2026 13:22:11 +0900
Subject: [PATCH v1] Avoid ABI break in ModifyTableState from the FDW pruning
fix
Commit 1ef917e3a6 fixed the re-indexing of ModifyTable's FDW arrays
when initial runtime pruning removes result relations, but it did so
by adding a new mt_fdwPrivLists field to ModifyTableState. Although
the field was placed at the end of the struct to keep the offsets of
existing fields stable, it still enlarges sizeof(ModifyTableState),
which the ABI compliance check flags on the buildfarm (e.g. crake).
The field existed only so that show_modifytable_info() could recover the
re-indexed fdw_private after executor startup; the executor-side fix in
ExecInitModifyTable() that actually prevents the crash does not depend on
it. Remove the field and have show_modifytable_info() instead look up
each kept relation's fdw_private from the original, pre-pruning
node->fdwPrivLists, which is parallel to node->resultRelations and is
left intact by pruning, by matching on the range table index.
This is applied to REL_18 only; master keeps the mt_fdwPrivLists field
and is unaffected, so the two diverge slightly here.
Reported on the buildfarm (member crake).
Per a suggestion from Tom Lane.
Discussion: https://postgr.es/m/CA+HiwqEhe7-v5Q0-oOoW3RaO4voYcGK-JfinbYEWXwutDGSOtQ@mail.gmail.com
---
src/backend/commands/explain.c | 21 ++++++++++++++++++++-
src/backend/executor/nodeModifyTable.c | 1 -
src/include/nodes/execnodes.h | 8 +++-----
3 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 6d2624e75b8..7aa6636af5f 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4609,7 +4609,26 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(mtstate->mt_fdwPrivLists, j);
+ Index rti = resultRelInfo->ri_RangeTableIndex;
+ List *fdw_private = NIL;
+ ListCell *lc1;
+ ListCell *lc2;
+
+ /*
+ * node->fdwPrivLists is indexed by the original, pre-pruning
+ * result relation order and is parallel to node->resultRelations.
+ * Initial pruning may have dropped earlier relations, so the kept
+ * index j need not match the original position; find this
+ * relation's entry by its range table index instead.
+ */
+ forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
+ {
+ if (lfirst_int(lc1) == (int) rti)
+ {
+ fdw_private = (List *) lfirst(lc2);
+ break;
+ }
+ }
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index cac30666663..7c1d0e9588e 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -4770,7 +4770,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
- mtstate->mt_fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6677a03caab..409e172bfb6 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1453,15 +1453,13 @@ typedef struct ModifyTableState
double mt_merge_deleted;
/*
- * Lists of valid updateColnosLists, mergeActionLists,
- * mergeJoinConditions, and fdwPrivLists. These contain only entries for
- * unpruned relations, filtered from the corresponding lists in
- * ModifyTable.
+ * Lists of valid updateColnosLists, mergeActionLists, and
+ * mergeJoinConditions. These contain only entries for unpruned
+ * relations, filtered from the corresponding lists in ModifyTable.
*/
List *mt_updateColnosLists;
List *mt_mergeActionLists;
List *mt_mergeJoinConditions;
- List *mt_fdwPrivLists;
} ModifyTableState;
/* ----------------
--
2.47.3
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 02:23 ` Re: BUG #19484: Segmentation fault triggered by FDW Richard Guo <[email protected]>
2026-06-24 04:25 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-24 09:15 ` Etsuro Fujita <[email protected]>
2026-06-24 11:20 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Etsuro Fujita @ 2026-06-24 09:15 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Richard Guo <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Amit-san,
On Wed, Jun 24, 2026 at 1:25 PM Amit Langote <[email protected]> wrote:
> On Wed, Jun 24, 2026 at 11:23 AM Richard Guo <[email protected]> wrote:
> > On Wed, Jun 24, 2026 at 10:43 AM Amit Langote <[email protected]> wrote:
> > > If we’d rather avoid it, I have a no-field alternative for REL_18: show_modifytable_info() is the only reader of the re-indexed list, and it can recompute the mapping from node->resultRelations and node->fdwPrivLists, both plan-ordered and untouched by pruning.
> >
> > This sounds like a nice solution. Since show_modifytable_info() is
> > only used for EXPLAIN, I guess the recompute overhead on the
> > re-indexed list should be fine.
>
> Thanks for chiming in, here is the patch to do so.
Thanks for the patch!
+ /*
+ * node->fdwPrivLists is indexed by the original, pre-pruning
+ * result relation order and is parallel to node->resultRelations.
+ * Initial pruning may have dropped earlier relations, so the kept
+ * index j need not match the original position; find this
+ * relation's entry by its range table index instead.
+ */
+ forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
+ {
+ if (lfirst_int(lc1) == (int) rti)
+ {
+ fdw_private = (List *) lfirst(lc2);
+ break;
+ }
+ }
I think it's good to skip this for efficiency, when there are no
pruned result relations.
Other than that the patch looks good to me.
I didn't know pg_rewrite's use of ModifyTableState, which was
different than I expected. Sorry for that.
Best regards,
Etsuro Fujita
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 02:23 ` Re: BUG #19484: Segmentation fault triggered by FDW Richard Guo <[email protected]>
2026-06-24 04:25 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
@ 2026-06-24 11:20 ` Amit Langote <[email protected]>
2026-06-24 17:02 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-24 11:20 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Richard Guo <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Fujita-san,
On Wed, Jun 24, 2026 at 6:15 PM Etsuro Fujita <[email protected]> wrote:
> On Wed, Jun 24, 2026 at 1:25 PM Amit Langote <[email protected]> wrote:
> > On Wed, Jun 24, 2026 at 11:23 AM Richard Guo <[email protected]> wrote:
> > > On Wed, Jun 24, 2026 at 10:43 AM Amit Langote <[email protected]> wrote:
> > > > If we’d rather avoid it, I have a no-field alternative for REL_18: show_modifytable_info() is the only reader of the re-indexed list, and it can recompute the mapping from node->resultRelations and node->fdwPrivLists, both plan-ordered and untouched by pruning.
> > >
> > > This sounds like a nice solution. Since show_modifytable_info() is
> > > only used for EXPLAIN, I guess the recompute overhead on the
> > > re-indexed list should be fine.
> >
> > Thanks for chiming in, here is the patch to do so.
>
> Thanks for the patch!
>
> + /*
> + * node->fdwPrivLists is indexed by the original, pre-pruning
> + * result relation order and is parallel to node->resultRelations.
> + * Initial pruning may have dropped earlier relations, so the kept
> + * index j need not match the original position; find this
> + * relation's entry by its range table index instead.
> + */
> + forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
> + {
> + if (lfirst_int(lc1) == (int) rti)
> + {
> + fdw_private = (List *) lfirst(lc2);
> + break;
> + }
> + }
>
> I think it's good to skip this for efficiency, when there are no
> pruned result relations.
Thanks for the review. v2 attached implements your suggestion: it
indexes node->fdwPrivLists directly with j when no result relations
were pruned, and only falls back to matching by range table index when
pruning appears to have dropped some.
> Other than that the patch looks good to me.
>
> I didn't know pg_rewrite's use of ModifyTableState, which was
> different than I expected. Sorry for that.
No need to apologize at all. Tom's point about it was new to me too.
I will push v2 to REL_18 tomorrow barring objections.
--
Thanks, Amit Langote
Attachments:
[application/octet-stream] v2-0001-Avoid-ABI-break-in-ModifyTableState-from-the-FDW-.patch (4.5K, ../../CA+HiwqFd61sXgUWijKg8DfRQDtwYEGSdxuEPDb8rq22rxzxN_g@mail.gmail.com/2-v2-0001-Avoid-ABI-break-in-ModifyTableState-from-the-FDW-.patch)
download | inline diff:
From 5407f57e9ce7a89946e0fe20a3f6d6cdf21eabd8 Mon Sep 17 00:00:00 2001
From: Amit Langote <[email protected]>
Date: Wed, 24 Jun 2026 20:12:00 +0900
Subject: [PATCH v2] Avoid ABI break in ModifyTableState from the FDW pruning
fix
Commit 1ef917e3a6 fixed the re-indexing of ModifyTable's FDW arrays
when initial runtime pruning removes result relations, but it did so
by adding a new mt_fdwPrivLists field to ModifyTableState. Although
the field was placed at the end of the struct to keep the offsets of
existing fields stable, it still enlarges sizeof(ModifyTableState),
which the ABI compliance check flags on the buildfarm (e.g. crake).
The field existed only so that show_modifytable_info() could recover the
re-indexed fdw_private after executor startup; the executor-side fix in
ExecInitModifyTable() that actually prevents the crash does not depend on
it. Remove the field and have show_modifytable_info() instead look up
each kept relation's fdw_private from the original, pre-pruning
node->fdwPrivLists, which is parallel to node->resultRelations and left
intact by pruning. When nothing was pruned the lookup is a direct index;
otherwise it matches on the range table index.
This is applied to REL_18 only; master keeps the mt_fdwPrivLists field
and is unaffected, so the two diverge slightly here.
Reported on the buildfarm (member crake).
Per a suggestion from Tom Lane.
Reviewed-by: Etsuro Fujita <[email protected]>
Discussion: https://postgr.es/m/CA+HiwqEhe7-v5Q0-oOoW3RaO4voYcGK-JfinbYEWXwutDGSOtQ@mail.gmail.com
---
src/backend/commands/explain.c | 29 +++++++++++++++++++++++++-
src/backend/executor/nodeModifyTable.c | 1 -
src/include/nodes/execnodes.h | 8 +++----
3 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 6d2624e75b8..444178ed89c 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4609,7 +4609,34 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(mtstate->mt_fdwPrivLists, j);
+ List *fdw_private;
+
+ /*
+ * node->fdwPrivLists is indexed by the original, pre-pruning
+ * result relation order and is parallel to node->resultRelations.
+ * If no result relations were pruned, the kept order matches that
+ * order and we can index it directly with j. Otherwise the kept
+ * index j need not match the original position, so find this
+ * relation's entry by its range table index instead.
+ */
+ if (list_length(node->resultRelations) == mtstate->mt_nrels)
+ fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ else
+ {
+ Index rti = resultRelInfo->ri_RangeTableIndex;
+ ListCell *lc1;
+ ListCell *lc2;
+
+ fdw_private = NIL;
+ forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
+ {
+ if (lfirst_int(lc1) == (int) rti)
+ {
+ fdw_private = (List *) lfirst(lc2);
+ break;
+ }
+ }
+ }
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index cac30666663..7c1d0e9588e 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -4770,7 +4770,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
- mtstate->mt_fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6677a03caab..409e172bfb6 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1453,15 +1453,13 @@ typedef struct ModifyTableState
double mt_merge_deleted;
/*
- * Lists of valid updateColnosLists, mergeActionLists,
- * mergeJoinConditions, and fdwPrivLists. These contain only entries for
- * unpruned relations, filtered from the corresponding lists in
- * ModifyTable.
+ * Lists of valid updateColnosLists, mergeActionLists, and
+ * mergeJoinConditions. These contain only entries for unpruned
+ * relations, filtered from the corresponding lists in ModifyTable.
*/
List *mt_updateColnosLists;
List *mt_mergeActionLists;
List *mt_mergeJoinConditions;
- List *mt_fdwPrivLists;
} ModifyTableState;
/* ----------------
--
2.47.3
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 02:23 ` Re: BUG #19484: Segmentation fault triggered by FDW Richard Guo <[email protected]>
2026-06-24 04:25 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 11:20 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-24 17:02 ` Etsuro Fujita <[email protected]>
2026-06-24 23:24 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Etsuro Fujita @ 2026-06-24 17:02 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Richard Guo <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Amit-san,
On Wed, Jun 24, 2026 at 8:20 PM Amit Langote <[email protected]> wrote:
> On Wed, Jun 24, 2026 at 6:15 PM Etsuro Fujita <[email protected]> wrote:
> > + /*
> > + * node->fdwPrivLists is indexed by the original, pre-pruning
> > + * result relation order and is parallel to node->resultRelations.
> > + * Initial pruning may have dropped earlier relations, so the kept
> > + * index j need not match the original position; find this
> > + * relation's entry by its range table index instead.
> > + */
> > + forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
> > + {
> > + if (lfirst_int(lc1) == (int) rti)
> > + {
> > + fdw_private = (List *) lfirst(lc2);
> > + break;
> > + }
> > + }
> >
> > I think it's good to skip this for efficiency, when there are no
> > pruned result relations.
>
> Thanks for the review. v2 attached implements your suggestion: it
> indexes node->fdwPrivLists directly with j when no result relations
> were pruned, and only falls back to matching by range table index when
> pruning appears to have dropped some.
Thank you for doing that work!
This might be nitpicking, but:
+ if (list_length(node->resultRelations) == mtstate->mt_nrels)
+ fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ else
+ {
+ Index rti = resultRelInfo->ri_RangeTableIndex;
+ ListCell *lc1;
+ ListCell *lc2;
+
+ fdw_private = NIL;
+ forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
+ {
+ if (lfirst_int(lc1) == (int) rti)
+ {
+ fdw_private = (List *) lfirst(lc2);
+ break;
+ }
+ }
+ }
I'd put the if-test outside of the outer loop to save cycles.
Other than that v2 looks good to me.
(The forboth loop actually causes an n-squared calculation, but it's
done only when pruning occurs, in which case the number of remaining
result relations would be reduced, so that wouldn't be a problem.)
Best regards,
Etsuro Fujita
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 02:23 ` Re: BUG #19484: Segmentation fault triggered by FDW Richard Guo <[email protected]>
2026-06-24 04:25 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 11:20 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 17:02 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
@ 2026-06-24 23:24 ` Amit Langote <[email protected]>
2026-06-25 06:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-24 23:24 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Richard Guo <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Fujita-san,
On Thu, Jun 25, 2026 at 2:02 AM Etsuro Fujita <[email protected]> wrote:
> On Wed, Jun 24, 2026 at 8:20 PM Amit Langote <[email protected]> wrote:
> > On Wed, Jun 24, 2026 at 6:15 PM Etsuro Fujita <[email protected]> wrote:
> > > + /*
> > > + * node->fdwPrivLists is indexed by the original, pre-pruning
> > > + * result relation order and is parallel to node->resultRelations.
> > > + * Initial pruning may have dropped earlier relations, so the kept
> > > + * index j need not match the original position; find this
> > > + * relation's entry by its range table index instead.
> > > + */
> > > + forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
> > > + {
> > > + if (lfirst_int(lc1) == (int) rti)
> > > + {
> > > + fdw_private = (List *) lfirst(lc2);
> > > + break;
> > > + }
> > > + }
> > >
> > > I think it's good to skip this for efficiency, when there are no
> > > pruned result relations.
> >
> > Thanks for the review. v2 attached implements your suggestion: it
> > indexes node->fdwPrivLists directly with j when no result relations
> > were pruned, and only falls back to matching by range table index when
> > pruning appears to have dropped some.
>
> Thank you for doing that work!
>
> This might be nitpicking, but:
>
> + if (list_length(node->resultRelations) == mtstate->mt_nrels)
> + fdw_private = (List *) list_nth(node->fdwPrivLists, j);
> + else
> + {
> + Index rti = resultRelInfo->ri_RangeTableIndex;
> + ListCell *lc1;
> + ListCell *lc2;
> +
> + fdw_private = NIL;
> + forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
> + {
> + if (lfirst_int(lc1) == (int) rti)
> + {
> + fdw_private = (List *) lfirst(lc2);
> + break;
> + }
> + }
> + }
>
> I'd put the if-test outside of the outer loop to save cycles.
Right, it's loop-invariant. v3 attached computes a boolean
(nopruning), like labeltargets, once before the loop and uses it
inside.
> Other than that v2 looks good to me.
>
> (The forboth loop actually causes an n-squared calculation, but it's
> done only when pruning occurs, in which case the number of remaining
> result relations would be reduced, so that wouldn't be a problem.)
Right, though strictly the inner forboth scans node->resultRelations,
which pruning leaves at its original length, so it's the original
relation count that bounds the scan rather than the reduced one.
Either way it's EXPLAIN-only with small counts, so it's not a concern.
Thanks again for the review.
--
Thanks, Amit Langote
Attachments:
[application/octet-stream] v3-0001-Avoid-ABI-break-in-ModifyTableState-from-the-FDW-.patch (5.2K, ../../CA+HiwqEr9AQoG=ySqC9nVJ7n9F52xPYGEb-r2xCW5ut0QhzauA@mail.gmail.com/2-v3-0001-Avoid-ABI-break-in-ModifyTableState-from-the-FDW-.patch)
download | inline diff:
From 08f4aeaff6bbc1bde65554c851d4b3da626cb3aa Mon Sep 17 00:00:00 2001
From: Amit Langote <[email protected]>
Date: Thu, 25 Jun 2026 08:13:28 +0900
Subject: [PATCH v3] Avoid ABI break in ModifyTableState from the FDW pruning
fix
Commit 1ef917e3a6 fixed the re-indexing of ModifyTable's FDW arrays
when initial runtime pruning removes result relations, but it did so
by adding a new mt_fdwPrivLists field to ModifyTableState. Although
the field was placed at the end of the struct to keep the offsets of
existing fields stable, it still enlarges sizeof(ModifyTableState),
which the ABI compliance check flags on the buildfarm (e.g. crake).
The field existed only so that show_modifytable_info() could recover the
re-indexed fdw_private after executor startup; the executor-side fix in
ExecInitModifyTable() that actually prevents the crash does not depend on
it. Remove the field and have show_modifytable_info() instead look up
each kept relation's fdw_private from the original, pre-pruning
node->fdwPrivLists, which is parallel to node->resultRelations and left
intact by pruning. When nothing was pruned the lookup is a direct index;
otherwise it matches on the range table index.
This is applied to REL_18 only; master keeps the mt_fdwPrivLists field
and is unaffected, so the two diverge slightly here.
Reported on the buildfarm (member crake).
Per a suggestion from Tom Lane.
Reviewed-by: Etsuro Fujita <[email protected]>
Discussion: https://postgr.es/m/CA+HiwqEhe7-v5Q0-oOoW3RaO4voYcGK-JfinbYEWXwutDGSOtQ@mail.gmail.com
---
src/backend/commands/explain.c | 36 +++++++++++++++++++++++++-
src/backend/executor/nodeModifyTable.c | 1 -
src/include/nodes/execnodes.h | 8 +++---
3 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 6d2624e75b8..15ef3304863 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4524,6 +4524,7 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
const char *operation;
const char *foperation;
bool labeltargets;
+ bool nopruning;
int j;
List *idxNames = NIL;
ListCell *lst;
@@ -4571,6 +4572,16 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
if (labeltargets)
ExplainOpenGroup("Target Tables", "Target Tables", false, es);
+ /*
+ * node->fdwPrivLists is parallel to node->resultRelations, in the
+ * original pre-pruning order. If no result relations were pruned, the
+ * entries in mtstate->resultRelInfo[] are in that same order and can be
+ * matched to fdwPrivLists positionally; otherwise we have to look each
+ * one up by range table index below. This test is loop-invariant, so
+ * compute it once here.
+ */
+ nopruning = (list_length(node->resultRelations) == mtstate->mt_nrels);
+
for (j = 0; j < mtstate->mt_nrels; j++)
{
ResultRelInfo *resultRelInfo = mtstate->resultRelInfo + j;
@@ -4609,7 +4620,30 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
fdwroutine != NULL &&
fdwroutine->ExplainForeignModify != NULL)
{
- List *fdw_private = (List *) list_nth(mtstate->mt_fdwPrivLists, j);
+ List *fdw_private;
+
+ /*
+ * Find this relation's fdw_private: index fdwPrivLists directly
+ * when nothing was pruned, else match by range table index.
+ */
+ if (nopruning)
+ fdw_private = (List *) list_nth(node->fdwPrivLists, j);
+ else
+ {
+ Index rti = resultRelInfo->ri_RangeTableIndex;
+ ListCell *lc1;
+ ListCell *lc2;
+
+ fdw_private = NIL;
+ forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
+ {
+ if (lfirst_int(lc1) == (int) rti)
+ {
+ fdw_private = (List *) lfirst(lc2);
+ break;
+ }
+ }
+ }
fdwroutine->ExplainForeignModify(mtstate,
resultRelInfo,
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index cac30666663..7c1d0e9588e 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -4770,7 +4770,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_updateColnosLists = updateColnosLists;
mtstate->mt_mergeActionLists = mergeActionLists;
mtstate->mt_mergeJoinConditions = mergeJoinConditions;
- mtstate->mt_fdwPrivLists = fdwPrivLists;
/*----------
* Resolve the target relation. This is the same as:
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6677a03caab..409e172bfb6 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1453,15 +1453,13 @@ typedef struct ModifyTableState
double mt_merge_deleted;
/*
- * Lists of valid updateColnosLists, mergeActionLists,
- * mergeJoinConditions, and fdwPrivLists. These contain only entries for
- * unpruned relations, filtered from the corresponding lists in
- * ModifyTable.
+ * Lists of valid updateColnosLists, mergeActionLists, and
+ * mergeJoinConditions. These contain only entries for unpruned
+ * relations, filtered from the corresponding lists in ModifyTable.
*/
List *mt_updateColnosLists;
List *mt_mergeActionLists;
List *mt_mergeJoinConditions;
- List *mt_fdwPrivLists;
} ModifyTableState;
/* ----------------
--
2.47.3
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 02:23 ` Re: BUG #19484: Segmentation fault triggered by FDW Richard Guo <[email protected]>
2026-06-24 04:25 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 11:20 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 17:02 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 23:24 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-25 06:15 ` Etsuro Fujita <[email protected]>
2026-06-25 11:47 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Etsuro Fujita @ 2026-06-25 06:15 UTC (permalink / raw)
To: Amit Langote <[email protected]>; +Cc: Richard Guo <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Amit-san,
On Thu, Jun 25, 2026 at 8:24 AM Amit Langote <[email protected]> wrote:
> On Thu, Jun 25, 2026 at 2:02 AM Etsuro Fujita <[email protected]> wrote:
> > This might be nitpicking, but:
> >
> > + if (list_length(node->resultRelations) == mtstate->mt_nrels)
> > + fdw_private = (List *) list_nth(node->fdwPrivLists, j);
> > + else
> > + {
> > + Index rti = resultRelInfo->ri_RangeTableIndex;
> > + ListCell *lc1;
> > + ListCell *lc2;
> > +
> > + fdw_private = NIL;
> > + forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
> > + {
> > + if (lfirst_int(lc1) == (int) rti)
> > + {
> > + fdw_private = (List *) lfirst(lc2);
> > + break;
> > + }
> > + }
> > + }
> >
> > I'd put the if-test outside of the outer loop to save cycles.
>
> Right, it's loop-invariant. v3 attached computes a boolean
> (nopruning), like labeltargets, once before the loop and uses it
> inside.
>
> > Other than that v2 looks good to me.
> >
> > (The forboth loop actually causes an n-squared calculation, but it's
> > done only when pruning occurs, in which case the number of remaining
> > result relations would be reduced, so that wouldn't be a problem.)
>
> Right, though strictly the inner forboth scans node->resultRelations,
> which pruning leaves at its original length, so it's the original
> relation count that bounds the scan rather than the reduced one.
> Either way it's EXPLAIN-only with small counts, so it's not a concern.
That's right.
The v3 patch looks good to me. Thanks for updating the patch!
Best regards,
Etsuro Fujita
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 02:23 ` Re: BUG #19484: Segmentation fault triggered by FDW Richard Guo <[email protected]>
2026-06-24 04:25 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 11:20 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 17:02 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 23:24 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-25 06:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
@ 2026-06-25 11:47 ` Amit Langote <[email protected]>
2026-06-25 12:21 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
0 siblings, 1 reply; 32+ messages in thread
From: Amit Langote @ 2026-06-25 11:47 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Richard Guo <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
Fujita-san,
On Thu, Jun 25, 2026 at 3:15 PM Etsuro Fujita <[email protected]> wrote:
> On Thu, Jun 25, 2026 at 8:24 AM Amit Langote <[email protected]> wrote:
> > On Thu, Jun 25, 2026 at 2:02 AM Etsuro Fujita <[email protected]> wrote:
> > > This might be nitpicking, but:
> > >
> > > + if (list_length(node->resultRelations) == mtstate->mt_nrels)
> > > + fdw_private = (List *) list_nth(node->fdwPrivLists, j);
> > > + else
> > > + {
> > > + Index rti = resultRelInfo->ri_RangeTableIndex;
> > > + ListCell *lc1;
> > > + ListCell *lc2;
> > > +
> > > + fdw_private = NIL;
> > > + forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
> > > + {
> > > + if (lfirst_int(lc1) == (int) rti)
> > > + {
> > > + fdw_private = (List *) lfirst(lc2);
> > > + break;
> > > + }
> > > + }
> > > + }
> > >
> > > I'd put the if-test outside of the outer loop to save cycles.
> >
> > Right, it's loop-invariant. v3 attached computes a boolean
> > (nopruning), like labeltargets, once before the loop and uses it
> > inside.
> >
> > > Other than that v2 looks good to me.
> > >
> > > (The forboth loop actually causes an n-squared calculation, but it's
> > > done only when pruning occurs, in which case the number of remaining
> > > result relations would be reduced, so that wouldn't be a problem.)
> >
> > Right, though strictly the inner forboth scans node->resultRelations,
> > which pruning leaves at its original length, so it's the original
> > relation count that bounds the scan rather than the reduced one.
> > Either way it's EXPLAIN-only with small counts, so it's not a concern.
>
> That's right.
>
> The v3 patch looks good to me. Thanks for updating the patch!
Pushed, thanks for checking.
--
Thanks, Amit Langote
^ permalink raw reply [nested|flat] 32+ messages in thread
* Re: BUG #19484: Segmentation fault triggered by FDW
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-05-22 20:56 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Re: BUG #19484: Segmentation fault triggered by FDW Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Re: BUG #19484: Segmentation fault triggered by FDW Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-10 13:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-11 10:40 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-18 10:50 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-19 11:59 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-23 08:27 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 01:43 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 02:23 ` Re: BUG #19484: Segmentation fault triggered by FDW Richard Guo <[email protected]>
2026-06-24 04:25 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 09:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 11:20 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-24 17:02 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-24 23:24 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
2026-06-25 06:15 ` Re: BUG #19484: Segmentation fault triggered by FDW Etsuro Fujita <[email protected]>
2026-06-25 11:47 ` Re: BUG #19484: Segmentation fault triggered by FDW Amit Langote <[email protected]>
@ 2026-06-25 12:21 ` Amit Langote <[email protected]>
0 siblings, 0 replies; 32+ messages in thread
From: Amit Langote @ 2026-06-25 12:21 UTC (permalink / raw)
To: Etsuro Fujita <[email protected]>; +Cc: Richard Guo <[email protected]>; Matheus Alcantara <[email protected]>; Ayush Tiwari <[email protected]>; Rafia Sabih <[email protected]>; [email protected]; [email protected]; Amit Langote <[email protected]>
On Thu, Jun 25, 2026 at 8:47 PM Amit Langote <[email protected]> wrote:
> On Thu, Jun 25, 2026 at 3:15 PM Etsuro Fujita <[email protected]> wrote:
> > On Thu, Jun 25, 2026 at 8:24 AM Amit Langote <[email protected]> wrote:
> > > On Thu, Jun 25, 2026 at 2:02 AM Etsuro Fujita <[email protected]> wrote:
> > > > This might be nitpicking, but:
> > > >
> > > > + if (list_length(node->resultRelations) == mtstate->mt_nrels)
> > > > + fdw_private = (List *) list_nth(node->fdwPrivLists, j);
> > > > + else
> > > > + {
> > > > + Index rti = resultRelInfo->ri_RangeTableIndex;
> > > > + ListCell *lc1;
> > > > + ListCell *lc2;
> > > > +
> > > > + fdw_private = NIL;
> > > > + forboth(lc1, node->resultRelations, lc2, node->fdwPrivLists)
> > > > + {
> > > > + if (lfirst_int(lc1) == (int) rti)
> > > > + {
> > > > + fdw_private = (List *) lfirst(lc2);
> > > > + break;
> > > > + }
> > > > + }
> > > > + }
> > > >
> > > > I'd put the if-test outside of the outer loop to save cycles.
> > >
> > > Right, it's loop-invariant. v3 attached computes a boolean
> > > (nopruning), like labeltargets, once before the loop and uses it
> > > inside.
> > >
> > > > Other than that v2 looks good to me.
> > > >
> > > > (The forboth loop actually causes an n-squared calculation, but it's
> > > > done only when pruning occurs, in which case the number of remaining
> > > > result relations would be reduced, so that wouldn't be a problem.)
> > >
> > > Right, though strictly the inner forboth scans node->resultRelations,
> > > which pruning leaves at its original length, so it's the original
> > > relation count that bounds the scan rather than the reduced one.
> > > Either way it's EXPLAIN-only with small counts, so it's not a concern.
> >
> > That's right.
> >
> > The v3 patch looks good to me. Thanks for updating the patch!
>
> Pushed, thanks for checking.
And crake turns green:
https://buildfarm.postgresql.org/cgi-bin/show_history.pl?nm=crake&br=REL_18_STABLE
--
Thanks, Amit Langote
^ permalink raw reply [nested|flat] 32+ messages in thread
end of thread, other threads:[~2026-06-25 12:21 UTC | newest]
Thread overview: 32+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-05-18 06:38 BUG #19484: Segmentation fault triggered by FDW PG Bug reporting form <[email protected]>
2026-05-20 12:37 ` Ayush Tiwari <[email protected]>
2026-05-20 17:46 ` Etsuro Fujita <[email protected]>
2026-05-22 20:56 ` Matheus Alcantara <[email protected]>
2026-05-30 06:18 ` Rafia Sabih <[email protected]>
2026-06-09 15:10 ` Matheus Alcantara <[email protected]>
2026-06-10 05:15 ` Ayush Tiwari <[email protected]>
2026-06-10 11:08 ` Matheus Alcantara <[email protected]>
2026-06-10 13:09 ` Amit Langote <[email protected]>
2026-06-10 13:27 ` Amit Langote <[email protected]>
2026-06-11 10:40 ` Etsuro Fujita <[email protected]>
2026-06-11 10:44 ` Amit Langote <[email protected]>
2026-06-18 09:15 ` Amit Langote <[email protected]>
2026-06-18 10:50 ` Etsuro Fujita <[email protected]>
2026-06-18 10:55 ` Etsuro Fujita <[email protected]>
2026-06-18 10:57 ` Amit Langote <[email protected]>
2026-06-19 11:59 ` Etsuro Fujita <[email protected]>
2026-06-22 08:28 ` Amit Langote <[email protected]>
2026-06-23 08:27 ` Etsuro Fujita <[email protected]>
2026-06-24 00:00 ` Amit Langote <[email protected]>
2026-06-24 01:43 ` Amit Langote <[email protected]>
2026-06-24 01:53 ` Tom Lane <[email protected]>
2026-06-24 03:50 ` Amit Langote <[email protected]>
2026-06-24 02:23 ` Richard Guo <[email protected]>
2026-06-24 04:25 ` Amit Langote <[email protected]>
2026-06-24 09:15 ` Etsuro Fujita <[email protected]>
2026-06-24 11:20 ` Amit Langote <[email protected]>
2026-06-24 17:02 ` Etsuro Fujita <[email protected]>
2026-06-24 23:24 ` Amit Langote <[email protected]>
2026-06-25 06:15 ` Etsuro Fujita <[email protected]>
2026-06-25 11:47 ` Amit Langote <[email protected]>
2026-06-25 12:21 ` Amit Langote <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox