From dade4a910109b353bdbfc1032cee50119e4c8bcb Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Thu, 30 Oct 2025 12:06:31 +0800
Subject: [PATCH v1 1/1] file_fdw may need AddForeignUpdateTargets

---
 contrib/file_fdw/file_fdw.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 70564a68b13..51d2cf7f354 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -32,6 +32,7 @@
 #include "foreign/foreign.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
+#include "optimizer/appendinfo.h"
 #include "optimizer/optimizer.h"
 #include "optimizer/pathnode.h"
 #include "optimizer/planmain.h"
@@ -146,6 +147,10 @@ static void fileBeginForeignScan(ForeignScanState *node, int eflags);
 static TupleTableSlot *fileIterateForeignScan(ForeignScanState *node);
 static void fileReScanForeignScan(ForeignScanState *node);
 static void fileEndForeignScan(ForeignScanState *node);
+static void fileAddForeignUpdateTargets(PlannerInfo *root,
+											Index rtindex,
+											RangeTblEntry *target_rte,
+											Relation target_relation);
 static bool fileAnalyzeForeignTable(Relation relation,
 									AcquireSampleRowsFunc *func,
 									BlockNumber *totalpages);
@@ -193,10 +198,39 @@ file_fdw_handler(PG_FUNCTION_ARGS)
 	fdwroutine->EndForeignScan = fileEndForeignScan;
 	fdwroutine->AnalyzeForeignTable = fileAnalyzeForeignTable;
 	fdwroutine->IsForeignScanParallelSafe = fileIsForeignScanParallelSafe;
+	fdwroutine->AddForeignUpdateTargets = fileAddForeignUpdateTargets;
 
 	PG_RETURN_POINTER(fdwroutine);
 }
 
+/*
+ * fileAddForeignUpdateTargets
+ *		Add resjunk column(s) needed for update/delete on a foreign table
+ */
+static void
+fileAddForeignUpdateTargets(PlannerInfo *root,
+							Index rtindex,
+							RangeTblEntry *target_rte,
+							Relation target_relation)
+{
+	Var		   *var;
+
+	/*
+	 * In file_fdw, what we need is the ctid, same as for a regular table.
+	 */
+
+	/* Make a Var representing the desired value */
+	var = makeVar(rtindex,
+				  SelfItemPointerAttributeNumber,
+				  TIDOID,
+				  -1,
+				  InvalidOid,
+				  0);
+
+	/* Register it as a row-identity column needed by this target rel */
+	add_row_identity_var(root, var, rtindex, "ctid");
+}
+
 /*
  * Validate the generic options given to a FOREIGN DATA WRAPPER, SERVER,
  * USER MAPPING or FOREIGN TABLE that uses file_fdw.
@@ -863,6 +897,10 @@ fileEndForeignScan(ForeignScanState *node)
 	EndCopyFrom(festate->cstate);
 }
 
+static void fileAddForeignUpdateTargets(PlannerInfo *root,
+											Index rtindex,
+											RangeTblEntry *target_rte,
+											Relation target_relation);
 /*
  * fileAnalyzeForeignTable
  *		Test whether analyzing this foreign table is supported
-- 
2.34.1

