PostgreSQL Source Code: src/backend/optimizer/path/joinpath.c Source File

PostgreSQL Source Code git master
joinpath.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * joinpath.c
4 * Routines to find all possible paths for processing a set of joins
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/optimizer/path/joinpath.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include <math.h>
18
19#include "executor/executor.h"
20#include "foreign/fdwapi.h"
21#include "nodes/nodeFuncs.h"
22#include "optimizer/cost.h"
23#include "optimizer/optimizer.h"
24#include "optimizer/pathnode.h"
25#include "optimizer/paths.h"
26#include "optimizer/placeholder.h"
27#include "optimizer/planmain.h"
28#include "optimizer/restrictinfo.h"
29#include "utils/lsyscache.h"
30#include "utils/typcache.h"
31
32/* Hook for plugins to get control in add_paths_to_joinrel() */
33 set_join_pathlist_hook_type set_join_pathlist_hook = NULL;
34
35/*
36 * Paths parameterized by a parent rel can be considered to be parameterized
37 * by any of its children, when we are performing partitionwise joins. These
38 * macros simplify checking for such cases. Beware multiple eval of args.
39 */
40 #define PATH_PARAM_BY_PARENT(path, rel) \
41 ((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), \
42 (rel)->top_parent_relids))
43 #define PATH_PARAM_BY_REL_SELF(path, rel) \
44 ((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), (rel)->relids))
45
46 #define PATH_PARAM_BY_REL(path, rel) \
47 (PATH_PARAM_BY_REL_SELF(path, rel) || PATH_PARAM_BY_PARENT(path, rel))
48
49static void try_partial_mergejoin_path(PlannerInfo *root,
50 RelOptInfo *joinrel,
51 Path *outer_path,
52 Path *inner_path,
53 List *pathkeys,
54 List *mergeclauses,
55 List *outersortkeys,
56 List *innersortkeys,
57 JoinType jointype,
58 JoinPathExtraData *extra);
59static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
60 RelOptInfo *outerrel, RelOptInfo *innerrel,
61 JoinType jointype, JoinPathExtraData *extra);
62static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel,
63 RelOptInfo *outerrel, RelOptInfo *innerrel,
64 JoinType jointype, JoinPathExtraData *extra);
65static void consider_parallel_nestloop(PlannerInfo *root,
66 RelOptInfo *joinrel,
67 RelOptInfo *outerrel,
68 RelOptInfo *innerrel,
69 JoinType jointype,
70 JoinPathExtraData *extra);
71static void consider_parallel_mergejoin(PlannerInfo *root,
72 RelOptInfo *joinrel,
73 RelOptInfo *outerrel,
74 RelOptInfo *innerrel,
75 JoinType jointype,
76 JoinPathExtraData *extra,
77 Path *inner_cheapest_total);
78static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
79 RelOptInfo *outerrel, RelOptInfo *innerrel,
80 JoinType jointype, JoinPathExtraData *extra);
81static List *select_mergejoin_clauses(PlannerInfo *root,
82 RelOptInfo *joinrel,
83 RelOptInfo *outerrel,
84 RelOptInfo *innerrel,
85 List *restrictlist,
86 JoinType jointype,
87 bool *mergejoin_allowed);
88static void generate_mergejoin_paths(PlannerInfo *root,
89 RelOptInfo *joinrel,
90 RelOptInfo *innerrel,
91 Path *outerpath,
92 JoinType jointype,
93 JoinPathExtraData *extra,
94 bool useallclauses,
95 Path *inner_cheapest_total,
96 List *merge_pathkeys,
97 bool is_partial);
98
99
100/*
101 * add_paths_to_joinrel
102 * Given a join relation and two component rels from which it can be made,
103 * consider all possible paths that use the two component rels as outer
104 * and inner rel respectively. Add these paths to the join rel's pathlist
105 * if they survive comparison with other paths (and remove any existing
106 * paths that are dominated by these paths).
107 *
108 * Modifies the pathlist field of the joinrel node to contain the best
109 * paths found so far.
110 *
111 * jointype is not necessarily the same as sjinfo->jointype; it might be
112 * "flipped around" if we are considering joining the rels in the opposite
113 * direction from what's indicated in sjinfo.
114 *
115 * Also, this routine accepts the special JoinTypes JOIN_UNIQUE_OUTER and
116 * JOIN_UNIQUE_INNER to indicate that the outer or inner relation has been
117 * unique-ified and a regular inner join should then be applied. These values
118 * are not allowed to propagate outside this routine, however. Path cost
119 * estimation code, as well as match_unsorted_outer, may need to recognize that
120 * it's dealing with such a case --- the combination of nominal jointype INNER
121 * with sjinfo->jointype == JOIN_SEMI indicates that.
122 */
123void
124 add_paths_to_joinrel(PlannerInfo *root,
125 RelOptInfo *joinrel,
126 RelOptInfo *outerrel,
127 RelOptInfo *innerrel,
128 JoinType jointype,
129 SpecialJoinInfo *sjinfo,
130 List *restrictlist)
131{
132 JoinType save_jointype = jointype;
133 JoinPathExtraData extra;
134 bool mergejoin_allowed = true;
135 ListCell *lc;
136 Relids joinrelids;
137
138 /*
139 * PlannerInfo doesn't contain the SpecialJoinInfos created for joins
140 * between child relations, even if there is a SpecialJoinInfo node for
141 * the join between the topmost parents. So, while calculating Relids set
142 * representing the restriction, consider relids of topmost parent of
143 * partitions.
144 */
145 if (joinrel->reloptkind == RELOPT_OTHER_JOINREL)
146 joinrelids = joinrel->top_parent_relids;
147 else
148 joinrelids = joinrel->relids;
149
150 extra.restrictlist = restrictlist;
151 extra.mergeclause_list = NIL;
152 extra.sjinfo = sjinfo;
153 extra.param_source_rels = NULL;
154
155 /*
156 * See if the inner relation is provably unique for this outer rel.
157 *
158 * We have some special cases: for JOIN_SEMI, it doesn't matter since the
159 * executor can make the equivalent optimization anyway. It also doesn't
160 * help enable use of Memoize, since a semijoin with a provably unique
161 * inner side should have been reduced to an inner join in that case.
162 * Therefore, we need not expend planner cycles on proofs. (For
163 * JOIN_ANTI, although it doesn't help the executor for the same reason,
164 * it can benefit Memoize paths.) For JOIN_UNIQUE_INNER, we must be
165 * considering a semijoin whose inner side is not provably unique (else
166 * reduce_unique_semijoins would've simplified it), so there's no point in
167 * calling innerrel_is_unique. However, if the LHS covers all of the
168 * semijoin's min_lefthand, then it's appropriate to set inner_unique
169 * because the unique relation produced by create_unique_paths will be
170 * unique relative to the LHS. (If we have an LHS that's only part of the
171 * min_lefthand, that is *not* true.) For JOIN_UNIQUE_OUTER, pass
172 * JOIN_INNER to avoid letting that value escape this module.
173 */
174 switch (jointype)
175 {
176 case JOIN_SEMI:
177 extra.inner_unique = false; /* well, unproven */
178 break;
179 case JOIN_UNIQUE_INNER:
180 extra.inner_unique = bms_is_subset(sjinfo->min_lefthand,
181 outerrel->relids);
182 break;
183 case JOIN_UNIQUE_OUTER:
184 extra.inner_unique = innerrel_is_unique(root,
185 joinrel->relids,
186 outerrel->relids,
187 innerrel,
188 JOIN_INNER,
189 restrictlist,
190 false);
191 break;
192 default:
193 extra.inner_unique = innerrel_is_unique(root,
194 joinrel->relids,
195 outerrel->relids,
196 innerrel,
197 jointype,
198 restrictlist,
199 false);
200 break;
201 }
202
203 /*
204 * If the outer or inner relation has been unique-ified, handle as a plain
205 * inner join.
206 */
207 if (jointype == JOIN_UNIQUE_OUTER || jointype == JOIN_UNIQUE_INNER)
208 jointype = JOIN_INNER;
209
210 /*
211 * Find potential mergejoin clauses. We can skip this if we are not
212 * interested in doing a mergejoin. However, mergejoin may be our only
213 * way of implementing a full outer join, so override enable_mergejoin if
214 * it's a full join.
215 */
216 if (enable_mergejoin || jointype == JOIN_FULL)
217 extra.mergeclause_list = select_mergejoin_clauses(root,
218 joinrel,
219 outerrel,
220 innerrel,
221 restrictlist,
222 jointype,
223 &mergejoin_allowed);
224
225 /*
226 * If it's SEMI, ANTI, or inner_unique join, compute correction factors
227 * for cost estimation. These will be the same for all paths.
228 */
229 if (jointype == JOIN_SEMI || jointype == JOIN_ANTI || extra.inner_unique)
230 compute_semi_anti_join_factors(root, joinrel, outerrel, innerrel,
231 jointype, sjinfo, restrictlist,
232 &extra.semifactors);
233
234 /*
235 * Decide whether it's sensible to generate parameterized paths for this
236 * joinrel, and if so, which relations such paths should require. There
237 * is usually no need to create a parameterized result path unless there
238 * is a join order restriction that prevents joining one of our input rels
239 * directly to the parameter source rel instead of joining to the other
240 * input rel. (But see allow_star_schema_join().) This restriction
241 * reduces the number of parameterized paths we have to deal with at
242 * higher join levels, without compromising the quality of the resulting
243 * plan. We express the restriction as a Relids set that must overlap the
244 * parameterization of any proposed join path. Note: param_source_rels
245 * should contain only baserels, not OJ relids, so starting from
246 * all_baserels not all_query_rels is correct.
247 */
248 foreach(lc, root->join_info_list)
249 {
250 SpecialJoinInfo *sjinfo2 = (SpecialJoinInfo *) lfirst(lc);
251
252 /*
253 * SJ is relevant to this join if we have some part of its RHS
254 * (possibly not all of it), and haven't yet joined to its LHS. (This
255 * test is pretty simplistic, but should be sufficient considering the
256 * join has already been proven legal.) If the SJ is relevant, it
257 * presents constraints for joining to anything not in its RHS.
258 */
259 if (bms_overlap(joinrelids, sjinfo2->min_righthand) &&
260 !bms_overlap(joinrelids, sjinfo2->min_lefthand))
261 extra.param_source_rels = bms_join(extra.param_source_rels,
262 bms_difference(root->all_baserels,
263 sjinfo2->min_righthand));
264
265 /* full joins constrain both sides symmetrically */
266 if (sjinfo2->jointype == JOIN_FULL &&
267 bms_overlap(joinrelids, sjinfo2->min_lefthand) &&
268 !bms_overlap(joinrelids, sjinfo2->min_righthand))
269 extra.param_source_rels = bms_join(extra.param_source_rels,
270 bms_difference(root->all_baserels,
271 sjinfo2->min_lefthand));
272 }
273
274 /*
275 * However, when a LATERAL subquery is involved, there will simply not be
276 * any paths for the joinrel that aren't parameterized by whatever the
277 * subquery is parameterized by, unless its parameterization is resolved
278 * within the joinrel. So we might as well allow additional dependencies
279 * on whatever residual lateral dependencies the joinrel will have.
280 */
281 extra.param_source_rels = bms_add_members(extra.param_source_rels,
282 joinrel->lateral_relids);
283
284 /*
285 * 1. Consider mergejoin paths where both relations must be explicitly
286 * sorted. Skip this if we can't mergejoin.
287 */
288 if (mergejoin_allowed)
289 sort_inner_and_outer(root, joinrel, outerrel, innerrel,
290 jointype, &extra);
291
292 /*
293 * 2. Consider paths where the outer relation need not be explicitly
294 * sorted. This includes both nestloops and mergejoins where the outer
295 * path is already ordered. Again, skip this if we can't mergejoin.
296 * (That's okay because we know that nestloop can't handle
297 * right/right-anti/right-semi/full joins at all, so it wouldn't work in
298 * the prohibited cases either.)
299 */
300 if (mergejoin_allowed)
301 match_unsorted_outer(root, joinrel, outerrel, innerrel,
302 jointype, &extra);
303
304#ifdef NOT_USED
305
306 /*
307 * 3. Consider paths where the inner relation need not be explicitly
308 * sorted. This includes mergejoins only (nestloops were already built in
309 * match_unsorted_outer).
310 *
311 * Diked out as redundant 2/13/2000 -- tgl. There isn't any really
312 * significant difference between the inner and outer side of a mergejoin,
313 * so match_unsorted_inner creates no paths that aren't equivalent to
314 * those made by match_unsorted_outer when add_paths_to_joinrel() is
315 * invoked with the two rels given in the other order.
316 */
317 if (mergejoin_allowed)
318 match_unsorted_inner(root, joinrel, outerrel, innerrel,
319 jointype, &extra);
320#endif
321
322 /*
323 * 4. Consider paths where both outer and inner relations must be hashed
324 * before being joined. As above, disregard enable_hashjoin for full
325 * joins, because there may be no other alternative.
326 */
327 if (enable_hashjoin || jointype == JOIN_FULL)
328 hash_inner_and_outer(root, joinrel, outerrel, innerrel,
329 jointype, &extra);
330
331 /*
332 * 5. If inner and outer relations are foreign tables (or joins) belonging
333 * to the same server and assigned to the same user to check access
334 * permissions as, give the FDW a chance to push down joins.
335 */
336 if (joinrel->fdwroutine &&
337 joinrel->fdwroutine->GetForeignJoinPaths)
338 joinrel->fdwroutine->GetForeignJoinPaths(root, joinrel,
339 outerrel, innerrel,
340 save_jointype, &extra);
341
342 /*
343 * 6. Finally, give extensions a chance to manipulate the path list. They
344 * could add new paths (such as CustomPaths) by calling add_path(), or
345 * add_partial_path() if parallel aware. They could also delete or modify
346 * paths added by the core code.
347 */
348 if (set_join_pathlist_hook)
349 set_join_pathlist_hook(root, joinrel, outerrel, innerrel,
350 save_jointype, &extra);
351}
352
353/*
354 * We override the param_source_rels heuristic to accept nestloop paths in
355 * which the outer rel satisfies some but not all of the inner path's
356 * parameterization. This is necessary to get good plans for star-schema
357 * scenarios, in which a parameterized path for a large table may require
358 * parameters from multiple small tables that will not get joined directly to
359 * each other. We can handle that by stacking nestloops that have the small
360 * tables on the outside; but this breaks the rule the param_source_rels
361 * heuristic is based on, namely that parameters should not be passed down
362 * across joins unless there's a join-order-constraint-based reason to do so.
363 * So we ignore the param_source_rels restriction when this case applies.
364 *
365 * allow_star_schema_join() returns true if the param_source_rels restriction
366 * should be overridden, ie, it's okay to perform this join.
367 */
368static inline bool
369 allow_star_schema_join(PlannerInfo *root,
370 Relids outerrelids,
371 Relids inner_paramrels)
372{
373 /*
374 * It's a star-schema case if the outer rel provides some but not all of
375 * the inner rel's parameterization.
376 */
377 return (bms_overlap(inner_paramrels, outerrelids) &&
378 bms_nonempty_difference(inner_paramrels, outerrelids));
379}
380
381/*
382 * If the parameterization is only partly satisfied by the outer rel,
383 * the unsatisfied part can't include any outer-join relids that could
384 * null rels of the satisfied part. That would imply that we're trying
385 * to use a clause involving a Var with nonempty varnullingrels at
386 * a join level where that value isn't yet computable.
387 *
388 * In practice, this test never finds a problem because earlier join order
389 * restrictions prevent us from attempting a join that would cause a problem.
390 * (That's unsurprising, because the code worked before we ever added
391 * outer-join relids to expression relids.) It still seems worth checking
392 * as a backstop, but we only do so in assert-enabled builds.
393 */
394#ifdef USE_ASSERT_CHECKING
395static inline bool
396have_unsafe_outer_join_ref(PlannerInfo *root,
397 Relids outerrelids,
398 Relids inner_paramrels)
399{
400 bool result = false;
401 Relids unsatisfied = bms_difference(inner_paramrels, outerrelids);
402 Relids satisfied = bms_intersect(inner_paramrels, outerrelids);
403
404 if (bms_overlap(unsatisfied, root->outer_join_rels))
405 {
406 ListCell *lc;
407
408 foreach(lc, root->join_info_list)
409 {
410 SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
411
412 if (!bms_is_member(sjinfo->ojrelid, unsatisfied))
413 continue; /* not relevant */
414 if (bms_overlap(satisfied, sjinfo->min_righthand) ||
415 (sjinfo->jointype == JOIN_FULL &&
416 bms_overlap(satisfied, sjinfo->min_lefthand)))
417 {
418 result = true; /* doesn't work */
419 break;
420 }
421 }
422 }
423
424 /* Waste no memory when we reject a path here */
425 bms_free(unsatisfied);
426 bms_free(satisfied);
427
428 return result;
429}
430#endif /* USE_ASSERT_CHECKING */
431
432/*
433 * paraminfo_get_equal_hashops
434 * Determine if the clauses in param_info and innerrel's lateral vars
435 * can be hashed.
436 * Returns true if hashing is possible, otherwise false.
437 *
438 * Additionally, on success we collect the outer expressions and the
439 * appropriate equality operators for each hashable parameter to innerrel.
440 * These are returned in parallel lists in *param_exprs and *operators.
441 * We also set *binary_mode to indicate whether strict binary matching is
442 * required.
443 */
444static bool
445 paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info,
446 RelOptInfo *outerrel, RelOptInfo *innerrel,
447 List *ph_lateral_vars, List **param_exprs,
448 List **operators, bool *binary_mode)
449
450{
451 List *lateral_vars;
452 ListCell *lc;
453
454 *param_exprs = NIL;
455 *operators = NIL;
456 *binary_mode = false;
457
458 /* Add join clauses from param_info to the hash key */
459 if (param_info != NULL)
460 {
461 List *clauses = param_info->ppi_clauses;
462
463 foreach(lc, clauses)
464 {
465 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
466 OpExpr *opexpr;
467 Node *expr;
468 Oid hasheqoperator;
469
470 opexpr = (OpExpr *) rinfo->clause;
471
472 /*
473 * Bail if the rinfo is not compatible. We need a join OpExpr
474 * with 2 args.
475 */
476 if (!IsA(opexpr, OpExpr) || list_length(opexpr->args) != 2 ||
477 !clause_sides_match_join(rinfo, outerrel->relids,
478 innerrel->relids))
479 {
480 list_free(*operators);
481 list_free(*param_exprs);
482 return false;
483 }
484
485 if (rinfo->outer_is_left)
486 {
487 expr = (Node *) linitial(opexpr->args);
488 hasheqoperator = rinfo->left_hasheqoperator;
489 }
490 else
491 {
492 expr = (Node *) lsecond(opexpr->args);
493 hasheqoperator = rinfo->right_hasheqoperator;
494 }
495
496 /* can't do memoize if we can't hash the outer type */
497 if (!OidIsValid(hasheqoperator))
498 {
499 list_free(*operators);
500 list_free(*param_exprs);
501 return false;
502 }
503
504 /*
505 * 'expr' may already exist as a parameter from a previous item in
506 * ppi_clauses. No need to include it again, however we'd better
507 * ensure we do switch into binary mode if required. See below.
508 */
509 if (!list_member(*param_exprs, expr))
510 {
511 *operators = lappend_oid(*operators, hasheqoperator);
512 *param_exprs = lappend(*param_exprs, expr);
513 }
514
515 /*
516 * When the join operator is not hashable then it's possible that
517 * the operator will be able to distinguish something that the
518 * hash equality operator could not. For example with floating
519 * point types -0.0 and +0.0 are classed as equal by the hash
520 * function and equality function, but some other operator may be
521 * able to tell those values apart. This means that we must put
522 * memoize into binary comparison mode so that it does bit-by-bit
523 * comparisons rather than a "logical" comparison as it would
524 * using the hash equality operator.
525 */
526 if (!OidIsValid(rinfo->hashjoinoperator))
527 *binary_mode = true;
528 }
529 }
530
531 /* Now add any lateral vars to the cache key too */
532 lateral_vars = list_concat(ph_lateral_vars, innerrel->lateral_vars);
533 foreach(lc, lateral_vars)
534 {
535 Node *expr = (Node *) lfirst(lc);
536 TypeCacheEntry *typentry;
537
538 /* Reject if there are any volatile functions in lateral vars */
539 if (contain_volatile_functions(expr))
540 {
541 list_free(*operators);
542 list_free(*param_exprs);
543 return false;
544 }
545
546 typentry = lookup_type_cache(exprType(expr),
547 TYPECACHE_HASH_PROC | TYPECACHE_EQ_OPR);
548
549 /* can't use memoize without a valid hash proc and equals operator */
550 if (!OidIsValid(typentry->hash_proc) || !OidIsValid(typentry->eq_opr))
551 {
552 list_free(*operators);
553 list_free(*param_exprs);
554 return false;
555 }
556
557 /*
558 * 'expr' may already exist as a parameter from the ppi_clauses. No
559 * need to include it again, however we'd better ensure we do switch
560 * into binary mode.
561 */
562 if (!list_member(*param_exprs, expr))
563 {
564 *operators = lappend_oid(*operators, typentry->eq_opr);
565 *param_exprs = lappend(*param_exprs, expr);
566 }
567
568 /*
569 * We must go into binary mode as we don't have too much of an idea of
570 * how these lateral Vars are being used. See comment above when we
571 * set *binary_mode for the non-lateral Var case. This could be
572 * relaxed a bit if we had the RestrictInfos and knew the operators
573 * being used, however for cases like Vars that are arguments to
574 * functions we must operate in binary mode as we don't have
575 * visibility into what the function is doing with the Vars.
576 */
577 *binary_mode = true;
578 }
579
580 /* We're okay to use memoize */
581 return true;
582}
583
584/*
585 * extract_lateral_vars_from_PHVs
586 * Extract lateral references within PlaceHolderVars that are due to be
587 * evaluated at 'innerrelids'.
588 */
589static List *
590 extract_lateral_vars_from_PHVs(PlannerInfo *root, Relids innerrelids)
591{
592 List *ph_lateral_vars = NIL;
593 ListCell *lc;
594
595 /* Nothing would be found if the query contains no LATERAL RTEs */
596 if (!root->hasLateralRTEs)
597 return NIL;
598
599 /*
600 * No need to consider PHVs that are due to be evaluated at joinrels,
601 * since we do not add Memoize nodes on top of joinrel paths.
602 */
603 if (bms_membership(innerrelids) == BMS_MULTIPLE)
604 return NIL;
605
606 foreach(lc, root->placeholder_list)
607 {
608 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
609 List *vars;
610 ListCell *cell;
611
612 /* PHV is uninteresting if no lateral refs */
613 if (phinfo->ph_lateral == NULL)
614 continue;
615
616 /* PHV is uninteresting if not due to be evaluated at innerrelids */
617 if (!bms_equal(phinfo->ph_eval_at, innerrelids))
618 continue;
619
620 /*
621 * If the PHV does not reference any rels in innerrelids, use its
622 * contained expression as a cache key rather than extracting the
623 * Vars/PHVs from it and using those. This can be beneficial in cases
624 * where the expression results in fewer distinct values to cache
625 * tuples for.
626 */
627 if (!bms_overlap(pull_varnos(root, (Node *) phinfo->ph_var->phexpr),
628 innerrelids))
629 {
630 ph_lateral_vars = lappend(ph_lateral_vars, phinfo->ph_var->phexpr);
631 continue;
632 }
633
634 /* Fetch Vars and PHVs of lateral references within PlaceHolderVars */
635 vars = pull_vars_of_level((Node *) phinfo->ph_var->phexpr, 0);
636 foreach(cell, vars)
637 {
638 Node *node = (Node *) lfirst(cell);
639
640 if (IsA(node, Var))
641 {
642 Var *var = (Var *) node;
643
644 Assert(var->varlevelsup == 0);
645
646 if (bms_is_member(var->varno, phinfo->ph_lateral))
647 ph_lateral_vars = lappend(ph_lateral_vars, node);
648 }
649 else if (IsA(node, PlaceHolderVar))
650 {
651 PlaceHolderVar *phv = (PlaceHolderVar *) node;
652
653 Assert(phv->phlevelsup == 0);
654
655 if (bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
656 phinfo->ph_lateral))
657 ph_lateral_vars = lappend(ph_lateral_vars, node);
658 }
659 else
660 Assert(false);
661 }
662
663 list_free(vars);
664 }
665
666 return ph_lateral_vars;
667}
668
669/*
670 * get_memoize_path
671 * If possible, make and return a Memoize path atop of 'inner_path'.
672 * Otherwise return NULL.
673 *
674 * Note that currently we do not add Memoize nodes on top of join relation
675 * paths. This is because the ParamPathInfos for join relation paths do not
676 * maintain ppi_clauses, as the set of relevant clauses varies depending on how
677 * the join is formed. In addition, joinrels do not maintain lateral_vars. So
678 * we do not have a way to extract cache keys from joinrels.
679 */
680static Path *
681 get_memoize_path(PlannerInfo *root, RelOptInfo *innerrel,
682 RelOptInfo *outerrel, Path *inner_path,
683 Path *outer_path, JoinType jointype,
684 JoinPathExtraData *extra)
685{
686 List *param_exprs;
687 List *hash_operators;
688 ListCell *lc;
689 bool binary_mode;
690 List *ph_lateral_vars;
691
692 /* Obviously not if it's disabled */
693 if (!enable_memoize)
694 return NULL;
695
696 /*
697 * We can safely not bother with all this unless we expect to perform more
698 * than one inner scan. The first scan is always going to be a cache
699 * miss. This would likely fail later anyway based on costs, so this is
700 * really just to save some wasted effort.
701 */
702 if (outer_path->parent->rows < 2)
703 return NULL;
704
705 /*
706 * Extract lateral Vars/PHVs within PlaceHolderVars that are due to be
707 * evaluated at innerrel. These lateral Vars/PHVs could be used as
708 * memoize cache keys.
709 */
710 ph_lateral_vars = extract_lateral_vars_from_PHVs(root, innerrel->relids);
711
712 /*
713 * We can only have a memoize node when there's some kind of cache key,
714 * either parameterized path clauses or lateral Vars. No cache key sounds
715 * more like something a Materialize node might be more useful for.
716 */
717 if ((inner_path->param_info == NULL ||
718 inner_path->param_info->ppi_clauses == NIL) &&
719 innerrel->lateral_vars == NIL &&
720 ph_lateral_vars == NIL)
721 return NULL;
722
723 /*
724 * Currently we don't do this for SEMI and ANTI joins, because nested loop
725 * SEMI/ANTI joins don't scan the inner node to completion, which means
726 * memoize cannot mark the cache entry as complete. Nor can we mark the
727 * cache entry as complete after fetching the first inner tuple, because
728 * if that tuple and the current outer tuple don't satisfy the join
729 * clauses, a second inner tuple that satisfies the parameters would find
730 * the cache entry already marked as complete. The only exception is when
731 * the inner relation is provably unique, as in that case, there won't be
732 * a second matching tuple and we can safely mark the cache entry as
733 * complete after fetching the first inner tuple. Note that in such
734 * cases, the SEMI join should have been reduced to an inner join by
735 * reduce_unique_semijoins.
736 */
737 if ((jointype == JOIN_SEMI || jointype == JOIN_ANTI) &&
738 !extra->inner_unique)
739 return NULL;
740
741 /*
742 * Memoize normally marks cache entries as complete when it runs out of
743 * tuples to read from its subplan. However, with unique joins, Nested
744 * Loop will skip to the next outer tuple after finding the first matching
745 * inner tuple. This means that we may not read the inner side of the
746 * join to completion which leaves no opportunity to mark the cache entry
747 * as complete. To work around that, when the join is unique we
748 * automatically mark cache entries as complete after fetching the first
749 * tuple. This works when the entire join condition is parameterized.
750 * Otherwise, when the parameterization is only a subset of the join
751 * condition, we can't be sure which part of it causes the join to be
752 * unique. This means there are no guarantees that only 1 tuple will be
753 * read. We cannot mark the cache entry as complete after reading the
754 * first tuple without that guarantee. This means the scope of Memoize
755 * node's usefulness is limited to only outer rows that have no join
756 * partner as this is the only case where Nested Loop would exhaust the
757 * inner scan of a unique join. Since the scope is limited to that, we
758 * just don't bother making a memoize path in this case.
759 *
760 * Lateral vars needn't be considered here as they're not considered when
761 * determining if the join is unique.
762 */
763 if (extra->inner_unique)
764 {
765 Bitmapset *ppi_serials;
766
767 if (inner_path->param_info == NULL)
768 return NULL;
769
770 ppi_serials = inner_path->param_info->ppi_serials;
771
772 foreach_node(RestrictInfo, rinfo, extra->restrictlist)
773 {
774 if (!bms_is_member(rinfo->rinfo_serial, ppi_serials))
775 return NULL;
776 }
777 }
778
779 /*
780 * We can't use a memoize node if there are volatile functions in the
781 * inner rel's target list or restrict list. A cache hit could reduce the
782 * number of calls to these functions.
783 */
784 if (contain_volatile_functions((Node *) innerrel->reltarget))
785 return NULL;
786
787 foreach(lc, innerrel->baserestrictinfo)
788 {
789 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
790
791 if (contain_volatile_functions((Node *) rinfo))
792 return NULL;
793 }
794
795 /*
796 * Also check the parameterized path restrictinfos for volatile functions.
797 * Indexed functions must be immutable so shouldn't have any volatile
798 * functions, however, with a lateral join the inner scan may not be an
799 * index scan.
800 */
801 if (inner_path->param_info != NULL)
802 {
803 foreach(lc, inner_path->param_info->ppi_clauses)
804 {
805 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
806
807 if (contain_volatile_functions((Node *) rinfo))
808 return NULL;
809 }
810 }
811
812 /* Check if we have hash ops for each parameter to the path */
813 if (paraminfo_get_equal_hashops(root,
814 inner_path->param_info,
815 outerrel->top_parent ?
816 outerrel->top_parent : outerrel,
817 innerrel,
818 ph_lateral_vars,
819 &param_exprs,
820 &hash_operators,
821 &binary_mode))
822 {
823 return (Path *) create_memoize_path(root,
824 innerrel,
825 inner_path,
826 param_exprs,
827 hash_operators,
828 extra->inner_unique,
829 binary_mode,
830 outer_path->rows);
831 }
832
833 return NULL;
834}
835
836/*
837 * try_nestloop_path
838 * Consider a nestloop join path; if it appears useful, push it into
839 * the joinrel's pathlist via add_path().
840 */
841static void
842 try_nestloop_path(PlannerInfo *root,
843 RelOptInfo *joinrel,
844 Path *outer_path,
845 Path *inner_path,
846 List *pathkeys,
847 JoinType jointype,
848 JoinPathExtraData *extra)
849{
850 Relids required_outer;
851 JoinCostWorkspace workspace;
852 RelOptInfo *innerrel = inner_path->parent;
853 RelOptInfo *outerrel = outer_path->parent;
854 Relids innerrelids;
855 Relids outerrelids;
856 Relids inner_paramrels = PATH_REQ_OUTER(inner_path);
857 Relids outer_paramrels = PATH_REQ_OUTER(outer_path);
858
859 /*
860 * If we are forming an outer join at this join, it's nonsensical to use
861 * an input path that uses the outer join as part of its parameterization.
862 * (This can happen despite our join order restrictions, since those apply
863 * to what is in an input relation not what its parameters are.)
864 */
865 if (extra->sjinfo->ojrelid != 0 &&
866 (bms_is_member(extra->sjinfo->ojrelid, inner_paramrels) ||
867 bms_is_member(extra->sjinfo->ojrelid, outer_paramrels)))
868 return;
869
870 /*
871 * Any parameterization of the input paths refers to topmost parents of
872 * the relevant relations, because reparameterize_path_by_child() hasn't
873 * been called yet. So we must consider topmost parents of the relations
874 * being joined, too, while determining parameterization of the result and
875 * checking for disallowed parameterization cases.
876 */
877 if (innerrel->top_parent_relids)
878 innerrelids = innerrel->top_parent_relids;
879 else
880 innerrelids = innerrel->relids;
881
882 if (outerrel->top_parent_relids)
883 outerrelids = outerrel->top_parent_relids;
884 else
885 outerrelids = outerrel->relids;
886
887 /*
888 * Check to see if proposed path is still parameterized, and reject if the
889 * parameterization wouldn't be sensible --- unless allow_star_schema_join
890 * says to allow it anyway.
891 */
892 required_outer = calc_nestloop_required_outer(outerrelids, outer_paramrels,
893 innerrelids, inner_paramrels);
894 if (required_outer &&
895 !bms_overlap(required_outer, extra->param_source_rels) &&
896 !allow_star_schema_join(root, outerrelids, inner_paramrels))
897 {
898 /* Waste no memory when we reject a path here */
899 bms_free(required_outer);
900 return;
901 }
902
903 /* If we got past that, we shouldn't have any unsafe outer-join refs */
904 Assert(!have_unsafe_outer_join_ref(root, outerrelids, inner_paramrels));
905
906 /*
907 * If the inner path is parameterized, it is parameterized by the topmost
908 * parent of the outer rel, not the outer rel itself. We will need to
909 * translate the parameterization, if this path is chosen, during
910 * create_plan(). Here we just check whether we will be able to perform
911 * the translation, and if not avoid creating a nestloop path.
912 */
913 if (PATH_PARAM_BY_PARENT(inner_path, outer_path->parent) &&
914 !path_is_reparameterizable_by_child(inner_path, outer_path->parent))
915 {
916 bms_free(required_outer);
917 return;
918 }
919
920 /*
921 * Do a precheck to quickly eliminate obviously-inferior paths. We
922 * calculate a cheap lower bound on the path's cost and then use
923 * add_path_precheck() to see if the path is clearly going to be dominated
924 * by some existing path for the joinrel. If not, do the full pushup with
925 * creating a fully valid path structure and submitting it to add_path().
926 * The latter two steps are expensive enough to make this two-phase
927 * methodology worthwhile.
928 */
929 initial_cost_nestloop(root, &workspace, jointype,
930 outer_path, inner_path, extra);
931
932 if (add_path_precheck(joinrel, workspace.disabled_nodes,
933 workspace.startup_cost, workspace.total_cost,
934 pathkeys, required_outer))
935 {
936 add_path(joinrel, (Path *)
937 create_nestloop_path(root,
938 joinrel,
939 jointype,
940 &workspace,
941 extra,
942 outer_path,
943 inner_path,
944 extra->restrictlist,
945 pathkeys,
946 required_outer));
947 }
948 else
949 {
950 /* Waste no memory when we reject a path here */
951 bms_free(required_outer);
952 }
953}
954
955/*
956 * try_partial_nestloop_path
957 * Consider a partial nestloop join path; if it appears useful, push it into
958 * the joinrel's partial_pathlist via add_partial_path().
959 */
960static void
961 try_partial_nestloop_path(PlannerInfo *root,
962 RelOptInfo *joinrel,
963 Path *outer_path,
964 Path *inner_path,
965 List *pathkeys,
966 JoinType jointype,
967 JoinPathExtraData *extra)
968{
969 JoinCostWorkspace workspace;
970
971 /*
972 * If the inner path is parameterized, the parameterization must be fully
973 * satisfied by the proposed outer path. Parameterized partial paths are
974 * not supported. The caller should already have verified that no lateral
975 * rels are required here.
976 */
977 Assert(bms_is_empty(joinrel->lateral_relids));
978 Assert(bms_is_empty(PATH_REQ_OUTER(outer_path)));
979 if (inner_path->param_info != NULL)
980 {
981 Relids inner_paramrels = inner_path->param_info->ppi_req_outer;
982 RelOptInfo *outerrel = outer_path->parent;
983 Relids outerrelids;
984
985 /*
986 * The inner and outer paths are parameterized, if at all, by the top
987 * level parents, not the child relations, so we must use those relids
988 * for our parameterization tests.
989 */
990 if (outerrel->top_parent_relids)
991 outerrelids = outerrel->top_parent_relids;
992 else
993 outerrelids = outerrel->relids;
994
995 if (!bms_is_subset(inner_paramrels, outerrelids))
996 return;
997 }
998
999 /*
1000 * If the inner path is parameterized, it is parameterized by the topmost
1001 * parent of the outer rel, not the outer rel itself. We will need to
1002 * translate the parameterization, if this path is chosen, during
1003 * create_plan(). Here we just check whether we will be able to perform
1004 * the translation, and if not avoid creating a nestloop path.
1005 */
1006 if (PATH_PARAM_BY_PARENT(inner_path, outer_path->parent) &&
1007 !path_is_reparameterizable_by_child(inner_path, outer_path->parent))
1008 return;
1009
1010 /*
1011 * Before creating a path, get a quick lower bound on what it is likely to
1012 * cost. Bail out right away if it looks terrible.
1013 */
1014 initial_cost_nestloop(root, &workspace, jointype,
1015 outer_path, inner_path, extra);
1016 if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
1017 workspace.total_cost, pathkeys))
1018 return;
1019
1020 /* Might be good enough to be worth trying, so let's try it. */
1021 add_partial_path(joinrel, (Path *)
1022 create_nestloop_path(root,
1023 joinrel,
1024 jointype,
1025 &workspace,
1026 extra,
1027 outer_path,
1028 inner_path,
1029 extra->restrictlist,
1030 pathkeys,
1031 NULL));
1032}
1033
1034/*
1035 * try_mergejoin_path
1036 * Consider a merge join path; if it appears useful, push it into
1037 * the joinrel's pathlist via add_path().
1038 */
1039static void
1040 try_mergejoin_path(PlannerInfo *root,
1041 RelOptInfo *joinrel,
1042 Path *outer_path,
1043 Path *inner_path,
1044 List *pathkeys,
1045 List *mergeclauses,
1046 List *outersortkeys,
1047 List *innersortkeys,
1048 JoinType jointype,
1049 JoinPathExtraData *extra,
1050 bool is_partial)
1051{
1052 Relids required_outer;
1053 int outer_presorted_keys = 0;
1054 JoinCostWorkspace workspace;
1055
1056 if (is_partial)
1057 {
1058 try_partial_mergejoin_path(root,
1059 joinrel,
1060 outer_path,
1061 inner_path,
1062 pathkeys,
1063 mergeclauses,
1064 outersortkeys,
1065 innersortkeys,
1066 jointype,
1067 extra);
1068 return;
1069 }
1070
1071 /*
1072 * If we are forming an outer join at this join, it's nonsensical to use
1073 * an input path that uses the outer join as part of its parameterization.
1074 * (This can happen despite our join order restrictions, since those apply
1075 * to what is in an input relation not what its parameters are.)
1076 */
1077 if (extra->sjinfo->ojrelid != 0 &&
1078 (bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(inner_path)) ||
1079 bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(outer_path))))
1080 return;
1081
1082 /*
1083 * Check to see if proposed path is still parameterized, and reject if the
1084 * parameterization wouldn't be sensible.
1085 */
1086 required_outer = calc_non_nestloop_required_outer(outer_path,
1087 inner_path);
1088 if (required_outer &&
1089 !bms_overlap(required_outer, extra->param_source_rels))
1090 {
1091 /* Waste no memory when we reject a path here */
1092 bms_free(required_outer);
1093 return;
1094 }
1095
1096 /*
1097 * If the given paths are already well enough ordered, we can skip doing
1098 * an explicit sort.
1099 *
1100 * We need to determine the number of presorted keys of the outer path to
1101 * decide whether explicit incremental sort can be applied when
1102 * outersortkeys is not NIL. We do not need to do the same for the inner
1103 * path though, as incremental sort currently does not support
1104 * mark/restore.
1105 */
1106 if (outersortkeys &&
1107 pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys,
1108 &outer_presorted_keys))
1109 outersortkeys = NIL;
1110 if (innersortkeys &&
1111 pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
1112 innersortkeys = NIL;
1113
1114 /*
1115 * See comments in try_nestloop_path().
1116 */
1117 initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
1118 outer_path, inner_path,
1119 outersortkeys, innersortkeys,
1120 outer_presorted_keys,
1121 extra);
1122
1123 if (add_path_precheck(joinrel, workspace.disabled_nodes,
1124 workspace.startup_cost, workspace.total_cost,
1125 pathkeys, required_outer))
1126 {
1127 add_path(joinrel, (Path *)
1128 create_mergejoin_path(root,
1129 joinrel,
1130 jointype,
1131 &workspace,
1132 extra,
1133 outer_path,
1134 inner_path,
1135 extra->restrictlist,
1136 pathkeys,
1137 required_outer,
1138 mergeclauses,
1139 outersortkeys,
1140 innersortkeys,
1141 outer_presorted_keys));
1142 }
1143 else
1144 {
1145 /* Waste no memory when we reject a path here */
1146 bms_free(required_outer);
1147 }
1148}
1149
1150/*
1151 * try_partial_mergejoin_path
1152 * Consider a partial merge join path; if it appears useful, push it into
1153 * the joinrel's pathlist via add_partial_path().
1154 */
1155static void
1156 try_partial_mergejoin_path(PlannerInfo *root,
1157 RelOptInfo *joinrel,
1158 Path *outer_path,
1159 Path *inner_path,
1160 List *pathkeys,
1161 List *mergeclauses,
1162 List *outersortkeys,
1163 List *innersortkeys,
1164 JoinType jointype,
1165 JoinPathExtraData *extra)
1166{
1167 int outer_presorted_keys = 0;
1168 JoinCostWorkspace workspace;
1169
1170 /*
1171 * See comments in try_partial_hashjoin_path().
1172 */
1173 Assert(bms_is_empty(joinrel->lateral_relids));
1174 Assert(bms_is_empty(PATH_REQ_OUTER(outer_path)));
1175 if (!bms_is_empty(PATH_REQ_OUTER(inner_path)))
1176 return;
1177
1178 /*
1179 * If the given paths are already well enough ordered, we can skip doing
1180 * an explicit sort.
1181 *
1182 * We need to determine the number of presorted keys of the outer path to
1183 * decide whether explicit incremental sort can be applied when
1184 * outersortkeys is not NIL. We do not need to do the same for the inner
1185 * path though, as incremental sort currently does not support
1186 * mark/restore.
1187 */
1188 if (outersortkeys &&
1189 pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys,
1190 &outer_presorted_keys))
1191 outersortkeys = NIL;
1192 if (innersortkeys &&
1193 pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
1194 innersortkeys = NIL;
1195
1196 /*
1197 * See comments in try_partial_nestloop_path().
1198 */
1199 initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
1200 outer_path, inner_path,
1201 outersortkeys, innersortkeys,
1202 outer_presorted_keys,
1203 extra);
1204
1205 if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
1206 workspace.total_cost, pathkeys))
1207 return;
1208
1209 /* Might be good enough to be worth trying, so let's try it. */
1210 add_partial_path(joinrel, (Path *)
1211 create_mergejoin_path(root,
1212 joinrel,
1213 jointype,
1214 &workspace,
1215 extra,
1216 outer_path,
1217 inner_path,
1218 extra->restrictlist,
1219 pathkeys,
1220 NULL,
1221 mergeclauses,
1222 outersortkeys,
1223 innersortkeys,
1224 outer_presorted_keys));
1225}
1226
1227/*
1228 * try_hashjoin_path
1229 * Consider a hash join path; if it appears useful, push it into
1230 * the joinrel's pathlist via add_path().
1231 */
1232static void
1233 try_hashjoin_path(PlannerInfo *root,
1234 RelOptInfo *joinrel,
1235 Path *outer_path,
1236 Path *inner_path,
1237 List *hashclauses,
1238 JoinType jointype,
1239 JoinPathExtraData *extra)
1240{
1241 Relids required_outer;
1242 JoinCostWorkspace workspace;
1243
1244 /*
1245 * If we are forming an outer join at this join, it's nonsensical to use
1246 * an input path that uses the outer join as part of its parameterization.
1247 * (This can happen despite our join order restrictions, since those apply
1248 * to what is in an input relation not what its parameters are.)
1249 */
1250 if (extra->sjinfo->ojrelid != 0 &&
1251 (bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(inner_path)) ||
1252 bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(outer_path))))
1253 return;
1254
1255 /*
1256 * Check to see if proposed path is still parameterized, and reject if the
1257 * parameterization wouldn't be sensible.
1258 */
1259 required_outer = calc_non_nestloop_required_outer(outer_path,
1260 inner_path);
1261 if (required_outer &&
1262 !bms_overlap(required_outer, extra->param_source_rels))
1263 {
1264 /* Waste no memory when we reject a path here */
1265 bms_free(required_outer);
1266 return;
1267 }
1268
1269 /*
1270 * See comments in try_nestloop_path(). Also note that hashjoin paths
1271 * never have any output pathkeys, per comments in create_hashjoin_path.
1272 */
1273 initial_cost_hashjoin(root, &workspace, jointype, hashclauses,
1274 outer_path, inner_path, extra, false);
1275
1276 if (add_path_precheck(joinrel, workspace.disabled_nodes,
1277 workspace.startup_cost, workspace.total_cost,
1278 NIL, required_outer))
1279 {
1280 add_path(joinrel, (Path *)
1281 create_hashjoin_path(root,
1282 joinrel,
1283 jointype,
1284 &workspace,
1285 extra,
1286 outer_path,
1287 inner_path,
1288 false, /* parallel_hash */
1289 extra->restrictlist,
1290 required_outer,
1291 hashclauses));
1292 }
1293 else
1294 {
1295 /* Waste no memory when we reject a path here */
1296 bms_free(required_outer);
1297 }
1298}
1299
1300/*
1301 * try_partial_hashjoin_path
1302 * Consider a partial hashjoin join path; if it appears useful, push it into
1303 * the joinrel's partial_pathlist via add_partial_path().
1304 * The outer side is partial. If parallel_hash is true, then the inner path
1305 * must be partial and will be run in parallel to create one or more shared
1306 * hash tables; otherwise the inner path must be complete and a copy of it
1307 * is run in every process to create separate identical private hash tables.
1308 */
1309static void
1310 try_partial_hashjoin_path(PlannerInfo *root,
1311 RelOptInfo *joinrel,
1312 Path *outer_path,
1313 Path *inner_path,
1314 List *hashclauses,
1315 JoinType jointype,
1316 JoinPathExtraData *extra,
1317 bool parallel_hash)
1318{
1319 JoinCostWorkspace workspace;
1320
1321 /*
1322 * If the inner path is parameterized, we can't use a partial hashjoin.
1323 * Parameterized partial paths are not supported. The caller should
1324 * already have verified that no lateral rels are required here.
1325 */
1326 Assert(bms_is_empty(joinrel->lateral_relids));
1327 Assert(bms_is_empty(PATH_REQ_OUTER(outer_path)));
1328 if (!bms_is_empty(PATH_REQ_OUTER(inner_path)))
1329 return;
1330
1331 /*
1332 * Before creating a path, get a quick lower bound on what it is likely to
1333 * cost. Bail out right away if it looks terrible.
1334 */
1335 initial_cost_hashjoin(root, &workspace, jointype, hashclauses,
1336 outer_path, inner_path, extra, parallel_hash);
1337 if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
1338 workspace.total_cost, NIL))
1339 return;
1340
1341 /* Might be good enough to be worth trying, so let's try it. */
1342 add_partial_path(joinrel, (Path *)
1343 create_hashjoin_path(root,
1344 joinrel,
1345 jointype,
1346 &workspace,
1347 extra,
1348 outer_path,
1349 inner_path,
1350 parallel_hash,
1351 extra->restrictlist,
1352 NULL,
1353 hashclauses));
1354}
1355
1356/*
1357 * sort_inner_and_outer
1358 * Create mergejoin join paths by explicitly sorting both the outer and
1359 * inner join relations on each available merge ordering.
1360 *
1361 * 'joinrel' is the join relation
1362 * 'outerrel' is the outer join relation
1363 * 'innerrel' is the inner join relation
1364 * 'jointype' is the type of join to do
1365 * 'extra' contains additional input values
1366 */
1367static void
1368 sort_inner_and_outer(PlannerInfo *root,
1369 RelOptInfo *joinrel,
1370 RelOptInfo *outerrel,
1371 RelOptInfo *innerrel,
1372 JoinType jointype,
1373 JoinPathExtraData *extra)
1374{
1375 Path *outer_path;
1376 Path *inner_path;
1377 Path *cheapest_partial_outer = NULL;
1378 Path *cheapest_safe_inner = NULL;
1379 List *all_pathkeys;
1380 ListCell *l;
1381
1382 /* Nothing to do if there are no available mergejoin clauses */
1383 if (extra->mergeclause_list == NIL)
1384 return;
1385
1386 /*
1387 * We only consider the cheapest-total-cost input paths, since we are
1388 * assuming here that a sort is required. We will consider
1389 * cheapest-startup-cost input paths later, and only if they don't need a
1390 * sort.
1391 *
1392 * This function intentionally does not consider parameterized input
1393 * paths, except when the cheapest-total is parameterized. If we did so,
1394 * we'd have a combinatorial explosion of mergejoin paths of dubious
1395 * value. This interacts with decisions elsewhere that also discriminate
1396 * against mergejoins with parameterized inputs; see comments in
1397 * src/backend/optimizer/README.
1398 */
1399 outer_path = outerrel->cheapest_total_path;
1400 inner_path = innerrel->cheapest_total_path;
1401
1402 /*
1403 * If either cheapest-total path is parameterized by the other rel, we
1404 * can't use a mergejoin. (There's no use looking for alternative input
1405 * paths, since these should already be the least-parameterized available
1406 * paths.)
1407 */
1408 if (PATH_PARAM_BY_REL(outer_path, innerrel) ||
1409 PATH_PARAM_BY_REL(inner_path, outerrel))
1410 return;
1411
1412 /*
1413 * If the joinrel is parallel-safe, we may be able to consider a partial
1414 * merge join. However, we can't handle JOIN_FULL, JOIN_RIGHT and
1415 * JOIN_RIGHT_ANTI, because they can produce false null extended rows.
1416 * Also, the resulting path must not be parameterized.
1417 */
1418 if (joinrel->consider_parallel &&
1419 jointype != JOIN_FULL &&
1420 jointype != JOIN_RIGHT &&
1421 jointype != JOIN_RIGHT_ANTI &&
1422 outerrel->partial_pathlist != NIL &&
1423 bms_is_empty(joinrel->lateral_relids))
1424 {
1425 cheapest_partial_outer = (Path *) linitial(outerrel->partial_pathlist);
1426
1427 if (inner_path->parallel_safe)
1428 cheapest_safe_inner = inner_path;
1429 else
1430 cheapest_safe_inner =
1431 get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
1432 }
1433
1434 /*
1435 * Each possible ordering of the available mergejoin clauses will generate
1436 * a differently-sorted result path at essentially the same cost. We have
1437 * no basis for choosing one over another at this level of joining, but
1438 * some sort orders may be more useful than others for higher-level
1439 * mergejoins, so it's worth considering multiple orderings.
1440 *
1441 * Actually, it's not quite true that every mergeclause ordering will
1442 * generate a different path order, because some of the clauses may be
1443 * partially redundant (refer to the same EquivalenceClasses). Therefore,
1444 * what we do is convert the mergeclause list to a list of canonical
1445 * pathkeys, and then consider different orderings of the pathkeys.
1446 *
1447 * Generating a path for *every* permutation of the pathkeys doesn't seem
1448 * like a winning strategy; the cost in planning time is too high. For
1449 * now, we generate one path for each pathkey, listing that pathkey first
1450 * and the rest in random order. This should allow at least a one-clause
1451 * mergejoin without re-sorting against any other possible mergejoin
1452 * partner path. But if we've not guessed the right ordering of secondary
1453 * keys, we may end up evaluating clauses as qpquals when they could have
1454 * been done as mergeclauses. (In practice, it's rare that there's more
1455 * than two or three mergeclauses, so expending a huge amount of thought
1456 * on that is probably not worth it.)
1457 *
1458 * The pathkey order returned by select_outer_pathkeys_for_merge() has
1459 * some heuristics behind it (see that function), so be sure to try it
1460 * exactly as-is as well as making variants.
1461 */
1462 all_pathkeys = select_outer_pathkeys_for_merge(root,
1463 extra->mergeclause_list,
1464 joinrel);
1465
1466 foreach(l, all_pathkeys)
1467 {
1468 PathKey *front_pathkey = (PathKey *) lfirst(l);
1469 List *cur_mergeclauses;
1470 List *outerkeys;
1471 List *innerkeys;
1472 List *merge_pathkeys;
1473
1474 /* Make a pathkey list with this guy first */
1475 if (l != list_head(all_pathkeys))
1476 outerkeys = lcons(front_pathkey,
1477 list_delete_nth_cell(list_copy(all_pathkeys),
1478 foreach_current_index(l)));
1479 else
1480 outerkeys = all_pathkeys; /* no work at first one... */
1481
1482 /* Sort the mergeclauses into the corresponding ordering */
1483 cur_mergeclauses =
1484 find_mergeclauses_for_outer_pathkeys(root,
1485 outerkeys,
1486 extra->mergeclause_list);
1487
1488 /* Should have used them all... */
1489 Assert(list_length(cur_mergeclauses) == list_length(extra->mergeclause_list));
1490
1491 /* Build sort pathkeys for the inner side */
1492 innerkeys = make_inner_pathkeys_for_merge(root,
1493 cur_mergeclauses,
1494 outerkeys);
1495
1496 /* Build pathkeys representing output sort order */
1497 merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
1498 outerkeys);
1499
1500 /*
1501 * And now we can make the path.
1502 *
1503 * Note: it's possible that the cheapest paths will already be sorted
1504 * properly. try_mergejoin_path will detect that case and suppress an
1505 * explicit sort step, so we needn't do so here.
1506 */
1507 try_mergejoin_path(root,
1508 joinrel,
1509 outer_path,
1510 inner_path,
1511 merge_pathkeys,
1512 cur_mergeclauses,
1513 outerkeys,
1514 innerkeys,
1515 jointype,
1516 extra,
1517 false);
1518
1519 /*
1520 * If we have partial outer and parallel safe inner path then try
1521 * partial mergejoin path.
1522 */
1523 if (cheapest_partial_outer && cheapest_safe_inner)
1524 try_partial_mergejoin_path(root,
1525 joinrel,
1526 cheapest_partial_outer,
1527 cheapest_safe_inner,
1528 merge_pathkeys,
1529 cur_mergeclauses,
1530 outerkeys,
1531 innerkeys,
1532 jointype,
1533 extra);
1534 }
1535}
1536
1537/*
1538 * generate_mergejoin_paths
1539 * Creates possible mergejoin paths for input outerpath.
1540 *
1541 * We generate mergejoins if mergejoin clauses are available. We have
1542 * two ways to generate the inner path for a mergejoin: sort the cheapest
1543 * inner path, or use an inner path that is already suitably ordered for the
1544 * merge. If we have several mergeclauses, it could be that there is no inner
1545 * path (or only a very expensive one) for the full list of mergeclauses, but
1546 * better paths exist if we truncate the mergeclause list (thereby discarding
1547 * some sort key requirements). So, we consider truncations of the
1548 * mergeclause list as well as the full list. (Ideally we'd consider all
1549 * subsets of the mergeclause list, but that seems way too expensive.)
1550 */
1551static void
1552 generate_mergejoin_paths(PlannerInfo *root,
1553 RelOptInfo *joinrel,
1554 RelOptInfo *innerrel,
1555 Path *outerpath,
1556 JoinType jointype,
1557 JoinPathExtraData *extra,
1558 bool useallclauses,
1559 Path *inner_cheapest_total,
1560 List *merge_pathkeys,
1561 bool is_partial)
1562{
1563 List *mergeclauses;
1564 List *innersortkeys;
1565 List *trialsortkeys;
1566 Path *cheapest_startup_inner;
1567 Path *cheapest_total_inner;
1568 int num_sortkeys;
1569 int sortkeycnt;
1570
1571 /* Look for useful mergeclauses (if any) */
1572 mergeclauses =
1573 find_mergeclauses_for_outer_pathkeys(root,
1574 outerpath->pathkeys,
1575 extra->mergeclause_list);
1576
1577 /*
1578 * Done with this outer path if no chance for a mergejoin.
1579 *
1580 * Special corner case: for "x FULL JOIN y ON true", there will be no join
1581 * clauses at all. Ordinarily we'd generate a clauseless nestloop path,
1582 * but since mergejoin is our only join type that supports FULL JOIN
1583 * without any join clauses, it's necessary to generate a clauseless
1584 * mergejoin path instead.
1585 */
1586 if (mergeclauses == NIL)
1587 {
1588 if (jointype == JOIN_FULL)
1589 /* okay to try for mergejoin */ ;
1590 else
1591 return;
1592 }
1593 if (useallclauses &&
1594 list_length(mergeclauses) != list_length(extra->mergeclause_list))
1595 return;
1596
1597 /* Compute the required ordering of the inner path */
1598 innersortkeys = make_inner_pathkeys_for_merge(root,
1599 mergeclauses,
1600 outerpath->pathkeys);
1601
1602 /*
1603 * Generate a mergejoin on the basis of sorting the cheapest inner. Since
1604 * a sort will be needed, only cheapest total cost matters. (But
1605 * try_mergejoin_path will do the right thing if inner_cheapest_total is
1606 * already correctly sorted.)
1607 */
1608 try_mergejoin_path(root,
1609 joinrel,
1610 outerpath,
1611 inner_cheapest_total,
1612 merge_pathkeys,
1613 mergeclauses,
1614 NIL,
1615 innersortkeys,
1616 jointype,
1617 extra,
1618 is_partial);
1619
1620 /*
1621 * Look for presorted inner paths that satisfy the innersortkey list ---
1622 * or any truncation thereof, if we are allowed to build a mergejoin using
1623 * a subset of the merge clauses. Here, we consider both cheap startup
1624 * cost and cheap total cost.
1625 *
1626 * Currently we do not consider parameterized inner paths here. This
1627 * interacts with decisions elsewhere that also discriminate against
1628 * mergejoins with parameterized inputs; see comments in
1629 * src/backend/optimizer/README.
1630 *
1631 * As we shorten the sortkey list, we should consider only paths that are
1632 * strictly cheaper than (in particular, not the same as) any path found
1633 * in an earlier iteration. Otherwise we'd be intentionally using fewer
1634 * merge keys than a given path allows (treating the rest as plain
1635 * joinquals), which is unlikely to be a good idea. Also, eliminating
1636 * paths here on the basis of compare_path_costs is a lot cheaper than
1637 * building the mergejoin path only to throw it away.
1638 *
1639 * If inner_cheapest_total is well enough sorted to have not required a
1640 * sort in the path made above, we shouldn't make a duplicate path with
1641 * it, either. We handle that case with the same logic that handles the
1642 * previous consideration, by initializing the variables that track
1643 * cheapest-so-far properly. Note that we do NOT reject
1644 * inner_cheapest_total if we find it matches some shorter set of
1645 * pathkeys. That case corresponds to using fewer mergekeys to avoid
1646 * sorting inner_cheapest_total, whereas we did sort it above, so the
1647 * plans being considered are different.
1648 */
1649 if (pathkeys_contained_in(innersortkeys,
1650 inner_cheapest_total->pathkeys))
1651 {
1652 /* inner_cheapest_total didn't require a sort */
1653 cheapest_startup_inner = inner_cheapest_total;
1654 cheapest_total_inner = inner_cheapest_total;
1655 }
1656 else
1657 {
1658 /* it did require a sort, at least for the full set of keys */
1659 cheapest_startup_inner = NULL;
1660 cheapest_total_inner = NULL;
1661 }
1662 num_sortkeys = list_length(innersortkeys);
1663 if (num_sortkeys > 1 && !useallclauses)
1664 trialsortkeys = list_copy(innersortkeys); /* need modifiable copy */
1665 else
1666 trialsortkeys = innersortkeys; /* won't really truncate */
1667
1668 for (sortkeycnt = num_sortkeys; sortkeycnt > 0; sortkeycnt--)
1669 {
1670 Path *innerpath;
1671 List *newclauses = NIL;
1672
1673 /*
1674 * Look for an inner path ordered well enough for the first
1675 * 'sortkeycnt' innersortkeys. NB: trialsortkeys list is modified
1676 * destructively, which is why we made a copy...
1677 */
1678 trialsortkeys = list_truncate(trialsortkeys, sortkeycnt);
1679 innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
1680 trialsortkeys,
1681 NULL,
1682 TOTAL_COST,
1683 is_partial);
1684 if (innerpath != NULL &&
1685 (cheapest_total_inner == NULL ||
1686 compare_path_costs(innerpath, cheapest_total_inner,
1687 TOTAL_COST) < 0))
1688 {
1689 /* Found a cheap (or even-cheaper) sorted path */
1690 /* Select the right mergeclauses, if we didn't already */
1691 if (sortkeycnt < num_sortkeys)
1692 {
1693 newclauses =
1694 trim_mergeclauses_for_inner_pathkeys(root,
1695 mergeclauses,
1696 trialsortkeys);
1697 Assert(newclauses != NIL);
1698 }
1699 else
1700 newclauses = mergeclauses;
1701 try_mergejoin_path(root,
1702 joinrel,
1703 outerpath,
1704 innerpath,
1705 merge_pathkeys,
1706 newclauses,
1707 NIL,
1708 NIL,
1709 jointype,
1710 extra,
1711 is_partial);
1712 cheapest_total_inner = innerpath;
1713 }
1714 /* Same on the basis of cheapest startup cost ... */
1715 innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
1716 trialsortkeys,
1717 NULL,
1718 STARTUP_COST,
1719 is_partial);
1720 if (innerpath != NULL &&
1721 (cheapest_startup_inner == NULL ||
1722 compare_path_costs(innerpath, cheapest_startup_inner,
1723 STARTUP_COST) < 0))
1724 {
1725 /* Found a cheap (or even-cheaper) sorted path */
1726 if (innerpath != cheapest_total_inner)
1727 {
1728 /*
1729 * Avoid rebuilding clause list if we already made one; saves
1730 * memory in big join trees...
1731 */
1732 if (newclauses == NIL)
1733 {
1734 if (sortkeycnt < num_sortkeys)
1735 {
1736 newclauses =
1737 trim_mergeclauses_for_inner_pathkeys(root,
1738 mergeclauses,
1739 trialsortkeys);
1740 Assert(newclauses != NIL);
1741 }
1742 else
1743 newclauses = mergeclauses;
1744 }
1745 try_mergejoin_path(root,
1746 joinrel,
1747 outerpath,
1748 innerpath,
1749 merge_pathkeys,
1750 newclauses,
1751 NIL,
1752 NIL,
1753 jointype,
1754 extra,
1755 is_partial);
1756 }
1757 cheapest_startup_inner = innerpath;
1758 }
1759
1760 /*
1761 * Don't consider truncated sortkeys if we need all clauses.
1762 */
1763 if (useallclauses)
1764 break;
1765 }
1766}
1767
1768/*
1769 * match_unsorted_outer
1770 * Creates possible join paths for processing a single join relation
1771 * 'joinrel' by employing either iterative substitution or
1772 * mergejoining on each of its possible outer paths (considering
1773 * only outer paths that are already ordered well enough for merging).
1774 *
1775 * We always generate a nestloop path for each available outer path.
1776 * In fact we may generate as many as five: one on the cheapest-total-cost
1777 * inner path, one on the same with materialization, one on the
1778 * cheapest-startup-cost inner path (if different), one on the
1779 * cheapest-total inner-indexscan path (if any), and one on the
1780 * cheapest-startup inner-indexscan path (if different).
1781 *
1782 * We also consider mergejoins if mergejoin clauses are available. See
1783 * detailed comments in generate_mergejoin_paths.
1784 *
1785 * 'joinrel' is the join relation
1786 * 'outerrel' is the outer join relation
1787 * 'innerrel' is the inner join relation
1788 * 'jointype' is the type of join to do
1789 * 'extra' contains additional input values
1790 */
1791static void
1792 match_unsorted_outer(PlannerInfo *root,
1793 RelOptInfo *joinrel,
1794 RelOptInfo *outerrel,
1795 RelOptInfo *innerrel,
1796 JoinType jointype,
1797 JoinPathExtraData *extra)
1798{
1799 bool nestjoinOK;
1800 bool useallclauses;
1801 Path *inner_cheapest_total = innerrel->cheapest_total_path;
1802 Path *matpath = NULL;
1803 ListCell *lc1;
1804
1805 /*
1806 * For now we do not support RIGHT_SEMI join in mergejoin or nestloop
1807 * join.
1808 */
1809 if (jointype == JOIN_RIGHT_SEMI)
1810 return;
1811
1812 /*
1813 * Nestloop only supports inner, left, semi, and anti joins. Also, if we
1814 * are doing a right, right-anti or full mergejoin, we must use *all* the
1815 * mergeclauses as join clauses, else we will not have a valid plan.
1816 * (Although these two flags are currently inverses, keep them separate
1817 * for clarity and possible future changes.)
1818 */
1819 switch (jointype)
1820 {
1821 case JOIN_INNER:
1822 case JOIN_LEFT:
1823 case JOIN_SEMI:
1824 case JOIN_ANTI:
1825 nestjoinOK = true;
1826 useallclauses = false;
1827 break;
1828 case JOIN_RIGHT:
1829 case JOIN_RIGHT_ANTI:
1830 case JOIN_FULL:
1831 nestjoinOK = false;
1832 useallclauses = true;
1833 break;
1834 default:
1835 elog(ERROR, "unrecognized join type: %d",
1836 (int) jointype);
1837 nestjoinOK = false; /* keep compiler quiet */
1838 useallclauses = false;
1839 break;
1840 }
1841
1842 /*
1843 * If inner_cheapest_total is parameterized by the outer rel, ignore it;
1844 * we will consider it below as a member of cheapest_parameterized_paths,
1845 * but the other possibilities considered in this routine aren't usable.
1846 *
1847 * Furthermore, if the inner side is a unique-ified relation, we cannot
1848 * generate any valid paths here, because the inner rel's dependency on
1849 * the outer rel makes unique-ification meaningless.
1850 */
1851 if (PATH_PARAM_BY_REL(inner_cheapest_total, outerrel))
1852 {
1853 inner_cheapest_total = NULL;
1854
1855 if (RELATION_WAS_MADE_UNIQUE(innerrel, extra->sjinfo, jointype))
1856 return;
1857 }
1858
1859 if (nestjoinOK)
1860 {
1861 /*
1862 * Consider materializing the cheapest inner path, unless
1863 * enable_material is off or the path in question materializes its
1864 * output anyway.
1865 */
1866 if (enable_material && inner_cheapest_total != NULL &&
1867 !ExecMaterializesOutput(inner_cheapest_total->pathtype))
1868 matpath = (Path *)
1869 create_material_path(innerrel, inner_cheapest_total);
1870 }
1871
1872 foreach(lc1, outerrel->pathlist)
1873 {
1874 Path *outerpath = (Path *) lfirst(lc1);
1875 List *merge_pathkeys;
1876
1877 /*
1878 * We cannot use an outer path that is parameterized by the inner rel.
1879 */
1880 if (PATH_PARAM_BY_REL(outerpath, innerrel))
1881 continue;
1882
1883 /*
1884 * The result will have this sort order (even if it is implemented as
1885 * a nestloop, and even if some of the mergeclauses are implemented by
1886 * qpquals rather than as true mergeclauses):
1887 */
1888 merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
1889 outerpath->pathkeys);
1890
1891 if (nestjoinOK)
1892 {
1893 /*
1894 * Consider nestloop joins using this outer path and various
1895 * available paths for the inner relation. We consider the
1896 * cheapest-total paths for each available parameterization of the
1897 * inner relation, including the unparameterized case.
1898 */
1899 ListCell *lc2;
1900
1901 foreach(lc2, innerrel->cheapest_parameterized_paths)
1902 {
1903 Path *innerpath = (Path *) lfirst(lc2);
1904 Path *mpath;
1905
1906 try_nestloop_path(root,
1907 joinrel,
1908 outerpath,
1909 innerpath,
1910 merge_pathkeys,
1911 jointype,
1912 extra);
1913
1914 /*
1915 * Try generating a memoize path and see if that makes the
1916 * nested loop any cheaper.
1917 */
1918 mpath = get_memoize_path(root, innerrel, outerrel,
1919 innerpath, outerpath, jointype,
1920 extra);
1921 if (mpath != NULL)
1922 try_nestloop_path(root,
1923 joinrel,
1924 outerpath,
1925 mpath,
1926 merge_pathkeys,
1927 jointype,
1928 extra);
1929 }
1930
1931 /* Also consider materialized form of the cheapest inner path */
1932 if (matpath != NULL)
1933 try_nestloop_path(root,
1934 joinrel,
1935 outerpath,
1936 matpath,
1937 merge_pathkeys,
1938 jointype,
1939 extra);
1940 }
1941
1942 /* Can't do anything else if inner rel is parameterized by outer */
1943 if (inner_cheapest_total == NULL)
1944 continue;
1945
1946 /* Generate merge join paths */
1947 generate_mergejoin_paths(root, joinrel, innerrel, outerpath,
1948 jointype, extra, useallclauses,
1949 inner_cheapest_total, merge_pathkeys,
1950 false);
1951 }
1952
1953 /*
1954 * Consider partial nestloop and mergejoin plan if outerrel has any
1955 * partial path and the joinrel is parallel-safe. However, we can't
1956 * handle joins needing lateral rels, since partial paths must not be
1957 * parameterized. Similarly, we can't handle JOIN_FULL, JOIN_RIGHT and
1958 * JOIN_RIGHT_ANTI, because they can produce false null extended rows.
1959 */
1960 if (joinrel->consider_parallel &&
1961 jointype != JOIN_FULL &&
1962 jointype != JOIN_RIGHT &&
1963 jointype != JOIN_RIGHT_ANTI &&
1964 outerrel->partial_pathlist != NIL &&
1965 bms_is_empty(joinrel->lateral_relids))
1966 {
1967 if (nestjoinOK)
1968 consider_parallel_nestloop(root, joinrel, outerrel, innerrel,
1969 jointype, extra);
1970
1971 /*
1972 * If inner_cheapest_total is NULL or non parallel-safe then find the
1973 * cheapest total parallel safe path.
1974 */
1975 if (inner_cheapest_total == NULL ||
1976 !inner_cheapest_total->parallel_safe)
1977 {
1978 inner_cheapest_total =
1979 get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
1980 }
1981
1982 if (inner_cheapest_total)
1983 consider_parallel_mergejoin(root, joinrel, outerrel, innerrel,
1984 jointype, extra,
1985 inner_cheapest_total);
1986 }
1987}
1988
1989/*
1990 * consider_parallel_mergejoin
1991 * Try to build partial paths for a joinrel by joining a partial path
1992 * for the outer relation to a complete path for the inner relation.
1993 *
1994 * 'joinrel' is the join relation
1995 * 'outerrel' is the outer join relation
1996 * 'innerrel' is the inner join relation
1997 * 'jointype' is the type of join to do
1998 * 'extra' contains additional input values
1999 * 'inner_cheapest_total' cheapest total path for innerrel
2000 */
2001static void
2002 consider_parallel_mergejoin(PlannerInfo *root,
2003 RelOptInfo *joinrel,
2004 RelOptInfo *outerrel,
2005 RelOptInfo *innerrel,
2006 JoinType jointype,
2007 JoinPathExtraData *extra,
2008 Path *inner_cheapest_total)
2009{
2010 ListCell *lc1;
2011
2012 /* generate merge join path for each partial outer path */
2013 foreach(lc1, outerrel->partial_pathlist)
2014 {
2015 Path *outerpath = (Path *) lfirst(lc1);
2016 List *merge_pathkeys;
2017
2018 /*
2019 * Figure out what useful ordering any paths we create will have.
2020 */
2021 merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
2022 outerpath->pathkeys);
2023
2024 generate_mergejoin_paths(root, joinrel, innerrel, outerpath, jointype,
2025 extra, false, inner_cheapest_total,
2026 merge_pathkeys, true);
2027 }
2028}
2029
2030/*
2031 * consider_parallel_nestloop
2032 * Try to build partial paths for a joinrel by joining a partial path for the
2033 * outer relation to a complete path for the inner relation.
2034 *
2035 * 'joinrel' is the join relation
2036 * 'outerrel' is the outer join relation
2037 * 'innerrel' is the inner join relation
2038 * 'jointype' is the type of join to do
2039 * 'extra' contains additional input values
2040 */
2041static void
2042 consider_parallel_nestloop(PlannerInfo *root,
2043 RelOptInfo *joinrel,
2044 RelOptInfo *outerrel,
2045 RelOptInfo *innerrel,
2046 JoinType jointype,
2047 JoinPathExtraData *extra)
2048{
2049 Path *inner_cheapest_total = innerrel->cheapest_total_path;
2050 Path *matpath = NULL;
2051 ListCell *lc1;
2052
2053 /*
2054 * Consider materializing the cheapest inner path, unless: 1)
2055 * enable_material is off, 2) the cheapest inner path is not
2056 * parallel-safe, 3) the cheapest inner path is parameterized by the outer
2057 * rel, or 4) the cheapest inner path materializes its output anyway.
2058 */
2059 if (enable_material && inner_cheapest_total->parallel_safe &&
2060 !PATH_PARAM_BY_REL(inner_cheapest_total, outerrel) &&
2061 !ExecMaterializesOutput(inner_cheapest_total->pathtype))
2062 {
2063 matpath = (Path *)
2064 create_material_path(innerrel, inner_cheapest_total);
2065 Assert(matpath->parallel_safe);
2066 }
2067
2068 foreach(lc1, outerrel->partial_pathlist)
2069 {
2070 Path *outerpath = (Path *) lfirst(lc1);
2071 List *pathkeys;
2072 ListCell *lc2;
2073
2074 /* Figure out what useful ordering any paths we create will have. */
2075 pathkeys = build_join_pathkeys(root, joinrel, jointype,
2076 outerpath->pathkeys);
2077
2078 /*
2079 * Try the cheapest parameterized paths; only those which will produce
2080 * an unparameterized path when joined to this outerrel will survive
2081 * try_partial_nestloop_path. The cheapest unparameterized path is
2082 * also in this list.
2083 */
2084 foreach(lc2, innerrel->cheapest_parameterized_paths)
2085 {
2086 Path *innerpath = (Path *) lfirst(lc2);
2087 Path *mpath;
2088
2089 /* Can't join to an inner path that is not parallel-safe */
2090 if (!innerpath->parallel_safe)
2091 continue;
2092
2093 try_partial_nestloop_path(root, joinrel, outerpath, innerpath,
2094 pathkeys, jointype, extra);
2095
2096 /*
2097 * Try generating a memoize path and see if that makes the nested
2098 * loop any cheaper.
2099 */
2100 mpath = get_memoize_path(root, innerrel, outerrel,
2101 innerpath, outerpath, jointype,
2102 extra);
2103 if (mpath != NULL)
2104 try_partial_nestloop_path(root, joinrel, outerpath, mpath,
2105 pathkeys, jointype, extra);
2106 }
2107
2108 /* Also consider materialized form of the cheapest inner path */
2109 if (matpath != NULL)
2110 try_partial_nestloop_path(root, joinrel, outerpath, matpath,
2111 pathkeys, jointype, extra);
2112 }
2113}
2114
2115/*
2116 * hash_inner_and_outer
2117 * Create hashjoin join paths by explicitly hashing both the outer and
2118 * inner keys of each available hash clause.
2119 *
2120 * 'joinrel' is the join relation
2121 * 'outerrel' is the outer join relation
2122 * 'innerrel' is the inner join relation
2123 * 'jointype' is the type of join to do
2124 * 'extra' contains additional input values
2125 */
2126static void
2127 hash_inner_and_outer(PlannerInfo *root,
2128 RelOptInfo *joinrel,
2129 RelOptInfo *outerrel,
2130 RelOptInfo *innerrel,
2131 JoinType jointype,
2132 JoinPathExtraData *extra)
2133{
2134 bool isouterjoin = IS_OUTER_JOIN(jointype);
2135 List *hashclauses;
2136 ListCell *l;
2137
2138 /*
2139 * We need to build only one hashclauses list for any given pair of outer
2140 * and inner relations; all of the hashable clauses will be used as keys.
2141 *
2142 * Scan the join's restrictinfo list to find hashjoinable clauses that are
2143 * usable with this pair of sub-relations.
2144 */
2145 hashclauses = NIL;
2146 foreach(l, extra->restrictlist)
2147 {
2148 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
2149
2150 /*
2151 * If processing an outer join, only use its own join clauses for
2152 * hashing. For inner joins we need not be so picky.
2153 */
2154 if (isouterjoin && RINFO_IS_PUSHED_DOWN(restrictinfo, joinrel->relids))
2155 continue;
2156
2157 if (!restrictinfo->can_join ||
2158 restrictinfo->hashjoinoperator == InvalidOid)
2159 continue; /* not hashjoinable */
2160
2161 /*
2162 * Check if clause has the form "outer op inner" or "inner op outer".
2163 */
2164 if (!clause_sides_match_join(restrictinfo, outerrel->relids,
2165 innerrel->relids))
2166 continue; /* no good for these input relations */
2167
2168 /*
2169 * If clause has the form "inner op outer", check if its operator has
2170 * valid commutator. This is necessary because hashclauses in this
2171 * form will get commuted in createplan.c to put the outer var on the
2172 * left (see get_switched_clauses). This probably shouldn't ever
2173 * fail, since hashable operators ought to have commutators, but be
2174 * paranoid.
2175 *
2176 * The clause being hashjoinable indicates that it's an OpExpr.
2177 */
2178 if (!restrictinfo->outer_is_left &&
2179 !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno)))
2180 continue;
2181
2182 hashclauses = lappend(hashclauses, restrictinfo);
2183 }
2184
2185 /* If we found any usable hashclauses, make paths */
2186 if (hashclauses)
2187 {
2188 /*
2189 * We consider both the cheapest-total-cost and cheapest-startup-cost
2190 * outer paths. There's no need to consider any but the
2191 * cheapest-total-cost inner path, however.
2192 */
2193 Path *cheapest_startup_outer = outerrel->cheapest_startup_path;
2194 Path *cheapest_total_outer = outerrel->cheapest_total_path;
2195 Path *cheapest_total_inner = innerrel->cheapest_total_path;
2196 ListCell *lc1;
2197 ListCell *lc2;
2198
2199 /*
2200 * If either cheapest-total path is parameterized by the other rel, we
2201 * can't use a hashjoin. (There's no use looking for alternative
2202 * input paths, since these should already be the least-parameterized
2203 * available paths.)
2204 */
2205 if (PATH_PARAM_BY_REL(cheapest_total_outer, innerrel) ||
2206 PATH_PARAM_BY_REL(cheapest_total_inner, outerrel))
2207 return;
2208
2209 /*
2210 * Consider the cheapest startup outer together with the cheapest
2211 * total inner, and then consider pairings of cheapest-total paths
2212 * including parameterized ones. There is no use in generating
2213 * parameterized paths on the basis of possibly cheap startup cost, so
2214 * this is sufficient.
2215 */
2216 if (cheapest_startup_outer != NULL)
2217 try_hashjoin_path(root,
2218 joinrel,
2219 cheapest_startup_outer,
2220 cheapest_total_inner,
2221 hashclauses,
2222 jointype,
2223 extra);
2224
2225 foreach(lc1, outerrel->cheapest_parameterized_paths)
2226 {
2227 Path *outerpath = (Path *) lfirst(lc1);
2228
2229 /*
2230 * We cannot use an outer path that is parameterized by the inner
2231 * rel.
2232 */
2233 if (PATH_PARAM_BY_REL(outerpath, innerrel))
2234 continue;
2235
2236 foreach(lc2, innerrel->cheapest_parameterized_paths)
2237 {
2238 Path *innerpath = (Path *) lfirst(lc2);
2239
2240 /*
2241 * We cannot use an inner path that is parameterized by the
2242 * outer rel, either.
2243 */
2244 if (PATH_PARAM_BY_REL(innerpath, outerrel))
2245 continue;
2246
2247 if (outerpath == cheapest_startup_outer &&
2248 innerpath == cheapest_total_inner)
2249 continue; /* already tried it */
2250
2251 try_hashjoin_path(root,
2252 joinrel,
2253 outerpath,
2254 innerpath,
2255 hashclauses,
2256 jointype,
2257 extra);
2258 }
2259 }
2260
2261 /*
2262 * If the joinrel is parallel-safe, we may be able to consider a
2263 * partial hash join. However, the resulting path must not be
2264 * parameterized.
2265 */
2266 if (joinrel->consider_parallel &&
2267 outerrel->partial_pathlist != NIL &&
2268 bms_is_empty(joinrel->lateral_relids))
2269 {
2270 Path *cheapest_partial_outer;
2271 Path *cheapest_partial_inner = NULL;
2272 Path *cheapest_safe_inner = NULL;
2273
2274 cheapest_partial_outer =
2275 (Path *) linitial(outerrel->partial_pathlist);
2276
2277 /*
2278 * Can we use a partial inner plan too, so that we can build a
2279 * shared hash table in parallel?
2280 */
2281 if (innerrel->partial_pathlist != NIL &&
2282 enable_parallel_hash)
2283 {
2284 cheapest_partial_inner =
2285 (Path *) linitial(innerrel->partial_pathlist);
2286 try_partial_hashjoin_path(root, joinrel,
2287 cheapest_partial_outer,
2288 cheapest_partial_inner,
2289 hashclauses, jointype, extra,
2290 true /* parallel_hash */ );
2291 }
2292
2293 /*
2294 * Normally, given that the joinrel is parallel-safe, the cheapest
2295 * total inner path will also be parallel-safe, but if not, we'll
2296 * have to search for the cheapest safe, unparameterized inner
2297 * path. If full, right, right-semi or right-anti join, we can't
2298 * use parallelism (building the hash table in each backend)
2299 * because no one process has all the match bits.
2300 */
2301 if (jointype == JOIN_FULL ||
2302 jointype == JOIN_RIGHT ||
2303 jointype == JOIN_RIGHT_SEMI ||
2304 jointype == JOIN_RIGHT_ANTI)
2305 cheapest_safe_inner = NULL;
2306 else if (cheapest_total_inner->parallel_safe)
2307 cheapest_safe_inner = cheapest_total_inner;
2308 else
2309 cheapest_safe_inner =
2310 get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
2311
2312 if (cheapest_safe_inner != NULL)
2313 try_partial_hashjoin_path(root, joinrel,
2314 cheapest_partial_outer,
2315 cheapest_safe_inner,
2316 hashclauses, jointype, extra,
2317 false /* parallel_hash */ );
2318 }
2319 }
2320}
2321
2322/*
2323 * select_mergejoin_clauses
2324 * Select mergejoin clauses that are usable for a particular join.
2325 * Returns a list of RestrictInfo nodes for those clauses.
2326 *
2327 * *mergejoin_allowed is normally set to true, but it is set to false if
2328 * this is a right-semi join, or this is a right/right-anti/full join and
2329 * there are nonmergejoinable join clauses. The executor's mergejoin
2330 * machinery cannot handle such cases, so we have to avoid generating a
2331 * mergejoin plan. (Note that this flag does NOT consider whether there are
2332 * actually any mergejoinable clauses. This is correct because in some
2333 * cases we need to build a clauseless mergejoin. Simply returning NIL is
2334 * therefore not enough to distinguish safe from unsafe cases.)
2335 *
2336 * We also mark each selected RestrictInfo to show which side is currently
2337 * being considered as outer. These are transient markings that are only
2338 * good for the duration of the current add_paths_to_joinrel() call!
2339 *
2340 * We examine each restrictinfo clause known for the join to see
2341 * if it is mergejoinable and involves vars from the two sub-relations
2342 * currently of interest.
2343 */
2344static List *
2345 select_mergejoin_clauses(PlannerInfo *root,
2346 RelOptInfo *joinrel,
2347 RelOptInfo *outerrel,
2348 RelOptInfo *innerrel,
2349 List *restrictlist,
2350 JoinType jointype,
2351 bool *mergejoin_allowed)
2352{
2353 List *result_list = NIL;
2354 bool isouterjoin = IS_OUTER_JOIN(jointype);
2355 bool have_nonmergeable_joinclause = false;
2356 ListCell *l;
2357
2358 /*
2359 * For now we do not support RIGHT_SEMI join in mergejoin: the benefit of
2360 * swapping inputs tends to be small here.
2361 */
2362 if (jointype == JOIN_RIGHT_SEMI)
2363 {
2364 *mergejoin_allowed = false;
2365 return NIL;
2366 }
2367
2368 foreach(l, restrictlist)
2369 {
2370 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
2371
2372 /*
2373 * If processing an outer join, only use its own join clauses in the
2374 * merge. For inner joins we can use pushed-down clauses too. (Note:
2375 * we don't set have_nonmergeable_joinclause here because pushed-down
2376 * clauses will become otherquals not joinquals.)
2377 */
2378 if (isouterjoin && RINFO_IS_PUSHED_DOWN(restrictinfo, joinrel->relids))
2379 continue;
2380
2381 /* Check that clause is a mergeable operator clause */
2382 if (!restrictinfo->can_join ||
2383 restrictinfo->mergeopfamilies == NIL)
2384 {
2385 /*
2386 * The executor can handle extra joinquals that are constants, but
2387 * not anything else, when doing right/right-anti/full merge join.
2388 * (The reason to support constants is so we can do FULL JOIN ON
2389 * FALSE.)
2390 */
2391 if (!restrictinfo->clause || !IsA(restrictinfo->clause, Const))
2392 have_nonmergeable_joinclause = true;
2393 continue; /* not mergejoinable */
2394 }
2395
2396 /*
2397 * Check if clause has the form "outer op inner" or "inner op outer".
2398 */
2399 if (!clause_sides_match_join(restrictinfo, outerrel->relids,
2400 innerrel->relids))
2401 {
2402 have_nonmergeable_joinclause = true;
2403 continue; /* no good for these input relations */
2404 }
2405
2406 /*
2407 * If clause has the form "inner op outer", check if its operator has
2408 * valid commutator. This is necessary because mergejoin clauses in
2409 * this form will get commuted in createplan.c to put the outer var on
2410 * the left (see get_switched_clauses). This probably shouldn't ever
2411 * fail, since mergejoinable operators ought to have commutators, but
2412 * be paranoid.
2413 *
2414 * The clause being mergejoinable indicates that it's an OpExpr.
2415 */
2416 if (!restrictinfo->outer_is_left &&
2417 !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno)))
2418 {
2419 have_nonmergeable_joinclause = true;
2420 continue;
2421 }
2422
2423 /*
2424 * Insist that each side have a non-redundant eclass. This
2425 * restriction is needed because various bits of the planner expect
2426 * that each clause in a merge be associable with some pathkey in a
2427 * canonical pathkey list, but redundant eclasses can't appear in
2428 * canonical sort orderings. (XXX it might be worth relaxing this,
2429 * but not enough time to address it for 8.3.)
2430 */
2431 update_mergeclause_eclasses(root, restrictinfo);
2432
2433 if (EC_MUST_BE_REDUNDANT(restrictinfo->left_ec) ||
2434 EC_MUST_BE_REDUNDANT(restrictinfo->right_ec))
2435 {
2436 have_nonmergeable_joinclause = true;
2437 continue; /* can't handle redundant eclasses */
2438 }
2439
2440 result_list = lappend(result_list, restrictinfo);
2441 }
2442
2443 /*
2444 * Report whether mergejoin is allowed (see comment at top of function).
2445 */
2446 switch (jointype)
2447 {
2448 case JOIN_RIGHT:
2449 case JOIN_RIGHT_ANTI:
2450 case JOIN_FULL:
2451 *mergejoin_allowed = !have_nonmergeable_joinclause;
2452 break;
2453 default:
2454 *mergejoin_allowed = true;
2455 break;
2456 }
2457
2458 return result_list;
2459}
bool innerrel_is_unique(PlannerInfo *root, Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache)
Definition: analyzejoins.c:1305
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:346
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:292
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:142
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:917
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:781
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:1230
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:641
#define bms_is_empty(a)
Definition: bitmapset.h:118
@ BMS_MULTIPLE
Definition: bitmapset.h:73
#define OidIsValid(objectId)
Definition: c.h:774
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:542
bool enable_memoize
Definition: costsize.c:155
void compute_semi_anti_join_factors(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, SpecialJoinInfo *sjinfo, List *restrictlist, SemiAntiJoinFactors *semifactors)
Definition: costsize.c:5149
bool enable_material
Definition: costsize.c:154
void initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace, JoinType jointype, List *hashclauses, Path *outer_path, Path *inner_path, JoinPathExtraData *extra, bool parallel_hash)
Definition: costsize.c:4194
bool enable_hashjoin
Definition: costsize.c:157
void initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, JoinType jointype, List *mergeclauses, Path *outer_path, Path *inner_path, List *outersortkeys, List *innersortkeys, int outer_presorted_keys, JoinPathExtraData *extra)
Definition: costsize.c:3584
bool enable_mergejoin
Definition: costsize.c:156
void initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace, JoinType jointype, Path *outer_path, Path *inner_path, JoinPathExtraData *extra)
Definition: costsize.c:3299
bool enable_parallel_hash
Definition: costsize.c:162
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
bool ExecMaterializesOutput(NodeTag plantype)
Definition: execAmi.c:636
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
static void try_hashjoin_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *hashclauses, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:1233
static List * select_mergejoin_clauses(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, JoinType jointype, bool *mergejoin_allowed)
Definition: joinpath.c:2345
static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:1368
static List * extract_lateral_vars_from_PHVs(PlannerInfo *root, Relids innerrelids)
Definition: joinpath.c:590
void add_paths_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: joinpath.c:124
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)
Definition: joinpath.c:445
static void try_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *pathkeys, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:842
static Path * get_memoize_path(PlannerInfo *root, RelOptInfo *innerrel, RelOptInfo *outerrel, Path *inner_path, Path *outer_path, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:681
static void consider_parallel_nestloop(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:2042
#define PATH_PARAM_BY_PARENT(path, rel)
Definition: joinpath.c:40
set_join_pathlist_hook_type set_join_pathlist_hook
Definition: joinpath.c:33
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)
Definition: joinpath.c:1040
static void consider_parallel_mergejoin(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra, Path *inner_cheapest_total)
Definition: joinpath.c:2002
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)
Definition: joinpath.c:1552
static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:2127
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)
Definition: joinpath.c:1156
#define PATH_PARAM_BY_REL(path, rel)
Definition: joinpath.c:46
static bool allow_star_schema_join(PlannerInfo *root, Relids outerrelids, Relids inner_paramrels)
Definition: joinpath.c:369
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)
Definition: joinpath.c:1310
static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:1792
static void try_partial_nestloop_path(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, List *pathkeys, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:961
List * lappend(List *list, void *datum)
Definition: list.c:339
List * list_delete_nth_cell(List *list, int n)
Definition: list.c:767
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
List * list_copy(const List *oldlist)
Definition: list.c:1573
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
List * lcons(void *datum, List *list)
Definition: list.c:495
void list_free(List *list)
Definition: list.c:1546
List * list_truncate(List *list, int new_size)
Definition: list.c:631
bool list_member(const List *list, const void *datum)
Definition: list.c:661
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1676
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:348
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
JoinType
Definition: nodes.h:298
@ JOIN_SEMI
Definition: nodes.h:317
@ JOIN_FULL
Definition: nodes.h:305
@ JOIN_INNER
Definition: nodes.h:303
@ JOIN_RIGHT
Definition: nodes.h:306
@ JOIN_RIGHT_SEMI
Definition: nodes.h:319
@ JOIN_LEFT
Definition: nodes.h:304
@ JOIN_UNIQUE_OUTER
Definition: nodes.h:326
@ JOIN_RIGHT_ANTI
Definition: nodes.h:320
@ JOIN_UNIQUE_INNER
Definition: nodes.h:327
@ JOIN_ANTI
Definition: nodes.h:318
Path * get_cheapest_path_for_pathkeys(List *paths, List *pathkeys, Relids required_outer, CostSelector cost_criterion, bool require_parallel_safe)
Definition: pathkeys.c:620
bool pathkeys_count_contained_in(List *keys1, List *keys2, int *n_common)
Definition: pathkeys.c:558
List * make_inner_pathkeys_for_merge(PlannerInfo *root, List *mergeclauses, List *outer_pathkeys)
Definition: pathkeys.c:1858
List * find_mergeclauses_for_outer_pathkeys(PlannerInfo *root, List *pathkeys, List *restrictinfos)
Definition: pathkeys.c:1544
void update_mergeclause_eclasses(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition: pathkeys.c:1510
List * trim_mergeclauses_for_inner_pathkeys(PlannerInfo *root, List *mergeclauses, List *pathkeys)
Definition: pathkeys.c:1961
List * select_outer_pathkeys_for_merge(PlannerInfo *root, List *mergeclauses, RelOptInfo *joinrel)
Definition: pathkeys.c:1659
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:343
List * build_join_pathkeys(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, List *outer_pathkeys)
Definition: pathkeys.c:1295
Path * get_cheapest_parallel_safe_total_inner(List *paths)
Definition: pathkeys.c:699
Relids calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path)
Definition: pathnode.c:2240
bool path_is_reparameterizable_by_child(Path *path, RelOptInfo *child_rel)
Definition: pathnode.c:4317
MemoizePath * create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *param_exprs, List *hash_operators, bool singlerow, bool binary_mode, Cardinality est_calls)
Definition: pathnode.c:1689
Relids calc_nestloop_required_outer(Relids outerrelids, Relids outer_paramrels, Relids innerrelids, Relids inner_paramrels)
Definition: pathnode.c:2213
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)
Definition: pathnode.c:2457
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:794
MaterialPath * create_material_path(RelOptInfo *rel, Path *subpath)
Definition: pathnode.c:1656
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:460
int compare_path_costs(Path *path1, Path *path2, CostSelector criterion)
Definition: pathnode.c:69
bool add_path_precheck(RelOptInfo *parent_rel, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer)
Definition: pathnode.c:687
bool add_partial_path_precheck(RelOptInfo *parent_rel, int disabled_nodes, Cost total_cost, List *pathkeys)
Definition: pathnode.c:920
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, int outer_presorted_keys)
Definition: pathnode.c:2389
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)
Definition: pathnode.c:2292
#define EC_MUST_BE_REDUNDANT(eclass)
Definition: pathnodes.h:1497
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
Definition: pathnodes.h:2861
@ TOTAL_COST
Definition: pathnodes.h:38
@ STARTUP_COST
Definition: pathnodes.h:38
#define PATH_REQ_OUTER(path)
Definition: pathnodes.h:1828
#define RELATION_WAS_MADE_UNIQUE(rel, sjinfo, nominal_jointype)
Definition: pathnodes.h:1123
@ RELOPT_OTHER_JOINREL
Definition: pathnodes.h:867
void(* set_join_pathlist_hook_type)(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
Definition: paths.h:37
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define foreach_current_index(var_or_cell)
Definition: pg_list.h:403
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
#define foreach_node(type, var, lst)
Definition: pg_list.h:496
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
Definition: placeholder.c:83
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
tree ctl root
Definition: radixtree.h:1857
static bool clause_sides_match_join(RestrictInfo *rinfo, Relids outerrelids, Relids innerrelids)
Definition: restrictinfo.h:73
Definition: primnodes.h:324
List * mergeclause_list
Definition: pathnodes.h:3366
Relids param_source_rels
Definition: pathnodes.h:3370
List * restrictlist
Definition: pathnodes.h:3365
SemiAntiJoinFactors semifactors
Definition: pathnodes.h:3369
SpecialJoinInfo * sjinfo
Definition: pathnodes.h:3368
Definition: pg_list.h:54
Definition: nodes.h:135
Definition: primnodes.h:846
List * args
Definition: primnodes.h:868
List * ppi_clauses
Definition: pathnodes.h:1739
Definition: pathnodes.h:1778
List * pathkeys
Definition: pathnodes.h:1824
NodeTag pathtype
Definition: pathnodes.h:1784
Cardinality rows
Definition: pathnodes.h:1818
bool parallel_safe
Definition: pathnodes.h:1813
Relids ph_lateral
Definition: pathnodes.h:3226
Relids ph_eval_at
Definition: pathnodes.h:3223
PlaceHolderVar * ph_var
Definition: pathnodes.h:3220
Index phlevelsup
Definition: pathnodes.h:2937
List * baserestrictinfo
Definition: pathnodes.h:1027
Relids relids
Definition: pathnodes.h:908
struct PathTarget * reltarget
Definition: pathnodes.h:930
List * lateral_vars
Definition: pathnodes.h:972
bool consider_parallel
Definition: pathnodes.h:924
Relids top_parent_relids
Definition: pathnodes.h:1051
Relids lateral_relids
Definition: pathnodes.h:949
List * cheapest_parameterized_paths
Definition: pathnodes.h:940
List * pathlist
Definition: pathnodes.h:935
RelOptKind reloptkind
Definition: pathnodes.h:902
struct Path * cheapest_startup_path
Definition: pathnodes.h:938
struct Path * cheapest_total_path
Definition: pathnodes.h:939
List * partial_pathlist
Definition: pathnodes.h:937
Expr * clause
Definition: pathnodes.h:2704
Relids min_righthand
Definition: pathnodes.h:3030
JoinType jointype
Definition: pathnodes.h:3033
Relids min_lefthand
Definition: pathnodes.h:3029
Index ojrelid
Definition: pathnodes.h:3034
Oid hash_proc
Definition: typcache.h:66
Oid eq_opr
Definition: typcache.h:62
Definition: primnodes.h:262
int varno
Definition: primnodes.h:269
Index varlevelsup
Definition: primnodes.h:294
Definition: regcomp.c:282
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_EQ_OPR
Definition: typcache.h:138
#define TYPECACHE_HASH_PROC
Definition: typcache.h:142
Definition: pg_list.h:46
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:114
List * pull_vars_of_level(Node *node, int levelsup)
Definition: var.c:339

AltStyle によって変換されたページ (->オリジナル) /