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.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 674eb982d06..2ac9d7bbe7a 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -1229,11 +1229,9 @@ postgresGetForeignPlan(PlannerInfo *root,
/*
* Ensure that the outer plan produces a tuple whose descriptor
- * matches our scan tuple slot. This is safe because all scans and
- * joins support projection, so we never need to insert a Result node.
- * Also, remove the local conditions from outer plan's quals, lest
- * they will be evaluated twice, once by the local plan and once by
- * the scan.
+ * matches our scan tuple slot. Also, remove the local conditions
+ * from outer plan's quals, lest they be evaluated twice, once by the
+ * local plan and once by the scan.
*/
if (outer_plan)
{
@@ -1246,23 +1244,42 @@ postgresGetForeignPlan(PlannerInfo *root,
*/
Assert(!IS_UPPER_REL(foreignrel));
- outer_plan->targetlist = fdw_scan_tlist;
-
+ /*
+ * First, update the plan's qual list if possible. In some cases
+ * the quals might be enforced below the topmost plan level, in
+ * which case we'll fail to remove them; it's not worth working
+ * harder than this.
+ */
foreach(lc, local_exprs)
{
- Join *join_plan = (Join *) outer_plan;
Node *qual = lfirst(lc);
outer_plan->qual = list_delete(outer_plan->qual, qual);
/*
* For an inner join the local conditions of foreign scan plan
- * can be part of the joinquals as well.
+ * can be part of the joinquals as well. (They might also be
+ * in the mergequals or hashquals, but we can't touch those
+ * without breaking the plan.)
*/
- if (join_plan->jointype == JOIN_INNER)
- join_plan->joinqual = list_delete(join_plan->joinqual,
- qual);
+ if (IsA(outer_plan, NestLoop) ||
+ IsA(outer_plan, MergeJoin) ||
+ IsA(outer_plan, HashJoin))
+ {
+ Join *join_plan = (Join *) outer_plan;
+
+ if (join_plan->jointype == JOIN_INNER)
+ join_plan->joinqual = list_delete(join_plan->joinqual,
+ qual);
+ }
}
+
+ /*
+ * Now fix the subplan's tlist --- this might result in inserting
+ * a Result node atop the plan tree.
+ */
+ outer_plan = change_plan_targetlist(outer_plan, fdw_scan_tlist,
+ best_path->path.parallel_safe);
}
}