PostgreSQL Source Code git master
relnode.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * relnode.c
4 * Relation-node lookup/construction routines
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/util/relnode.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include <limits.h>
18
19#include "miscadmin.h"
20#include "nodes/nodeFuncs.h"
22#include "optimizer/clauses.h"
23#include "optimizer/cost.h"
24#include "optimizer/inherit.h"
25#include "optimizer/optimizer.h"
26#include "optimizer/pathnode.h"
27#include "optimizer/paths.h"
29#include "optimizer/plancat.h"
31#include "optimizer/tlist.h"
34#include "utils/hsearch.h"
35#include "utils/lsyscache.h"
36
37
38typedef struct JoinHashEntry
39{
40 Relids join_relids; /* hash key --- MUST BE FIRST */
43
44static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
45 RelOptInfo *input_rel,
46 SpecialJoinInfo *sjinfo,
47 List *pushed_down_joins,
48 bool can_null);
50 RelOptInfo *joinrel,
51 RelOptInfo *outer_rel,
52 RelOptInfo *inner_rel,
53 SpecialJoinInfo *sjinfo);
54static void build_joinrel_joinlist(RelOptInfo *joinrel,
55 RelOptInfo *outer_rel,
56 RelOptInfo *inner_rel);
58 RelOptInfo *joinrel,
59 RelOptInfo *input_rel,
60 Relids both_input_relids,
61 List *new_restrictlist);
63 List *joininfo_list,
64 List *new_joininfo);
65static void set_foreign_rel_properties(RelOptInfo *joinrel,
66 RelOptInfo *outer_rel, RelOptInfo *inner_rel);
67static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel);
69 RelOptInfo *joinrel,
70 RelOptInfo *outer_rel, RelOptInfo *inner_rel,
71 SpecialJoinInfo *sjinfo,
72 List *restrictlist);
74 RelOptInfo *rel1, RelOptInfo *rel2,
75 JoinType jointype, List *restrictlist);
76static int match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel,
77 bool strict_op);
79 RelOptInfo *outer_rel, RelOptInfo *inner_rel,
80 JoinType jointype);
82 RelOptInfo *parentrel,
83 RelOptInfo *childrel,
84 int nappinfos,
85 AppendRelInfo **appinfos);
86
87
88/*
89 * setup_simple_rel_arrays
90 * Prepare the arrays we use for quickly accessing base relations
91 * and AppendRelInfos.
92 */
93void
95{
96 int size;
97 Index rti;
98 ListCell *lc;
99
100 /* Arrays are accessed using RT indexes (1..N) */
101 size = list_length(root->parse->rtable) + 1;
102 root->simple_rel_array_size = size;
103
104 /*
105 * simple_rel_array is initialized to all NULLs, since no RelOptInfos
106 * exist yet. It'll be filled by later calls to build_simple_rel().
107 */
108 root->simple_rel_array = (RelOptInfo **)
109 palloc0(size * sizeof(RelOptInfo *));
110
111 /* simple_rte_array is an array equivalent of the rtable list */
112 root->simple_rte_array = (RangeTblEntry **)
113 palloc0(size * sizeof(RangeTblEntry *));
114 rti = 1;
115 foreach(lc, root->parse->rtable)
116 {
117 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
118
119 root->simple_rte_array[rti++] = rte;
120 }
121
122 /* append_rel_array is not needed if there are no AppendRelInfos */
123 if (root->append_rel_list == NIL)
124 {
125 root->append_rel_array = NULL;
126 return;
127 }
128
129 root->append_rel_array = (AppendRelInfo **)
130 palloc0(size * sizeof(AppendRelInfo *));
131
132 /*
133 * append_rel_array is filled with any already-existing AppendRelInfos,
134 * which currently could only come from UNION ALL flattening. We might
135 * add more later during inheritance expansion, but it's the
136 * responsibility of the expansion code to update the array properly.
137 */
138 foreach(lc, root->append_rel_list)
139 {
141 int child_relid = appinfo->child_relid;
142
143 /* Sanity check */
144 Assert(child_relid < size);
145
146 if (root->append_rel_array[child_relid])
147 elog(ERROR, "child relation already exists");
148
149 root->append_rel_array[child_relid] = appinfo;
150 }
151}
152
153/*
154 * expand_planner_arrays
155 * Expand the PlannerInfo's per-RTE arrays by add_size members
156 * and initialize the newly added entries to NULLs
157 *
158 * Note: this causes the append_rel_array to become allocated even if
159 * it was not before. This is okay for current uses, because we only call
160 * this when adding child relations, which always have AppendRelInfos.
161 */
162void
164{
165 int new_size;
166
167 Assert(add_size > 0);
168
169 new_size = root->simple_rel_array_size + add_size;
170
171 root->simple_rel_array =
172 repalloc0_array(root->simple_rel_array, RelOptInfo *, root->simple_rel_array_size, new_size);
173
174 root->simple_rte_array =
175 repalloc0_array(root->simple_rte_array, RangeTblEntry *, root->simple_rel_array_size, new_size);
176
177 if (root->append_rel_array)
178 root->append_rel_array =
179 repalloc0_array(root->append_rel_array, AppendRelInfo *, root->simple_rel_array_size, new_size);
180 else
181 root->append_rel_array =
182 palloc0_array(AppendRelInfo *, new_size);
183
184 root->simple_rel_array_size = new_size;
185}
186
187/*
188 * build_simple_rel
189 * Construct a new RelOptInfo for a base relation or 'other' relation.
190 */
193{
194 RelOptInfo *rel;
195 RangeTblEntry *rte;
196
197 /* Rel should not exist already */
198 Assert(relid > 0 && relid < root->simple_rel_array_size);
199 if (root->simple_rel_array[relid] != NULL)
200 elog(ERROR, "rel %d already exists", relid);
201
202 /* Fetch RTE for relation */
203 rte = root->simple_rte_array[relid];
204 Assert(rte != NULL);
205
206 rel = makeNode(RelOptInfo);
208 rel->relids = bms_make_singleton(relid);
209 rel->rows = 0;
210 /* cheap startup cost is interesting iff not all tuples to be retrieved */
211 rel->consider_startup = (root->tuple_fraction > 0);
212 rel->consider_param_startup = false; /* might get changed later */
213 rel->consider_parallel = false; /* might get changed later */
215 rel->pathlist = NIL;
216 rel->ppilist = NIL;
217 rel->partial_pathlist = NIL;
218 rel->cheapest_startup_path = NULL;
219 rel->cheapest_total_path = NULL;
220 rel->cheapest_unique_path = NULL;
222 rel->relid = relid;
223 rel->rtekind = rte->rtekind;
224 /* min_attr, max_attr, attr_needed, attr_widths are set below */
225 rel->notnullattnums = NULL;
226 rel->lateral_vars = NIL;
227 rel->indexlist = NIL;
228 rel->statlist = NIL;
229 rel->pages = 0;
230 rel->tuples = 0;
231 rel->allvisfrac = 0;
232 rel->eclass_indexes = NULL;
233 rel->subroot = NULL;
234 rel->subplan_params = NIL;
235 rel->rel_parallel_workers = -1; /* set up in get_relation_info */
236 rel->amflags = 0;
237 rel->serverid = InvalidOid;
238 if (rte->rtekind == RTE_RELATION)
239 {
240 Assert(parent == NULL ||
241 parent->rtekind == RTE_RELATION ||
242 parent->rtekind == RTE_SUBQUERY);
243
244 /*
245 * For any RELATION rte, we need a userid with which to check
246 * permission access. Baserels simply use their own
247 * RTEPermissionInfo's checkAsUser.
248 *
249 * For otherrels normally there's no RTEPermissionInfo, so we use the
250 * parent's, which normally has one. The exceptional case is that the
251 * parent is a subquery, in which case the otherrel will have its own.
252 */
253 if (rel->reloptkind == RELOPT_BASEREL ||
255 parent->rtekind == RTE_SUBQUERY))
256 {
257 RTEPermissionInfo *perminfo;
258
259 perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
260 rel->userid = perminfo->checkAsUser;
261 }
262 else
263 rel->userid = parent->userid;
264 }
265 else
266 rel->userid = InvalidOid;
267 rel->useridiscurrent = false;
268 rel->fdwroutine = NULL;
269 rel->fdw_private = NULL;
270 rel->unique_for_rels = NIL;
272 rel->baserestrictinfo = NIL;
273 rel->baserestrictcost.startup = 0;
275 rel->baserestrict_min_security = UINT_MAX;
276 rel->joininfo = NIL;
277 rel->has_eclass_joins = false;
278 rel->consider_partitionwise_join = false; /* might get changed later */
279 rel->part_scheme = NULL;
280 rel->nparts = -1;
281 rel->boundinfo = NULL;
282 rel->partbounds_merged = false;
283 rel->partition_qual = NIL;
284 rel->part_rels = NULL;
285 rel->live_parts = NULL;
286 rel->all_partrels = NULL;
287 rel->partexprs = NULL;
288 rel->nullable_partexprs = NULL;
289
290 /*
291 * Pass assorted information down the inheritance hierarchy.
292 */
293 if (parent)
294 {
295 /* We keep back-links to immediate parent and topmost parent. */
296 rel->parent = parent;
297 rel->top_parent = parent->top_parent ? parent->top_parent : parent;
298 rel->top_parent_relids = rel->top_parent->relids;
299
300 /*
301 * A child rel is below the same outer joins as its parent. (We
302 * presume this info was already calculated for the parent.)
303 */
304 rel->nulling_relids = parent->nulling_relids;
305
306 /*
307 * Also propagate lateral-reference information from appendrel parent
308 * rels to their child rels. We intentionally give each child rel the
309 * same minimum parameterization, even though it's quite possible that
310 * some don't reference all the lateral rels. This is because any
311 * append path for the parent will have to have the same
312 * parameterization for every child anyway, and there's no value in
313 * forcing extra reparameterize_path() calls. Similarly, a lateral
314 * reference to the parent prevents use of otherwise-movable join rels
315 * for each child.
316 *
317 * It's possible for child rels to have their own children, in which
318 * case the topmost parent's lateral info propagates all the way down.
319 */
321 rel->lateral_relids = parent->lateral_relids;
323 }
324 else
325 {
326 rel->parent = NULL;
327 rel->top_parent = NULL;
328 rel->top_parent_relids = NULL;
329 rel->nulling_relids = NULL;
330 rel->direct_lateral_relids = NULL;
331 rel->lateral_relids = NULL;
332 rel->lateral_referencers = NULL;
333 }
334
335 /* Check type of rtable entry */
336 switch (rte->rtekind)
337 {
338 case RTE_RELATION:
339 /* Table --- retrieve statistics from the system catalogs */
340 get_relation_info(root, rte->relid, rte->inh, rel);
341 break;
342 case RTE_SUBQUERY:
343 case RTE_FUNCTION:
344 case RTE_TABLEFUNC:
345 case RTE_VALUES:
346 case RTE_CTE:
348
349 /*
350 * Subquery, function, tablefunc, values list, CTE, or ENR --- set
351 * up attr range and arrays
352 *
353 * Note: 0 is included in range to support whole-row Vars
354 */
355 rel->min_attr = 0;
356 rel->max_attr = list_length(rte->eref->colnames);
357 rel->attr_needed = (Relids *)
358 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
359 rel->attr_widths = (int32 *)
360 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
361 break;
362 case RTE_RESULT:
363 /* RTE_RESULT has no columns, nor could it have whole-row Var */
364 rel->min_attr = 0;
365 rel->max_attr = -1;
366 rel->attr_needed = NULL;
367 rel->attr_widths = NULL;
368 break;
369 default:
370 elog(ERROR, "unrecognized RTE kind: %d",
371 (int) rte->rtekind);
372 break;
373 }
374
375 /*
376 * We must apply the partially filled in RelOptInfo before calling
377 * apply_child_basequals due to some transformations within that function
378 * which require the RelOptInfo to be available in the simple_rel_array.
379 */
380 root->simple_rel_array[relid] = rel;
381
382 /*
383 * Apply the parent's quals to the child, with appropriate substitution of
384 * variables. If the resulting clause is constant-FALSE or NULL after
385 * applying transformations, apply_child_basequals returns false to
386 * indicate that scanning this relation won't yield any rows. In this
387 * case, we mark the child as dummy right away. (We must do this
388 * immediately so that pruning works correctly when recursing in
389 * expand_partitioned_rtentry.)
390 */
391 if (parent)
392 {
393 AppendRelInfo *appinfo = root->append_rel_array[relid];
394
395 Assert(appinfo != NULL);
396 if (!apply_child_basequals(root, parent, rel, rte, appinfo))
397 {
398 /*
399 * Restriction clause reduced to constant FALSE or NULL. Mark as
400 * dummy so we won't scan this relation.
401 */
402 mark_dummy_rel(rel);
403 }
404 }
405
406 return rel;
407}
408
409/*
410 * find_base_rel
411 * Find a base or otherrel relation entry, which must already exist.
412 */
415{
416 RelOptInfo *rel;
417
418 /* use an unsigned comparison to prevent negative array element access */
419 if ((uint32) relid < (uint32) root->simple_rel_array_size)
420 {
421 rel = root->simple_rel_array[relid];
422 if (rel)
423 return rel;
424 }
425
426 elog(ERROR, "no relation entry for relid %d", relid);
427
428 return NULL; /* keep compiler quiet */
429}
430
431/*
432 * find_base_rel_noerr
433 * Find a base or otherrel relation entry, returning NULL if there's none
434 */
437{
438 /* use an unsigned comparison to prevent negative array element access */
439 if ((uint32) relid < (uint32) root->simple_rel_array_size)
440 return root->simple_rel_array[relid];
441 return NULL;
442}
443
444/*
445 * find_base_rel_ignore_join
446 * Find a base or otherrel relation entry, which must already exist.
447 *
448 * Unlike find_base_rel, if relid references an outer join then this
449 * will return NULL rather than raising an error. This is convenient
450 * for callers that must deal with relid sets including both base and
451 * outer joins.
452 */
455{
456 /* use an unsigned comparison to prevent negative array element access */
457 if ((uint32) relid < (uint32) root->simple_rel_array_size)
458 {
459 RelOptInfo *rel;
460 RangeTblEntry *rte;
461
462 rel = root->simple_rel_array[relid];
463 if (rel)
464 return rel;
465
466 /*
467 * We could just return NULL here, but for debugging purposes it seems
468 * best to actually verify that the relid is an outer join and not
469 * something weird.
470 */
471 rte = root->simple_rte_array[relid];
472 if (rte && rte->rtekind == RTE_JOIN && rte->jointype != JOIN_INNER)
473 return NULL;
474 }
475
476 elog(ERROR, "no relation entry for relid %d", relid);
477
478 return NULL; /* keep compiler quiet */
479}
480
481/*
482 * build_join_rel_hash
483 * Construct the auxiliary hash table for join relations.
484 */
485static void
487{
488 HTAB *hashtab;
489 HASHCTL hash_ctl;
490 ListCell *l;
491
492 /* Create the hash table */
493 hash_ctl.keysize = sizeof(Relids);
494 hash_ctl.entrysize = sizeof(JoinHashEntry);
495 hash_ctl.hash = bitmap_hash;
496 hash_ctl.match = bitmap_match;
497 hash_ctl.hcxt = CurrentMemoryContext;
498 hashtab = hash_create("JoinRelHashTable",
499 256L,
500 &hash_ctl,
502
503 /* Insert all the already-existing joinrels */
504 foreach(l, root->join_rel_list)
505 {
506 RelOptInfo *rel = (RelOptInfo *) lfirst(l);
507 JoinHashEntry *hentry;
508 bool found;
509
510 hentry = (JoinHashEntry *) hash_search(hashtab,
511 &(rel->relids),
513 &found);
514 Assert(!found);
515 hentry->join_rel = rel;
516 }
517
518 root->join_rel_hash = hashtab;
519}
520
521/*
522 * find_join_rel
523 * Returns relation entry corresponding to 'relids' (a set of RT indexes),
524 * or NULL if none exists. This is for join relations.
525 */
528{
529 /*
530 * Switch to using hash lookup when list grows "too long". The threshold
531 * is arbitrary and is known only here.
532 */
533 if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)
535
536 /*
537 * Use either hashtable lookup or linear search, as appropriate.
538 *
539 * Note: the seemingly redundant hashkey variable is used to avoid taking
540 * the address of relids; unless the compiler is exceedingly smart, doing
541 * so would force relids out of a register and thus probably slow down the
542 * list-search case.
543 */
544 if (root->join_rel_hash)
545 {
546 Relids hashkey = relids;
547 JoinHashEntry *hentry;
548
549 hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
550 &hashkey,
551 HASH_FIND,
552 NULL);
553 if (hentry)
554 return hentry->join_rel;
555 }
556 else
557 {
558 ListCell *l;
559
560 foreach(l, root->join_rel_list)
561 {
562 RelOptInfo *rel = (RelOptInfo *) lfirst(l);
563
564 if (bms_equal(rel->relids, relids))
565 return rel;
566 }
567 }
568
569 return NULL;
570}
571
572/*
573 * set_foreign_rel_properties
574 * Set up foreign-join fields if outer and inner relation are foreign
575 * tables (or joins) belonging to the same server and assigned to the same
576 * user to check access permissions as.
577 *
578 * In addition to an exact match of userid, we allow the case where one side
579 * has zero userid (implying current user) and the other side has explicit
580 * userid that happens to equal the current user; but in that case, pushdown of
581 * the join is only valid for the current user. The useridiscurrent field
582 * records whether we had to make such an assumption for this join or any
583 * sub-join.
584 *
585 * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
586 * called for the join relation.
587 */
588static void
590 RelOptInfo *inner_rel)
591{
592 if (OidIsValid(outer_rel->serverid) &&
593 inner_rel->serverid == outer_rel->serverid)
594 {
595 if (inner_rel->userid == outer_rel->userid)
596 {
597 joinrel->serverid = outer_rel->serverid;
598 joinrel->userid = outer_rel->userid;
599 joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
600 joinrel->fdwroutine = outer_rel->fdwroutine;
601 }
602 else if (!OidIsValid(inner_rel->userid) &&
603 outer_rel->userid == GetUserId())
604 {
605 joinrel->serverid = outer_rel->serverid;
606 joinrel->userid = outer_rel->userid;
607 joinrel->useridiscurrent = true;
608 joinrel->fdwroutine = outer_rel->fdwroutine;
609 }
610 else if (!OidIsValid(outer_rel->userid) &&
611 inner_rel->userid == GetUserId())
612 {
613 joinrel->serverid = outer_rel->serverid;
614 joinrel->userid = inner_rel->userid;
615 joinrel->useridiscurrent = true;
616 joinrel->fdwroutine = outer_rel->fdwroutine;
617 }
618 }
619}
620
621/*
622 * add_join_rel
623 * Add given join relation to the list of join relations in the given
624 * PlannerInfo. Also add it to the auxiliary hashtable if there is one.
625 */
626static void
628{
629 /* GEQO requires us to append the new joinrel to the end of the list! */
630 root->join_rel_list = lappend(root->join_rel_list, joinrel);
631
632 /* store it into the auxiliary hashtable if there is one. */
633 if (root->join_rel_hash)
634 {
635 JoinHashEntry *hentry;
636 bool found;
637
638 hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
639 &(joinrel->relids),
641 &found);
642 Assert(!found);
643 hentry->join_rel = joinrel;
644 }
645}
646
647/*
648 * build_join_rel
649 * Returns relation entry corresponding to the union of two given rels,
650 * creating a new relation entry if none already exists.
651 *
652 * 'joinrelids' is the Relids set that uniquely identifies the join
653 * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
654 * joined
655 * 'sjinfo': join context info
656 * 'pushed_down_joins': any pushed-down outer joins that are now completed
657 * 'restrictlist_ptr': result variable. If not NULL, *restrictlist_ptr
658 * receives the list of RestrictInfo nodes that apply to this
659 * particular pair of joinable relations.
660 *
661 * restrictlist_ptr makes the routine's API a little grotty, but it saves
662 * duplicated calculation of the restrictlist...
663 */
666 Relids joinrelids,
667 RelOptInfo *outer_rel,
668 RelOptInfo *inner_rel,
669 SpecialJoinInfo *sjinfo,
670 List *pushed_down_joins,
671 List **restrictlist_ptr)
672{
673 RelOptInfo *joinrel;
674 List *restrictlist;
675
676 /* This function should be used only for join between parents. */
677 Assert(!IS_OTHER_REL(outer_rel) && !IS_OTHER_REL(inner_rel));
678
679 /*
680 * See if we already have a joinrel for this set of base rels.
681 */
682 joinrel = find_join_rel(root, joinrelids);
683
684 if (joinrel)
685 {
686 /*
687 * Yes, so we only need to figure the restrictlist for this particular
688 * pair of component relations.
689 */
690 if (restrictlist_ptr)
691 *restrictlist_ptr = build_joinrel_restrictlist(root,
692 joinrel,
693 outer_rel,
694 inner_rel,
695 sjinfo);
696 return joinrel;
697 }
698
699 /*
700 * Nope, so make one.
701 */
702 joinrel = makeNode(RelOptInfo);
703 joinrel->reloptkind = RELOPT_JOINREL;
704 joinrel->relids = bms_copy(joinrelids);
705 joinrel->rows = 0;
706 /* cheap startup cost is interesting iff not all tuples to be retrieved */
707 joinrel->consider_startup = (root->tuple_fraction > 0);
708 joinrel->consider_param_startup = false;
709 joinrel->consider_parallel = false;
711 joinrel->pathlist = NIL;
712 joinrel->ppilist = NIL;
713 joinrel->partial_pathlist = NIL;
714 joinrel->cheapest_startup_path = NULL;
715 joinrel->cheapest_total_path = NULL;
716 joinrel->cheapest_unique_path = NULL;
718 /* init direct_lateral_relids from children; we'll finish it up below */
719 joinrel->direct_lateral_relids =
721 inner_rel->direct_lateral_relids);
723 outer_rel, inner_rel);
724 joinrel->relid = 0; /* indicates not a baserel */
725 joinrel->rtekind = RTE_JOIN;
726 joinrel->min_attr = 0;
727 joinrel->max_attr = 0;
728 joinrel->attr_needed = NULL;
729 joinrel->attr_widths = NULL;
730 joinrel->notnullattnums = NULL;
731 joinrel->nulling_relids = NULL;
732 joinrel->lateral_vars = NIL;
733 joinrel->lateral_referencers = NULL;
734 joinrel->indexlist = NIL;
735 joinrel->statlist = NIL;
736 joinrel->pages = 0;
737 joinrel->tuples = 0;
738 joinrel->allvisfrac = 0;
739 joinrel->eclass_indexes = NULL;
740 joinrel->subroot = NULL;
741 joinrel->subplan_params = NIL;
742 joinrel->rel_parallel_workers = -1;
743 joinrel->amflags = 0;
744 joinrel->serverid = InvalidOid;
745 joinrel->userid = InvalidOid;
746 joinrel->useridiscurrent = false;
747 joinrel->fdwroutine = NULL;
748 joinrel->fdw_private = NULL;
749 joinrel->unique_for_rels = NIL;
750 joinrel->non_unique_for_rels = NIL;
751 joinrel->baserestrictinfo = NIL;
752 joinrel->baserestrictcost.startup = 0;
753 joinrel->baserestrictcost.per_tuple = 0;
754 joinrel->baserestrict_min_security = UINT_MAX;
755 joinrel->joininfo = NIL;
756 joinrel->has_eclass_joins = false;
757 joinrel->consider_partitionwise_join = false; /* might get changed later */
758 joinrel->parent = NULL;
759 joinrel->top_parent = NULL;
760 joinrel->top_parent_relids = NULL;
761 joinrel->part_scheme = NULL;
762 joinrel->nparts = -1;
763 joinrel->boundinfo = NULL;
764 joinrel->partbounds_merged = false;
765 joinrel->partition_qual = NIL;
766 joinrel->part_rels = NULL;
767 joinrel->live_parts = NULL;
768 joinrel->all_partrels = NULL;
769 joinrel->partexprs = NULL;
770 joinrel->nullable_partexprs = NULL;
771
772 /* Compute information relevant to the foreign relations. */
773 set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
774
775 /*
776 * Fill the joinrel's tlist with just the Vars and PHVs that need to be
777 * output from this join (ie, are needed for higher joinclauses or final
778 * output).
779 *
780 * NOTE: the tlist order for a join rel will depend on which pair of outer
781 * and inner rels we first try to build it from. But the contents should
782 * be the same regardless.
783 */
784 build_joinrel_tlist(root, joinrel, outer_rel, sjinfo, pushed_down_joins,
785 (sjinfo->jointype == JOIN_FULL));
786 build_joinrel_tlist(root, joinrel, inner_rel, sjinfo, pushed_down_joins,
787 (sjinfo->jointype != JOIN_INNER));
788 add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel, sjinfo);
789
790 /*
791 * add_placeholders_to_joinrel also took care of adding the ph_lateral
792 * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
793 * now we can finish computing that. This is much like the computation of
794 * the transitively-closed lateral_relids in min_join_parameterization,
795 * except that here we *do* have to consider the added PHVs.
796 */
797 joinrel->direct_lateral_relids =
798 bms_del_members(joinrel->direct_lateral_relids, joinrel->relids);
799
800 /*
801 * Construct restrict and join clause lists for the new joinrel. (The
802 * caller might or might not need the restrictlist, but I need it anyway
803 * for set_joinrel_size_estimates().)
804 */
805 restrictlist = build_joinrel_restrictlist(root, joinrel,
806 outer_rel, inner_rel,
807 sjinfo);
808 if (restrictlist_ptr)
809 *restrictlist_ptr = restrictlist;
810 build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
811
812 /*
813 * This is also the right place to check whether the joinrel has any
814 * pending EquivalenceClass joins.
815 */
817
818 /* Store the partition information. */
819 build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
820 restrictlist);
821
822 /*
823 * Set estimates of the joinrel's size.
824 */
825 set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
826 sjinfo, restrictlist);
827
828 /*
829 * Set the consider_parallel flag if this joinrel could potentially be
830 * scanned within a parallel worker. If this flag is false for either
831 * inner_rel or outer_rel, then it must be false for the joinrel also.
832 * Even if both are true, there might be parallel-restricted expressions
833 * in the targetlist or quals.
834 *
835 * Note that if there are more than two rels in this relation, they could
836 * be divided between inner_rel and outer_rel in any arbitrary way. We
837 * assume this doesn't matter, because we should hit all the same baserels
838 * and joinclauses while building up to this joinrel no matter which we
839 * take; therefore, we should make the same decision here however we get
840 * here.
841 */
842 if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
843 is_parallel_safe(root, (Node *) restrictlist) &&
844 is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
845 joinrel->consider_parallel = true;
846
847 /* Add the joinrel to the PlannerInfo. */
848 add_join_rel(root, joinrel);
849
850 /*
851 * Also, if dynamic-programming join search is active, add the new joinrel
852 * to the appropriate sublist. Note: you might think the Assert on number
853 * of members should be for equality, but some of the level 1 rels might
854 * have been joinrels already, so we can only assert <=.
855 */
856 if (root->join_rel_level)
857 {
858 Assert(root->join_cur_level > 0);
859 Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
860 root->join_rel_level[root->join_cur_level] =
861 lappend(root->join_rel_level[root->join_cur_level], joinrel);
862 }
863
864 return joinrel;
865}
866
867/*
868 * build_child_join_rel
869 * Builds RelOptInfo representing join between given two child relations.
870 *
871 * 'outer_rel' and 'inner_rel' are the RelOptInfos of child relations being
872 * joined
873 * 'parent_joinrel' is the RelOptInfo representing the join between parent
874 * relations. Some of the members of new RelOptInfo are produced by
875 * translating corresponding members of this RelOptInfo
876 * 'restrictlist': list of RestrictInfo nodes that apply to this particular
877 * pair of joinable relations
878 * 'sjinfo': child join's join-type details
879 * 'nappinfos' and 'appinfos': AppendRelInfo array for child relids
880 */
883 RelOptInfo *inner_rel, RelOptInfo *parent_joinrel,
884 List *restrictlist, SpecialJoinInfo *sjinfo,
885 int nappinfos, AppendRelInfo **appinfos)
886{
887 RelOptInfo *joinrel = makeNode(RelOptInfo);
888
889 /* Only joins between "other" relations land here. */
890 Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
891
892 /* The parent joinrel should have consider_partitionwise_join set. */
893 Assert(parent_joinrel->consider_partitionwise_join);
894
896 joinrel->relids = adjust_child_relids(parent_joinrel->relids,
897 nappinfos, appinfos);
898 joinrel->rows = 0;
899 /* cheap startup cost is interesting iff not all tuples to be retrieved */
900 joinrel->consider_startup = (root->tuple_fraction > 0);
901 joinrel->consider_param_startup = false;
902 joinrel->consider_parallel = false;
904 joinrel->pathlist = NIL;
905 joinrel->ppilist = NIL;
906 joinrel->partial_pathlist = NIL;
907 joinrel->cheapest_startup_path = NULL;
908 joinrel->cheapest_total_path = NULL;
909 joinrel->cheapest_unique_path = NULL;
911 joinrel->direct_lateral_relids = NULL;
912 joinrel->lateral_relids = NULL;
913 joinrel->relid = 0; /* indicates not a baserel */
914 joinrel->rtekind = RTE_JOIN;
915 joinrel->min_attr = 0;
916 joinrel->max_attr = 0;
917 joinrel->attr_needed = NULL;
918 joinrel->attr_widths = NULL;
919 joinrel->notnullattnums = NULL;
920 joinrel->nulling_relids = NULL;
921 joinrel->lateral_vars = NIL;
922 joinrel->lateral_referencers = NULL;
923 joinrel->indexlist = NIL;
924 joinrel->pages = 0;
925 joinrel->tuples = 0;
926 joinrel->allvisfrac = 0;
927 joinrel->eclass_indexes = NULL;
928 joinrel->subroot = NULL;
929 joinrel->subplan_params = NIL;
930 joinrel->amflags = 0;
931 joinrel->serverid = InvalidOid;
932 joinrel->userid = InvalidOid;
933 joinrel->useridiscurrent = false;
934 joinrel->fdwroutine = NULL;
935 joinrel->fdw_private = NULL;
936 joinrel->baserestrictinfo = NIL;
937 joinrel->baserestrictcost.startup = 0;
938 joinrel->baserestrictcost.per_tuple = 0;
939 joinrel->joininfo = NIL;
940 joinrel->has_eclass_joins = false;
941 joinrel->consider_partitionwise_join = false; /* might get changed later */
942 joinrel->parent = parent_joinrel;
943 joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
944 joinrel->top_parent_relids = joinrel->top_parent->relids;
945 joinrel->part_scheme = NULL;
946 joinrel->nparts = -1;
947 joinrel->boundinfo = NULL;
948 joinrel->partbounds_merged = false;
949 joinrel->partition_qual = NIL;
950 joinrel->part_rels = NULL;
951 joinrel->live_parts = NULL;
952 joinrel->all_partrels = NULL;
953 joinrel->partexprs = NULL;
954 joinrel->nullable_partexprs = NULL;
955
956 /* Compute information relevant to foreign relations. */
957 set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
958
959 /* Set up reltarget struct */
960 build_child_join_reltarget(root, parent_joinrel, joinrel,
961 nappinfos, appinfos);
962
963 /* Construct joininfo list. */
965 (Node *) parent_joinrel->joininfo,
966 nappinfos,
967 appinfos);
968
969 /*
970 * Lateral relids referred in child join will be same as that referred in
971 * the parent relation.
972 */
973 joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
974 joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
975
976 /*
977 * If the parent joinrel has pending equivalence classes, so does the
978 * child.
979 */
980 joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
981
982 /* Is the join between partitions itself partitioned? */
983 build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
984 restrictlist);
985
986 /* Child joinrel is parallel safe if parent is parallel safe. */
987 joinrel->consider_parallel = parent_joinrel->consider_parallel;
988
989 /* Set estimates of the child-joinrel's size. */
990 set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
991 sjinfo, restrictlist);
992
993 /* We build the join only once. */
994 Assert(!find_join_rel(root, joinrel->relids));
995
996 /* Add the relation to the PlannerInfo. */
997 add_join_rel(root, joinrel);
998
999 /*
1000 * We might need EquivalenceClass members corresponding to the child join,
1001 * so that we can represent sort pathkeys for it. As with children of
1002 * baserels, we shouldn't need this unless there are relevant eclass joins
1003 * (implying that a merge join might be possible) or pathkeys to sort by.
1004 */
1005 if (joinrel->has_eclass_joins || has_useful_pathkeys(root, parent_joinrel))
1007 nappinfos, appinfos,
1008 parent_joinrel, joinrel);
1009
1010 return joinrel;
1011}
1012
1013/*
1014 * min_join_parameterization
1015 *
1016 * Determine the minimum possible parameterization of a joinrel, that is, the
1017 * set of other rels it contains LATERAL references to. We save this value in
1018 * the join's RelOptInfo. This function is split out of build_join_rel()
1019 * because join_is_legal() needs the value to check a prospective join.
1020 */
1021Relids
1023 Relids joinrelids,
1024 RelOptInfo *outer_rel,
1025 RelOptInfo *inner_rel)
1026{
1027 Relids result;
1028
1029 /*
1030 * Basically we just need the union of the inputs' lateral_relids, less
1031 * whatever is already in the join.
1032 *
1033 * It's not immediately obvious that this is a valid way to compute the
1034 * result, because it might seem that we're ignoring possible lateral refs
1035 * of PlaceHolderVars that are due to be computed at the join but not in
1036 * either input. However, because create_lateral_join_info() already
1037 * charged all such PHV refs to each member baserel of the join, they'll
1038 * be accounted for already in the inputs' lateral_relids. Likewise, we
1039 * do not need to worry about doing transitive closure here, because that
1040 * was already accounted for in the original baserel lateral_relids.
1041 */
1042 result = bms_union(outer_rel->lateral_relids, inner_rel->lateral_relids);
1043 result = bms_del_members(result, joinrelids);
1044 return result;
1045}
1046
1047/*
1048 * build_joinrel_tlist
1049 * Builds a join relation's target list from an input relation.
1050 * (This is invoked twice to handle the two input relations.)
1051 *
1052 * The join's targetlist includes all Vars of its member relations that
1053 * will still be needed above the join. This subroutine adds all such
1054 * Vars from the specified input rel's tlist to the join rel's tlist.
1055 * Likewise for any PlaceHolderVars emitted by the input rel.
1056 *
1057 * We also compute the expected width of the join's output, making use
1058 * of data that was cached at the baserel level by set_rel_width().
1059 *
1060 * Pass can_null as true if the join is an outer join that can null Vars
1061 * from this input relation. If so, we will (normally) add the join's relid
1062 * to the nulling bitmaps of Vars and PHVs bubbled up from the input.
1063 *
1064 * When forming an outer join's target list, special handling is needed in
1065 * case the outer join was commuted with another one per outer join identity 3
1066 * (see optimizer/README). We must take steps to ensure that the output Vars
1067 * have the same nulling bitmaps that they would if the two joins had been
1068 * done in syntactic order; else they won't match Vars appearing higher in
1069 * the query tree. An exception to the match-the-syntactic-order rule is
1070 * that when an outer join is pushed down into another one's RHS per identity
1071 * 3, we can't mark its Vars as nulled until the now-upper outer join is also
1072 * completed. So we need to do three things:
1073 *
1074 * First, we add the outer join's relid to the nulling bitmap only if the
1075 * outer join has been completely performed and the Var or PHV actually
1076 * comes from within the syntactically nullable side(s) of the outer join.
1077 * This takes care of the possibility that we have transformed
1078 * (A leftjoin B on (Pab)) leftjoin C on (Pbc)
1079 * to
1080 * A leftjoin (B leftjoin C on (Pbc)) on (Pab)
1081 * Here the pushed-down B/C join cannot mark C columns as nulled yet,
1082 * while the now-upper A/B join must not mark C columns as nulled by itself.
1083 *
1084 * Second, perform the same operation for each SpecialJoinInfo listed in
1085 * pushed_down_joins (which, in this example, would be the B/C join when
1086 * we are at the now-upper A/B join). This allows the now-upper join to
1087 * complete the marking of "C" Vars that now have fully valid values.
1088 *
1089 * Third, any relid in sjinfo->commute_above_r that is already part of
1090 * the joinrel is added to the nulling bitmaps of nullable Vars and PHVs.
1091 * This takes care of the reverse case where we implement
1092 * A leftjoin (B leftjoin C on (Pbc)) on (Pab)
1093 * as
1094 * (A leftjoin B on (Pab)) leftjoin C on (Pbc)
1095 * The C columns emitted by the B/C join need to be shown as nulled by both
1096 * the B/C and A/B joins, even though they've not physically traversed the
1097 * A/B join.
1098 */
1099static void
1101 RelOptInfo *input_rel,
1102 SpecialJoinInfo *sjinfo,
1103 List *pushed_down_joins,
1104 bool can_null)
1105{
1106 Relids relids = joinrel->relids;
1107 int64 tuple_width = joinrel->reltarget->width;
1108 ListCell *vars;
1109 ListCell *lc;
1110
1111 foreach(vars, input_rel->reltarget->exprs)
1112 {
1113 Var *var = (Var *) lfirst(vars);
1114
1115 /*
1116 * For a PlaceHolderVar, we have to look up the PlaceHolderInfo.
1117 */
1118 if (IsA(var, PlaceHolderVar))
1119 {
1120 PlaceHolderVar *phv = (PlaceHolderVar *) var;
1122
1123 /* Is it still needed above this joinrel? */
1124 if (bms_nonempty_difference(phinfo->ph_needed, relids))
1125 {
1126 /*
1127 * Yup, add it to the output. If this join potentially nulls
1128 * this input, we have to update the PHV's phnullingrels,
1129 * which means making a copy.
1130 */
1131 if (can_null)
1132 {
1133 phv = copyObject(phv);
1134 /* See comments above to understand this logic */
1135 if (sjinfo->ojrelid != 0 &&
1136 bms_is_member(sjinfo->ojrelid, relids) &&
1137 (bms_is_subset(phv->phrels, sjinfo->syn_righthand) ||
1138 (sjinfo->jointype == JOIN_FULL &&
1139 bms_is_subset(phv->phrels, sjinfo->syn_lefthand))))
1141 sjinfo->ojrelid);
1142 foreach(lc, pushed_down_joins)
1143 {
1144 SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
1145
1146 Assert(bms_is_member(othersj->ojrelid, relids));
1147 if (bms_is_subset(phv->phrels, othersj->syn_righthand))
1149 othersj->ojrelid);
1150 }
1151 phv->phnullingrels =
1154 relids));
1155 }
1156
1157 joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
1158 phv);
1159 /* Bubbling up the precomputed result has cost zero */
1160 tuple_width += phinfo->ph_width;
1161 }
1162 continue;
1163 }
1164
1165 /*
1166 * Otherwise, anything in a baserel or joinrel targetlist ought to be
1167 * a Var. (More general cases can only appear in appendrel child
1168 * rels, which will never be seen here.)
1169 */
1170 if (!IsA(var, Var))
1171 elog(ERROR, "unexpected node type in rel targetlist: %d",
1172 (int) nodeTag(var));
1173
1174 if (var->varno == ROWID_VAR)
1175 {
1176 /* UPDATE/DELETE/MERGE row identity vars are always needed */
1178 list_nth(root->row_identity_vars, var->varattno - 1);
1179
1180 /* Update reltarget width estimate from RowIdentityVarInfo */
1181 tuple_width += ridinfo->rowidwidth;
1182 }
1183 else
1184 {
1185 RelOptInfo *baserel;
1186 int ndx;
1187
1188 /* Get the Var's original base rel */
1189 baserel = find_base_rel(root, var->varno);
1190
1191 /* Is it still needed above this joinrel? */
1192 ndx = var->varattno - baserel->min_attr;
1193 if (!bms_nonempty_difference(baserel->attr_needed[ndx], relids))
1194 continue; /* nope, skip it */
1195
1196 /* Update reltarget width estimate from baserel's attr_widths */
1197 tuple_width += baserel->attr_widths[ndx];
1198 }
1199
1200 /*
1201 * Add the Var to the output. If this join potentially nulls this
1202 * input, we have to update the Var's varnullingrels, which means
1203 * making a copy. But note that we don't ever add nullingrel bits to
1204 * row identity Vars (cf. comments in setrefs.c).
1205 */
1206 if (can_null && var->varno != ROWID_VAR)
1207 {
1208 var = copyObject(var);
1209 /* See comments above to understand this logic */
1210 if (sjinfo->ojrelid != 0 &&
1211 bms_is_member(sjinfo->ojrelid, relids) &&
1212 (bms_is_member(var->varno, sjinfo->syn_righthand) ||
1213 (sjinfo->jointype == JOIN_FULL &&
1214 bms_is_member(var->varno, sjinfo->syn_lefthand))))
1215 var->varnullingrels = bms_add_member(var->varnullingrels,
1216 sjinfo->ojrelid);
1217 foreach(lc, pushed_down_joins)
1218 {
1219 SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
1220
1221 Assert(bms_is_member(othersj->ojrelid, relids));
1222 if (bms_is_member(var->varno, othersj->syn_righthand))
1223 var->varnullingrels = bms_add_member(var->varnullingrels,
1224 othersj->ojrelid);
1225 }
1226 var->varnullingrels =
1227 bms_join(var->varnullingrels,
1229 relids));
1230 }
1231
1232 joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
1233 var);
1234
1235 /* Vars have cost zero, so no need to adjust reltarget->cost */
1236 }
1237
1238 joinrel->reltarget->width = clamp_width_est(tuple_width);
1239}
1240
1241/*
1242 * build_joinrel_restrictlist
1243 * build_joinrel_joinlist
1244 * These routines build lists of restriction and join clauses for a
1245 * join relation from the joininfo lists of the relations it joins.
1246 *
1247 * These routines are separate because the restriction list must be
1248 * built afresh for each pair of input sub-relations we consider, whereas
1249 * the join list need only be computed once for any join RelOptInfo.
1250 * The join list is fully determined by the set of rels making up the
1251 * joinrel, so we should get the same results (up to ordering) from any
1252 * candidate pair of sub-relations. But the restriction list is whatever
1253 * is not handled in the sub-relations, so it depends on which
1254 * sub-relations are considered.
1255 *
1256 * If a join clause from an input relation refers to base+OJ rels still not
1257 * present in the joinrel, then it is still a join clause for the joinrel;
1258 * we put it into the joininfo list for the joinrel. Otherwise,
1259 * the clause is now a restrict clause for the joined relation, and we
1260 * return it to the caller of build_joinrel_restrictlist() to be stored in
1261 * join paths made from this pair of sub-relations. (It will not need to
1262 * be considered further up the join tree.)
1263 *
1264 * In many cases we will find the same RestrictInfos in both input
1265 * relations' joinlists, so be careful to eliminate duplicates.
1266 * Pointer equality should be a sufficient test for dups, since all
1267 * the various joinlist entries ultimately refer to RestrictInfos
1268 * pushed into them by distribute_restrictinfo_to_rels().
1269 *
1270 * 'joinrel' is a join relation node
1271 * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
1272 * to form joinrel.
1273 * 'sjinfo': join context info
1274 *
1275 * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
1276 * whereas build_joinrel_joinlist() stores its results in the joinrel's
1277 * joininfo list. One or the other must accept each given clause!
1278 *
1279 * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
1280 * up to the join relation. I believe this is no longer necessary, because
1281 * RestrictInfo nodes are no longer context-dependent. Instead, just include
1282 * the original nodes in the lists made for the join relation.
1283 */
1284static List *
1286 RelOptInfo *joinrel,
1287 RelOptInfo *outer_rel,
1288 RelOptInfo *inner_rel,
1289 SpecialJoinInfo *sjinfo)
1290{
1291 List *result;
1292 Relids both_input_relids;
1293
1294 both_input_relids = bms_union(outer_rel->relids, inner_rel->relids);
1295
1296 /*
1297 * Collect all the clauses that syntactically belong at this level,
1298 * eliminating any duplicates (important since we will see many of the
1299 * same clauses arriving from both input relations).
1300 */
1301 result = subbuild_joinrel_restrictlist(root, joinrel, outer_rel,
1302 both_input_relids, NIL);
1303 result = subbuild_joinrel_restrictlist(root, joinrel, inner_rel,
1304 both_input_relids, result);
1305
1306 /*
1307 * Add on any clauses derived from EquivalenceClasses. These cannot be
1308 * redundant with the clauses in the joininfo lists, so don't bother
1309 * checking.
1310 */
1311 result = list_concat(result,
1313 joinrel->relids,
1314 outer_rel->relids,
1315 inner_rel,
1316 sjinfo));
1317
1318 return result;
1319}
1320
1321static void
1323 RelOptInfo *outer_rel,
1324 RelOptInfo *inner_rel)
1325{
1326 List *result;
1327
1328 /*
1329 * Collect all the clauses that syntactically belong above this level,
1330 * eliminating any duplicates (important since we will see many of the
1331 * same clauses arriving from both input relations).
1332 */
1333 result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL);
1334 result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result);
1335
1336 joinrel->joininfo = result;
1337}
1338
1339static List *
1341 RelOptInfo *joinrel,
1342 RelOptInfo *input_rel,
1343 Relids both_input_relids,
1344 List *new_restrictlist)
1345{
1346 ListCell *l;
1347
1348 foreach(l, input_rel->joininfo)
1349 {
1350 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1351
1352 if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1353 {
1354 /*
1355 * This clause should become a restriction clause for the joinrel,
1356 * since it refers to no outside rels. However, if it's a clone
1357 * clause then it might be too late to evaluate it, so we have to
1358 * check. (If it is too late, just ignore the clause, taking it
1359 * on faith that another clone was or will be selected.) Clone
1360 * clauses should always be outer-join clauses, so we compare
1361 * against both_input_relids.
1362 */
1363 if (rinfo->has_clone || rinfo->is_clone)
1364 {
1365 Assert(!RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids));
1366 if (!bms_is_subset(rinfo->required_relids, both_input_relids))
1367 continue;
1368 if (bms_overlap(rinfo->incompatible_relids, both_input_relids))
1369 continue;
1370 }
1371 else
1372 {
1373 /*
1374 * For non-clone clauses, we just Assert it's OK. These might
1375 * be either join or filter clauses; if it's a join clause
1376 * then it should not refer to the current join's output.
1377 * (There is little point in checking incompatible_relids,
1378 * because it'll be NULL.)
1379 */
1380 Assert(RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids) ||
1382 both_input_relids));
1383 }
1384
1385 /*
1386 * OK, so add it to the list, being careful to eliminate
1387 * duplicates. (Since RestrictInfo nodes in different joinlists
1388 * will have been multiply-linked rather than copied, pointer
1389 * equality should be a sufficient test.)
1390 */
1391 new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
1392 }
1393 else
1394 {
1395 /*
1396 * This clause is still a join clause at this level, so we ignore
1397 * it in this routine.
1398 */
1399 }
1400 }
1401
1402 return new_restrictlist;
1403}
1404
1405static List *
1407 List *joininfo_list,
1408 List *new_joininfo)
1409{
1410 ListCell *l;
1411
1412 /* Expected to be called only for join between parent relations. */
1413 Assert(joinrel->reloptkind == RELOPT_JOINREL);
1414
1415 foreach(l, joininfo_list)
1416 {
1417 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1418
1419 if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1420 {
1421 /*
1422 * This clause becomes a restriction clause for the joinrel, since
1423 * it refers to no outside rels. So we can ignore it in this
1424 * routine.
1425 */
1426 }
1427 else
1428 {
1429 /*
1430 * This clause is still a join clause at this level, so add it to
1431 * the new joininfo list, being careful to eliminate duplicates.
1432 * (Since RestrictInfo nodes in different joinlists will have been
1433 * multiply-linked rather than copied, pointer equality should be
1434 * a sufficient test.)
1435 */
1436 new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
1437 }
1438 }
1439
1440 return new_joininfo;
1441}
1442
1443
1444/*
1445 * fetch_upper_rel
1446 * Build a RelOptInfo describing some post-scan/join query processing,
1447 * or return a pre-existing one if somebody already built it.
1448 *
1449 * An "upper" relation is identified by an UpperRelationKind and a Relids set.
1450 * The meaning of the Relids set is not specified here, and very likely will
1451 * vary for different relation kinds.
1452 *
1453 * Most of the fields in an upper-level RelOptInfo are not used and are not
1454 * set here (though makeNode should ensure they're zeroes). We basically only
1455 * care about fields that are of interest to add_path() and set_cheapest().
1456 */
1457RelOptInfo *
1459{
1460 RelOptInfo *upperrel;
1461 ListCell *lc;
1462
1463 /*
1464 * For the moment, our indexing data structure is just a List for each
1465 * relation kind. If we ever get so many of one kind that this stops
1466 * working well, we can improve it. No code outside this function should
1467 * assume anything about how to find a particular upperrel.
1468 */
1469
1470 /* If we already made this upperrel for the query, return it */
1471 foreach(lc, root->upper_rels[kind])
1472 {
1473 upperrel = (RelOptInfo *) lfirst(lc);
1474
1475 if (bms_equal(upperrel->relids, relids))
1476 return upperrel;
1477 }
1478
1479 upperrel = makeNode(RelOptInfo);
1480 upperrel->reloptkind = RELOPT_UPPER_REL;
1481 upperrel->relids = bms_copy(relids);
1482
1483 /* cheap startup cost is interesting iff not all tuples to be retrieved */
1484 upperrel->consider_startup = (root->tuple_fraction > 0);
1485 upperrel->consider_param_startup = false;
1486 upperrel->consider_parallel = false; /* might get changed later */
1487 upperrel->reltarget = create_empty_pathtarget();
1488 upperrel->pathlist = NIL;
1489 upperrel->cheapest_startup_path = NULL;
1490 upperrel->cheapest_total_path = NULL;
1491 upperrel->cheapest_unique_path = NULL;
1493
1494 root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel);
1495
1496 return upperrel;
1497}
1498
1499
1500/*
1501 * find_childrel_parents
1502 * Compute the set of parent relids of an appendrel child rel.
1503 *
1504 * Since appendrels can be nested, a child could have multiple levels of
1505 * appendrel ancestors. This function computes a Relids set of all the
1506 * parent relation IDs.
1507 */
1508Relids
1510{
1511 Relids result = NULL;
1512
1514 Assert(rel->relid > 0 && rel->relid < root->simple_rel_array_size);
1515
1516 do
1517 {
1518 AppendRelInfo *appinfo = root->append_rel_array[rel->relid];
1519 Index prelid = appinfo->parent_relid;
1520
1521 result = bms_add_member(result, prelid);
1522
1523 /* traverse up to the parent rel, loop if it's also a child rel */
1524 rel = find_base_rel(root, prelid);
1525 } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
1526
1528
1529 return result;
1530}
1531
1532
1533/*
1534 * get_baserel_parampathinfo
1535 * Get the ParamPathInfo for a parameterized path for a base relation,
1536 * constructing one if we don't have one already.
1537 *
1538 * This centralizes estimating the rowcounts for parameterized paths.
1539 * We need to cache those to be sure we use the same rowcount for all paths
1540 * of the same parameterization for a given rel. This is also a convenient
1541 * place to determine which movable join clauses the parameterized path will
1542 * be responsible for evaluating.
1543 */
1546 Relids required_outer)
1547{
1548 ParamPathInfo *ppi;
1549 Relids joinrelids;
1550 List *pclauses;
1551 List *eqclauses;
1552 Bitmapset *pserials;
1553 double rows;
1554 ListCell *lc;
1555
1556 /* If rel has LATERAL refs, every path for it should account for them */
1557 Assert(bms_is_subset(baserel->lateral_relids, required_outer));
1558
1559 /* Unparameterized paths have no ParamPathInfo */
1560 if (bms_is_empty(required_outer))
1561 return NULL;
1562
1563 Assert(!bms_overlap(baserel->relids, required_outer));
1564
1565 /* If we already have a PPI for this parameterization, just return it */
1566 if ((ppi = find_param_path_info(baserel, required_outer)))
1567 return ppi;
1568
1569 /*
1570 * Identify all joinclauses that are movable to this base rel given this
1571 * parameterization.
1572 */
1573 joinrelids = bms_union(baserel->relids, required_outer);
1574 pclauses = NIL;
1575 foreach(lc, baserel->joininfo)
1576 {
1577 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1578
1580 baserel->relids,
1581 joinrelids))
1582 pclauses = lappend(pclauses, rinfo);
1583 }
1584
1585 /*
1586 * Add in joinclauses generated by EquivalenceClasses, too. (These
1587 * necessarily satisfy join_clause_is_movable_into; but in assert-enabled
1588 * builds, let's verify that.)
1589 */
1591 joinrelids,
1592 required_outer,
1593 baserel,
1594 NULL);
1595#ifdef USE_ASSERT_CHECKING
1596 foreach(lc, eqclauses)
1597 {
1598 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1599
1601 baserel->relids,
1602 joinrelids));
1603 }
1604#endif
1605 pclauses = list_concat(pclauses, eqclauses);
1606
1607 /* Compute set of serial numbers of the enforced clauses */
1608 pserials = NULL;
1609 foreach(lc, pclauses)
1610 {
1611 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1612
1613 pserials = bms_add_member(pserials, rinfo->rinfo_serial);
1614 }
1615
1616 /* Estimate the number of rows returned by the parameterized scan */
1617 rows = get_parameterized_baserel_size(root, baserel, pclauses);
1618
1619 /* And now we can build the ParamPathInfo */
1620 ppi = makeNode(ParamPathInfo);
1621 ppi->ppi_req_outer = required_outer;
1622 ppi->ppi_rows = rows;
1623 ppi->ppi_clauses = pclauses;
1624 ppi->ppi_serials = pserials;
1625 baserel->ppilist = lappend(baserel->ppilist, ppi);
1626
1627 return ppi;
1628}
1629
1630/*
1631 * get_joinrel_parampathinfo
1632 * Get the ParamPathInfo for a parameterized path for a join relation,
1633 * constructing one if we don't have one already.
1634 *
1635 * This centralizes estimating the rowcounts for parameterized paths.
1636 * We need to cache those to be sure we use the same rowcount for all paths
1637 * of the same parameterization for a given rel. This is also a convenient
1638 * place to determine which movable join clauses the parameterized path will
1639 * be responsible for evaluating.
1640 *
1641 * outer_path and inner_path are a pair of input paths that can be used to
1642 * construct the join, and restrict_clauses is the list of regular join
1643 * clauses (including clauses derived from EquivalenceClasses) that must be
1644 * applied at the join node when using these inputs.
1645 *
1646 * Unlike the situation for base rels, the set of movable join clauses to be
1647 * enforced at a join varies with the selected pair of input paths, so we
1648 * must calculate that and pass it back, even if we already have a matching
1649 * ParamPathInfo. We handle this by adding any clauses moved down to this
1650 * join to *restrict_clauses, which is an in/out parameter. (The addition
1651 * is done in such a way as to not modify the passed-in List structure.)
1652 *
1653 * Note: when considering a nestloop join, the caller must have removed from
1654 * restrict_clauses any movable clauses that are themselves scheduled to be
1655 * pushed into the right-hand path. We do not do that here since it's
1656 * unnecessary for other join types.
1657 */
1660 Path *outer_path,
1661 Path *inner_path,
1662 SpecialJoinInfo *sjinfo,
1663 Relids required_outer,
1664 List **restrict_clauses)
1665{
1666 ParamPathInfo *ppi;
1667 Relids join_and_req;
1668 Relids outer_and_req;
1669 Relids inner_and_req;
1670 List *pclauses;
1671 List *eclauses;
1672 List *dropped_ecs;
1673 double rows;
1674 ListCell *lc;
1675
1676 /* If rel has LATERAL refs, every path for it should account for them */
1677 Assert(bms_is_subset(joinrel->lateral_relids, required_outer));
1678
1679 /* Unparameterized paths have no ParamPathInfo or extra join clauses */
1680 if (bms_is_empty(required_outer))
1681 return NULL;
1682
1683 Assert(!bms_overlap(joinrel->relids, required_outer));
1684
1685 /*
1686 * Identify all joinclauses that are movable to this join rel given this
1687 * parameterization. These are the clauses that are movable into this
1688 * join, but not movable into either input path. Treat an unparameterized
1689 * input path as not accepting parameterized clauses (because it won't,
1690 * per the shortcut exit above), even though the joinclause movement rules
1691 * might allow the same clauses to be moved into a parameterized path for
1692 * that rel.
1693 */
1694 join_and_req = bms_union(joinrel->relids, required_outer);
1695 if (outer_path->param_info)
1696 outer_and_req = bms_union(outer_path->parent->relids,
1697 PATH_REQ_OUTER(outer_path));
1698 else
1699 outer_and_req = NULL; /* outer path does not accept parameters */
1700 if (inner_path->param_info)
1701 inner_and_req = bms_union(inner_path->parent->relids,
1702 PATH_REQ_OUTER(inner_path));
1703 else
1704 inner_and_req = NULL; /* inner path does not accept parameters */
1705
1706 pclauses = NIL;
1707 foreach(lc, joinrel->joininfo)
1708 {
1709 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1710
1712 joinrel->relids,
1713 join_and_req) &&
1715 outer_path->parent->relids,
1716 outer_and_req) &&
1718 inner_path->parent->relids,
1719 inner_and_req))
1720 pclauses = lappend(pclauses, rinfo);
1721 }
1722
1723 /* Consider joinclauses generated by EquivalenceClasses, too */
1725 join_and_req,
1726 required_outer,
1727 joinrel,
1728 NULL);
1729 /* We only want ones that aren't movable to lower levels */
1730 dropped_ecs = NIL;
1731 foreach(lc, eclauses)
1732 {
1733 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1734
1736 joinrel->relids,
1737 join_and_req));
1739 outer_path->parent->relids,
1740 outer_and_req))
1741 continue; /* drop if movable into LHS */
1743 inner_path->parent->relids,
1744 inner_and_req))
1745 {
1746 /* drop if movable into RHS, but remember EC for use below */
1747 Assert(rinfo->left_ec == rinfo->right_ec);
1748 dropped_ecs = lappend(dropped_ecs, rinfo->left_ec);
1749 continue;
1750 }
1751 pclauses = lappend(pclauses, rinfo);
1752 }
1753
1754 /*
1755 * EquivalenceClasses are harder to deal with than we could wish, because
1756 * of the fact that a given EC can generate different clauses depending on
1757 * context. Suppose we have an EC {X.X, Y.Y, Z.Z} where X and Y are the
1758 * LHS and RHS of the current join and Z is in required_outer, and further
1759 * suppose that the inner_path is parameterized by both X and Z. The code
1760 * above will have produced either Z.Z = X.X or Z.Z = Y.Y from that EC,
1761 * and in the latter case will have discarded it as being movable into the
1762 * RHS. However, the EC machinery might have produced either Y.Y = X.X or
1763 * Y.Y = Z.Z as the EC enforcement clause within the inner_path; it will
1764 * not have produced both, and we can't readily tell from here which one
1765 * it did pick. If we add no clause to this join, we'll end up with
1766 * insufficient enforcement of the EC; either Z.Z or X.X will fail to be
1767 * constrained to be equal to the other members of the EC. (When we come
1768 * to join Z to this X/Y path, we will certainly drop whichever EC clause
1769 * is generated at that join, so this omission won't get fixed later.)
1770 *
1771 * To handle this, for each EC we discarded such a clause from, try to
1772 * generate a clause connecting the required_outer rels to the join's LHS
1773 * ("Z.Z = X.X" in the terms of the above example). If successful, and if
1774 * the clause can't be moved to the LHS, add it to the current join's
1775 * restriction clauses. (If an EC cannot generate such a clause then it
1776 * has nothing that needs to be enforced here, while if the clause can be
1777 * moved into the LHS then it should have been enforced within that path.)
1778 *
1779 * Note that we don't need similar processing for ECs whose clause was
1780 * considered to be movable into the LHS, because the LHS can't refer to
1781 * the RHS so there is no comparable ambiguity about what it might
1782 * actually be enforcing internally.
1783 */
1784 if (dropped_ecs)
1785 {
1786 Relids real_outer_and_req;
1787
1788 real_outer_and_req = bms_union(outer_path->parent->relids,
1789 required_outer);
1790 eclauses =
1792 dropped_ecs,
1793 real_outer_and_req,
1794 required_outer,
1795 outer_path->parent);
1796 foreach(lc, eclauses)
1797 {
1798 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1799
1801 outer_path->parent->relids,
1802 real_outer_and_req));
1803 if (!join_clause_is_movable_into(rinfo,
1804 outer_path->parent->relids,
1805 outer_and_req))
1806 pclauses = lappend(pclauses, rinfo);
1807 }
1808 }
1809
1810 /*
1811 * Now, attach the identified moved-down clauses to the caller's
1812 * restrict_clauses list. By using list_concat in this order, we leave
1813 * the original list structure of restrict_clauses undamaged.
1814 */
1815 *restrict_clauses = list_concat(pclauses, *restrict_clauses);
1816
1817 /* If we already have a PPI for this parameterization, just return it */
1818 if ((ppi = find_param_path_info(joinrel, required_outer)))
1819 return ppi;
1820
1821 /* Estimate the number of rows returned by the parameterized join */
1822 rows = get_parameterized_joinrel_size(root, joinrel,
1823 outer_path,
1824 inner_path,
1825 sjinfo,
1826 *restrict_clauses);
1827
1828 /*
1829 * And now we can build the ParamPathInfo. No point in saving the
1830 * input-pair-dependent clause list, though.
1831 *
1832 * Note: in GEQO mode, we'll be called in a temporary memory context, but
1833 * the joinrel structure is there too, so no problem.
1834 */
1835 ppi = makeNode(ParamPathInfo);
1836 ppi->ppi_req_outer = required_outer;
1837 ppi->ppi_rows = rows;
1838 ppi->ppi_clauses = NIL;
1839 ppi->ppi_serials = NULL;
1840 joinrel->ppilist = lappend(joinrel->ppilist, ppi);
1841
1842 return ppi;
1843}
1844
1845/*
1846 * get_appendrel_parampathinfo
1847 * Get the ParamPathInfo for a parameterized path for an append relation.
1848 *
1849 * For an append relation, the rowcount estimate will just be the sum of
1850 * the estimates for its children. However, we still need a ParamPathInfo
1851 * to flag the fact that the path requires parameters. So this just creates
1852 * a suitable struct with zero ppi_rows (and no ppi_clauses either, since
1853 * the Append node isn't responsible for checking quals).
1854 */
1857{
1858 ParamPathInfo *ppi;
1859
1860 /* If rel has LATERAL refs, every path for it should account for them */
1861 Assert(bms_is_subset(appendrel->lateral_relids, required_outer));
1862
1863 /* Unparameterized paths have no ParamPathInfo */
1864 if (bms_is_empty(required_outer))
1865 return NULL;
1866
1867 Assert(!bms_overlap(appendrel->relids, required_outer));
1868
1869 /* If we already have a PPI for this parameterization, just return it */
1870 if ((ppi = find_param_path_info(appendrel, required_outer)))
1871 return ppi;
1872
1873 /* Else build the ParamPathInfo */
1874 ppi = makeNode(ParamPathInfo);
1875 ppi->ppi_req_outer = required_outer;
1876 ppi->ppi_rows = 0;
1877 ppi->ppi_clauses = NIL;
1878 ppi->ppi_serials = NULL;
1879 appendrel->ppilist = lappend(appendrel->ppilist, ppi);
1880
1881 return ppi;
1882}
1883
1884/*
1885 * Returns a ParamPathInfo for the parameterization given by required_outer, if
1886 * already available in the given rel. Returns NULL otherwise.
1887 */
1890{
1891 ListCell *lc;
1892
1893 foreach(lc, rel->ppilist)
1894 {
1895 ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
1896
1897 if (bms_equal(ppi->ppi_req_outer, required_outer))
1898 return ppi;
1899 }
1900
1901 return NULL;
1902}
1903
1904/*
1905 * get_param_path_clause_serials
1906 * Given a parameterized Path, return the set of pushed-down clauses
1907 * (identified by rinfo_serial numbers) enforced within the Path.
1908 */
1909Bitmapset *
1911{
1912 if (path->param_info == NULL)
1913 return NULL; /* not parameterized */
1914
1915 /*
1916 * We don't currently support parameterized MergeAppend paths, as
1917 * explained in the comments for generate_orderedappend_paths.
1918 */
1919 Assert(!IsA(path, MergeAppendPath));
1920
1921 if (IsA(path, NestPath) ||
1922 IsA(path, MergePath) ||
1923 IsA(path, HashPath))
1924 {
1925 /*
1926 * For a join path, combine clauses enforced within either input path
1927 * with those enforced as joinrestrictinfo in this path. Note that
1928 * joinrestrictinfo may include some non-pushed-down clauses, but for
1929 * current purposes it's okay if we include those in the result. (To
1930 * be more careful, we could check for clause_relids overlapping the
1931 * path parameterization, but it's not worth the cycles for now.)
1932 */
1933 JoinPath *jpath = (JoinPath *) path;
1934 Bitmapset *pserials;
1935 ListCell *lc;
1936
1937 pserials = NULL;
1938 pserials = bms_add_members(pserials,
1940 pserials = bms_add_members(pserials,
1942 foreach(lc, jpath->joinrestrictinfo)
1943 {
1944 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1945
1946 pserials = bms_add_member(pserials, rinfo->rinfo_serial);
1947 }
1948 return pserials;
1949 }
1950 else if (IsA(path, AppendPath))
1951 {
1952 /*
1953 * For an appendrel, take the intersection of the sets of clauses
1954 * enforced in each input path.
1955 */
1956 AppendPath *apath = (AppendPath *) path;
1957 Bitmapset *pserials;
1958 ListCell *lc;
1959
1960 pserials = NULL;
1961 foreach(lc, apath->subpaths)
1962 {
1963 Path *subpath = (Path *) lfirst(lc);
1964 Bitmapset *subserials;
1965
1967 if (lc == list_head(apath->subpaths))
1968 pserials = bms_copy(subserials);
1969 else
1970 pserials = bms_int_members(pserials, subserials);
1971 }
1972 return pserials;
1973 }
1974 else
1975 {
1976 /*
1977 * Otherwise, it's a baserel path and we can use the
1978 * previously-computed set of serial numbers.
1979 */
1980 return path->param_info->ppi_serials;
1981 }
1982}
1983
1984/*
1985 * build_joinrel_partition_info
1986 * Checks if the two relations being joined can use partitionwise join
1987 * and if yes, initialize partitioning information of the resulting
1988 * partitioned join relation.
1989 */
1990static void
1992 RelOptInfo *joinrel, RelOptInfo *outer_rel,
1993 RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo,
1994 List *restrictlist)
1995{
1996 PartitionScheme part_scheme;
1997
1998 /* Nothing to do if partitionwise join technique is disabled. */
2000 {
2001 Assert(!IS_PARTITIONED_REL(joinrel));
2002 return;
2003 }
2004
2005 /*
2006 * We can only consider this join as an input to further partitionwise
2007 * joins if (a) the input relations are partitioned and have
2008 * consider_partitionwise_join=true, (b) the partition schemes match, and
2009 * (c) we can identify an equi-join between the partition keys. Note that
2010 * if it were possible for have_partkey_equi_join to return different
2011 * answers for the same joinrel depending on which join ordering we try
2012 * first, this logic would break. That shouldn't happen, though, because
2013 * of the way the query planner deduces implied equalities and reorders
2014 * the joins. Please see optimizer/README for details.
2015 */
2016 if (outer_rel->part_scheme == NULL || inner_rel->part_scheme == NULL ||
2017 !outer_rel->consider_partitionwise_join ||
2018 !inner_rel->consider_partitionwise_join ||
2019 outer_rel->part_scheme != inner_rel->part_scheme ||
2020 !have_partkey_equi_join(root, joinrel, outer_rel, inner_rel,
2021 sjinfo->jointype, restrictlist))
2022 {
2023 Assert(!IS_PARTITIONED_REL(joinrel));
2024 return;
2025 }
2026
2027 part_scheme = outer_rel->part_scheme;
2028
2029 /*
2030 * This function will be called only once for each joinrel, hence it
2031 * should not have partitioning fields filled yet.
2032 */
2033 Assert(!joinrel->part_scheme && !joinrel->partexprs &&
2034 !joinrel->nullable_partexprs && !joinrel->part_rels &&
2035 !joinrel->boundinfo);
2036
2037 /*
2038 * If the join relation is partitioned, it uses the same partitioning
2039 * scheme as the joining relations.
2040 *
2041 * Note: we calculate the partition bounds, number of partitions, and
2042 * child-join relations of the join relation in try_partitionwise_join().
2043 */
2044 joinrel->part_scheme = part_scheme;
2045 set_joinrel_partition_key_exprs(joinrel, outer_rel, inner_rel,
2046 sjinfo->jointype);
2047
2048 /*
2049 * Set the consider_partitionwise_join flag.
2050 */
2053 joinrel->consider_partitionwise_join = true;
2054}
2055
2056/*
2057 * have_partkey_equi_join
2058 *
2059 * Returns true if there exist equi-join conditions involving pairs
2060 * of matching partition keys of the relations being joined for all
2061 * partition keys.
2062 */
2063static bool
2065 RelOptInfo *rel1, RelOptInfo *rel2,
2066 JoinType jointype, List *restrictlist)
2067{
2068 PartitionScheme part_scheme = rel1->part_scheme;
2069 bool pk_known_equal[PARTITION_MAX_KEYS];
2070 int num_equal_pks;
2071 ListCell *lc;
2072
2073 /*
2074 * This function must only be called when the joined relations have same
2075 * partitioning scheme.
2076 */
2077 Assert(rel1->part_scheme == rel2->part_scheme);
2078 Assert(part_scheme);
2079
2080 /* We use a bool array to track which partkey columns are known equal */
2081 memset(pk_known_equal, 0, sizeof(pk_known_equal));
2082 /* ... as well as a count of how many are known equal */
2083 num_equal_pks = 0;
2084
2085 /* First, look through the join's restriction clauses */
2086 foreach(lc, restrictlist)
2087 {
2089 OpExpr *opexpr;
2090 Expr *expr1;
2091 Expr *expr2;
2092 bool strict_op;
2093 int ipk1;
2094 int ipk2;
2095
2096 /* If processing an outer join, only use its own join clauses. */
2097 if (IS_OUTER_JOIN(jointype) &&
2098 RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
2099 continue;
2100
2101 /* Skip clauses which can not be used for a join. */
2102 if (!rinfo->can_join)
2103 continue;
2104
2105 /* Skip clauses which are not equality conditions. */
2106 if (!rinfo->mergeopfamilies && !OidIsValid(rinfo->hashjoinoperator))
2107 continue;
2108
2109 /* Should be OK to assume it's an OpExpr. */
2110 opexpr = castNode(OpExpr, rinfo->clause);
2111
2112 /* Match the operands to the relation. */
2113 if (bms_is_subset(rinfo->left_relids, rel1->relids) &&
2114 bms_is_subset(rinfo->right_relids, rel2->relids))
2115 {
2116 expr1 = linitial(opexpr->args);
2117 expr2 = lsecond(opexpr->args);
2118 }
2119 else if (bms_is_subset(rinfo->left_relids, rel2->relids) &&
2120 bms_is_subset(rinfo->right_relids, rel1->relids))
2121 {
2122 expr1 = lsecond(opexpr->args);
2123 expr2 = linitial(opexpr->args);
2124 }
2125 else
2126 continue;
2127
2128 /*
2129 * Now we need to know whether the join operator is strict; see
2130 * comments in pathnodes.h.
2131 */
2132 strict_op = op_strict(opexpr->opno);
2133
2134 /*
2135 * Vars appearing in the relation's partition keys will not have any
2136 * varnullingrels, but those in expr1 and expr2 will if we're above
2137 * outer joins that could null the respective rels. It's okay to
2138 * match anyway, if the join operator is strict.
2139 */
2140 if (strict_op)
2141 {
2142 if (bms_overlap(rel1->relids, root->outer_join_rels))
2143 expr1 = (Expr *) remove_nulling_relids((Node *) expr1,
2144 root->outer_join_rels,
2145 NULL);
2146 if (bms_overlap(rel2->relids, root->outer_join_rels))
2147 expr2 = (Expr *) remove_nulling_relids((Node *) expr2,
2148 root->outer_join_rels,
2149 NULL);
2150 }
2151
2152 /*
2153 * Only clauses referencing the partition keys are useful for
2154 * partitionwise join.
2155 */
2156 ipk1 = match_expr_to_partition_keys(expr1, rel1, strict_op);
2157 if (ipk1 < 0)
2158 continue;
2159 ipk2 = match_expr_to_partition_keys(expr2, rel2, strict_op);
2160 if (ipk2 < 0)
2161 continue;
2162
2163 /*
2164 * If the clause refers to keys at different ordinal positions, it can
2165 * not be used for partitionwise join.
2166 */
2167 if (ipk1 != ipk2)
2168 continue;
2169
2170 /* Ignore clause if we already proved these keys equal. */
2171 if (pk_known_equal[ipk1])
2172 continue;
2173
2174 /* Reject if the partition key collation differs from the clause's. */
2175 if (rel1->part_scheme->partcollation[ipk1] != opexpr->inputcollid)
2176 return false;
2177
2178 /*
2179 * The clause allows partitionwise join only if it uses the same
2180 * operator family as that specified by the partition key.
2181 */
2182 if (part_scheme->strategy == PARTITION_STRATEGY_HASH)
2183 {
2184 if (!OidIsValid(rinfo->hashjoinoperator) ||
2185 !op_in_opfamily(rinfo->hashjoinoperator,
2186 part_scheme->partopfamily[ipk1]))
2187 continue;
2188 }
2189 else if (!list_member_oid(rinfo->mergeopfamilies,
2190 part_scheme->partopfamily[ipk1]))
2191 continue;
2192
2193 /* Mark the partition key as having an equi-join clause. */
2194 pk_known_equal[ipk1] = true;
2195
2196 /* We can stop examining clauses once we prove all keys equal. */
2197 if (++num_equal_pks == part_scheme->partnatts)
2198 return true;
2199 }
2200
2201 /*
2202 * Also check to see if any keys are known equal by equivclass.c. In most
2203 * cases there would have been a join restriction clause generated from
2204 * any EC that had such knowledge, but there might be no such clause, or
2205 * it might happen to constrain other members of the ECs than the ones we
2206 * are looking for.
2207 */
2208 for (int ipk = 0; ipk < part_scheme->partnatts; ipk++)
2209 {
2210 Oid btree_opfamily;
2211
2212 /* Ignore if we already proved these keys equal. */
2213 if (pk_known_equal[ipk])
2214 continue;
2215
2216 /*
2217 * We need a btree opfamily to ask equivclass.c about. If the
2218 * partopfamily is a hash opfamily, look up its equality operator, and
2219 * select some btree opfamily that that operator is part of. (Any
2220 * such opfamily should be good enough, since equivclass.c will track
2221 * multiple opfamilies as appropriate.)
2222 */
2223 if (part_scheme->strategy == PARTITION_STRATEGY_HASH)
2224 {
2225 Oid eq_op;
2226 List *eq_opfamilies;
2227
2228 eq_op = get_opfamily_member(part_scheme->partopfamily[ipk],
2229 part_scheme->partopcintype[ipk],
2230 part_scheme->partopcintype[ipk],
2232 if (!OidIsValid(eq_op))
2233 break; /* we're not going to succeed */
2234 eq_opfamilies = get_mergejoin_opfamilies(eq_op);
2235 if (eq_opfamilies == NIL)
2236 break; /* we're not going to succeed */
2237 btree_opfamily = linitial_oid(eq_opfamilies);
2238 }
2239 else
2240 btree_opfamily = part_scheme->partopfamily[ipk];
2241
2242 /*
2243 * We consider only non-nullable partition keys here; nullable ones
2244 * would not be treated as part of the same equivalence classes as
2245 * non-nullable ones.
2246 */
2247 foreach(lc, rel1->partexprs[ipk])
2248 {
2249 Node *expr1 = (Node *) lfirst(lc);
2250 ListCell *lc2;
2251 Oid partcoll1 = rel1->part_scheme->partcollation[ipk];
2252 Oid exprcoll1 = exprCollation(expr1);
2253
2254 foreach(lc2, rel2->partexprs[ipk])
2255 {
2256 Node *expr2 = (Node *) lfirst(lc2);
2257
2258 if (exprs_known_equal(root, expr1, expr2, btree_opfamily))
2259 {
2260 /*
2261 * Ensure that the collation of the expression matches
2262 * that of the partition key. Checking just one collation
2263 * (partcoll1 and exprcoll1) suffices because partcoll1
2264 * and partcoll2, as well as exprcoll1 and exprcoll2,
2265 * should be identical. This holds because both rel1 and
2266 * rel2 use the same PartitionScheme and expr1 and expr2
2267 * are equal.
2268 */
2269 if (partcoll1 == exprcoll1)
2270 {
2271 Oid partcoll2 PG_USED_FOR_ASSERTS_ONLY =
2272 rel2->part_scheme->partcollation[ipk];
2273 Oid exprcoll2 PG_USED_FOR_ASSERTS_ONLY =
2274 exprCollation(expr2);
2275
2276 Assert(partcoll2 == exprcoll2);
2277 pk_known_equal[ipk] = true;
2278 break;
2279 }
2280 }
2281 }
2282 if (pk_known_equal[ipk])
2283 break;
2284 }
2285
2286 if (pk_known_equal[ipk])
2287 {
2288 /* We can stop examining keys once we prove all keys equal. */
2289 if (++num_equal_pks == part_scheme->partnatts)
2290 return true;
2291 }
2292 else
2293 break; /* no chance to succeed, give up */
2294 }
2295
2296 return false;
2297}
2298
2299/*
2300 * match_expr_to_partition_keys
2301 *
2302 * Tries to match an expression to one of the nullable or non-nullable
2303 * partition keys of "rel". Returns the matched key's ordinal position,
2304 * or -1 if the expression could not be matched to any of the keys.
2305 *
2306 * strict_op must be true if the expression will be compared with the
2307 * partition key using a strict operator. This allows us to consider
2308 * nullable as well as nonnullable partition keys.
2309 */
2310static int
2312{
2313 int cnt;
2314
2315 /* This function should be called only for partitioned relations. */
2316 Assert(rel->part_scheme);
2317 Assert(rel->partexprs);
2318 Assert(rel->nullable_partexprs);
2319
2320 /* Remove any relabel decorations. */
2321 while (IsA(expr, RelabelType))
2322 expr = (Expr *) (castNode(RelabelType, expr))->arg;
2323
2324 for (cnt = 0; cnt < rel->part_scheme->partnatts; cnt++)
2325 {
2326 ListCell *lc;
2327
2328 /* We can always match to the non-nullable partition keys. */
2329 foreach(lc, rel->partexprs[cnt])
2330 {
2331 if (equal(lfirst(lc), expr))
2332 return cnt;
2333 }
2334
2335 if (!strict_op)
2336 continue;
2337
2338 /*
2339 * If it's a strict join operator then a NULL partition key on one
2340 * side will not join to any partition key on the other side, and in
2341 * particular such a row can't join to a row from a different
2342 * partition on the other side. So, it's okay to search the nullable
2343 * partition keys as well.
2344 */
2345 foreach(lc, rel->nullable_partexprs[cnt])
2346 {
2347 if (equal(lfirst(lc), expr))
2348 return cnt;
2349 }
2350 }
2351
2352 return -1;
2353}
2354
2355/*
2356 * set_joinrel_partition_key_exprs
2357 * Initialize partition key expressions for a partitioned joinrel.
2358 */
2359static void
2361 RelOptInfo *outer_rel, RelOptInfo *inner_rel,
2362 JoinType jointype)
2363{
2364 PartitionScheme part_scheme = joinrel->part_scheme;
2365 int partnatts = part_scheme->partnatts;
2366
2367 joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
2368 joinrel->nullable_partexprs =
2369 (List **) palloc0(sizeof(List *) * partnatts);
2370
2371 /*
2372 * The joinrel's partition expressions are the same as those of the input
2373 * rels, but we must properly classify them as nullable or not in the
2374 * joinrel's output. (Also, we add some more partition expressions if
2375 * it's a FULL JOIN.)
2376 */
2377 for (int cnt = 0; cnt < partnatts; cnt++)
2378 {
2379 /* mark these const to enforce that we copy them properly */
2380 const List *outer_expr = outer_rel->partexprs[cnt];
2381 const List *outer_null_expr = outer_rel->nullable_partexprs[cnt];
2382 const List *inner_expr = inner_rel->partexprs[cnt];
2383 const List *inner_null_expr = inner_rel->nullable_partexprs[cnt];
2384 List *partexpr = NIL;
2385 List *nullable_partexpr = NIL;
2386 ListCell *lc;
2387
2388 switch (jointype)
2389 {
2390 /*
2391 * A join relation resulting from an INNER join may be
2392 * regarded as partitioned by either of the inner and outer
2393 * relation keys. For example, A INNER JOIN B ON A.a = B.b
2394 * can be regarded as partitioned on either A.a or B.b. So we
2395 * add both keys to the joinrel's partexpr lists. However,
2396 * anything that was already nullable still has to be treated
2397 * as nullable.
2398 */
2399 case JOIN_INNER:
2400 partexpr = list_concat_copy(outer_expr, inner_expr);
2401 nullable_partexpr = list_concat_copy(outer_null_expr,
2402 inner_null_expr);
2403 break;
2404
2405 /*
2406 * A join relation resulting from a SEMI or ANTI join may be
2407 * regarded as partitioned by the outer relation keys. The
2408 * inner relation's keys are no longer interesting; since they
2409 * aren't visible in the join output, nothing could join to
2410 * them.
2411 */
2412 case JOIN_SEMI:
2413 case JOIN_ANTI:
2414 partexpr = list_copy(outer_expr);
2415 nullable_partexpr = list_copy(outer_null_expr);
2416 break;
2417
2418 /*
2419 * A join relation resulting from a LEFT OUTER JOIN likewise
2420 * may be regarded as partitioned on the (non-nullable) outer
2421 * relation keys. The inner (nullable) relation keys are okay
2422 * as partition keys for further joins as long as they involve
2423 * strict join operators.
2424 */
2425 case JOIN_LEFT:
2426 partexpr = list_copy(outer_expr);
2427 nullable_partexpr = list_concat_copy(inner_expr,
2428 outer_null_expr);
2429 nullable_partexpr = list_concat(nullable_partexpr,
2430 inner_null_expr);
2431 break;
2432
2433 /*
2434 * For FULL OUTER JOINs, both relations are nullable, so the
2435 * resulting join relation may be regarded as partitioned on
2436 * either of inner and outer relation keys, but only for joins
2437 * that involve strict join operators.
2438 */
2439 case JOIN_FULL:
2440 nullable_partexpr = list_concat_copy(outer_expr,
2441 inner_expr);
2442 nullable_partexpr = list_concat(nullable_partexpr,
2443 outer_null_expr);
2444 nullable_partexpr = list_concat(nullable_partexpr,
2445 inner_null_expr);
2446
2447 /*
2448 * Also add CoalesceExprs corresponding to each possible
2449 * full-join output variable (that is, left side coalesced to
2450 * right side), so that we can match equijoin expressions
2451 * using those variables. We really only need these for
2452 * columns merged by JOIN USING, and only with the pairs of
2453 * input items that correspond to the data structures that
2454 * parse analysis would build for such variables. But it's
2455 * hard to tell which those are, so just make all the pairs.
2456 * Extra items in the nullable_partexprs list won't cause big
2457 * problems. (It's possible that such items will get matched
2458 * to user-written COALESCEs, but it should still be valid to
2459 * partition on those, since they're going to be either the
2460 * partition column or NULL; it's the same argument as for
2461 * partitionwise nesting of any outer join.) We assume no
2462 * type coercions are needed to make the coalesce expressions,
2463 * since columns of different types won't have gotten
2464 * classified as the same PartitionScheme. Note that we
2465 * intentionally leave out the varnullingrels decoration that
2466 * would ordinarily appear on the Vars inside these
2467 * CoalesceExprs, because have_partkey_equi_join will strip
2468 * varnullingrels from the expressions it will compare to the
2469 * partexprs.
2470 */
2471 foreach(lc, list_concat_copy(outer_expr, outer_null_expr))
2472 {
2473 Node *larg = (Node *) lfirst(lc);
2474 ListCell *lc2;
2475
2476 foreach(lc2, list_concat_copy(inner_expr, inner_null_expr))
2477 {
2478 Node *rarg = (Node *) lfirst(lc2);
2480
2481 c->coalescetype = exprType(larg);
2482 c->coalescecollid = exprCollation(larg);
2483 c->args = list_make2(larg, rarg);
2484 c->location = -1;
2485 nullable_partexpr = lappend(nullable_partexpr, c);
2486 }
2487 }
2488 break;
2489
2490 default:
2491 elog(ERROR, "unrecognized join type: %d", (int) jointype);
2492 }
2493
2494 joinrel->partexprs[cnt] = partexpr;
2495 joinrel->nullable_partexprs[cnt] = nullable_partexpr;
2496 }
2497}
2498
2499/*
2500 * build_child_join_reltarget
2501 * Set up a child-join relation's reltarget from a parent-join relation.
2502 */
2503static void
2505 RelOptInfo *parentrel,
2506 RelOptInfo *childrel,
2507 int nappinfos,
2508 AppendRelInfo **appinfos)
2509{
2510 /* Build the targetlist */
2511 childrel->reltarget->exprs = (List *)
2513 (Node *) parentrel->reltarget->exprs,
2514 nappinfos, appinfos);
2515
2516 /* Set the cost and width fields */
2517 childrel->reltarget->cost.startup = parentrel->reltarget->cost.startup;
2518 childrel->reltarget->cost.per_tuple = parentrel->reltarget->cost.per_tuple;
2519 childrel->reltarget->width = parentrel->reltarget->width;
2520}
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:200
Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:574
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:216
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:1109
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:292
uint32 bitmap_hash(const void *key, Size keysize)
Definition: bitmapset.c:1432
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:142
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:1161
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:751
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:917
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:251
int bitmap_match(const void *key1, const void *key2, Size keysize)
Definition: bitmapset.c:1442
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
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:122
#define bms_is_empty(a)
Definition: bitmapset.h:118
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:204
#define Assert(condition)
Definition: c.h:815
int64_t int64
Definition: c.h:485
int32_t int32
Definition: c.h:484
uint32_t uint32
Definition: c.h:488
unsigned int Index
Definition: c.h:571
#define OidIsValid(objectId)
Definition: c.h:732
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:752
double get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, List *param_clauses)
Definition: costsize.c:5355
double get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, List *restrict_clauses)
Definition: costsize.c:5436
void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: costsize.c:5404
bool enable_partitionwise_join
Definition: costsize.c:159
int32 clamp_width_est(int64 tuple_width)
Definition: costsize.c:242
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2, Oid opfamily)
Definition: equivclass.c:2498
List * generate_join_implied_equalities_for_ecs(PlannerInfo *root, List *eclasses, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
Definition: equivclass.c:1485
void add_child_join_rel_equivalences(PlannerInfo *root, int nappinfos, AppendRelInfo **appinfos, RelOptInfo *parent_joinrel, RelOptInfo *child_joinrel)
Definition: equivclass.c:2812
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
Definition: equivclass.c:1385
bool has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1)
Definition: equivclass.c:3222
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_COMPARE
Definition: hsearch.h:99
#define HASH_FUNCTION
Definition: hsearch.h:98
bool apply_child_basequals(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, RangeTblEntry *childRTE, AppendRelInfo *appinfo)
Definition: inherit.c:843
void mark_dummy_rel(RelOptInfo *rel)
Definition: joinrels.c:1384
List * lappend(List *list, void *datum)
Definition: list.c:339
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:598
List * list_copy(const List *oldlist)
Definition: list.c:1573
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
List * list_append_unique_ptr(List *list, void *datum)
Definition: list.c:1356
bool op_strict(Oid opno)
Definition: lsyscache.c:1477
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:166
List * get_mergejoin_opfamilies(Oid opno)
Definition: lsyscache.c:366
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition: lsyscache.c:66
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:308
void * palloc0(Size size)
Definition: mcxt.c:1347
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
Oid GetUserId(void)
Definition: miscinit.c:517
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:821
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:224
#define nodeTag(nodeptr)
Definition: nodes.h:133
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:338
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
JoinType
Definition: nodes.h:288
@ JOIN_SEMI
Definition: nodes.h:307
@ JOIN_FULL
Definition: nodes.h:295
@ JOIN_INNER
Definition: nodes.h:293
@ JOIN_LEFT
Definition: nodes.h:294
@ JOIN_ANTI
Definition: nodes.h:308
#define repalloc0_array(pointer, type, oldcount, count)
Definition: palloc.h:109
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ PARTITION_STRATEGY_HASH
Definition: parsenodes.h:885
@ RTE_JOIN
Definition: parsenodes.h:1028
@ RTE_CTE
Definition: parsenodes.h:1032
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1033
@ RTE_VALUES
Definition: parsenodes.h:1031
@ RTE_SUBQUERY
Definition: parsenodes.h:1027
@ RTE_RESULT
Definition: parsenodes.h:1034
@ RTE_FUNCTION
Definition: parsenodes.h:1029
@ RTE_TABLEFUNC
Definition: parsenodes.h:1030
@ RTE_RELATION
Definition: parsenodes.h:1026
bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel)
Definition: pathkeys.c:2315
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
Definition: pathnodes.h:2732
#define IS_PARTITIONED_REL(rel)
Definition: pathnodes.h:1062
#define PATH_REQ_OUTER(path)
Definition: pathnodes.h:1681
Bitmapset * Relids
Definition: pathnodes.h:30
UpperRelationKind
Definition: pathnodes.h:70
@ RELOPT_BASEREL
Definition: pathnodes.h:827
@ RELOPT_OTHER_MEMBER_REL
Definition: pathnodes.h:829
@ RELOPT_UPPER_REL
Definition: pathnodes.h:831
@ RELOPT_JOINREL
Definition: pathnodes.h:828
@ RELOPT_OTHER_JOINREL
Definition: pathnodes.h:830
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:854
void * arg
#define PARTITION_MAX_KEYS
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
#define linitial_oid(l)
Definition: pg_list.h:180
#define list_make2(x1, x2)
Definition: pg_list.h:214
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
Definition: placeholder.c:83
void add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
Definition: placeholder.c:400
void get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel)
Definition: plancat.c:116
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
char * c
#define ROWID_VAR
Definition: primnodes.h:244
tree ctl root
Definition: radixtree.h:1857
static void build_joinrel_partition_info(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: relnode.c:1991
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:414
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:94
static void set_joinrel_partition_key_exprs(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype)
Definition: relnode.c:2360
ParamPathInfo * get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
Definition: relnode.c:1856
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, bool can_null)
Definition: relnode.c:1100
RelOptInfo * build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel, RelOptInfo *parent_joinrel, List *restrictlist, SpecialJoinInfo *sjinfo, int nappinfos, AppendRelInfo **appinfos)
Definition: relnode.c:882
static bool have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *rel1, RelOptInfo *rel2, JoinType jointype, List *restrictlist)
Definition: relnode.c:2064
RelOptInfo * find_base_rel_noerr(PlannerInfo *root, int relid)
Definition: relnode.c:436
Relids min_join_parameterization(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:1022
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Definition: relnode.c:527
static void build_join_rel_hash(PlannerInfo *root)
Definition: relnode.c:486
ParamPathInfo * get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, Relids required_outer, List **restrict_clauses)
Definition: relnode.c:1659
Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:1509
void expand_planner_arrays(PlannerInfo *root, int add_size)
Definition: relnode.c:163
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
Definition: relnode.c:1545
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1458
RelOptInfo * build_join_rel(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, List **restrictlist_ptr)
Definition: relnode.c:665
static void build_child_join_reltarget(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, int nappinfos, AppendRelInfo **appinfos)
Definition: relnode.c:2504
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:192
static List * build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
Definition: relnode.c:1285
static int match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel, bool strict_op)
Definition: relnode.c:2311
ParamPathInfo * find_param_path_info(RelOptInfo *rel, Relids required_outer)
Definition: relnode.c:1889
static void set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:589
struct JoinHashEntry JoinHashEntry
static void build_joinrel_joinlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:1322
Bitmapset * get_param_path_clause_serials(Path *path)
Definition: relnode.c:1910
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
Definition: relnode.c:627
RelOptInfo * find_base_rel_ignore_join(PlannerInfo *root, int relid)
Definition: relnode.c:454
static List * subbuild_joinrel_joinlist(RelOptInfo *joinrel, List *joininfo_list, List *new_joininfo)
Definition: relnode.c:1406
static List * subbuild_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel, Relids both_input_relids, List *new_restrictlist)
Definition: relnode.c:1340
bool join_clause_is_movable_into(RestrictInfo *rinfo, Relids currentrelids, Relids current_and_outer)
Definition: restrictinfo.c:661
Node * remove_nulling_relids(Node *node, const Bitmapset *removable_relids, const Bitmapset *except_relids)
Size add_size(Size s1, Size s2)
Definition: shmem.c:488
static pg_noinline void Size size
Definition: slab.c:607
#define HTEqualStrategyNumber
Definition: stratnum.h:41
List * subpaths
Definition: pathnodes.h:1944
Index child_relid
Definition: pathnodes.h:2981
Index parent_relid
Definition: pathnodes.h:2980
Size keysize
Definition: hsearch.h:75
HashValueFunc hash
Definition: hsearch.h:78
Size entrysize
Definition: hsearch.h:76
HashCompareFunc match
Definition: hsearch.h:80
MemoryContext hcxt
Definition: hsearch.h:86
Definition: dynahash.c:220
Relids join_relids
Definition: relnode.c:40
RelOptInfo * join_rel
Definition: relnode.c:41
Path * outerjoinpath
Definition: pathnodes.h:2086
Path * innerjoinpath
Definition: pathnodes.h:2087
List * joinrestrictinfo
Definition: pathnodes.h:2089
Definition: pg_list.h:54
Definition: nodes.h:129
Oid opno
Definition: primnodes.h:834
List * args
Definition: primnodes.h:852
Cardinality ppi_rows
Definition: pathnodes.h:1591
List * ppi_clauses
Definition: pathnodes.h:1592
Bitmapset * ppi_serials
Definition: pathnodes.h:1593
Relids ppi_req_outer
Definition: pathnodes.h:1590
List * exprs
Definition: pathnodes.h:1544
QualCost cost
Definition: pathnodes.h:1550
Relids ph_needed
Definition: pathnodes.h:3105
Relids phnullingrels
Definition: pathnodes.h:2802
Cost per_tuple
Definition: pathnodes.h:48
Cost startup
Definition: pathnodes.h:47
JoinType jointype
Definition: parsenodes.h:1160
RTEKind rtekind
Definition: parsenodes.h:1056
List * baserestrictinfo
Definition: pathnodes.h:985
bool consider_param_startup
Definition: pathnodes.h:885
List * subplan_params
Definition: pathnodes.h:954
List * ppilist
Definition: pathnodes.h:899
bool useridiscurrent
Definition: pathnodes.h:968
uint32 amflags
Definition: pathnodes.h:958
List * joininfo
Definition: pathnodes.h:991
Bitmapset * notnullattnums
Definition: pathnodes.h:936
List * partition_qual
Definition: pathnodes.h:1027
Relids relids
Definition: pathnodes.h:871
struct PathTarget * reltarget
Definition: pathnodes.h:893
Index relid
Definition: pathnodes.h:918
List * statlist
Definition: pathnodes.h:946
List * lateral_vars
Definition: pathnodes.h:940
List * unique_for_rels
Definition: pathnodes.h:977
Cardinality tuples
Definition: pathnodes.h:949
bool consider_parallel
Definition: pathnodes.h:887
Relids top_parent_relids
Definition: pathnodes.h:1009
bool partbounds_merged
Definition: pathnodes.h:1025
BlockNumber pages
Definition: pathnodes.h:948
Relids lateral_relids
Definition: pathnodes.h:913
List * cheapest_parameterized_paths
Definition: pathnodes.h:904
List * pathlist
Definition: pathnodes.h:898
RelOptKind reloptkind
Definition: pathnodes.h:865
List * indexlist
Definition: pathnodes.h:944
struct Path * cheapest_unique_path
Definition: pathnodes.h:903
Relids lateral_referencers
Definition: pathnodes.h:942
struct Path * cheapest_startup_path
Definition: pathnodes.h:901
QualCost baserestrictcost
Definition: pathnodes.h:987
struct Path * cheapest_total_path
Definition: pathnodes.h:902
Oid userid
Definition: pathnodes.h:966
List * non_unique_for_rels
Definition: pathnodes.h:979
Bitmapset * eclass_indexes
Definition: pathnodes.h:952
Relids all_partrels
Definition: pathnodes.h:1041
Relids direct_lateral_relids
Definition: pathnodes.h:911
bool has_eclass_joins
Definition: pathnodes.h:993
Oid serverid
Definition: pathnodes.h:964
bool consider_startup
Definition: pathnodes.h:883
Bitmapset * live_parts
Definition: pathnodes.h:1039
int rel_parallel_workers
Definition: pathnodes.h:956
bool consider_partitionwise_join
Definition: pathnodes.h:999
List * partial_pathlist
Definition: pathnodes.h:900
PlannerInfo * subroot
Definition: pathnodes.h:953
AttrNumber max_attr
Definition: pathnodes.h:926
Relids nulling_relids
Definition: pathnodes.h:938
Index baserestrict_min_security
Definition: pathnodes.h:989
double allvisfrac
Definition: pathnodes.h:950
Cardinality rows
Definition: pathnodes.h:877
AttrNumber min_attr
Definition: pathnodes.h:924
RTEKind rtekind
Definition: pathnodes.h:922
Relids required_relids
Definition: pathnodes.h:2606
int rinfo_serial
Definition: pathnodes.h:2647
Relids incompatible_relids
Definition: pathnodes.h:2609
Expr * clause
Definition: pathnodes.h:2575
bool has_clone
Definition: pathnodes.h:2587
Relids commute_above_r
Definition: pathnodes.h:2912
Relids syn_lefthand
Definition: pathnodes.h:2907
JoinType jointype
Definition: pathnodes.h:2909
Relids syn_righthand
Definition: pathnodes.h:2908
Definition: primnodes.h:261
AttrNumber varattno
Definition: primnodes.h:273
int varno
Definition: primnodes.h:268
Definition: regcomp.c:282
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:681