aboutsummaryrefslogtreecommitdiff
path: root/contrib/postgres_fdw/postgres_fdw.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/postgres_fdw/postgres_fdw.c')
-rw-r--r--contrib/postgres_fdw/postgres_fdw.c95
1 files changed, 39 insertions, 56 deletions
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 93ebd8cab68..931bcfd37df 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -67,8 +67,6 @@ enum FdwScanPrivateIndex
FdwScanPrivateRetrievedAttrs,
/* Integer representing the desired fetch_size */
FdwScanPrivateFetchSize,
- /* Oid of user mapping to be used while connecting to the foreign server */
- FdwScanPrivateUserMappingOid,
/*
* String describing join i.e. names of relations being joined and types
@@ -1226,11 +1224,10 @@ postgresGetForeignPlan(PlannerInfo *root,
* Build the fdw_private list that will be available to the executor.
* Items in the list must match order in enum FdwScanPrivateIndex.
*/
- fdw_private = list_make5(makeString(sql.data),
+ fdw_private = list_make4(makeString(sql.data),
remote_conds,
retrieved_attrs,
- makeInteger(fpinfo->fetch_size),
- makeInteger(foreignrel->umid));
+ makeInteger(fpinfo->fetch_size));
if (foreignrel->reloptkind == RELOPT_JOINREL)
fdw_private = lappend(fdw_private,
makeString(fpinfo->relation_name->data));
@@ -1262,7 +1259,11 @@ postgresBeginForeignScan(ForeignScanState *node, int eflags)
ForeignScan *fsplan = (ForeignScan *) node->ss.ps.plan;
EState *estate = node->ss.ps.state;
PgFdwScanState *fsstate;
+ RangeTblEntry *rte;
+ Oid userid;
+ ForeignTable *table;
UserMapping *user;
+ int rtindex;
int numParams;
/*
@@ -1278,36 +1279,20 @@ postgresBeginForeignScan(ForeignScanState *node, int eflags)
node->fdw_state = (void *) fsstate;
/*
- * Obtain the foreign server where to connect and user mapping to use for
- * connection. For base relations we obtain this information from
- * catalogs. For join relations, this information is frozen at the time of
- * planning to ensure that the join is safe to pushdown. In case the
- * information goes stale between planning and execution, plan will be
- * invalidated and replanned.
+ * Identify which user to do the remote access as. This should match what
+ * ExecCheckRTEPerms() does. In case of a join, use the lowest-numbered
+ * member RTE as a representative; we would get the same result from any.
*/
if (fsplan->scan.scanrelid > 0)
- {
- ForeignTable *table;
-
- /*
- * Identify which user to do the remote access as. This should match
- * what ExecCheckRTEPerms() does.
- */
- RangeTblEntry *rte = rt_fetch(fsplan->scan.scanrelid, estate->es_range_table);
- Oid userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
-
- fsstate->rel = node->ss.ss_currentRelation;
- table = GetForeignTable(RelationGetRelid(fsstate->rel));
-
- user = GetUserMapping(userid, table->serverid);
- }
+ rtindex = fsplan->scan.scanrelid;
else
- {
- Oid umid = intVal(list_nth(fsplan->fdw_private, FdwScanPrivateUserMappingOid));
+ rtindex = bms_next_member(fsplan->fs_relids, -1);
+ rte = rt_fetch(rtindex, estate->es_range_table);
+ userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
- user = GetUserMappingById(umid);
- Assert(fsplan->fs_server == user->serverid);
- }
+ /* Get info about foreign table. */
+ table = GetForeignTable(rte->relid);
+ user = GetUserMapping(userid, table->serverid);
/*
* Get connection to the foreign server. Connection manager will
@@ -1344,9 +1329,15 @@ postgresBeginForeignScan(ForeignScanState *node, int eflags)
* into local representation and error reporting during that process.
*/
if (fsplan->scan.scanrelid > 0)
+ {
+ fsstate->rel = node->ss.ss_currentRelation;
fsstate->tupdesc = RelationGetDescr(fsstate->rel);
+ }
else
+ {
+ fsstate->rel = NULL;
fsstate->tupdesc = node->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
+ }
fsstate->attinmeta = TupleDescGetAttInMetadata(fsstate->tupdesc);
@@ -3966,16 +3957,6 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
List *otherclauses;
/*
- * Core code may call GetForeignJoinPaths hook even when the join relation
- * doesn't have a valid user mapping associated with it. See
- * build_join_rel() for details. We can't push down such join, since there
- * doesn't exist a user mapping which can be used to connect to the
- * foreign server.
- */
- if (!OidIsValid(joinrel->umid))
- return false;
-
- /*
* We support pushing down INNER, LEFT, RIGHT and FULL OUTER joins.
* Constructing queries representing SEMI and ANTI joins is hard, hence
* not considered right now.
@@ -4151,6 +4132,20 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate ||
fpinfo_i->use_remote_estimate;
+ /* Get user mapping */
+ if (fpinfo->use_remote_estimate)
+ {
+ if (fpinfo_o->use_remote_estimate)
+ fpinfo->user = fpinfo_o->user;
+ else
+ fpinfo->user = fpinfo_i->user;
+ }
+ else
+ fpinfo->user = NULL;
+
+ /* Get foreign server */
+ fpinfo->server = fpinfo_o->server;
+
/*
* Since both the joining relations come from the same server, the server
* level options should have same value for both the relations. Pick from
@@ -4312,26 +4307,14 @@ postgresGetForeignJoinPaths(PlannerInfo *root,
cost_qual_eval(&fpinfo->local_conds_cost, fpinfo->local_conds, root);
/*
- * If we are going to estimate the costs using EXPLAIN, we will need
- * connection information. Fill it here.
+ * If we are going to estimate costs locally, estimate the join clause
+ * selectivity here while we have special join info.
*/
- if (fpinfo->use_remote_estimate)
- fpinfo->user = GetUserMappingById(joinrel->umid);
- else
- {
- fpinfo->user = NULL;
-
- /*
- * If we are going to estimate costs locally, estimate the join clause
- * selectivity here while we have special join info.
- */
+ if (!fpinfo->use_remote_estimate)
fpinfo->joinclause_sel = clauselist_selectivity(root, fpinfo->joinclauses,
0, fpinfo->jointype,
extra->sjinfo);
- }
- fpinfo->server = GetForeignServer(joinrel->serverid);
-
/* Estimate costs for bare join relation */
estimate_path_cost_size(root, joinrel, NIL, NIL, &rows,
&width, &startup_cost, &total_cost);