aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/path/joinpath.c19
-rw-r--r--src/backend/optimizer/plan/createplan.c21
-rw-r--r--src/backend/optimizer/util/pathnode.c10
-rw-r--r--src/backend/optimizer/util/restrictinfo.c30
-rw-r--r--src/include/nodes/pathnodes.h10
-rw-r--r--src/include/optimizer/pathnode.h3
-rw-r--r--src/include/optimizer/restrictinfo.h2
7 files changed, 45 insertions, 50 deletions
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 059e605e04e..821d282497b 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -24,7 +24,6 @@
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/planmain.h"
-#include "optimizer/restrictinfo.h"
#include "utils/typcache.h"
/* Hook for plugins to get control in add_paths_to_joinrel() */
@@ -131,7 +130,6 @@ add_paths_to_joinrel(PlannerInfo *root,
{
JoinPathExtraData extra;
bool mergejoin_allowed = true;
- bool consider_join_pushdown = false;
ListCell *lc;
Relids joinrelids;
@@ -324,24 +322,12 @@ add_paths_to_joinrel(PlannerInfo *root,
jointype, &extra);
/*
- * createplan.c does not currently support handling of pseudoconstant
- * clauses assigned to joins pushed down by extensions; check if the
- * restrictlist has such clauses, and if so, disallow pushing down joins.
- */
- if ((joinrel->fdwroutine &&
- joinrel->fdwroutine->GetForeignJoinPaths) ||
- set_join_pathlist_hook)
- consider_join_pushdown = !has_pseudoconstant_clauses(root,
- restrictlist);
-
- /*
* 5. If inner and outer relations are foreign tables (or joins) belonging
* to the same server and assigned to the same user to check access
* permissions as, give the FDW a chance to push down joins.
*/
if (joinrel->fdwroutine &&
- joinrel->fdwroutine->GetForeignJoinPaths &&
- consider_join_pushdown)
+ joinrel->fdwroutine->GetForeignJoinPaths)
joinrel->fdwroutine->GetForeignJoinPaths(root, joinrel,
outerrel, innerrel,
jointype, &extra);
@@ -349,8 +335,7 @@ add_paths_to_joinrel(PlannerInfo *root,
/*
* 6. Finally, give extensions a chance to manipulate the path list.
*/
- if (set_join_pathlist_hook &&
- consider_join_pushdown)
+ if (set_join_pathlist_hook)
set_join_pathlist_hook(root, joinrel, outerrel, innerrel,
jointype, &extra);
}
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index af48109058d..34ca6d4ac21 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -599,8 +599,27 @@ create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
* Detect whether we have any pseudoconstant quals to deal with. Then, if
* we'll need a gating Result node, it will be able to project, so there
* are no requirements on the child's tlist.
+ *
+ * If this replaces a join, it must be a foreign scan or a custom scan,
+ * and the FDW or the custom scan provider would have stored in the best
+ * path the list of RestrictInfo nodes to apply to the join; check against
+ * that list in that case.
*/
- gating_clauses = get_gating_quals(root, scan_clauses);
+ if (IS_JOIN_REL(rel))
+ {
+ List *join_clauses;
+
+ Assert(best_path->pathtype == T_ForeignScan ||
+ best_path->pathtype == T_CustomScan);
+ if (best_path->pathtype == T_ForeignScan)
+ join_clauses = ((ForeignPath *) best_path)->fdw_restrictinfo;
+ else
+ join_clauses = ((CustomPath *) best_path)->custom_restrictinfo;
+
+ gating_clauses = get_gating_quals(root, join_clauses);
+ }
+ else
+ gating_clauses = get_gating_quals(root, scan_clauses);
if (gating_clauses)
flags = 0;
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 754f0b9f34c..211ba65389d 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -2229,6 +2229,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
List *pathkeys,
Relids required_outer,
Path *fdw_outerpath,
+ List *fdw_restrictinfo,
List *fdw_private)
{
ForeignPath *pathnode = makeNode(ForeignPath);
@@ -2250,6 +2251,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->path.pathkeys = pathkeys;
pathnode->fdw_outerpath = fdw_outerpath;
+ pathnode->fdw_restrictinfo = fdw_restrictinfo;
pathnode->fdw_private = fdw_private;
return pathnode;
@@ -2273,6 +2275,7 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
List *pathkeys,
Relids required_outer,
Path *fdw_outerpath,
+ List *fdw_restrictinfo,
List *fdw_private)
{
ForeignPath *pathnode = makeNode(ForeignPath);
@@ -2300,6 +2303,7 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->path.pathkeys = pathkeys;
pathnode->fdw_outerpath = fdw_outerpath;
+ pathnode->fdw_restrictinfo = fdw_restrictinfo;
pathnode->fdw_private = fdw_private;
return pathnode;
@@ -2322,6 +2326,7 @@ create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel,
double rows, Cost startup_cost, Cost total_cost,
List *pathkeys,
Path *fdw_outerpath,
+ List *fdw_restrictinfo,
List *fdw_private)
{
ForeignPath *pathnode = makeNode(ForeignPath);
@@ -2345,6 +2350,7 @@ create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->path.pathkeys = pathkeys;
pathnode->fdw_outerpath = fdw_outerpath;
+ pathnode->fdw_restrictinfo = fdw_restrictinfo;
pathnode->fdw_private = fdw_private;
return pathnode;
@@ -4149,6 +4155,8 @@ do { \
FLAT_COPY_PATH(fpath, path, ForeignPath);
if (fpath->fdw_outerpath)
REPARAMETERIZE_CHILD_PATH(fpath->fdw_outerpath);
+ if (fpath->fdw_restrictinfo)
+ ADJUST_CHILD_ATTRS(fpath->fdw_restrictinfo);
/* Hand over to FDW if needed. */
rfpc_func =
@@ -4166,6 +4174,8 @@ do { \
FLAT_COPY_PATH(cpath, path, CustomPath);
REPARAMETERIZE_CHILD_PATH_LIST(cpath->custom_paths);
+ if (cpath->custom_restrictinfo)
+ ADJUST_CHILD_ATTRS(cpath->custom_restrictinfo);
if (cpath->methods &&
cpath->methods->ReparameterizeCustomPathByChild)
cpath->custom_private =
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index c1fbbb6bfee..d6d26a2b515 100644
--- a/src/backend/optimizer/util/restrictinfo.c
+++ b/src/backend/optimizer/util/restrictinfo.c
@@ -550,36 +550,6 @@ extract_actual_join_clauses(List *restrictinfo_list,
}
/*
- * has_pseudoconstant_clauses
- *
- * Returns true if 'restrictinfo_list' includes pseudoconstant clauses.
- *
- * This is used when we determine whether to allow extensions to consider
- * pushing down joins in add_paths_to_joinrel().
- */
-bool
-has_pseudoconstant_clauses(PlannerInfo *root,
- List *restrictinfo_list)
-{
- ListCell *l;
-
- /* No need to look if we know there are no pseudoconstants */
- if (!root->hasPseudoConstantQuals)
- return false;
-
- /* See if there are pseudoconstants in the RestrictInfo list */
- foreach(l, restrictinfo_list)
- {
- RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
-
- if (rinfo->pseudoconstant &&
- !rinfo_is_constant_true(rinfo))
- return true;
- }
- return false;
-}
-
-/*
* join_clause_is_movable_to
* Test whether a join clause is a safe candidate for parameterization
* of a scan on the specified base relation.
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index a1dc1d07e18..5702fbba60c 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -1822,6 +1822,10 @@ typedef struct SubqueryScanPath
* ForeignPath represents a potential scan of a foreign table, foreign join
* or foreign upper-relation.
*
+ * In the case of a foreign join, fdw_restrictinfo stores the RestrictInfos to
+ * apply to the join, which are used by createplan.c to get pseudoconstant
+ * clauses evaluated as one-time quals in a gating Result plan node.
+ *
* fdw_private stores FDW private data about the scan. While fdw_private is
* not actually touched by the core code during normal operations, it's
* generally a good idea to use a representation that can be dumped by
@@ -1832,6 +1836,7 @@ typedef struct ForeignPath
{
Path path;
Path *fdw_outerpath;
+ List *fdw_restrictinfo;
List *fdw_private;
} ForeignPath;
@@ -1849,6 +1854,10 @@ typedef struct ForeignPath
* relation by set_rel_pathlist_hook or set_join_pathlist_hook functions,
* respectively.
*
+ * In the case of a table join, custom_restrictinfo stores the RestrictInfos
+ * to apply to the join, which are used by createplan.c to get pseudoconstant
+ * clauses evaluated as one-time quals in a gating Result plan node.
+ *
* Core code must avoid assuming that the CustomPath is only as large as
* the structure declared here; providers are allowed to make it the first
* element in a larger structure. (Since the planner never copies Paths,
@@ -1865,6 +1874,7 @@ typedef struct CustomPath
uint32 flags; /* mask of CUSTOMPATH_* flags, see
* nodes/extensible.h */
List *custom_paths; /* list of child Path nodes, if any */
+ List *custom_restrictinfo;
List *custom_private;
const struct CustomPathMethods *methods;
} CustomPath;
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index 001e75b5b76..6e557bebc44 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -128,6 +128,7 @@ extern ForeignPath *create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
List *pathkeys,
Relids required_outer,
Path *fdw_outerpath,
+ List *fdw_restrictinfo,
List *fdw_private);
extern ForeignPath *create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
PathTarget *target,
@@ -135,12 +136,14 @@ extern ForeignPath *create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
List *pathkeys,
Relids required_outer,
Path *fdw_outerpath,
+ List *fdw_restrictinfo,
List *fdw_private);
extern ForeignPath *create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel,
PathTarget *target,
double rows, Cost startup_cost, Cost total_cost,
List *pathkeys,
Path *fdw_outerpath,
+ List *fdw_restrictinfo,
List *fdw_private);
extern Relids calc_nestloop_required_outer(Relids outerrelids,
diff --git a/src/include/optimizer/restrictinfo.h b/src/include/optimizer/restrictinfo.h
index 14cdce750cb..e140e619ace 100644
--- a/src/include/optimizer/restrictinfo.h
+++ b/src/include/optimizer/restrictinfo.h
@@ -43,8 +43,6 @@ extern void extract_actual_join_clauses(List *restrictinfo_list,
Relids joinrelids,
List **joinquals,
List **otherquals);
-extern bool has_pseudoconstant_clauses(PlannerInfo *root,
- List *restrictinfo_list);
extern bool join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel);
extern bool join_clause_is_movable_into(RestrictInfo *rinfo,
Relids currentrelids,