Currently, DELETE or UPDATE on a partitioned table with foreign partitions
fail with an error as below, if the FDW does not support the operation:
`ERROR: cannot delete from foreign table`
This occurs because during executor initialization (ExecInitModifyTable),
PostgreSQL scans all partitions of the target table and checks whether each one
supports the requested operation. If any foreign partition's FDW lacks support
for DELETE or UPDATE, the operation is rejected outright, even if that
partition would not be affected by the query.
As a result, DELETE/UPDATE operations are blocked even when they only target
non-foreign partitions. This means the system errors out without considering
whether foreign partitions are actually involved in the operation. Even if no
matching rows exist in a foreign partition, the operation still fails.
This commit defers the FDW check for foreign partitions from
`ExecInitModifyTable` to `ExecDelete` and `ExecUpdate`. This change ensures
that foreign partitions are checked only when they are actually targeted by the
operation.
However, if a DELETE or UPDATE is issued on the root partition and it includes
foreign partitions that do not support the operation, it will still result in
an error. This is intentional because the responsibility for managing data in
foreign partitions lies with the user. Only after the user has removed relevant
data from those foreign partitions will such operations on the root partition
succeed.
** Mini repro: **
```
CREATE EXTENSION file_fdw;
CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;
CREATE TABLE pt (a int, b numeric) PARTITION BY RANGE(a);
CREATE TABLE pt_part1 PARTITION OF pt FOR VALUES FROM (0) TO (10);
INSERT INTO pt SELECT 5, 0.1;
INSERT INTO pt SELECT 6, 0.2;
CREATE FOREIGN TABLE ext (a int, b numeric) SERVER file_server OPTIONS (filename '/Users/sshirisha/workspace/postgres/src/test/regress/data/test_data_float.csv', format 'csv', delimiter ',');
ALTER TABLE pt ATTACH PARTITION ext FOR VALUES FROM (10) TO (20);
postgres=# SELECT * FROM pt;
a | b
----+-----
5 | 0.1
6 | 0.2
15 | 0.3
21 | 0.4
(4 rows)
```
** Before Fix: **
```
postgres=# DELETE FROM pt WHERE b = 0.2;
ERROR: cannot delete from foreign table "ext"
postgres=# DELETE FROM pt;
ERROR: cannot delete from foreign table "ext"
postgres=# UPDATE pt set b = 0.5 WHERE b = 0.1;
ERROR: cannot update foreign table "ext"
postgres=# UPDATE pt SET b = 0.5;
ERROR: cannot update foreign table "ext"
```
** After Fix: **
```
postgres=# DELETE FROM pt WHERE b = 0.2;
DELETE 1
postgres=# DELETE FROM pt;
ERROR: cannot delete from foreign table "ext"
postgres=# UPDATE pt SET b = 0.5 WHERE b = 0.1;
UPDATE 1
postgres=# UPDATE pt SET b = 0.5;
ERROR: cannot update foreign table "ext"
```
Co-authored-by: Ashwin Agrawal <[email protected]>