diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/optimizer/path/joinpath.c | 19 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 21 | ||||
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 10 | ||||
-rw-r--r-- | src/backend/optimizer/util/restrictinfo.c | 30 | ||||
-rw-r--r-- | src/include/nodes/pathnodes.h | 10 | ||||
-rw-r--r-- | src/include/optimizer/pathnode.h | 3 | ||||
-rw-r--r-- | src/include/optimizer/restrictinfo.h | 2 |
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, |