38 #define PATH_PARAM_BY_PARENT(path, rel) \
39 ((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), \
40 (rel)->top_parent_relids))
41 #define PATH_PARAM_BY_REL_SELF(path, rel) \
42 ((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), (rel)->relids))
44 #define PATH_PARAM_BY_REL(path, rel) \
45 (PATH_PARAM_BY_REL_SELF(path, rel) || PATH_PARAM_BY_PARENT(path, rel))
78 Path *inner_cheapest_total);
88 bool *mergejoin_allowed);
96 Path *inner_cheapest_total,
134 bool mergejoin_allowed =
true;
148 joinrelids = joinrel->
relids;
226 jointype, sjinfo, restrictlist,
243 foreach(lc,
root->join_info_list)
283 if (mergejoin_allowed)
295 if (mergejoin_allowed)
312 if (mergejoin_allowed)
313 match_unsorted_inner(
root, joinrel, outerrel, innerrel,
331 if (joinrel->fdwroutine &&
332 joinrel->fdwroutine->GetForeignJoinPaths)
333 joinrel->fdwroutine->GetForeignJoinPaths(
root, joinrel,
372 return (
bms_overlap(inner_paramrels, outerrelids) &&
389 #ifdef USE_ASSERT_CHECKING
403 foreach(lc,
root->join_info_list)
442 List *ph_lateral_vars,
List **param_exprs,
443 List **operators,
bool *binary_mode)
451 *binary_mode =
false;
454 if (param_info != NULL)
479 if (rinfo->outer_is_left)
482 hasheqoperator = rinfo->left_hasheqoperator;
487 hasheqoperator = rinfo->right_hasheqoperator;
505 *operators =
lappend_oid(*operators, hasheqoperator);
506 *param_exprs =
lappend(*param_exprs, expr);
527 foreach(lc, lateral_vars)
559 *param_exprs =
lappend(*param_exprs, expr);
590 if (!
root->hasLateralRTEs)
600 foreach(lc,
root->placeholder_list)
624 ph_lateral_vars =
lappend(ph_lateral_vars, phinfo->
ph_var->phexpr);
641 ph_lateral_vars =
lappend(ph_lateral_vars, node);
651 ph_lateral_vars =
lappend(ph_lateral_vars, node);
660 return ph_lateral_vars;
681 List *hash_operators;
684 List *ph_lateral_vars;
696 if (outer_path->parent->
rows < 2)
711 if ((inner_path->param_info == NULL ||
712 inner_path->param_info->ppi_clauses ==
NIL) &&
714 ph_lateral_vars ==
NIL)
757 (inner_path->param_info == NULL ||
784 if (inner_path->param_info != NULL)
786 foreach(lc, inner_path->param_info->ppi_clauses)
797 inner_path->param_info,
798 outerrel->top_parent ?
799 outerrel->top_parent : outerrel,
863 innerrelids = innerrel->
relids;
868 outerrelids = outerrel->
relids;
878 innerrelids, inner_paramrels);
879 if (required_outer &&
890 Assert(!have_unsafe_outer_join_ref(
root, outerrelids, inner_paramrels));
916 outer_path, inner_path, extra);
920 pathkeys, required_outer))
964 if (inner_path->param_info != NULL)
966 Relids inner_paramrels = inner_path->param_info->ppi_req_outer;
978 outerrelids = outerrel->
relids;
1000 outer_path, inner_path, extra);
1030 List *outersortkeys,
1031 List *innersortkeys,
1071 if (required_outer &&
1083 if (outersortkeys &&
1085 outersortkeys =
NIL;
1086 if (innersortkeys &&
1088 innersortkeys =
NIL;
1094 outer_path, inner_path,
1095 outersortkeys, innersortkeys,
1100 pathkeys, required_outer))
1136 List *outersortkeys,
1137 List *innersortkeys,
1147 if (inner_path->param_info != NULL)
1149 Relids inner_paramrels = inner_path->param_info->ppi_req_outer;
1159 if (outersortkeys &&
1161 outersortkeys =
NIL;
1162 if (innersortkeys &&
1164 innersortkeys =
NIL;
1170 outer_path, inner_path,
1171 outersortkeys, innersortkeys,
1228 if (required_outer &&
1241 outer_path, inner_path, extra,
false);
1245 NIL, required_outer))
1295 if (inner_path->param_info != NULL)
1297 Relids inner_paramrels = inner_path->param_info->ppi_req_outer;
1308 outer_path, inner_path, extra, parallel_hash);
1345 rinfo->outer_is_left =
true;
1352 rinfo->outer_is_left =
false;
1380 Path *cheapest_partial_outer = NULL;
1381 Path *cheapest_safe_inner = NULL;
1418 outer_path, extra->
sjinfo);
1425 inner_path, extra->
sjinfo);
1449 cheapest_safe_inner = inner_path;
1451 cheapest_safe_inner =
1487 foreach(l, all_pathkeys)
1490 List *cur_mergeclauses;
1493 List *merge_pathkeys;
1497 outerkeys =
lcons(front_pathkey,
1501 outerkeys = all_pathkeys;
1544 if (cheapest_partial_outer && cheapest_safe_inner)
1547 cheapest_partial_outer,
1548 cheapest_safe_inner,
1580 Path *inner_cheapest_total,
1581 List *merge_pathkeys,
1585 List *innersortkeys;
1586 List *trialsortkeys;
1587 Path *cheapest_startup_inner;
1588 Path *cheapest_total_inner;
1611 if (mergeclauses ==
NIL)
1618 if (useallclauses &&
1636 inner_cheapest_total,
1682 cheapest_startup_inner = inner_cheapest_total;
1683 cheapest_total_inner = inner_cheapest_total;
1688 cheapest_startup_inner = NULL;
1689 cheapest_total_inner = NULL;
1692 if (num_sortkeys > 1 && !useallclauses)
1693 trialsortkeys =
list_copy(innersortkeys);
1695 trialsortkeys = innersortkeys;
1697 for (sortkeycnt = num_sortkeys; sortkeycnt > 0; sortkeycnt--)
1713 if (innerpath != NULL &&
1714 (cheapest_total_inner == NULL ||
1720 if (sortkeycnt < num_sortkeys)
1729 newclauses = mergeclauses;
1741 cheapest_total_inner = innerpath;
1749 if (innerpath != NULL &&
1750 (cheapest_startup_inner == NULL ||
1755 if (innerpath != cheapest_total_inner)
1761 if (newclauses ==
NIL)
1763 if (sortkeycnt < num_sortkeys)
1772 newclauses = mergeclauses;
1786 cheapest_startup_inner = innerpath;
1832 Path *matpath = NULL;
1856 useallclauses =
false;
1862 useallclauses =
true;
1868 useallclauses =
false;
1871 elog(
ERROR,
"unrecognized join type: %d",
1874 useallclauses =
false;
1884 inner_cheapest_total = NULL;
1893 if (inner_cheapest_total == NULL)
1895 inner_cheapest_total = (
Path *)
1897 Assert(inner_cheapest_total);
1899 else if (nestjoinOK)
1915 List *merge_pathkeys;
1933 outerpath, extra->
sjinfo);
1954 inner_cheapest_total,
1959 else if (nestjoinOK)
1987 innerpath, outerpath, jointype,
2000 if (matpath != NULL)
2015 if (inner_cheapest_total == NULL)
2020 save_jointype, extra, useallclauses,
2021 inner_cheapest_total, merge_pathkeys,
2044 save_jointype, extra);
2051 if (inner_cheapest_total == NULL ||
2060 if (inner_cheapest_total)
2062 save_jointype, extra,
2063 inner_cheapest_total);
2086 Path *inner_cheapest_total)
2094 List *merge_pathkeys;
2103 extra,
false, inner_cheapest_total,
2104 merge_pathkeys,
true);
2129 Path *matpath = NULL;
2196 pathkeys, jointype, extra);
2203 innerpath, outerpath, jointype,
2207 pathkeys, jointype, extra);
2211 if (matpath != NULL)
2213 pathkeys, jointype, extra);
2260 if (!restrictinfo->can_join ||
2261 restrictinfo->hashjoinoperator ==
InvalidOid)
2270 hashclauses =
lappend(hashclauses, restrictinfo);
2298 cheapest_total_outer = (
Path *)
2300 cheapest_total_outer, extra->
sjinfo);
2301 Assert(cheapest_total_outer);
2305 cheapest_total_outer,
2306 cheapest_total_inner,
2314 cheapest_total_inner = (
Path *)
2316 cheapest_total_inner, extra->
sjinfo);
2317 Assert(cheapest_total_inner);
2321 cheapest_total_outer,
2322 cheapest_total_inner,
2326 if (cheapest_startup_outer != NULL &&
2327 cheapest_startup_outer != cheapest_total_outer)
2330 cheapest_startup_outer,
2331 cheapest_total_inner,
2348 if (cheapest_startup_outer != NULL)
2351 cheapest_startup_outer,
2352 cheapest_total_inner,
2379 if (outerpath == cheapest_startup_outer &&
2380 innerpath == cheapest_total_inner)
2406 Path *cheapest_partial_outer;
2407 Path *cheapest_partial_inner = NULL;
2408 Path *cheapest_safe_inner = NULL;
2410 cheapest_partial_outer =
2422 cheapest_partial_inner =
2425 cheapest_partial_outer,
2426 cheapest_partial_inner,
2427 hashclauses, jointype, extra,
2444 cheapest_safe_inner = NULL;
2446 cheapest_safe_inner = cheapest_total_inner;
2448 cheapest_safe_inner =
2451 if (cheapest_safe_inner != NULL)
2453 cheapest_partial_outer,
2454 cheapest_safe_inner,
2455 hashclauses, jointype, extra,
2490 bool *mergejoin_allowed)
2494 bool have_nonmergeable_joinclause =
false;
2503 *mergejoin_allowed =
false;
2507 foreach(l, restrictlist)
2521 if (!restrictinfo->can_join ||
2522 restrictinfo->mergeopfamilies ==
NIL)
2531 have_nonmergeable_joinclause =
true;
2540 have_nonmergeable_joinclause =
true;
2557 have_nonmergeable_joinclause =
true;
2561 result_list =
lappend(result_list, restrictinfo);
2572 *mergejoin_allowed = !have_nonmergeable_joinclause;
2575 *mergejoin_allowed =
true;
bool innerrel_is_unique(PlannerInfo *root, Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache)
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
void bms_free(Bitmapset *a)
int bms_num_members(const Bitmapset *a)
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
BMS_Membership bms_membership(const Bitmapset *a)
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
#define Assert(condition)
#define OidIsValid(objectId)
bool contain_volatile_functions(Node *clause)
void initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, JoinType jointype, List *mergeclauses, Path *outer_path, Path *inner_path, List *outersortkeys, List *innersortkeys, JoinPathExtraData *extra)
void compute_semi_anti_join_factors(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, SpecialJoinInfo *sjinfo, List *restrictlist, SemiAntiJoinFactors *semifactors)
void initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace, JoinType jointype, List *hashclauses, Path *outer_path, Path *inner_path, JoinPathExtraData *extra, bool parallel_hash)
void initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace, JoinType jointype, Path *outer_path, Path *inner_path, JoinPathExtraData *extra)
bool enable_parallel_hash
bool ExecMaterializesOutput(NodeTag plantype)
if(TABLE==NULL||TABLE_index==NULL)
static void try_hashjoin_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *hashclauses, JoinType jointype, JoinPathExtraData *extra)
static Path * get_memoize_path(PlannerInfo *root, RelOptInfo *innerrel, RelOptInfo *outerrel, Path *inner_path, Path *outer_path, JoinType jointype, JoinPathExtraData *extra)
static bool clause_sides_match_join(RestrictInfo *rinfo, RelOptInfo *outerrel, RelOptInfo *innerrel)
static List * select_mergejoin_clauses(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, JoinType jointype, bool *mergejoin_allowed)
static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
void add_paths_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, SpecialJoinInfo *sjinfo, List *restrictlist)
static List * extract_lateral_vars_from_PHVs(PlannerInfo *root, Relids innerrelids)
static bool paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info, RelOptInfo *outerrel, RelOptInfo *innerrel, List *ph_lateral_vars, List **param_exprs, List **operators, bool *binary_mode)
static void try_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *pathkeys, JoinType jointype, JoinPathExtraData *extra)
static void consider_parallel_nestloop(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
#define PATH_PARAM_BY_PARENT(path, rel)
set_join_pathlist_hook_type set_join_pathlist_hook
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)
static void consider_parallel_mergejoin(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra, Path *inner_cheapest_total)
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 void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
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)
#define PATH_PARAM_BY_REL(path, rel)
static bool allow_star_schema_join(PlannerInfo *root, Relids outerrelids, Relids inner_paramrels)
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)
static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
static void try_partial_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *pathkeys, JoinType jointype, JoinPathExtraData *extra)
bool have_dangerous_phv(PlannerInfo *root, Relids outer_relids, Relids inner_params)
List * list_truncate(List *list, int new_size)
List * lappend(List *list, void *datum)
List * lappend_oid(List *list, Oid datum)
List * list_copy(const List *oldlist)
List * list_delete_nth_cell(List *list, int n)
void list_free(List *list)
List * list_concat(List *list1, const List *list2)
bool list_member(const List *list, const void *datum)
List * lcons(void *datum, List *list)
Oid exprType(const Node *expr)
#define IsA(nodeptr, _type_)
#define IS_OUTER_JOIN(jointype)
List * build_join_pathkeys(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, List *outer_pathkeys)
List * make_inner_pathkeys_for_merge(PlannerInfo *root, List *mergeclauses, List *outer_pathkeys)
Path * get_cheapest_path_for_pathkeys(List *paths, List *pathkeys, Relids required_outer, CostSelector cost_criterion, bool require_parallel_safe)
List * find_mergeclauses_for_outer_pathkeys(PlannerInfo *root, List *pathkeys, List *restrictinfos)
List * trim_mergeclauses_for_inner_pathkeys(PlannerInfo *root, List *mergeclauses, List *pathkeys)
List * select_outer_pathkeys_for_merge(PlannerInfo *root, List *mergeclauses, RelOptInfo *joinrel)
void update_mergeclause_eclasses(PlannerInfo *root, RestrictInfo *restrictinfo)
Path * get_cheapest_parallel_safe_total_inner(List *paths)
bool pathkeys_contained_in(List *keys1, List *keys2)
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)
Relids calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path)
UniquePath * create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, SpecialJoinInfo *sjinfo)
bool path_is_reparameterizable_by_child(Path *path, RelOptInfo *child_rel)
Relids calc_nestloop_required_outer(Relids outerrelids, Relids outer_paramrels, Relids innerrelids, Relids inner_paramrels)
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)
MemoizePath * create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *param_exprs, List *hash_operators, bool singlerow, bool binary_mode, double calls)
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
MaterialPath * create_material_path(RelOptInfo *rel, Path *subpath)
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)
bool add_partial_path_precheck(RelOptInfo *parent_rel, Cost total_cost, List *pathkeys)
void add_path(RelOptInfo *parent_rel, Path *new_path)
int compare_path_costs(Path *path1, Path *path2, CostSelector criterion)
bool add_path_precheck(RelOptInfo *parent_rel, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer)
#define EC_MUST_BE_REDUNDANT(eclass)
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
#define PATH_REQ_OUTER(path)
void(* set_join_pathlist_hook_type)(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
static int list_length(const List *l)
#define foreach_current_index(var_or_cell)
static ListCell * list_head(const List *l)
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
struct PathTarget * reltarget
List * cheapest_parameterized_paths
struct Path * cheapest_startup_path
struct Path * cheapest_total_path
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
#define TYPECACHE_HASH_PROC
List * pull_vars_of_level(Node *node, int levelsup)
Relids pull_varnos(PlannerInfo *root, Node *node)