diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 033aeb2556..9982007082 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -197,6 +197,7 @@ typedef struct PgFdwModifyState
typedef struct PgFdwDirectModifyState
{
Relation rel; /* relcache entry for the foreign table */
+ ResultRelInfo *relInfo; /* ResultRelInfo for the foreign table */
AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
/* extracted fdw_private data */
@@ -2303,6 +2304,7 @@ postgresPlanDirectModify(PlannerInfo *root,
* Update the operation info.
*/
fscan->operation = operation;
+ fscan->resultRelation = resultRelation;
/*
* Update the fdw_exprs list that will be available to the executor.
@@ -2368,7 +2370,7 @@ postgresBeginDirectModify(ForeignScanState *node, int eflags)
* Identify which user to do the remote access as. This should match what
* ExecCheckRTEPerms() does.
*/
- rtindex = estate->es_result_relation_info->ri_RangeTableIndex;
+ rtindex = fsplan->resultRelation;
rte = exec_rt_fetch(rtindex, estate);
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
@@ -2380,6 +2382,9 @@ postgresBeginDirectModify(ForeignScanState *node, int eflags)
table = GetForeignTable(RelationGetRelid(dmstate->rel));
user = GetUserMapping(userid, table->serverid);
+ /* Get ResultRelInfo for foreign table. */
+ dmstate->relInfo = ExecFindResultRelInfo(estate, rtindex, false);
+
/*
* Get connection to the foreign server. Connection manager will
* establish new connection if necessary.
@@ -2463,7 +2468,7 @@ postgresIterateDirectModify(ForeignScanState *node)
{
PgFdwDirectModifyState *dmstate = (PgFdwDirectModifyState *) node->fdw_state;
EState *estate = node->ss.ps.state;
- ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
+ ResultRelInfo *resultRelInfo = dmstate->relInfo;
/*
* If this is the first call after Begin, execute the statement.
@@ -4033,7 +4038,7 @@ get_returning_data(ForeignScanState *node)
{
PgFdwDirectModifyState *dmstate = (PgFdwDirectModifyState *) node->fdw_state;
EState *estate = node->ss.ps.state;
- ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
+ ResultRelInfo *resultRelInfo = dmstate->relInfo;
TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
TupleTableSlot *resultSlot;
@@ -4180,7 +4185,7 @@ apply_returning_filter(PgFdwDirectModifyState *dmstate,
TupleTableSlot *slot,
EState *estate)
{
- ResultRelInfo *relInfo = estate->es_result_relation_info;
+ ResultRelInfo *relInfo = dmstate->relInfo;
TupleDesc resultTupType = RelationGetDescr(dmstate->resultRel);
TupleTableSlot *resultSlot;
Datum *values;
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index dbd7dd9bcd..4d0d0553be 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1349,6 +1349,31 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
resultRelInfo->ri_CopyMultiInsertBuffer = NULL;
}
+/*
+ * ExecFindResultRelInfo -- find the ResultRelInfo struct for given rangetable
+ * index
+ *
+ * This function only searches through the query result relations. If no such
+ * struct, either return NULL or throw error depending on missing_ok
+ */
+ResultRelInfo *
+ExecFindResultRelInfo(EState *estate, Index rti, bool missing_ok)
+{
+ ResultRelInfo *rInfo = estate->es_result_relations;
+ int nr = estate->es_num_result_relations;
+
+ while (nr > 0)
+ {
+ if (rInfo->ri_RangeTableIndex == rti)
+ return rInfo;
+ rInfo++;
+ nr--;
+ }
+ if (!missing_ok)
+ elog(ERROR, "failed to find ResultRelInfo for rangetable index %u", rti);
+ return NULL;
+}
+
/*
* ExecGetTriggerResultRel
* Get a ResultRelInfo for a trigger target relation.
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 6414aded0e..9342b99aae 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -751,6 +751,7 @@ _copyForeignScan(const ForeignScan *from)
* copy remainder of node
*/
COPY_SCALAR_FIELD(operation);
+ COPY_SCALAR_FIELD(resultRelation);
COPY_SCALAR_FIELD(fs_server);
COPY_NODE_FIELD(fdw_exprs);
COPY_NODE_FIELD(fdw_private);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 86c31a48c9..4dadb9ff7c 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -688,6 +688,7 @@ _outForeignScan(StringInfo str, const ForeignScan *node)
_outScanInfo(str, (const Scan *) node);
WRITE_ENUM_FIELD(operation, CmdType);
+ WRITE_UINT_FIELD(resultRelation);
WRITE_OID_FIELD(fs_server);
WRITE_NODE_FIELD(fdw_exprs);
WRITE_NODE_FIELD(fdw_private);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 6c2626ee62..04080c752a 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -1976,6 +1976,7 @@ _readForeignScan(void)
ReadCommonScan(&local_node->scan);
READ_ENUM_FIELD(operation, CmdType);
+ READ_UINT_FIELD(resultRelation);
READ_OID_FIELD(fs_server);
READ_NODE_FIELD(fdw_exprs);
READ_NODE_FIELD(fdw_private);
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index c6b8553a08..cc5be409ec 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -5415,6 +5415,7 @@ make_foreignscan(List *qptlist,
plan->righttree = NULL;
node->scan.scanrelid = scanrelid;
node->operation = CMD_SELECT;
+ node->resultRelation = 0;
/* fs_server will be filled in by create_foreignscan_plan */
node->fs_server = InvalidOid;
node->fdw_exprs = fdw_exprs;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index dc11f098e0..25c1e7dfc7 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -1158,6 +1158,10 @@ set_foreignscan_references(PlannerInfo *root,
if (fscan->scan.scanrelid > 0)
fscan->scan.scanrelid += rtoffset;
+ /* Adjust resultRelation if it's valid */
+ if (fscan->resultRelation > 0)
+ fscan->resultRelation += rtoffset;
+
if (fscan->fdw_scan_tlist != NIL || fscan->scan.scanrelid == 0)
{
/*
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 1fb28b4596..a0533df779 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -184,6 +184,7 @@ extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
Index resultRelationIndex,
Relation partition_root,
int instrument_options);
+extern ResultRelInfo *ExecFindResultRelInfo(EState *estate, Index rti, bool missing_ok);
extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid);
extern void ExecCleanUpTriggerState(EState *estate);
extern void ExecConstraints(ResultRelInfo *resultRelInfo,
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 70f8b8e22b..218626254f 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -609,6 +609,8 @@ typedef struct ForeignScan
{
Scan scan;
CmdType operation; /* SELECT/INSERT/UPDATE/DELETE */
+ Index resultRelation; /* rtable index of target relation for
+ * INSERT/UPDATE/DELETE; 0 for SELECT */
Oid fs_server; /* OID of foreign server */
List *fdw_exprs; /* expressions that FDW may evaluate */
List *fdw_private; /* private data for FDW */