33 #define PATH_PARAM_BY_PARENT(path, rel) \ 34 ((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), \ 35 (rel)->top_parent_relids)) 36 #define PATH_PARAM_BY_REL_SELF(path, rel) \ 37 ((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), (rel)->relids)) 39 #define PATH_PARAM_BY_REL(path, rel) \ 40 (PATH_PARAM_BY_REL_SELF(path, rel) || PATH_PARAM_BY_PARENT(path, rel)) 70 Path *inner_cheapest_total);
80 bool *mergejoin_allowed);
88 Path *inner_cheapest_total,
126 bool mergejoin_allowed =
true;
140 joinrelids = joinrel->
relids;
213 jointype, sjinfo, restrictlist,
268 if (mergejoin_allowed)
279 if (mergejoin_allowed)
296 if (mergejoin_allowed)
297 match_unsorted_inner(root, joinrel, outerrel, innerrel,
353 return (
bms_overlap(inner_paramrels, outerrelids) &&
387 innerrelids = innerrel->
relids;
392 outerrelids = outerrel->
relids;
402 innerrelids, inner_paramrels);
403 if (required_outer &&
423 outer_path, inner_path, extra);
427 pathkeys, required_outer))
506 outerrelids = outerrel->
relids;
517 outer_path, inner_path, extra);
593 if (required_outer &&
616 outer_path, inner_path,
617 outersortkeys, innersortkeys,
622 pathkeys, required_outer))
692 outer_path, inner_path,
693 outersortkeys, innersortkeys,
739 if (required_outer &&
752 outer_path, inner_path, extra,
false);
756 NIL, required_outer))
819 outer_path, inner_path, extra, parallel_hash);
891 Path *cheapest_partial_outer = NULL;
892 Path *cheapest_safe_inner = NULL;
929 outer_path, extra->
sjinfo);
936 inner_path, extra->
sjinfo);
959 cheapest_safe_inner = inner_path;
961 cheapest_safe_inner =
997 foreach(l, all_pathkeys)
1000 List *cur_mergeclauses;
1003 List *merge_pathkeys;
1007 outerkeys =
lcons(front_pathkey,
1011 outerkeys = all_pathkeys;
1054 if (cheapest_partial_outer && cheapest_safe_inner)
1057 cheapest_partial_outer,
1058 cheapest_safe_inner,
1090 Path *inner_cheapest_total,
1091 List *merge_pathkeys,
1095 List *innersortkeys;
1096 List *trialsortkeys;
1097 Path *cheapest_startup_inner;
1098 Path *cheapest_total_inner;
1121 if (mergeclauses ==
NIL)
1128 if (useallclauses &&
1146 inner_cheapest_total,
1192 cheapest_startup_inner = inner_cheapest_total;
1193 cheapest_total_inner = inner_cheapest_total;
1198 cheapest_startup_inner = NULL;
1199 cheapest_total_inner = NULL;
1202 if (num_sortkeys > 1 && !useallclauses)
1203 trialsortkeys =
list_copy(innersortkeys);
1205 trialsortkeys = innersortkeys;
1207 for (sortkeycnt = num_sortkeys; sortkeycnt > 0; sortkeycnt--)
1223 if (innerpath != NULL &&
1224 (cheapest_total_inner == NULL ||
1230 if (sortkeycnt < num_sortkeys)
1239 newclauses = mergeclauses;
1251 cheapest_total_inner = innerpath;
1259 if (innerpath != NULL &&
1260 (cheapest_startup_inner == NULL ||
1265 if (innerpath != cheapest_total_inner)
1271 if (newclauses ==
NIL)
1273 if (sortkeycnt < num_sortkeys)
1282 newclauses = mergeclauses;
1296 cheapest_startup_inner = innerpath;
1342 Path *matpath = NULL;
1359 useallclauses =
false;
1364 useallclauses =
true;
1370 useallclauses =
false;
1373 elog(
ERROR,
"unrecognized join type: %d",
1376 useallclauses =
false;
1386 inner_cheapest_total = NULL;
1395 if (inner_cheapest_total == NULL)
1397 inner_cheapest_total = (
Path *)
1399 Assert(inner_cheapest_total);
1401 else if (nestjoinOK)
1417 List *merge_pathkeys;
1435 outerpath, extra->
sjinfo);
1456 inner_cheapest_total,
1461 else if (nestjoinOK)
1485 if (matpath != NULL)
1500 if (inner_cheapest_total == NULL)
1505 save_jointype, extra, useallclauses,
1506 inner_cheapest_total, merge_pathkeys,
1528 save_jointype, extra);
1535 if (inner_cheapest_total == NULL ||
1544 if (inner_cheapest_total)
1546 save_jointype, extra,
1547 inner_cheapest_total);
1570 Path *inner_cheapest_total)
1578 List *merge_pathkeys;
1587 extra,
false, inner_cheapest_total,
1588 merge_pathkeys,
true);
1659 pathkeys, jointype, extra);
1717 hashclauses =
lappend(hashclauses, restrictinfo);
1745 cheapest_total_outer = (
Path *)
1747 cheapest_total_outer, extra->
sjinfo);
1748 Assert(cheapest_total_outer);
1752 cheapest_total_outer,
1753 cheapest_total_inner,
1761 cheapest_total_inner = (
Path *)
1763 cheapest_total_inner, extra->
sjinfo);
1764 Assert(cheapest_total_inner);
1768 cheapest_total_outer,
1769 cheapest_total_inner,
1773 if (cheapest_startup_outer != NULL &&
1774 cheapest_startup_outer != cheapest_total_outer)
1777 cheapest_startup_outer,
1778 cheapest_total_inner,
1795 if (cheapest_startup_outer != NULL)
1798 cheapest_startup_outer,
1799 cheapest_total_inner,
1826 if (outerpath == cheapest_startup_outer &&
1827 innerpath == cheapest_total_inner)
1860 Path *cheapest_partial_outer;
1861 Path *cheapest_partial_inner = NULL;
1862 Path *cheapest_safe_inner = NULL;
1864 cheapest_partial_outer =
1876 cheapest_partial_inner =
1879 cheapest_partial_outer,
1880 cheapest_partial_inner,
1881 hashclauses, jointype, extra,
1893 cheapest_safe_inner = cheapest_total_inner;
1895 cheapest_safe_inner =
1898 if (cheapest_safe_inner != NULL)
1900 cheapest_partial_outer,
1901 cheapest_safe_inner,
1902 hashclauses, jointype, extra,
1937 bool *mergejoin_allowed)
1941 bool have_nonmergeable_joinclause =
false;
1944 foreach(l, restrictlist)
1968 have_nonmergeable_joinclause =
true;
1977 have_nonmergeable_joinclause =
true;
2006 have_nonmergeable_joinclause =
true;
2010 result_list =
lappend(result_list, restrictinfo);
2020 *mergejoin_allowed = !have_nonmergeable_joinclause;
2023 *mergejoin_allowed =
true;
Path * get_cheapest_path_for_pathkeys(List *paths, List *pathkeys, Relids required_outer, CostSelector cost_criterion, bool require_parallel_safe)
static void try_mergejoin_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *pathkeys, List *mergeclauses, List *outersortkeys, List *innersortkeys, JoinType jointype, JoinPathExtraData *extra, bool is_partial)
#define IsA(nodeptr, _type_)
static void try_hashjoin_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *hashclauses, JoinType jointype, JoinPathExtraData *extra)
void add_path(RelOptInfo *parent_rel, Path *new_path)
static void try_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *pathkeys, JoinType jointype, JoinPathExtraData *extra)
static void try_partial_hashjoin_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *hashclauses, JoinType jointype, JoinPathExtraData *extra, bool parallel_hash)
bool add_partial_path_precheck(RelOptInfo *parent_rel, Cost total_cost, List *pathkeys)
bool add_path_precheck(RelOptInfo *parent_rel, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer)
struct Path * cheapest_startup_path
MaterialPath * create_material_path(RelOptInfo *rel, Path *subpath)
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
List * list_truncate(List *list, int new_size)
#define IS_OUTER_JOIN(jointype)
ParamPathInfo * param_info
bool enable_parallel_hash
Relids calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path)
List * list_copy(const List *oldlist)
List * make_inner_pathkeys_for_merge(PlannerInfo *root, List *mergeclauses, List *outer_pathkeys)
HashPath * create_hashjoin_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, JoinCostWorkspace *workspace, JoinPathExtraData *extra, Path *outer_path, Path *inner_path, bool parallel_hash, List *restrict_clauses, Relids required_outer, List *hashclauses)
void initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace, JoinType jointype, List *hashclauses, Path *outer_path, Path *inner_path, JoinPathExtraData *extra, bool parallel_hash)
bool innerrel_is_unique(PlannerInfo *root, Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache)
EquivalenceClass * right_ec
List * cheapest_parameterized_paths
UniquePath * create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, SpecialJoinInfo *sjinfo)
MergePath * create_mergejoin_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, JoinCostWorkspace *workspace, JoinPathExtraData *extra, Path *outer_path, Path *inner_path, List *restrict_clauses, List *pathkeys, Relids required_outer, List *mergeclauses, List *outersortkeys, List *innersortkeys)
void initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, JoinType jointype, List *mergeclauses, Path *outer_path, Path *inner_path, List *outersortkeys, List *innersortkeys, JoinPathExtraData *extra)
List * build_join_pathkeys(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, List *outer_pathkeys)
List * find_mergeclauses_for_outer_pathkeys(PlannerInfo *root, List *pathkeys, List *restrictinfos)
#define PATH_PARAM_BY_PARENT(path, rel)
static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
GetForeignJoinPaths_function GetForeignJoinPaths
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Path * reparameterize_path_by_child(PlannerInfo *root, Path *path, RelOptInfo *child_rel)
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
int compare_path_costs(Path *path1, Path *path2, CostSelector criterion)
NestPath * create_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, JoinCostWorkspace *workspace, JoinPathExtraData *extra, Path *outer_path, Path *inner_path, List *restrict_clauses, List *pathkeys, Relids required_outer)
struct Path * cheapest_total_path
#define PATH_REQ_OUTER(path)
#define EC_MUST_BE_REDUNDANT(eclass)
static void try_partial_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *pathkeys, JoinType jointype, JoinPathExtraData *extra)
struct FdwRoutine * fdwroutine
static void generate_mergejoin_paths(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *innerrel, Path *outerpath, JoinType jointype, JoinPathExtraData *extra, bool useallclauses, Path *inner_cheapest_total, List *merge_pathkeys, bool is_partial)
static ListCell * list_head(const List *l)
Path * get_cheapest_parallel_safe_total_inner(List *paths)
List * lappend(List *list, void *datum)
static void consider_parallel_nestloop(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
bool bms_is_empty(const Bitmapset *a)
static List * select_mergejoin_clauses(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, JoinType jointype, bool *mergejoin_allowed)
bool pathkeys_contained_in(List *keys1, List *keys2)
static void consider_parallel_mergejoin(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra, Path *inner_cheapest_total)
List * trim_mergeclauses_for_inner_pathkeys(PlannerInfo *root, List *mergeclauses, List *pathkeys)
set_join_pathlist_hook_type set_join_pathlist_hook
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
List * select_outer_pathkeys_for_merge(PlannerInfo *root, List *mergeclauses, RelOptInfo *joinrel)
#define PATH_PARAM_BY_REL(path, rel)
List * lcons(void *datum, List *list)
void bms_free(Bitmapset *a)
#define Assert(condition)
static bool clause_sides_match_join(RestrictInfo *rinfo, RelOptInfo *outerrel, RelOptInfo *innerrel)
static int list_length(const List *l)
Relids calc_nestloop_required_outer(Relids outerrelids, Relids outer_paramrels, Relids innerrelids, Relids inner_paramrels)
void compute_semi_anti_join_factors(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, SpecialJoinInfo *sjinfo, List *restrictlist, SemiAntiJoinFactors *semifactors)
void(* set_join_pathlist_hook_type)(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
EquivalenceClass * left_ec
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
static void try_partial_mergejoin_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *pathkeys, List *mergeclauses, List *outersortkeys, List *innersortkeys, JoinType jointype, JoinPathExtraData *extra)
void add_paths_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, SpecialJoinInfo *sjinfo, List *restrictlist)
bool ExecMaterializesOutput(NodeTag plantype)
void initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace, JoinType jointype, Path *outer_path, Path *inner_path, JoinPathExtraData *extra)
List * list_delete_nth_cell(List *list, int n)
static bool allow_star_schema_join(PlannerInfo *root, Relids outerrelids, Relids inner_paramrels)
void update_mergeclause_eclasses(PlannerInfo *root, RestrictInfo *restrictinfo)
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
#define foreach_current_index(cell)
bool have_dangerous_phv(PlannerInfo *root, Relids outer_relids, Relids inner_params)
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)