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 "access/nbtree.h"
21#include "miscadmin.h"
22#include "nodes/nodeFuncs.h"
24#include "optimizer/clauses.h"
25#include "optimizer/cost.h"
26#include "optimizer/inherit.h"
27#include "optimizer/optimizer.h"
28#include "optimizer/pathnode.h"
29#include "optimizer/paths.h"
31#include "optimizer/plancat.h"
32#include "optimizer/planner.h"
34#include "optimizer/tlist.h"
35#include "parser/parse_oper.h"
38#include "utils/hsearch.h"
39#include "utils/lsyscache.h"
40#include "utils/selfuncs.h"
41#include "utils/typcache.h"
42
43
44typedef struct JoinHashEntry
45{
46 Relids join_relids; /* hash key --- MUST BE FIRST */
49
50static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
51 RelOptInfo *input_rel,
52 SpecialJoinInfo *sjinfo,
53 List *pushed_down_joins,
54 bool can_null);
56 RelOptInfo *joinrel,
57 RelOptInfo *outer_rel,
58 RelOptInfo *inner_rel,
59 SpecialJoinInfo *sjinfo);
60static void build_joinrel_joinlist(RelOptInfo *joinrel,
61 RelOptInfo *outer_rel,
62 RelOptInfo *inner_rel);
64 RelOptInfo *joinrel,
65 RelOptInfo *input_rel,
66 Relids both_input_relids,
67 List *new_restrictlist);
69 List *joininfo_list,
70 List *new_joininfo);
71static void set_foreign_rel_properties(RelOptInfo *joinrel,
72 RelOptInfo *outer_rel, RelOptInfo *inner_rel);
73static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel);
75 RelOptInfo *joinrel,
76 RelOptInfo *outer_rel, RelOptInfo *inner_rel,
77 SpecialJoinInfo *sjinfo,
78 List *restrictlist);
80 RelOptInfo *rel1, RelOptInfo *rel2,
81 JoinType jointype, List *restrictlist);
82static int match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel,
83 bool strict_op);
85 RelOptInfo *outer_rel, RelOptInfo *inner_rel,
86 JoinType jointype);
88 RelOptInfo *parentrel,
89 RelOptInfo *childrel,
90 int nappinfos,
91 AppendRelInfo **appinfos);
93 RelOptInfo *rel);
95 PathTarget *target, PathTarget *agg_input,
96 List **group_clauses, List **group_exprs);
97static bool is_var_in_aggref_only(PlannerInfo *root, Var *var);
98static bool is_var_needed_by_join(PlannerInfo *root, Var *var, RelOptInfo *rel);
100
101
102/*
103 * setup_simple_rel_arrays
104 * Prepare the arrays we use for quickly accessing base relations
105 * and AppendRelInfos.
106 */
107void
109{
110 int size;
111 Index rti;
112 ListCell *lc;
113
114 /* Arrays are accessed using RT indexes (1..N) */
115 size = list_length(root->parse->rtable) + 1;
116 root->simple_rel_array_size = size;
117
118 /*
119 * simple_rel_array is initialized to all NULLs, since no RelOptInfos
120 * exist yet. It'll be filled by later calls to build_simple_rel().
121 */
122 root->simple_rel_array = (RelOptInfo **)
123 palloc0(size * sizeof(RelOptInfo *));
124
125 /* simple_rte_array is an array equivalent of the rtable list */
126 root->simple_rte_array = (RangeTblEntry **)
127 palloc0(size * sizeof(RangeTblEntry *));
128 rti = 1;
129 foreach(lc, root->parse->rtable)
130 {
131 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
132
133 root->simple_rte_array[rti++] = rte;
134 }
135
136 /* append_rel_array is not needed if there are no AppendRelInfos */
137 if (root->append_rel_list == NIL)
138 {
139 root->append_rel_array = NULL;
140 return;
141 }
142
143 root->append_rel_array = (AppendRelInfo **)
144 palloc0(size * sizeof(AppendRelInfo *));
145
146 /*
147 * append_rel_array is filled with any already-existing AppendRelInfos,
148 * which currently could only come from UNION ALL flattening. We might
149 * add more later during inheritance expansion, but it's the
150 * responsibility of the expansion code to update the array properly.
151 */
152 foreach(lc, root->append_rel_list)
153 {
155 int child_relid = appinfo->child_relid;
156
157 /* Sanity check */
158 Assert(child_relid < size);
159
160 if (root->append_rel_array[child_relid])
161 elog(ERROR, "child relation already exists");
162
163 root->append_rel_array[child_relid] = appinfo;
164 }
165}
166
167/*
168 * expand_planner_arrays
169 * Expand the PlannerInfo's per-RTE arrays by add_size members
170 * and initialize the newly added entries to NULLs
171 *
172 * Note: this causes the append_rel_array to become allocated even if
173 * it was not before. This is okay for current uses, because we only call
174 * this when adding child relations, which always have AppendRelInfos.
175 */
176void
178{
179 int new_size;
180
181 Assert(add_size > 0);
182
183 new_size = root->simple_rel_array_size + add_size;
184
185 root->simple_rel_array =
186 repalloc0_array(root->simple_rel_array, RelOptInfo *, root->simple_rel_array_size, new_size);
187
188 root->simple_rte_array =
189 repalloc0_array(root->simple_rte_array, RangeTblEntry *, root->simple_rel_array_size, new_size);
190
191 if (root->append_rel_array)
192 root->append_rel_array =
193 repalloc0_array(root->append_rel_array, AppendRelInfo *, root->simple_rel_array_size, new_size);
194 else
195 root->append_rel_array =
196 palloc0_array(AppendRelInfo *, new_size);
197
198 root->simple_rel_array_size = new_size;
199}
200
201/*
202 * build_simple_rel
203 * Construct a new RelOptInfo for a base relation or 'other' relation.
204 */
207{
208 RelOptInfo *rel;
209 RangeTblEntry *rte;
210
211 /* Rel should not exist already */
212 Assert(relid > 0 && relid < root->simple_rel_array_size);
213 if (root->simple_rel_array[relid] != NULL)
214 elog(ERROR, "rel %d already exists", relid);
215
216 /* Fetch RTE for relation */
217 rte = root->simple_rte_array[relid];
218 Assert(rte != NULL);
219
220 rel = makeNode(RelOptInfo);
222 rel->relids = bms_make_singleton(relid);
223 rel->rows = 0;
224 /* cheap startup cost is interesting iff not all tuples to be retrieved */
225 rel->consider_startup = (root->tuple_fraction > 0);
226 rel->consider_param_startup = false; /* might get changed later */
227 rel->consider_parallel = false; /* might get changed later */
229 rel->pathlist = NIL;
230 rel->ppilist = NIL;
231 rel->partial_pathlist = NIL;
232 rel->cheapest_startup_path = NULL;
233 rel->cheapest_total_path = NULL;
235 rel->relid = relid;
236 rel->rtekind = rte->rtekind;
237 /* min_attr, max_attr, attr_needed, attr_widths are set below */
238 rel->notnullattnums = NULL;
239 rel->lateral_vars = NIL;
240 rel->indexlist = NIL;
241 rel->statlist = NIL;
242 rel->pages = 0;
243 rel->tuples = 0;
244 rel->allvisfrac = 0;
245 rel->eclass_indexes = NULL;
246 rel->subroot = NULL;
247 rel->subplan_params = NIL;
248 rel->rel_parallel_workers = -1; /* set up in get_relation_info */
249 rel->amflags = 0;
250 rel->serverid = InvalidOid;
251 if (rte->rtekind == RTE_RELATION)
252 {
253 Assert(parent == NULL ||
254 parent->rtekind == RTE_RELATION ||
255 parent->rtekind == RTE_SUBQUERY);
256
257 /*
258 * For any RELATION rte, we need a userid with which to check
259 * permission access. Baserels simply use their own
260 * RTEPermissionInfo's checkAsUser.
261 *
262 * For otherrels normally there's no RTEPermissionInfo, so we use the
263 * parent's, which normally has one. The exceptional case is that the
264 * parent is a subquery, in which case the otherrel will have its own.
265 */
266 if (rel->reloptkind == RELOPT_BASEREL ||
268 parent->rtekind == RTE_SUBQUERY))
269 {
270 RTEPermissionInfo *perminfo;
271
272 perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
273 rel->userid = perminfo->checkAsUser;
274 }
275 else
276 rel->userid = parent->userid;
277 }
278 else
279 rel->userid = InvalidOid;
280 rel->useridiscurrent = false;
281 rel->fdwroutine = NULL;
282 rel->fdw_private = NULL;
283 rel->unique_for_rels = NIL;
285 rel->unique_rel = NULL;
286 rel->unique_pathkeys = NIL;
287 rel->unique_groupclause = NIL;
288 rel->baserestrictinfo = NIL;
289 rel->baserestrictcost.startup = 0;
291 rel->baserestrict_min_security = UINT_MAX;
292 rel->joininfo = NIL;
293 rel->has_eclass_joins = false;
294 rel->consider_partitionwise_join = false; /* might get changed later */
295 rel->agg_info = NULL;
296 rel->grouped_rel = NULL;
297 rel->part_scheme = NULL;
298 rel->nparts = -1;
299 rel->boundinfo = NULL;
300 rel->partbounds_merged = false;
301 rel->partition_qual = NIL;
302 rel->part_rels = NULL;
303 rel->live_parts = NULL;
304 rel->all_partrels = NULL;
305 rel->partexprs = NULL;
306 rel->nullable_partexprs = NULL;
307
308 /*
309 * Pass assorted information down the inheritance hierarchy.
310 */
311 if (parent)
312 {
313 /* We keep back-links to immediate parent and topmost parent. */
314 rel->parent = parent;
315 rel->top_parent = parent->top_parent ? parent->top_parent : parent;
316 rel->top_parent_relids = rel->top_parent->relids;
317
318 /*
319 * A child rel is below the same outer joins as its parent. (We
320 * presume this info was already calculated for the parent.)
321 */
322 rel->nulling_relids = parent->nulling_relids;
323
324 /*
325 * Also propagate lateral-reference information from appendrel parent
326 * rels to their child rels. We intentionally give each child rel the
327 * same minimum parameterization, even though it's quite possible that
328 * some don't reference all the lateral rels. This is because any
329 * append path for the parent will have to have the same
330 * parameterization for every child anyway, and there's no value in
331 * forcing extra reparameterize_path() calls. Similarly, a lateral
332 * reference to the parent prevents use of otherwise-movable join rels
333 * for each child.
334 *
335 * It's possible for child rels to have their own children, in which
336 * case the topmost parent's lateral info propagates all the way down.
337 */
339 rel->lateral_relids = parent->lateral_relids;
341 }
342 else
343 {
344 rel->parent = NULL;
345 rel->top_parent = NULL;
346 rel->top_parent_relids = NULL;
347 rel->nulling_relids = NULL;
348 rel->direct_lateral_relids = NULL;
349 rel->lateral_relids = NULL;
350 rel->lateral_referencers = NULL;
351 }
352
353 /* Check type of rtable entry */
354 switch (rte->rtekind)
355 {
356 case RTE_RELATION:
357 /* Table --- retrieve statistics from the system catalogs */
358 get_relation_info(root, rte->relid, rte->inh, rel);
359 break;
360 case RTE_SUBQUERY:
361 case RTE_FUNCTION:
362 case RTE_TABLEFUNC:
363 case RTE_VALUES:
364 case RTE_CTE:
366
367 /*
368 * Subquery, function, tablefunc, values list, CTE, or ENR --- set
369 * up attr range and arrays
370 *
371 * Note: 0 is included in range to support whole-row Vars
372 */
373 rel->min_attr = 0;
374 rel->max_attr = list_length(rte->eref->colnames);
375 rel->attr_needed = (Relids *)
376 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
377 rel->attr_widths = (int32 *)
378 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
379 break;
380 case RTE_RESULT:
381 /* RTE_RESULT has no columns, nor could it have whole-row Var */
382 rel->min_attr = 0;
383 rel->max_attr = -1;
384 rel->attr_needed = NULL;
385 rel->attr_widths = NULL;
386 break;
387 default:
388 elog(ERROR, "unrecognized RTE kind: %d",
389 (int) rte->rtekind);
390 break;
391 }
392
393 /*
394 * We must apply the partially filled in RelOptInfo before calling
395 * apply_child_basequals due to some transformations within that function
396 * which require the RelOptInfo to be available in the simple_rel_array.
397 */
398 root->simple_rel_array[relid] = rel;
399
400 /*
401 * Apply the parent's quals to the child, with appropriate substitution of
402 * variables. If the resulting clause is constant-FALSE or NULL after
403 * applying transformations, apply_child_basequals returns false to
404 * indicate that scanning this relation won't yield any rows. In this
405 * case, we mark the child as dummy right away. (We must do this
406 * immediately so that pruning works correctly when recursing in
407 * expand_partitioned_rtentry.)
408 */
409 if (parent)
410 {
411 AppendRelInfo *appinfo = root->append_rel_array[relid];
412
413 Assert(appinfo != NULL);
414 if (!apply_child_basequals(root, parent, rel, rte, appinfo))
415 {
416 /*
417 * Restriction clause reduced to constant FALSE or NULL. Mark as
418 * dummy so we won't scan this relation.
419 */
420 mark_dummy_rel(rel);
421 }
422 }
423
424 return rel;
425}
426
427/*
428 * build_simple_grouped_rel
429 * Construct a new RelOptInfo representing a grouped version of the input
430 * simple relation.
431 */
434{
435 RelOptInfo *grouped_rel;
436 RelAggInfo *agg_info;
437
438 /*
439 * We should have available aggregate expressions and grouping
440 * expressions, otherwise we cannot reach here.
441 */
442 Assert(root->agg_clause_list != NIL);
443 Assert(root->group_expr_list != NIL);
444
445 /* nothing to do for dummy rel */
446 if (IS_DUMMY_REL(rel))
447 return NULL;
448
449 /*
450 * Prepare the information needed to create grouped paths for this simple
451 * relation.
452 */
453 agg_info = create_rel_agg_info(root, rel, true);
454 if (agg_info == NULL)
455 return NULL;
456
457 /*
458 * If grouped paths for the given simple relation are not considered
459 * useful, skip building the grouped relation.
460 */
461 if (!agg_info->agg_useful)
462 return NULL;
463
464 /* Track the set of relids at which partial aggregation is applied */
465 agg_info->apply_agg_at = bms_copy(rel->relids);
466
467 /* build the grouped relation */
468 grouped_rel = build_grouped_rel(root, rel);
469 grouped_rel->reltarget = agg_info->target;
470 grouped_rel->rows = agg_info->grouped_rows;
471 grouped_rel->agg_info = agg_info;
472
473 rel->grouped_rel = grouped_rel;
474
475 return grouped_rel;
476}
477
478/*
479 * build_grouped_rel
480 * Build a grouped relation by flat copying the input relation and resetting
481 * the necessary fields.
482 */
485{
486 RelOptInfo *grouped_rel;
487
488 grouped_rel = makeNode(RelOptInfo);
489 memcpy(grouped_rel, rel, sizeof(RelOptInfo));
490
491 /*
492 * clear path info
493 */
494 grouped_rel->pathlist = NIL;
495 grouped_rel->ppilist = NIL;
496 grouped_rel->partial_pathlist = NIL;
497 grouped_rel->cheapest_startup_path = NULL;
498 grouped_rel->cheapest_total_path = NULL;
499 grouped_rel->cheapest_parameterized_paths = NIL;
500
501 /*
502 * clear partition info
503 */
504 grouped_rel->part_scheme = NULL;
505 grouped_rel->nparts = -1;
506 grouped_rel->boundinfo = NULL;
507 grouped_rel->partbounds_merged = false;
508 grouped_rel->partition_qual = NIL;
509 grouped_rel->part_rels = NULL;
510 grouped_rel->live_parts = NULL;
511 grouped_rel->all_partrels = NULL;
512 grouped_rel->partexprs = NULL;
513 grouped_rel->nullable_partexprs = NULL;
514 grouped_rel->consider_partitionwise_join = false;
515
516 /*
517 * clear size estimates
518 */
519 grouped_rel->rows = 0;
520
521 return grouped_rel;
522}
523
524/*
525 * find_base_rel
526 * Find a base or otherrel relation entry, which must already exist.
527 */
530{
531 RelOptInfo *rel;
532
533 /* use an unsigned comparison to prevent negative array element access */
534 if ((uint32) relid < (uint32) root->simple_rel_array_size)
535 {
536 rel = root->simple_rel_array[relid];
537 if (rel)
538 return rel;
539 }
540
541 elog(ERROR, "no relation entry for relid %d", relid);
542
543 return NULL; /* keep compiler quiet */
544}
545
546/*
547 * find_base_rel_noerr
548 * Find a base or otherrel relation entry, returning NULL if there's none
549 */
552{
553 /* use an unsigned comparison to prevent negative array element access */
554 if ((uint32) relid < (uint32) root->simple_rel_array_size)
555 return root->simple_rel_array[relid];
556 return NULL;
557}
558
559/*
560 * find_base_rel_ignore_join
561 * Find a base or otherrel relation entry, which must already exist.
562 *
563 * Unlike find_base_rel, if relid references an outer join then this
564 * will return NULL rather than raising an error. This is convenient
565 * for callers that must deal with relid sets including both base and
566 * outer joins.
567 */
570{
571 /* use an unsigned comparison to prevent negative array element access */
572 if ((uint32) relid < (uint32) root->simple_rel_array_size)
573 {
574 RelOptInfo *rel;
575 RangeTblEntry *rte;
576
577 rel = root->simple_rel_array[relid];
578 if (rel)
579 return rel;
580
581 /*
582 * We could just return NULL here, but for debugging purposes it seems
583 * best to actually verify that the relid is an outer join and not
584 * something weird.
585 */
586 rte = root->simple_rte_array[relid];
587 if (rte && rte->rtekind == RTE_JOIN && rte->jointype != JOIN_INNER)
588 return NULL;
589 }
590
591 elog(ERROR, "no relation entry for relid %d", relid);
592
593 return NULL; /* keep compiler quiet */
594}
595
596/*
597 * build_join_rel_hash
598 * Construct the auxiliary hash table for join relations.
599 */
600static void
602{
603 HTAB *hashtab;
604 HASHCTL hash_ctl;
605 ListCell *l;
606
607 /* Create the hash table */
608 hash_ctl.keysize = sizeof(Relids);
609 hash_ctl.entrysize = sizeof(JoinHashEntry);
610 hash_ctl.hash = bitmap_hash;
611 hash_ctl.match = bitmap_match;
612 hash_ctl.hcxt = CurrentMemoryContext;
613 hashtab = hash_create("JoinRelHashTable",
614 256L,
615 &hash_ctl,
617
618 /* Insert all the already-existing joinrels */
619 foreach(l, root->join_rel_list)
620 {
621 RelOptInfo *rel = (RelOptInfo *) lfirst(l);
622 JoinHashEntry *hentry;
623 bool found;
624
625 hentry = (JoinHashEntry *) hash_search(hashtab,
626 &(rel->relids),
628 &found);
629 Assert(!found);
630 hentry->join_rel = rel;
631 }
632
633 root->join_rel_hash = hashtab;
634}
635
636/*
637 * find_join_rel
638 * Returns relation entry corresponding to 'relids' (a set of RT indexes),
639 * or NULL if none exists. This is for join relations.
640 */
643{
644 /*
645 * Switch to using hash lookup when list grows "too long". The threshold
646 * is arbitrary and is known only here.
647 */
648 if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)
650
651 /*
652 * Use either hashtable lookup or linear search, as appropriate.
653 *
654 * Note: the seemingly redundant hashkey variable is used to avoid taking
655 * the address of relids; unless the compiler is exceedingly smart, doing
656 * so would force relids out of a register and thus probably slow down the
657 * list-search case.
658 */
659 if (root->join_rel_hash)
660 {
661 Relids hashkey = relids;
662 JoinHashEntry *hentry;
663
664 hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
665 &hashkey,
666 HASH_FIND,
667 NULL);
668 if (hentry)
669 return hentry->join_rel;
670 }
671 else
672 {
673 ListCell *l;
674
675 foreach(l, root->join_rel_list)
676 {
677 RelOptInfo *rel = (RelOptInfo *) lfirst(l);
678
679 if (bms_equal(rel->relids, relids))
680 return rel;
681 }
682 }
683
684 return NULL;
685}
686
687/*
688 * set_foreign_rel_properties
689 * Set up foreign-join fields if outer and inner relation are foreign
690 * tables (or joins) belonging to the same server and assigned to the same
691 * user to check access permissions as.
692 *
693 * In addition to an exact match of userid, we allow the case where one side
694 * has zero userid (implying current user) and the other side has explicit
695 * userid that happens to equal the current user; but in that case, pushdown of
696 * the join is only valid for the current user. The useridiscurrent field
697 * records whether we had to make such an assumption for this join or any
698 * sub-join.
699 *
700 * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
701 * called for the join relation.
702 */
703static void
705 RelOptInfo *inner_rel)
706{
707 if (OidIsValid(outer_rel->serverid) &&
708 inner_rel->serverid == outer_rel->serverid)
709 {
710 if (inner_rel->userid == outer_rel->userid)
711 {
712 joinrel->serverid = outer_rel->serverid;
713 joinrel->userid = outer_rel->userid;
714 joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
715 joinrel->fdwroutine = outer_rel->fdwroutine;
716 }
717 else if (!OidIsValid(inner_rel->userid) &&
718 outer_rel->userid == GetUserId())
719 {
720 joinrel->serverid = outer_rel->serverid;
721 joinrel->userid = outer_rel->userid;
722 joinrel->useridiscurrent = true;
723 joinrel->fdwroutine = outer_rel->fdwroutine;
724 }
725 else if (!OidIsValid(outer_rel->userid) &&
726 inner_rel->userid == GetUserId())
727 {
728 joinrel->serverid = outer_rel->serverid;
729 joinrel->userid = inner_rel->userid;
730 joinrel->useridiscurrent = true;
731 joinrel->fdwroutine = outer_rel->fdwroutine;
732 }
733 }
734}
735
736/*
737 * add_join_rel
738 * Add given join relation to the list of join relations in the given
739 * PlannerInfo. Also add it to the auxiliary hashtable if there is one.
740 */
741static void
743{
744 /* GEQO requires us to append the new joinrel to the end of the list! */
745 root->join_rel_list = lappend(root->join_rel_list, joinrel);
746
747 /* store it into the auxiliary hashtable if there is one. */
748 if (root->join_rel_hash)
749 {
750 JoinHashEntry *hentry;
751 bool found;
752
753 hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
754 &(joinrel->relids),
756 &found);
757 Assert(!found);
758 hentry->join_rel = joinrel;
759 }
760}
761
762/*
763 * build_join_rel
764 * Returns relation entry corresponding to the union of two given rels,
765 * creating a new relation entry if none already exists.
766 *
767 * 'joinrelids' is the Relids set that uniquely identifies the join
768 * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
769 * joined
770 * 'sjinfo': join context info
771 * 'pushed_down_joins': any pushed-down outer joins that are now completed
772 * 'restrictlist_ptr': result variable. If not NULL, *restrictlist_ptr
773 * receives the list of RestrictInfo nodes that apply to this
774 * particular pair of joinable relations.
775 *
776 * restrictlist_ptr makes the routine's API a little grotty, but it saves
777 * duplicated calculation of the restrictlist...
778 */
781 Relids joinrelids,
782 RelOptInfo *outer_rel,
783 RelOptInfo *inner_rel,
784 SpecialJoinInfo *sjinfo,
785 List *pushed_down_joins,
786 List **restrictlist_ptr)
787{
788 RelOptInfo *joinrel;
789 List *restrictlist;
790
791 /* This function should be used only for join between parents. */
792 Assert(!IS_OTHER_REL(outer_rel) && !IS_OTHER_REL(inner_rel));
793
794 /*
795 * See if we already have a joinrel for this set of base rels.
796 */
797 joinrel = find_join_rel(root, joinrelids);
798
799 if (joinrel)
800 {
801 /*
802 * Yes, so we only need to figure the restrictlist for this particular
803 * pair of component relations.
804 */
805 if (restrictlist_ptr)
806 *restrictlist_ptr = build_joinrel_restrictlist(root,
807 joinrel,
808 outer_rel,
809 inner_rel,
810 sjinfo);
811 return joinrel;
812 }
813
814 /*
815 * Nope, so make one.
816 */
817 joinrel = makeNode(RelOptInfo);
818 joinrel->reloptkind = RELOPT_JOINREL;
819 joinrel->relids = bms_copy(joinrelids);
820 joinrel->rows = 0;
821 /* cheap startup cost is interesting iff not all tuples to be retrieved */
822 joinrel->consider_startup = (root->tuple_fraction > 0);
823 joinrel->consider_param_startup = false;
824 joinrel->consider_parallel = false;
826 joinrel->pathlist = NIL;
827 joinrel->ppilist = NIL;
828 joinrel->partial_pathlist = NIL;
829 joinrel->cheapest_startup_path = NULL;
830 joinrel->cheapest_total_path = NULL;
832 /* init direct_lateral_relids from children; we'll finish it up below */
833 joinrel->direct_lateral_relids =
835 inner_rel->direct_lateral_relids);
837 outer_rel, inner_rel);
838 joinrel->relid = 0; /* indicates not a baserel */
839 joinrel->rtekind = RTE_JOIN;
840 joinrel->min_attr = 0;
841 joinrel->max_attr = 0;
842 joinrel->attr_needed = NULL;
843 joinrel->attr_widths = NULL;
844 joinrel->notnullattnums = NULL;
845 joinrel->nulling_relids = NULL;
846 joinrel->lateral_vars = NIL;
847 joinrel->lateral_referencers = NULL;
848 joinrel->indexlist = NIL;
849 joinrel->statlist = NIL;
850 joinrel->pages = 0;
851 joinrel->tuples = 0;
852 joinrel->allvisfrac = 0;
853 joinrel->eclass_indexes = NULL;
854 joinrel->subroot = NULL;
855 joinrel->subplan_params = NIL;
856 joinrel->rel_parallel_workers = -1;
857 joinrel->amflags = 0;
858 joinrel->serverid = InvalidOid;
859 joinrel->userid = InvalidOid;
860 joinrel->useridiscurrent = false;
861 joinrel->fdwroutine = NULL;
862 joinrel->fdw_private = NULL;
863 joinrel->unique_for_rels = NIL;
864 joinrel->non_unique_for_rels = NIL;
865 joinrel->unique_rel = NULL;
866 joinrel->unique_pathkeys = NIL;
867 joinrel->unique_groupclause = NIL;
868 joinrel->baserestrictinfo = NIL;
869 joinrel->baserestrictcost.startup = 0;
870 joinrel->baserestrictcost.per_tuple = 0;
871 joinrel->baserestrict_min_security = UINT_MAX;
872 joinrel->joininfo = NIL;
873 joinrel->has_eclass_joins = false;
874 joinrel->consider_partitionwise_join = false; /* might get changed later */
875 joinrel->agg_info = NULL;
876 joinrel->grouped_rel = NULL;
877 joinrel->parent = NULL;
878 joinrel->top_parent = NULL;
879 joinrel->top_parent_relids = NULL;
880 joinrel->part_scheme = NULL;
881 joinrel->nparts = -1;
882 joinrel->boundinfo = NULL;
883 joinrel->partbounds_merged = false;
884 joinrel->partition_qual = NIL;
885 joinrel->part_rels = NULL;
886 joinrel->live_parts = NULL;
887 joinrel->all_partrels = NULL;
888 joinrel->partexprs = NULL;
889 joinrel->nullable_partexprs = NULL;
890
891 /* Compute information relevant to the foreign relations. */
892 set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
893
894 /*
895 * Fill the joinrel's tlist with just the Vars and PHVs that need to be
896 * output from this join (ie, are needed for higher joinclauses or final
897 * output).
898 *
899 * NOTE: the tlist order for a join rel will depend on which pair of outer
900 * and inner rels we first try to build it from. But the contents should
901 * be the same regardless.
902 */
903 build_joinrel_tlist(root, joinrel, outer_rel, sjinfo, pushed_down_joins,
904 (sjinfo->jointype == JOIN_FULL));
905 build_joinrel_tlist(root, joinrel, inner_rel, sjinfo, pushed_down_joins,
906 (sjinfo->jointype != JOIN_INNER));
907 add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel, sjinfo);
908
909 /*
910 * add_placeholders_to_joinrel also took care of adding the ph_lateral
911 * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
912 * now we can finish computing that. This is much like the computation of
913 * the transitively-closed lateral_relids in min_join_parameterization,
914 * except that here we *do* have to consider the added PHVs.
915 */
916 joinrel->direct_lateral_relids =
917 bms_del_members(joinrel->direct_lateral_relids, joinrel->relids);
918
919 /*
920 * Construct restrict and join clause lists for the new joinrel. (The
921 * caller might or might not need the restrictlist, but I need it anyway
922 * for set_joinrel_size_estimates().)
923 */
924 restrictlist = build_joinrel_restrictlist(root, joinrel,
925 outer_rel, inner_rel,
926 sjinfo);
927 if (restrictlist_ptr)
928 *restrictlist_ptr = restrictlist;
929 build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
930
931 /*
932 * This is also the right place to check whether the joinrel has any
933 * pending EquivalenceClass joins.
934 */
936
937 /* Store the partition information. */
938 build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
939 restrictlist);
940
941 /*
942 * Set estimates of the joinrel's size.
943 */
944 set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
945 sjinfo, restrictlist);
946
947 /*
948 * Set the consider_parallel flag if this joinrel could potentially be
949 * scanned within a parallel worker. If this flag is false for either
950 * inner_rel or outer_rel, then it must be false for the joinrel also.
951 * Even if both are true, there might be parallel-restricted expressions
952 * in the targetlist or quals.
953 *
954 * Note that if there are more than two rels in this relation, they could
955 * be divided between inner_rel and outer_rel in any arbitrary way. We
956 * assume this doesn't matter, because we should hit all the same baserels
957 * and joinclauses while building up to this joinrel no matter which we
958 * take; therefore, we should make the same decision here however we get
959 * here.
960 */
961 if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
962 is_parallel_safe(root, (Node *) restrictlist) &&
963 is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
964 joinrel->consider_parallel = true;
965
966 /* Add the joinrel to the PlannerInfo. */
967 add_join_rel(root, joinrel);
968
969 /*
970 * Also, if dynamic-programming join search is active, add the new joinrel
971 * to the appropriate sublist. Note: you might think the Assert on number
972 * of members should be for equality, but some of the level 1 rels might
973 * have been joinrels already, so we can only assert <=.
974 */
975 if (root->join_rel_level)
976 {
977 Assert(root->join_cur_level > 0);
978 Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
979 root->join_rel_level[root->join_cur_level] =
980 lappend(root->join_rel_level[root->join_cur_level], joinrel);
981 }
982
983 return joinrel;
984}
985
986/*
987 * build_child_join_rel
988 * Builds RelOptInfo representing join between given two child relations.
989 *
990 * 'outer_rel' and 'inner_rel' are the RelOptInfos of child relations being
991 * joined
992 * 'parent_joinrel' is the RelOptInfo representing the join between parent
993 * relations. Some of the members of new RelOptInfo are produced by
994 * translating corresponding members of this RelOptInfo
995 * 'restrictlist': list of RestrictInfo nodes that apply to this particular
996 * pair of joinable relations
997 * 'sjinfo': child join's join-type details
998 * 'nappinfos' and 'appinfos': AppendRelInfo array for child relids
999 */
1000RelOptInfo *
1002 RelOptInfo *inner_rel, RelOptInfo *parent_joinrel,
1003 List *restrictlist, SpecialJoinInfo *sjinfo,
1004 int nappinfos, AppendRelInfo **appinfos)
1005{
1006 RelOptInfo *joinrel = makeNode(RelOptInfo);
1007
1008 /* Only joins between "other" relations land here. */
1009 Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
1010
1011 /* The parent joinrel should have consider_partitionwise_join set. */
1012 Assert(parent_joinrel->consider_partitionwise_join);
1013
1015 joinrel->relids = adjust_child_relids(parent_joinrel->relids,
1016 nappinfos, appinfos);
1017 joinrel->rows = 0;
1018 /* cheap startup cost is interesting iff not all tuples to be retrieved */
1019 joinrel->consider_startup = (root->tuple_fraction > 0);
1020 joinrel->consider_param_startup = false;
1021 joinrel->consider_parallel = false;
1023 joinrel->pathlist = NIL;
1024 joinrel->ppilist = NIL;
1025 joinrel->partial_pathlist = NIL;
1026 joinrel->cheapest_startup_path = NULL;
1027 joinrel->cheapest_total_path = NULL;
1029 joinrel->direct_lateral_relids = NULL;
1030 joinrel->lateral_relids = NULL;
1031 joinrel->relid = 0; /* indicates not a baserel */
1032 joinrel->rtekind = RTE_JOIN;
1033 joinrel->min_attr = 0;
1034 joinrel->max_attr = 0;
1035 joinrel->attr_needed = NULL;
1036 joinrel->attr_widths = NULL;
1037 joinrel->notnullattnums = NULL;
1038 joinrel->nulling_relids = NULL;
1039 joinrel->lateral_vars = NIL;
1040 joinrel->lateral_referencers = NULL;
1041 joinrel->indexlist = NIL;
1042 joinrel->pages = 0;
1043 joinrel->tuples = 0;
1044 joinrel->allvisfrac = 0;
1045 joinrel->eclass_indexes = NULL;
1046 joinrel->subroot = NULL;
1047 joinrel->subplan_params = NIL;
1048 joinrel->amflags = 0;
1049 joinrel->serverid = InvalidOid;
1050 joinrel->userid = InvalidOid;
1051 joinrel->useridiscurrent = false;
1052 joinrel->fdwroutine = NULL;
1053 joinrel->fdw_private = NULL;
1054 joinrel->unique_rel = NULL;
1055 joinrel->unique_pathkeys = NIL;
1056 joinrel->unique_groupclause = NIL;
1057 joinrel->baserestrictinfo = NIL;
1058 joinrel->baserestrictcost.startup = 0;
1059 joinrel->baserestrictcost.per_tuple = 0;
1060 joinrel->joininfo = NIL;
1061 joinrel->has_eclass_joins = false;
1062 joinrel->consider_partitionwise_join = false; /* might get changed later */
1063 joinrel->agg_info = NULL;
1064 joinrel->grouped_rel = NULL;
1065 joinrel->parent = parent_joinrel;
1066 joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
1067 joinrel->top_parent_relids = joinrel->top_parent->relids;
1068 joinrel->part_scheme = NULL;
1069 joinrel->nparts = -1;
1070 joinrel->boundinfo = NULL;
1071 joinrel->partbounds_merged = false;
1072 joinrel->partition_qual = NIL;
1073 joinrel->part_rels = NULL;
1074 joinrel->live_parts = NULL;
1075 joinrel->all_partrels = NULL;
1076 joinrel->partexprs = NULL;
1077 joinrel->nullable_partexprs = NULL;
1078
1079 /* Compute information relevant to foreign relations. */
1080 set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
1081
1082 /* Set up reltarget struct */
1083 build_child_join_reltarget(root, parent_joinrel, joinrel,
1084 nappinfos, appinfos);
1085
1086 /* Construct joininfo list. */
1088 (Node *) parent_joinrel->joininfo,
1089 nappinfos,
1090 appinfos);
1091
1092 /*
1093 * Lateral relids referred in child join will be same as that referred in
1094 * the parent relation.
1095 */
1096 joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
1097 joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
1098
1099 /*
1100 * If the parent joinrel has pending equivalence classes, so does the
1101 * child.
1102 */
1103 joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
1104
1105 /* Is the join between partitions itself partitioned? */
1106 build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
1107 restrictlist);
1108
1109 /* Child joinrel is parallel safe if parent is parallel safe. */
1110 joinrel->consider_parallel = parent_joinrel->consider_parallel;
1111
1112 /* Set estimates of the child-joinrel's size. */
1113 set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
1114 sjinfo, restrictlist);
1115
1116 /* We build the join only once. */
1117 Assert(!find_join_rel(root, joinrel->relids));
1118
1119 /* Add the relation to the PlannerInfo. */
1120 add_join_rel(root, joinrel);
1121
1122 /*
1123 * We might need EquivalenceClass members corresponding to the child join,
1124 * so that we can represent sort pathkeys for it. As with children of
1125 * baserels, we shouldn't need this unless there are relevant eclass joins
1126 * (implying that a merge join might be possible) or pathkeys to sort by.
1127 */
1128 if (joinrel->has_eclass_joins || has_useful_pathkeys(root, parent_joinrel))
1130 nappinfos, appinfos,
1131 parent_joinrel, joinrel);
1132
1133 return joinrel;
1134}
1135
1136/*
1137 * min_join_parameterization
1138 *
1139 * Determine the minimum possible parameterization of a joinrel, that is, the
1140 * set of other rels it contains LATERAL references to. We save this value in
1141 * the join's RelOptInfo. This function is split out of build_join_rel()
1142 * because join_is_legal() needs the value to check a prospective join.
1143 */
1144Relids
1146 Relids joinrelids,
1147 RelOptInfo *outer_rel,
1148 RelOptInfo *inner_rel)
1149{
1150 Relids result;
1151
1152 /*
1153 * Basically we just need the union of the inputs' lateral_relids, less
1154 * whatever is already in the join.
1155 *
1156 * It's not immediately obvious that this is a valid way to compute the
1157 * result, because it might seem that we're ignoring possible lateral refs
1158 * of PlaceHolderVars that are due to be computed at the join but not in
1159 * either input. However, because create_lateral_join_info() already
1160 * charged all such PHV refs to each member baserel of the join, they'll
1161 * be accounted for already in the inputs' lateral_relids. Likewise, we
1162 * do not need to worry about doing transitive closure here, because that
1163 * was already accounted for in the original baserel lateral_relids.
1164 */
1165 result = bms_union(outer_rel->lateral_relids, inner_rel->lateral_relids);
1166 result = bms_del_members(result, joinrelids);
1167 return result;
1168}
1169
1170/*
1171 * build_joinrel_tlist
1172 * Builds a join relation's target list from an input relation.
1173 * (This is invoked twice to handle the two input relations.)
1174 *
1175 * The join's targetlist includes all Vars of its member relations that
1176 * will still be needed above the join. This subroutine adds all such
1177 * Vars from the specified input rel's tlist to the join rel's tlist.
1178 * Likewise for any PlaceHolderVars emitted by the input rel.
1179 *
1180 * We also compute the expected width of the join's output, making use
1181 * of data that was cached at the baserel level by set_rel_width().
1182 *
1183 * Pass can_null as true if the join is an outer join that can null Vars
1184 * from this input relation. If so, we will (normally) add the join's relid
1185 * to the nulling bitmaps of Vars and PHVs bubbled up from the input.
1186 *
1187 * When forming an outer join's target list, special handling is needed in
1188 * case the outer join was commuted with another one per outer join identity 3
1189 * (see optimizer/README). We must take steps to ensure that the output Vars
1190 * have the same nulling bitmaps that they would if the two joins had been
1191 * done in syntactic order; else they won't match Vars appearing higher in
1192 * the query tree. An exception to the match-the-syntactic-order rule is
1193 * that when an outer join is pushed down into another one's RHS per identity
1194 * 3, we can't mark its Vars as nulled until the now-upper outer join is also
1195 * completed. So we need to do three things:
1196 *
1197 * First, we add the outer join's relid to the nulling bitmap only if the
1198 * outer join has been completely performed and the Var or PHV actually
1199 * comes from within the syntactically nullable side(s) of the outer join.
1200 * This takes care of the possibility that we have transformed
1201 * (A leftjoin B on (Pab)) leftjoin C on (Pbc)
1202 * to
1203 * A leftjoin (B leftjoin C on (Pbc)) on (Pab)
1204 * Here the pushed-down B/C join cannot mark C columns as nulled yet,
1205 * while the now-upper A/B join must not mark C columns as nulled by itself.
1206 *
1207 * Second, perform the same operation for each SpecialJoinInfo listed in
1208 * pushed_down_joins (which, in this example, would be the B/C join when
1209 * we are at the now-upper A/B join). This allows the now-upper join to
1210 * complete the marking of "C" Vars that now have fully valid values.
1211 *
1212 * Third, any relid in sjinfo->commute_above_r that is already part of
1213 * the joinrel is added to the nulling bitmaps of nullable Vars and PHVs.
1214 * This takes care of the reverse case where we implement
1215 * A leftjoin (B leftjoin C on (Pbc)) on (Pab)
1216 * as
1217 * (A leftjoin B on (Pab)) leftjoin C on (Pbc)
1218 * The C columns emitted by the B/C join need to be shown as nulled by both
1219 * the B/C and A/B joins, even though they've not physically traversed the
1220 * A/B join.
1221 */
1222static void
1224 RelOptInfo *input_rel,
1225 SpecialJoinInfo *sjinfo,
1226 List *pushed_down_joins,
1227 bool can_null)
1228{
1229 Relids relids = joinrel->relids;
1230 int64 tuple_width = joinrel->reltarget->width;
1231 ListCell *vars;
1232 ListCell *lc;
1233
1234 foreach(vars, input_rel->reltarget->exprs)
1235 {
1236 Var *var = (Var *) lfirst(vars);
1237
1238 /*
1239 * For a PlaceHolderVar, we have to look up the PlaceHolderInfo.
1240 */
1241 if (IsA(var, PlaceHolderVar))
1242 {
1243 PlaceHolderVar *phv = (PlaceHolderVar *) var;
1245
1246 /* Is it still needed above this joinrel? */
1247 if (bms_nonempty_difference(phinfo->ph_needed, relids))
1248 {
1249 /*
1250 * Yup, add it to the output. If this join potentially nulls
1251 * this input, we have to update the PHV's phnullingrels,
1252 * which means making a copy.
1253 */
1254 if (can_null)
1255 {
1256 phv = copyObject(phv);
1257 /* See comments above to understand this logic */
1258 if (sjinfo->ojrelid != 0 &&
1259 bms_is_member(sjinfo->ojrelid, relids) &&
1260 (bms_is_subset(phv->phrels, sjinfo->syn_righthand) ||
1261 (sjinfo->jointype == JOIN_FULL &&
1262 bms_is_subset(phv->phrels, sjinfo->syn_lefthand))))
1264 sjinfo->ojrelid);
1265 foreach(lc, pushed_down_joins)
1266 {
1267 SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
1268
1269 Assert(bms_is_member(othersj->ojrelid, relids));
1270 if (bms_is_subset(phv->phrels, othersj->syn_righthand))
1272 othersj->ojrelid);
1273 }
1274 phv->phnullingrels =
1277 relids));
1278 }
1279
1280 joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
1281 phv);
1282 /* Bubbling up the precomputed result has cost zero */
1283 tuple_width += phinfo->ph_width;
1284 }
1285 continue;
1286 }
1287
1288 /*
1289 * Otherwise, anything in a baserel or joinrel targetlist ought to be
1290 * a Var. (More general cases can only appear in appendrel child
1291 * rels, which will never be seen here.)
1292 */
1293 if (!IsA(var, Var))
1294 elog(ERROR, "unexpected node type in rel targetlist: %d",
1295 (int) nodeTag(var));
1296
1297 if (var->varno == ROWID_VAR)
1298 {
1299 /* UPDATE/DELETE/MERGE row identity vars are always needed */
1301 list_nth(root->row_identity_vars, var->varattno - 1);
1302
1303 /* Update reltarget width estimate from RowIdentityVarInfo */
1304 tuple_width += ridinfo->rowidwidth;
1305 }
1306 else
1307 {
1308 RelOptInfo *baserel;
1309 int ndx;
1310
1311 /* Get the Var's original base rel */
1312 baserel = find_base_rel(root, var->varno);
1313
1314 /* Is it still needed above this joinrel? */
1315 ndx = var->varattno - baserel->min_attr;
1316 if (!bms_nonempty_difference(baserel->attr_needed[ndx], relids))
1317 continue; /* nope, skip it */
1318
1319 /* Update reltarget width estimate from baserel's attr_widths */
1320 tuple_width += baserel->attr_widths[ndx];
1321 }
1322
1323 /*
1324 * Add the Var to the output. If this join potentially nulls this
1325 * input, we have to update the Var's varnullingrels, which means
1326 * making a copy. But note that we don't ever add nullingrel bits to
1327 * row identity Vars (cf. comments in setrefs.c).
1328 */
1329 if (can_null && var->varno != ROWID_VAR)
1330 {
1331 var = copyObject(var);
1332 /* See comments above to understand this logic */
1333 if (sjinfo->ojrelid != 0 &&
1334 bms_is_member(sjinfo->ojrelid, relids) &&
1335 (bms_is_member(var->varno, sjinfo->syn_righthand) ||
1336 (sjinfo->jointype == JOIN_FULL &&
1337 bms_is_member(var->varno, sjinfo->syn_lefthand))))
1338 var->varnullingrels = bms_add_member(var->varnullingrels,
1339 sjinfo->ojrelid);
1340 foreach(lc, pushed_down_joins)
1341 {
1342 SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
1343
1344 Assert(bms_is_member(othersj->ojrelid, relids));
1345 if (bms_is_member(var->varno, othersj->syn_righthand))
1346 var->varnullingrels = bms_add_member(var->varnullingrels,
1347 othersj->ojrelid);
1348 }
1349 var->varnullingrels =
1350 bms_join(var->varnullingrels,
1352 relids));
1353 }
1354
1355 joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
1356 var);
1357
1358 /* Vars have cost zero, so no need to adjust reltarget->cost */
1359 }
1360
1361 joinrel->reltarget->width = clamp_width_est(tuple_width);
1362}
1363
1364/*
1365 * build_joinrel_restrictlist
1366 * build_joinrel_joinlist
1367 * These routines build lists of restriction and join clauses for a
1368 * join relation from the joininfo lists of the relations it joins.
1369 *
1370 * These routines are separate because the restriction list must be
1371 * built afresh for each pair of input sub-relations we consider, whereas
1372 * the join list need only be computed once for any join RelOptInfo.
1373 * The join list is fully determined by the set of rels making up the
1374 * joinrel, so we should get the same results (up to ordering) from any
1375 * candidate pair of sub-relations. But the restriction list is whatever
1376 * is not handled in the sub-relations, so it depends on which
1377 * sub-relations are considered.
1378 *
1379 * If a join clause from an input relation refers to base+OJ rels still not
1380 * present in the joinrel, then it is still a join clause for the joinrel;
1381 * we put it into the joininfo list for the joinrel. Otherwise,
1382 * the clause is now a restrict clause for the joined relation, and we
1383 * return it to the caller of build_joinrel_restrictlist() to be stored in
1384 * join paths made from this pair of sub-relations. (It will not need to
1385 * be considered further up the join tree.)
1386 *
1387 * In many cases we will find the same RestrictInfos in both input
1388 * relations' joinlists, so be careful to eliminate duplicates.
1389 * Pointer equality should be a sufficient test for dups, since all
1390 * the various joinlist entries ultimately refer to RestrictInfos
1391 * pushed into them by distribute_restrictinfo_to_rels().
1392 *
1393 * 'joinrel' is a join relation node
1394 * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
1395 * to form joinrel.
1396 * 'sjinfo': join context info
1397 *
1398 * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
1399 * whereas build_joinrel_joinlist() stores its results in the joinrel's
1400 * joininfo list. One or the other must accept each given clause!
1401 *
1402 * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
1403 * up to the join relation. I believe this is no longer necessary, because
1404 * RestrictInfo nodes are no longer context-dependent. Instead, just include
1405 * the original nodes in the lists made for the join relation.
1406 */
1407static List *
1409 RelOptInfo *joinrel,
1410 RelOptInfo *outer_rel,
1411 RelOptInfo *inner_rel,
1412 SpecialJoinInfo *sjinfo)
1413{
1414 List *result;
1415 Relids both_input_relids;
1416
1417 both_input_relids = bms_union(outer_rel->relids, inner_rel->relids);
1418
1419 /*
1420 * Collect all the clauses that syntactically belong at this level,
1421 * eliminating any duplicates (important since we will see many of the
1422 * same clauses arriving from both input relations).
1423 */
1424 result = subbuild_joinrel_restrictlist(root, joinrel, outer_rel,
1425 both_input_relids, NIL);
1426 result = subbuild_joinrel_restrictlist(root, joinrel, inner_rel,
1427 both_input_relids, result);
1428
1429 /*
1430 * Add on any clauses derived from EquivalenceClasses. These cannot be
1431 * redundant with the clauses in the joininfo lists, so don't bother
1432 * checking.
1433 */
1434 result = list_concat(result,
1436 joinrel->relids,
1437 outer_rel->relids,
1438 inner_rel,
1439 sjinfo));
1440
1441 return result;
1442}
1443
1444static void
1446 RelOptInfo *outer_rel,
1447 RelOptInfo *inner_rel)
1448{
1449 List *result;
1450
1451 /*
1452 * Collect all the clauses that syntactically belong above this level,
1453 * eliminating any duplicates (important since we will see many of the
1454 * same clauses arriving from both input relations).
1455 */
1456 result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL);
1457 result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result);
1458
1459 joinrel->joininfo = result;
1460}
1461
1462static List *
1464 RelOptInfo *joinrel,
1465 RelOptInfo *input_rel,
1466 Relids both_input_relids,
1467 List *new_restrictlist)
1468{
1469 ListCell *l;
1470
1471 foreach(l, input_rel->joininfo)
1472 {
1473 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1474
1475 if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1476 {
1477 /*
1478 * This clause should become a restriction clause for the joinrel,
1479 * since it refers to no outside rels. However, if it's a clone
1480 * clause then it might be too late to evaluate it, so we have to
1481 * check. (If it is too late, just ignore the clause, taking it
1482 * on faith that another clone was or will be selected.) Clone
1483 * clauses should always be outer-join clauses, so we compare
1484 * against both_input_relids.
1485 */
1486 if (rinfo->has_clone || rinfo->is_clone)
1487 {
1488 Assert(!RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids));
1489 if (!bms_is_subset(rinfo->required_relids, both_input_relids))
1490 continue;
1491 if (bms_overlap(rinfo->incompatible_relids, both_input_relids))
1492 continue;
1493 }
1494 else
1495 {
1496 /*
1497 * For non-clone clauses, we just Assert it's OK. These might
1498 * be either join or filter clauses; if it's a join clause
1499 * then it should not refer to the current join's output.
1500 * (There is little point in checking incompatible_relids,
1501 * because it'll be NULL.)
1502 */
1503 Assert(RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids) ||
1505 both_input_relids));
1506 }
1507
1508 /*
1509 * OK, so add it to the list, being careful to eliminate
1510 * duplicates. (Since RestrictInfo nodes in different joinlists
1511 * will have been multiply-linked rather than copied, pointer
1512 * equality should be a sufficient test.)
1513 */
1514 new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
1515 }
1516 else
1517 {
1518 /*
1519 * This clause is still a join clause at this level, so we ignore
1520 * it in this routine.
1521 */
1522 }
1523 }
1524
1525 return new_restrictlist;
1526}
1527
1528static List *
1530 List *joininfo_list,
1531 List *new_joininfo)
1532{
1533 ListCell *l;
1534
1535 /* Expected to be called only for join between parent relations. */
1536 Assert(joinrel->reloptkind == RELOPT_JOINREL);
1537
1538 foreach(l, joininfo_list)
1539 {
1540 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1541
1542 if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1543 {
1544 /*
1545 * This clause becomes a restriction clause for the joinrel, since
1546 * it refers to no outside rels. So we can ignore it in this
1547 * routine.
1548 */
1549 }
1550 else
1551 {
1552 /*
1553 * This clause is still a join clause at this level, so add it to
1554 * the new joininfo list, being careful to eliminate duplicates.
1555 * (Since RestrictInfo nodes in different joinlists will have been
1556 * multiply-linked rather than copied, pointer equality should be
1557 * a sufficient test.)
1558 */
1559 new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
1560 }
1561 }
1562
1563 return new_joininfo;
1564}
1565
1566
1567/*
1568 * fetch_upper_rel
1569 * Build a RelOptInfo describing some post-scan/join query processing,
1570 * or return a pre-existing one if somebody already built it.
1571 *
1572 * An "upper" relation is identified by an UpperRelationKind and a Relids set.
1573 * The meaning of the Relids set is not specified here, and very likely will
1574 * vary for different relation kinds.
1575 *
1576 * Most of the fields in an upper-level RelOptInfo are not used and are not
1577 * set here (though makeNode should ensure they're zeroes). We basically only
1578 * care about fields that are of interest to add_path() and set_cheapest().
1579 */
1580RelOptInfo *
1582{
1583 RelOptInfo *upperrel;
1584 ListCell *lc;
1585
1586 /*
1587 * For the moment, our indexing data structure is just a List for each
1588 * relation kind. If we ever get so many of one kind that this stops
1589 * working well, we can improve it. No code outside this function should
1590 * assume anything about how to find a particular upperrel.
1591 */
1592
1593 /* If we already made this upperrel for the query, return it */
1594 foreach(lc, root->upper_rels[kind])
1595 {
1596 upperrel = (RelOptInfo *) lfirst(lc);
1597
1598 if (bms_equal(upperrel->relids, relids))
1599 return upperrel;
1600 }
1601
1602 upperrel = makeNode(RelOptInfo);
1603 upperrel->reloptkind = RELOPT_UPPER_REL;
1604 upperrel->relids = bms_copy(relids);
1605
1606 /* cheap startup cost is interesting iff not all tuples to be retrieved */
1607 upperrel->consider_startup = (root->tuple_fraction > 0);
1608 upperrel->consider_param_startup = false;
1609 upperrel->consider_parallel = false; /* might get changed later */
1610 upperrel->reltarget = create_empty_pathtarget();
1611 upperrel->pathlist = NIL;
1612 upperrel->cheapest_startup_path = NULL;
1613 upperrel->cheapest_total_path = NULL;
1615
1616 root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel);
1617
1618 return upperrel;
1619}
1620
1621
1622/*
1623 * find_childrel_parents
1624 * Compute the set of parent relids of an appendrel child rel.
1625 *
1626 * Since appendrels can be nested, a child could have multiple levels of
1627 * appendrel ancestors. This function computes a Relids set of all the
1628 * parent relation IDs.
1629 */
1630Relids
1632{
1633 Relids result = NULL;
1634
1636 Assert(rel->relid > 0 && rel->relid < root->simple_rel_array_size);
1637
1638 do
1639 {
1640 AppendRelInfo *appinfo = root->append_rel_array[rel->relid];
1641 Index prelid = appinfo->parent_relid;
1642
1643 result = bms_add_member(result, prelid);
1644
1645 /* traverse up to the parent rel, loop if it's also a child rel */
1646 rel = find_base_rel(root, prelid);
1647 } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
1648
1650
1651 return result;
1652}
1653
1654
1655/*
1656 * get_baserel_parampathinfo
1657 * Get the ParamPathInfo for a parameterized path for a base relation,
1658 * constructing one if we don't have one already.
1659 *
1660 * This centralizes estimating the rowcounts for parameterized paths.
1661 * We need to cache those to be sure we use the same rowcount for all paths
1662 * of the same parameterization for a given rel. This is also a convenient
1663 * place to determine which movable join clauses the parameterized path will
1664 * be responsible for evaluating.
1665 */
1668 Relids required_outer)
1669{
1670 ParamPathInfo *ppi;
1671 Relids joinrelids;
1672 List *pclauses;
1673 List *eqclauses;
1674 Bitmapset *pserials;
1675 double rows;
1676 ListCell *lc;
1677
1678 /* If rel has LATERAL refs, every path for it should account for them */
1679 Assert(bms_is_subset(baserel->lateral_relids, required_outer));
1680
1681 /* Unparameterized paths have no ParamPathInfo */
1682 if (bms_is_empty(required_outer))
1683 return NULL;
1684
1685 Assert(!bms_overlap(baserel->relids, required_outer));
1686
1687 /* If we already have a PPI for this parameterization, just return it */
1688 if ((ppi = find_param_path_info(baserel, required_outer)))
1689 return ppi;
1690
1691 /*
1692 * Identify all joinclauses that are movable to this base rel given this
1693 * parameterization.
1694 */
1695 joinrelids = bms_union(baserel->relids, required_outer);
1696 pclauses = NIL;
1697 foreach(lc, baserel->joininfo)
1698 {
1699 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1700
1702 baserel->relids,
1703 joinrelids))
1704 pclauses = lappend(pclauses, rinfo);
1705 }
1706
1707 /*
1708 * Add in joinclauses generated by EquivalenceClasses, too. (These
1709 * necessarily satisfy join_clause_is_movable_into; but in assert-enabled
1710 * builds, let's verify that.)
1711 */
1713 joinrelids,
1714 required_outer,
1715 baserel,
1716 NULL);
1717#ifdef USE_ASSERT_CHECKING
1718 foreach(lc, eqclauses)
1719 {
1720 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1721
1723 baserel->relids,
1724 joinrelids));
1725 }
1726#endif
1727 pclauses = list_concat(pclauses, eqclauses);
1728
1729 /* Compute set of serial numbers of the enforced clauses */
1730 pserials = NULL;
1731 foreach(lc, pclauses)
1732 {
1733 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1734
1735 pserials = bms_add_member(pserials, rinfo->rinfo_serial);
1736 }
1737
1738 /* Estimate the number of rows returned by the parameterized scan */
1739 rows = get_parameterized_baserel_size(root, baserel, pclauses);
1740
1741 /* And now we can build the ParamPathInfo */
1742 ppi = makeNode(ParamPathInfo);
1743 ppi->ppi_req_outer = required_outer;
1744 ppi->ppi_rows = rows;
1745 ppi->ppi_clauses = pclauses;
1746 ppi->ppi_serials = pserials;
1747 baserel->ppilist = lappend(baserel->ppilist, ppi);
1748
1749 return ppi;
1750}
1751
1752/*
1753 * get_joinrel_parampathinfo
1754 * Get the ParamPathInfo for a parameterized path for a join relation,
1755 * constructing one if we don't have one already.
1756 *
1757 * This centralizes estimating the rowcounts for parameterized paths.
1758 * We need to cache those to be sure we use the same rowcount for all paths
1759 * of the same parameterization for a given rel. This is also a convenient
1760 * place to determine which movable join clauses the parameterized path will
1761 * be responsible for evaluating.
1762 *
1763 * outer_path and inner_path are a pair of input paths that can be used to
1764 * construct the join, and restrict_clauses is the list of regular join
1765 * clauses (including clauses derived from EquivalenceClasses) that must be
1766 * applied at the join node when using these inputs.
1767 *
1768 * Unlike the situation for base rels, the set of movable join clauses to be
1769 * enforced at a join varies with the selected pair of input paths, so we
1770 * must calculate that and pass it back, even if we already have a matching
1771 * ParamPathInfo. We handle this by adding any clauses moved down to this
1772 * join to *restrict_clauses, which is an in/out parameter. (The addition
1773 * is done in such a way as to not modify the passed-in List structure.)
1774 *
1775 * Note: when considering a nestloop join, the caller must have removed from
1776 * restrict_clauses any movable clauses that are themselves scheduled to be
1777 * pushed into the right-hand path. We do not do that here since it's
1778 * unnecessary for other join types.
1779 */
1782 Path *outer_path,
1783 Path *inner_path,
1784 SpecialJoinInfo *sjinfo,
1785 Relids required_outer,
1786 List **restrict_clauses)
1787{
1788 ParamPathInfo *ppi;
1789 Relids join_and_req;
1790 Relids outer_and_req;
1791 Relids inner_and_req;
1792 List *pclauses;
1793 List *eclauses;
1794 List *dropped_ecs;
1795 double rows;
1796 ListCell *lc;
1797
1798 /* If rel has LATERAL refs, every path for it should account for them */
1799 Assert(bms_is_subset(joinrel->lateral_relids, required_outer));
1800
1801 /* Unparameterized paths have no ParamPathInfo or extra join clauses */
1802 if (bms_is_empty(required_outer))
1803 return NULL;
1804
1805 Assert(!bms_overlap(joinrel->relids, required_outer));
1806
1807 /*
1808 * Identify all joinclauses that are movable to this join rel given this
1809 * parameterization. These are the clauses that are movable into this
1810 * join, but not movable into either input path. Treat an unparameterized
1811 * input path as not accepting parameterized clauses (because it won't,
1812 * per the shortcut exit above), even though the joinclause movement rules
1813 * might allow the same clauses to be moved into a parameterized path for
1814 * that rel.
1815 */
1816 join_and_req = bms_union(joinrel->relids, required_outer);
1817 if (outer_path->param_info)
1818 outer_and_req = bms_union(outer_path->parent->relids,
1819 PATH_REQ_OUTER(outer_path));
1820 else
1821 outer_and_req = NULL; /* outer path does not accept parameters */
1822 if (inner_path->param_info)
1823 inner_and_req = bms_union(inner_path->parent->relids,
1824 PATH_REQ_OUTER(inner_path));
1825 else
1826 inner_and_req = NULL; /* inner path does not accept parameters */
1827
1828 pclauses = NIL;
1829 foreach(lc, joinrel->joininfo)
1830 {
1831 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1832
1834 joinrel->relids,
1835 join_and_req) &&
1837 outer_path->parent->relids,
1838 outer_and_req) &&
1840 inner_path->parent->relids,
1841 inner_and_req))
1842 pclauses = lappend(pclauses, rinfo);
1843 }
1844
1845 /* Consider joinclauses generated by EquivalenceClasses, too */
1847 join_and_req,
1848 required_outer,
1849 joinrel,
1850 NULL);
1851 /* We only want ones that aren't movable to lower levels */
1852 dropped_ecs = NIL;
1853 foreach(lc, eclauses)
1854 {
1855 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1856
1858 joinrel->relids,
1859 join_and_req));
1861 outer_path->parent->relids,
1862 outer_and_req))
1863 continue; /* drop if movable into LHS */
1865 inner_path->parent->relids,
1866 inner_and_req))
1867 {
1868 /* drop if movable into RHS, but remember EC for use below */
1869 Assert(rinfo->left_ec == rinfo->right_ec);
1870 dropped_ecs = lappend(dropped_ecs, rinfo->left_ec);
1871 continue;
1872 }
1873 pclauses = lappend(pclauses, rinfo);
1874 }
1875
1876 /*
1877 * EquivalenceClasses are harder to deal with than we could wish, because
1878 * of the fact that a given EC can generate different clauses depending on
1879 * context. Suppose we have an EC {X.X, Y.Y, Z.Z} where X and Y are the
1880 * LHS and RHS of the current join and Z is in required_outer, and further
1881 * suppose that the inner_path is parameterized by both X and Z. The code
1882 * above will have produced either Z.Z = X.X or Z.Z = Y.Y from that EC,
1883 * and in the latter case will have discarded it as being movable into the
1884 * RHS. However, the EC machinery might have produced either Y.Y = X.X or
1885 * Y.Y = Z.Z as the EC enforcement clause within the inner_path; it will
1886 * not have produced both, and we can't readily tell from here which one
1887 * it did pick. If we add no clause to this join, we'll end up with
1888 * insufficient enforcement of the EC; either Z.Z or X.X will fail to be
1889 * constrained to be equal to the other members of the EC. (When we come
1890 * to join Z to this X/Y path, we will certainly drop whichever EC clause
1891 * is generated at that join, so this omission won't get fixed later.)
1892 *
1893 * To handle this, for each EC we discarded such a clause from, try to
1894 * generate a clause connecting the required_outer rels to the join's LHS
1895 * ("Z.Z = X.X" in the terms of the above example). If successful, and if
1896 * the clause can't be moved to the LHS, add it to the current join's
1897 * restriction clauses. (If an EC cannot generate such a clause then it
1898 * has nothing that needs to be enforced here, while if the clause can be
1899 * moved into the LHS then it should have been enforced within that path.)
1900 *
1901 * Note that we don't need similar processing for ECs whose clause was
1902 * considered to be movable into the LHS, because the LHS can't refer to
1903 * the RHS so there is no comparable ambiguity about what it might
1904 * actually be enforcing internally.
1905 */
1906 if (dropped_ecs)
1907 {
1908 Relids real_outer_and_req;
1909
1910 real_outer_and_req = bms_union(outer_path->parent->relids,
1911 required_outer);
1912 eclauses =
1914 dropped_ecs,
1915 real_outer_and_req,
1916 required_outer,
1917 outer_path->parent);
1918 foreach(lc, eclauses)
1919 {
1920 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1921
1923 outer_path->parent->relids,
1924 real_outer_and_req));
1925 if (!join_clause_is_movable_into(rinfo,
1926 outer_path->parent->relids,
1927 outer_and_req))
1928 pclauses = lappend(pclauses, rinfo);
1929 }
1930 }
1931
1932 /*
1933 * Now, attach the identified moved-down clauses to the caller's
1934 * restrict_clauses list. By using list_concat in this order, we leave
1935 * the original list structure of restrict_clauses undamaged.
1936 */
1937 *restrict_clauses = list_concat(pclauses, *restrict_clauses);
1938
1939 /* If we already have a PPI for this parameterization, just return it */
1940 if ((ppi = find_param_path_info(joinrel, required_outer)))
1941 return ppi;
1942
1943 /* Estimate the number of rows returned by the parameterized join */
1944 rows = get_parameterized_joinrel_size(root, joinrel,
1945 outer_path,
1946 inner_path,
1947 sjinfo,
1948 *restrict_clauses);
1949
1950 /*
1951 * And now we can build the ParamPathInfo. No point in saving the
1952 * input-pair-dependent clause list, though.
1953 *
1954 * Note: in GEQO mode, we'll be called in a temporary memory context, but
1955 * the joinrel structure is there too, so no problem.
1956 */
1957 ppi = makeNode(ParamPathInfo);
1958 ppi->ppi_req_outer = required_outer;
1959 ppi->ppi_rows = rows;
1960 ppi->ppi_clauses = NIL;
1961 ppi->ppi_serials = NULL;
1962 joinrel->ppilist = lappend(joinrel->ppilist, ppi);
1963
1964 return ppi;
1965}
1966
1967/*
1968 * get_appendrel_parampathinfo
1969 * Get the ParamPathInfo for a parameterized path for an append relation.
1970 *
1971 * For an append relation, the rowcount estimate will just be the sum of
1972 * the estimates for its children. However, we still need a ParamPathInfo
1973 * to flag the fact that the path requires parameters. So this just creates
1974 * a suitable struct with zero ppi_rows (and no ppi_clauses either, since
1975 * the Append node isn't responsible for checking quals).
1976 */
1979{
1980 ParamPathInfo *ppi;
1981
1982 /* If rel has LATERAL refs, every path for it should account for them */
1983 Assert(bms_is_subset(appendrel->lateral_relids, required_outer));
1984
1985 /* Unparameterized paths have no ParamPathInfo */
1986 if (bms_is_empty(required_outer))
1987 return NULL;
1988
1989 Assert(!bms_overlap(appendrel->relids, required_outer));
1990
1991 /* If we already have a PPI for this parameterization, just return it */
1992 if ((ppi = find_param_path_info(appendrel, required_outer)))
1993 return ppi;
1994
1995 /* Else build the ParamPathInfo */
1996 ppi = makeNode(ParamPathInfo);
1997 ppi->ppi_req_outer = required_outer;
1998 ppi->ppi_rows = 0;
1999 ppi->ppi_clauses = NIL;
2000 ppi->ppi_serials = NULL;
2001 appendrel->ppilist = lappend(appendrel->ppilist, ppi);
2002
2003 return ppi;
2004}
2005
2006/*
2007 * Returns a ParamPathInfo for the parameterization given by required_outer, if
2008 * already available in the given rel. Returns NULL otherwise.
2009 */
2012{
2013 ListCell *lc;
2014
2015 foreach(lc, rel->ppilist)
2016 {
2017 ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
2018
2019 if (bms_equal(ppi->ppi_req_outer, required_outer))
2020 return ppi;
2021 }
2022
2023 return NULL;
2024}
2025
2026/*
2027 * get_param_path_clause_serials
2028 * Given a parameterized Path, return the set of pushed-down clauses
2029 * (identified by rinfo_serial numbers) enforced within the Path.
2030 */
2031Bitmapset *
2033{
2034 if (path->param_info == NULL)
2035 return NULL; /* not parameterized */
2036
2037 /*
2038 * We don't currently support parameterized MergeAppend paths, as
2039 * explained in the comments for generate_orderedappend_paths.
2040 */
2041 Assert(!IsA(path, MergeAppendPath));
2042
2043 if (IsA(path, NestPath) ||
2044 IsA(path, MergePath) ||
2045 IsA(path, HashPath))
2046 {
2047 /*
2048 * For a join path, combine clauses enforced within either input path
2049 * with those enforced as joinrestrictinfo in this path. Note that
2050 * joinrestrictinfo may include some non-pushed-down clauses, but for
2051 * current purposes it's okay if we include those in the result. (To
2052 * be more careful, we could check for clause_relids overlapping the
2053 * path parameterization, but it's not worth the cycles for now.)
2054 */
2055 JoinPath *jpath = (JoinPath *) path;
2056 Bitmapset *pserials;
2057 ListCell *lc;
2058
2059 pserials = NULL;
2060 pserials = bms_add_members(pserials,
2062 pserials = bms_add_members(pserials,
2064 foreach(lc, jpath->joinrestrictinfo)
2065 {
2066 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
2067
2068 pserials = bms_add_member(pserials, rinfo->rinfo_serial);
2069 }
2070 return pserials;
2071 }
2072 else if (IsA(path, AppendPath))
2073 {
2074 /*
2075 * For an appendrel, take the intersection of the sets of clauses
2076 * enforced in each input path.
2077 */
2078 AppendPath *apath = (AppendPath *) path;
2079 Bitmapset *pserials;
2080 ListCell *lc;
2081
2082 pserials = NULL;
2083 foreach(lc, apath->subpaths)
2084 {
2085 Path *subpath = (Path *) lfirst(lc);
2086 Bitmapset *subserials;
2087
2089 if (lc == list_head(apath->subpaths))
2090 pserials = bms_copy(subserials);
2091 else
2092 pserials = bms_int_members(pserials, subserials);
2093 }
2094 return pserials;
2095 }
2096 else
2097 {
2098 /*
2099 * Otherwise, it's a baserel path and we can use the
2100 * previously-computed set of serial numbers.
2101 */
2102 return path->param_info->ppi_serials;
2103 }
2104}
2105
2106/*
2107 * build_joinrel_partition_info
2108 * Checks if the two relations being joined can use partitionwise join
2109 * and if yes, initialize partitioning information of the resulting
2110 * partitioned join relation.
2111 */
2112static void
2114 RelOptInfo *joinrel, RelOptInfo *outer_rel,
2115 RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo,
2116 List *restrictlist)
2117{
2118 PartitionScheme part_scheme;
2119
2120 /* Nothing to do if partitionwise join technique is disabled. */
2122 {
2123 Assert(!IS_PARTITIONED_REL(joinrel));
2124 return;
2125 }
2126
2127 /*
2128 * We can only consider this join as an input to further partitionwise
2129 * joins if (a) the input relations are partitioned and have
2130 * consider_partitionwise_join=true, (b) the partition schemes match, and
2131 * (c) we can identify an equi-join between the partition keys. Note that
2132 * if it were possible for have_partkey_equi_join to return different
2133 * answers for the same joinrel depending on which join ordering we try
2134 * first, this logic would break. That shouldn't happen, though, because
2135 * of the way the query planner deduces implied equalities and reorders
2136 * the joins. Please see optimizer/README for details.
2137 */
2138 if (outer_rel->part_scheme == NULL || inner_rel->part_scheme == NULL ||
2139 !outer_rel->consider_partitionwise_join ||
2140 !inner_rel->consider_partitionwise_join ||
2141 outer_rel->part_scheme != inner_rel->part_scheme ||
2142 !have_partkey_equi_join(root, joinrel, outer_rel, inner_rel,
2143 sjinfo->jointype, restrictlist))
2144 {
2145 Assert(!IS_PARTITIONED_REL(joinrel));
2146 return;
2147 }
2148
2149 part_scheme = outer_rel->part_scheme;
2150
2151 /*
2152 * This function will be called only once for each joinrel, hence it
2153 * should not have partitioning fields filled yet.
2154 */
2155 Assert(!joinrel->part_scheme && !joinrel->partexprs &&
2156 !joinrel->nullable_partexprs && !joinrel->part_rels &&
2157 !joinrel->boundinfo);
2158
2159 /*
2160 * If the join relation is partitioned, it uses the same partitioning
2161 * scheme as the joining relations.
2162 *
2163 * Note: we calculate the partition bounds, number of partitions, and
2164 * child-join relations of the join relation in try_partitionwise_join().
2165 */
2166 joinrel->part_scheme = part_scheme;
2167 set_joinrel_partition_key_exprs(joinrel, outer_rel, inner_rel,
2168 sjinfo->jointype);
2169
2170 /*
2171 * Set the consider_partitionwise_join flag.
2172 */
2175 joinrel->consider_partitionwise_join = true;
2176}
2177
2178/*
2179 * have_partkey_equi_join
2180 *
2181 * Returns true if there exist equi-join conditions involving pairs
2182 * of matching partition keys of the relations being joined for all
2183 * partition keys.
2184 */
2185static bool
2187 RelOptInfo *rel1, RelOptInfo *rel2,
2188 JoinType jointype, List *restrictlist)
2189{
2190 PartitionScheme part_scheme = rel1->part_scheme;
2191 bool pk_known_equal[PARTITION_MAX_KEYS];
2192 int num_equal_pks;
2193 ListCell *lc;
2194
2195 /*
2196 * This function must only be called when the joined relations have same
2197 * partitioning scheme.
2198 */
2199 Assert(rel1->part_scheme == rel2->part_scheme);
2200 Assert(part_scheme);
2201
2202 /* We use a bool array to track which partkey columns are known equal */
2203 memset(pk_known_equal, 0, sizeof(pk_known_equal));
2204 /* ... as well as a count of how many are known equal */
2205 num_equal_pks = 0;
2206
2207 /* First, look through the join's restriction clauses */
2208 foreach(lc, restrictlist)
2209 {
2211 OpExpr *opexpr;
2212 Expr *expr1;
2213 Expr *expr2;
2214 bool strict_op;
2215 int ipk1;
2216 int ipk2;
2217
2218 /* If processing an outer join, only use its own join clauses. */
2219 if (IS_OUTER_JOIN(jointype) &&
2220 RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
2221 continue;
2222
2223 /* Skip clauses which can not be used for a join. */
2224 if (!rinfo->can_join)
2225 continue;
2226
2227 /* Skip clauses which are not equality conditions. */
2228 if (!rinfo->mergeopfamilies && !OidIsValid(rinfo->hashjoinoperator))
2229 continue;
2230
2231 /* Should be OK to assume it's an OpExpr. */
2232 opexpr = castNode(OpExpr, rinfo->clause);
2233
2234 /* Match the operands to the relation. */
2235 if (bms_is_subset(rinfo->left_relids, rel1->relids) &&
2236 bms_is_subset(rinfo->right_relids, rel2->relids))
2237 {
2238 expr1 = linitial(opexpr->args);
2239 expr2 = lsecond(opexpr->args);
2240 }
2241 else if (bms_is_subset(rinfo->left_relids, rel2->relids) &&
2242 bms_is_subset(rinfo->right_relids, rel1->relids))
2243 {
2244 expr1 = lsecond(opexpr->args);
2245 expr2 = linitial(opexpr->args);
2246 }
2247 else
2248 continue;
2249
2250 /*
2251 * Now we need to know whether the join operator is strict; see
2252 * comments in pathnodes.h.
2253 */
2254 strict_op = op_strict(opexpr->opno);
2255
2256 /*
2257 * Vars appearing in the relation's partition keys will not have any
2258 * varnullingrels, but those in expr1 and expr2 will if we're above
2259 * outer joins that could null the respective rels. It's okay to
2260 * match anyway, if the join operator is strict.
2261 */
2262 if (strict_op)
2263 {
2264 if (bms_overlap(rel1->relids, root->outer_join_rels))
2265 expr1 = (Expr *) remove_nulling_relids((Node *) expr1,
2266 root->outer_join_rels,
2267 NULL);
2268 if (bms_overlap(rel2->relids, root->outer_join_rels))
2269 expr2 = (Expr *) remove_nulling_relids((Node *) expr2,
2270 root->outer_join_rels,
2271 NULL);
2272 }
2273
2274 /*
2275 * Only clauses referencing the partition keys are useful for
2276 * partitionwise join.
2277 */
2278 ipk1 = match_expr_to_partition_keys(expr1, rel1, strict_op);
2279 if (ipk1 < 0)
2280 continue;
2281 ipk2 = match_expr_to_partition_keys(expr2, rel2, strict_op);
2282 if (ipk2 < 0)
2283 continue;
2284
2285 /*
2286 * If the clause refers to keys at different ordinal positions, it can
2287 * not be used for partitionwise join.
2288 */
2289 if (ipk1 != ipk2)
2290 continue;
2291
2292 /* Ignore clause if we already proved these keys equal. */
2293 if (pk_known_equal[ipk1])
2294 continue;
2295
2296 /* Reject if the partition key collation differs from the clause's. */
2297 if (rel1->part_scheme->partcollation[ipk1] != opexpr->inputcollid)
2298 return false;
2299
2300 /*
2301 * The clause allows partitionwise join only if it uses the same
2302 * operator family as that specified by the partition key.
2303 */
2304 if (part_scheme->strategy == PARTITION_STRATEGY_HASH)
2305 {
2306 if (!OidIsValid(rinfo->hashjoinoperator) ||
2307 !op_in_opfamily(rinfo->hashjoinoperator,
2308 part_scheme->partopfamily[ipk1]))
2309 continue;
2310 }
2311 else if (!list_member_oid(rinfo->mergeopfamilies,
2312 part_scheme->partopfamily[ipk1]))
2313 continue;
2314
2315 /* Mark the partition key as having an equi-join clause. */
2316 pk_known_equal[ipk1] = true;
2317
2318 /* We can stop examining clauses once we prove all keys equal. */
2319 if (++num_equal_pks == part_scheme->partnatts)
2320 return true;
2321 }
2322
2323 /*
2324 * Also check to see if any keys are known equal by equivclass.c. In most
2325 * cases there would have been a join restriction clause generated from
2326 * any EC that had such knowledge, but there might be no such clause, or
2327 * it might happen to constrain other members of the ECs than the ones we
2328 * are looking for.
2329 */
2330 for (int ipk = 0; ipk < part_scheme->partnatts; ipk++)
2331 {
2332 Oid btree_opfamily;
2333
2334 /* Ignore if we already proved these keys equal. */
2335 if (pk_known_equal[ipk])
2336 continue;
2337
2338 /*
2339 * We need a btree opfamily to ask equivclass.c about. If the
2340 * partopfamily is a hash opfamily, look up its equality operator, and
2341 * select some btree opfamily that that operator is part of. (Any
2342 * such opfamily should be good enough, since equivclass.c will track
2343 * multiple opfamilies as appropriate.)
2344 */
2345 if (part_scheme->strategy == PARTITION_STRATEGY_HASH)
2346 {
2347 Oid eq_op;
2348 List *eq_opfamilies;
2349
2350 eq_op = get_opfamily_member(part_scheme->partopfamily[ipk],
2351 part_scheme->partopcintype[ipk],
2352 part_scheme->partopcintype[ipk],
2354 if (!OidIsValid(eq_op))
2355 break; /* we're not going to succeed */
2356 eq_opfamilies = get_mergejoin_opfamilies(eq_op);
2357 if (eq_opfamilies == NIL)
2358 break; /* we're not going to succeed */
2359 btree_opfamily = linitial_oid(eq_opfamilies);
2360 }
2361 else
2362 btree_opfamily = part_scheme->partopfamily[ipk];
2363
2364 /*
2365 * We consider only non-nullable partition keys here; nullable ones
2366 * would not be treated as part of the same equivalence classes as
2367 * non-nullable ones.
2368 */
2369 foreach(lc, rel1->partexprs[ipk])
2370 {
2371 Node *expr1 = (Node *) lfirst(lc);
2372 ListCell *lc2;
2373 Oid partcoll1 = rel1->part_scheme->partcollation[ipk];
2374 Oid exprcoll1 = exprCollation(expr1);
2375
2376 foreach(lc2, rel2->partexprs[ipk])
2377 {
2378 Node *expr2 = (Node *) lfirst(lc2);
2379
2380 if (exprs_known_equal(root, expr1, expr2, btree_opfamily))
2381 {
2382 /*
2383 * Ensure that the collation of the expression matches
2384 * that of the partition key. Checking just one collation
2385 * (partcoll1 and exprcoll1) suffices because partcoll1
2386 * and partcoll2, as well as exprcoll1 and exprcoll2,
2387 * should be identical. This holds because both rel1 and
2388 * rel2 use the same PartitionScheme and expr1 and expr2
2389 * are equal.
2390 */
2391 if (partcoll1 == exprcoll1)
2392 {
2393 Oid partcoll2 PG_USED_FOR_ASSERTS_ONLY =
2394 rel2->part_scheme->partcollation[ipk];
2395 Oid exprcoll2 PG_USED_FOR_ASSERTS_ONLY =
2396 exprCollation(expr2);
2397
2398 Assert(partcoll2 == exprcoll2);
2399 pk_known_equal[ipk] = true;
2400 break;
2401 }
2402 }
2403 }
2404 if (pk_known_equal[ipk])
2405 break;
2406 }
2407
2408 if (pk_known_equal[ipk])
2409 {
2410 /* We can stop examining keys once we prove all keys equal. */
2411 if (++num_equal_pks == part_scheme->partnatts)
2412 return true;
2413 }
2414 else
2415 break; /* no chance to succeed, give up */
2416 }
2417
2418 return false;
2419}
2420
2421/*
2422 * match_expr_to_partition_keys
2423 *
2424 * Tries to match an expression to one of the nullable or non-nullable
2425 * partition keys of "rel". Returns the matched key's ordinal position,
2426 * or -1 if the expression could not be matched to any of the keys.
2427 *
2428 * strict_op must be true if the expression will be compared with the
2429 * partition key using a strict operator. This allows us to consider
2430 * nullable as well as nonnullable partition keys.
2431 */
2432static int
2434{
2435 int cnt;
2436
2437 /* This function should be called only for partitioned relations. */
2438 Assert(rel->part_scheme);
2439 Assert(rel->partexprs);
2440 Assert(rel->nullable_partexprs);
2441
2442 /* Remove any relabel decorations. */
2443 while (IsA(expr, RelabelType))
2444 expr = (Expr *) (castNode(RelabelType, expr))->arg;
2445
2446 for (cnt = 0; cnt < rel->part_scheme->partnatts; cnt++)
2447 {
2448 ListCell *lc;
2449
2450 /* We can always match to the non-nullable partition keys. */
2451 foreach(lc, rel->partexprs[cnt])
2452 {
2453 if (equal(lfirst(lc), expr))
2454 return cnt;
2455 }
2456
2457 if (!strict_op)
2458 continue;
2459
2460 /*
2461 * If it's a strict join operator then a NULL partition key on one
2462 * side will not join to any partition key on the other side, and in
2463 * particular such a row can't join to a row from a different
2464 * partition on the other side. So, it's okay to search the nullable
2465 * partition keys as well.
2466 */
2467 foreach(lc, rel->nullable_partexprs[cnt])
2468 {
2469 if (equal(lfirst(lc), expr))
2470 return cnt;
2471 }
2472 }
2473
2474 return -1;
2475}
2476
2477/*
2478 * set_joinrel_partition_key_exprs
2479 * Initialize partition key expressions for a partitioned joinrel.
2480 */
2481static void
2483 RelOptInfo *outer_rel, RelOptInfo *inner_rel,
2484 JoinType jointype)
2485{
2486 PartitionScheme part_scheme = joinrel->part_scheme;
2487 int partnatts = part_scheme->partnatts;
2488
2489 joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
2490 joinrel->nullable_partexprs =
2491 (List **) palloc0(sizeof(List *) * partnatts);
2492
2493 /*
2494 * The joinrel's partition expressions are the same as those of the input
2495 * rels, but we must properly classify them as nullable or not in the
2496 * joinrel's output. (Also, we add some more partition expressions if
2497 * it's a FULL JOIN.)
2498 */
2499 for (int cnt = 0; cnt < partnatts; cnt++)
2500 {
2501 /* mark these const to enforce that we copy them properly */
2502 const List *outer_expr = outer_rel->partexprs[cnt];
2503 const List *outer_null_expr = outer_rel->nullable_partexprs[cnt];
2504 const List *inner_expr = inner_rel->partexprs[cnt];
2505 const List *inner_null_expr = inner_rel->nullable_partexprs[cnt];
2506 List *partexpr = NIL;
2507 List *nullable_partexpr = NIL;
2508 ListCell *lc;
2509
2510 switch (jointype)
2511 {
2512 /*
2513 * A join relation resulting from an INNER join may be
2514 * regarded as partitioned by either of the inner and outer
2515 * relation keys. For example, A INNER JOIN B ON A.a = B.b
2516 * can be regarded as partitioned on either A.a or B.b. So we
2517 * add both keys to the joinrel's partexpr lists. However,
2518 * anything that was already nullable still has to be treated
2519 * as nullable.
2520 */
2521 case JOIN_INNER:
2522 partexpr = list_concat_copy(outer_expr, inner_expr);
2523 nullable_partexpr = list_concat_copy(outer_null_expr,
2524 inner_null_expr);
2525 break;
2526
2527 /*
2528 * A join relation resulting from a SEMI or ANTI join may be
2529 * regarded as partitioned by the outer relation keys. The
2530 * inner relation's keys are no longer interesting; since they
2531 * aren't visible in the join output, nothing could join to
2532 * them.
2533 */
2534 case JOIN_SEMI:
2535 case JOIN_ANTI:
2536 partexpr = list_copy(outer_expr);
2537 nullable_partexpr = list_copy(outer_null_expr);
2538 break;
2539
2540 /*
2541 * A join relation resulting from a LEFT OUTER JOIN likewise
2542 * may be regarded as partitioned on the (non-nullable) outer
2543 * relation keys. The inner (nullable) relation keys are okay
2544 * as partition keys for further joins as long as they involve
2545 * strict join operators.
2546 */
2547 case JOIN_LEFT:
2548 partexpr = list_copy(outer_expr);
2549 nullable_partexpr = list_concat_copy(inner_expr,
2550 outer_null_expr);
2551 nullable_partexpr = list_concat(nullable_partexpr,
2552 inner_null_expr);
2553 break;
2554
2555 /*
2556 * For FULL OUTER JOINs, both relations are nullable, so the
2557 * resulting join relation may be regarded as partitioned on
2558 * either of inner and outer relation keys, but only for joins
2559 * that involve strict join operators.
2560 */
2561 case JOIN_FULL:
2562 nullable_partexpr = list_concat_copy(outer_expr,
2563 inner_expr);
2564 nullable_partexpr = list_concat(nullable_partexpr,
2565 outer_null_expr);
2566 nullable_partexpr = list_concat(nullable_partexpr,
2567 inner_null_expr);
2568
2569 /*
2570 * Also add CoalesceExprs corresponding to each possible
2571 * full-join output variable (that is, left side coalesced to
2572 * right side), so that we can match equijoin expressions
2573 * using those variables. We really only need these for
2574 * columns merged by JOIN USING, and only with the pairs of
2575 * input items that correspond to the data structures that
2576 * parse analysis would build for such variables. But it's
2577 * hard to tell which those are, so just make all the pairs.
2578 * Extra items in the nullable_partexprs list won't cause big
2579 * problems. (It's possible that such items will get matched
2580 * to user-written COALESCEs, but it should still be valid to
2581 * partition on those, since they're going to be either the
2582 * partition column or NULL; it's the same argument as for
2583 * partitionwise nesting of any outer join.) We assume no
2584 * type coercions are needed to make the coalesce expressions,
2585 * since columns of different types won't have gotten
2586 * classified as the same PartitionScheme. Note that we
2587 * intentionally leave out the varnullingrels decoration that
2588 * would ordinarily appear on the Vars inside these
2589 * CoalesceExprs, because have_partkey_equi_join will strip
2590 * varnullingrels from the expressions it will compare to the
2591 * partexprs.
2592 */
2593 foreach(lc, list_concat_copy(outer_expr, outer_null_expr))
2594 {
2595 Node *larg = (Node *) lfirst(lc);
2596 ListCell *lc2;
2597
2598 foreach(lc2, list_concat_copy(inner_expr, inner_null_expr))
2599 {
2600 Node *rarg = (Node *) lfirst(lc2);
2602
2603 c->coalescetype = exprType(larg);
2604 c->coalescecollid = exprCollation(larg);
2605 c->args = list_make2(larg, rarg);
2606 c->location = -1;
2607 nullable_partexpr = lappend(nullable_partexpr, c);
2608 }
2609 }
2610 break;
2611
2612 default:
2613 elog(ERROR, "unrecognized join type: %d", (int) jointype);
2614 }
2615
2616 joinrel->partexprs[cnt] = partexpr;
2617 joinrel->nullable_partexprs[cnt] = nullable_partexpr;
2618 }
2619}
2620
2621/*
2622 * build_child_join_reltarget
2623 * Set up a child-join relation's reltarget from a parent-join relation.
2624 */
2625static void
2627 RelOptInfo *parentrel,
2628 RelOptInfo *childrel,
2629 int nappinfos,
2630 AppendRelInfo **appinfos)
2631{
2632 /* Build the targetlist */
2633 childrel->reltarget->exprs = (List *)
2635 (Node *) parentrel->reltarget->exprs,
2636 nappinfos, appinfos);
2637
2638 /* Set the cost and width fields */
2639 childrel->reltarget->cost.startup = parentrel->reltarget->cost.startup;
2640 childrel->reltarget->cost.per_tuple = parentrel->reltarget->cost.per_tuple;
2641 childrel->reltarget->width = parentrel->reltarget->width;
2642}
2643
2644/*
2645 * create_rel_agg_info
2646 * Create the RelAggInfo structure for the given relation if it can produce
2647 * grouped paths. The given relation is the non-grouped one which has the
2648 * reltarget already constructed.
2649 *
2650 * calculate_grouped_rows: if true, calculate the estimated number of grouped
2651 * rows for the relation. If false, skip the estimation to avoid unnecessary
2652 * planning overhead.
2653 */
2654RelAggInfo *
2656 bool calculate_grouped_rows)
2657{
2658 ListCell *lc;
2659 RelAggInfo *result;
2660 PathTarget *agg_input;
2661 PathTarget *target;
2662 List *group_clauses = NIL;
2663 List *group_exprs = NIL;
2664
2665 /*
2666 * The lists of aggregate expressions and grouping expressions should have
2667 * been constructed.
2668 */
2669 Assert(root->agg_clause_list != NIL);
2670 Assert(root->group_expr_list != NIL);
2671
2672 /*
2673 * If this is a child rel, the grouped rel for its parent rel must have
2674 * been created if it can. So we can just use parent's RelAggInfo if
2675 * there is one, with appropriate variable substitutions.
2676 */
2677 if (IS_OTHER_REL(rel))
2678 {
2679 RelOptInfo *grouped_rel;
2680 RelAggInfo *agg_info;
2681
2682 grouped_rel = rel->top_parent->grouped_rel;
2683 if (grouped_rel == NULL)
2684 return NULL;
2685
2686 Assert(IS_GROUPED_REL(grouped_rel));
2687
2688 /* Must do multi-level transformation */
2689 agg_info = (RelAggInfo *)
2691 (Node *) grouped_rel->agg_info,
2692 rel,
2693 rel->top_parent);
2694
2695 agg_info->apply_agg_at = NULL; /* caller will change this later */
2696
2697 if (calculate_grouped_rows)
2698 {
2699 agg_info->grouped_rows =
2701 rel->rows, NULL, NULL);
2702
2703 /*
2704 * The grouped paths for the given relation are considered useful
2705 * iff the average group size is no less than
2706 * min_eager_agg_group_size.
2707 */
2708 agg_info->agg_useful =
2709 (rel->rows / agg_info->grouped_rows) >= min_eager_agg_group_size;
2710 }
2711
2712 return agg_info;
2713 }
2714
2715 /* Check if it's possible to produce grouped paths for this relation. */
2717 return NULL;
2718
2719 /*
2720 * Create targets for the grouped paths and for the input paths of the
2721 * grouped paths.
2722 */
2723 target = create_empty_pathtarget();
2724 agg_input = create_empty_pathtarget();
2725
2726 /* ... and initialize these targets */
2727 if (!init_grouping_targets(root, rel, target, agg_input,
2728 &group_clauses, &group_exprs))
2729 return NULL;
2730
2731 /*
2732 * Eager aggregation is not applicable if there are no available grouping
2733 * expressions.
2734 */
2735 if (group_clauses == NIL)
2736 return NULL;
2737
2738 /* Add aggregates to the grouping target */
2739 foreach(lc, root->agg_clause_list)
2740 {
2741 AggClauseInfo *ac_info = lfirst_node(AggClauseInfo, lc);
2742 Aggref *aggref;
2743
2744 Assert(IsA(ac_info->aggref, Aggref));
2745
2746 aggref = (Aggref *) copyObject(ac_info->aggref);
2748
2749 add_column_to_pathtarget(target, (Expr *) aggref, 0);
2750 }
2751
2752 /* Set the estimated eval cost and output width for both targets */
2754 set_pathtarget_cost_width(root, agg_input);
2755
2756 /* build the RelAggInfo result */
2757 result = makeNode(RelAggInfo);
2758 result->target = target;
2759 result->agg_input = agg_input;
2760 result->group_clauses = group_clauses;
2761 result->group_exprs = group_exprs;
2762 result->apply_agg_at = NULL; /* caller will change this later */
2763
2764 if (calculate_grouped_rows)
2765 {
2767 rel->rows, NULL, NULL);
2768
2769 /*
2770 * The grouped paths for the given relation are considered useful iff
2771 * the average group size is no less than min_eager_agg_group_size.
2772 */
2773 result->agg_useful =
2774 (rel->rows / result->grouped_rows) >= min_eager_agg_group_size;
2775 }
2776
2777 return result;
2778}
2779
2780/*
2781 * eager_aggregation_possible_for_relation
2782 * Check if it's possible to produce grouped paths for the given relation.
2783 */
2784static bool
2786{
2787 ListCell *lc;
2788 int cur_relid;
2789
2790 /*
2791 * Check to see if the given relation is in the nullable side of an outer
2792 * join. In this case, we cannot push a partial aggregation down to the
2793 * relation, because the NULL-extended rows produced by the outer join
2794 * would not be available when we perform the partial aggregation, while
2795 * with a non-eager-aggregation plan these rows are available for the
2796 * top-level aggregation. Doing so may result in the rows being grouped
2797 * differently than expected, or produce incorrect values from the
2798 * aggregate functions.
2799 */
2800 cur_relid = -1;
2801 while ((cur_relid = bms_next_member(rel->relids, cur_relid)) >= 0)
2802 {
2803 RelOptInfo *baserel = find_base_rel_ignore_join(root, cur_relid);
2804
2805 if (baserel == NULL)
2806 continue; /* ignore outer joins in rel->relids */
2807
2808 if (!bms_is_subset(baserel->nulling_relids, rel->relids))
2809 return false;
2810 }
2811
2812 /*
2813 * For now we don't try to support PlaceHolderVars.
2814 */
2815 foreach(lc, rel->reltarget->exprs)
2816 {
2817 Expr *expr = lfirst(lc);
2818
2819 if (IsA(expr, PlaceHolderVar))
2820 return false;
2821 }
2822
2823 /* Caller should only pass base relations or joins. */
2825 rel->reloptkind == RELOPT_JOINREL);
2826
2827 /*
2828 * Check if all aggregate expressions can be evaluated on this relation
2829 * level.
2830 */
2831 foreach(lc, root->agg_clause_list)
2832 {
2833 AggClauseInfo *ac_info = lfirst_node(AggClauseInfo, lc);
2834
2835 Assert(IsA(ac_info->aggref, Aggref));
2836
2837 /*
2838 * Give up if any aggregate requires relations other than the current
2839 * one. If the aggregate requires the current relation plus
2840 * additional relations, grouping the current relation could make some
2841 * input rows unavailable for the higher aggregate and may reduce the
2842 * number of input rows it receives. If the aggregate does not
2843 * require the current relation at all, it should not be grouped, as
2844 * we do not support joining two grouped relations.
2845 */
2846 if (!bms_is_subset(ac_info->agg_eval_at, rel->relids))
2847 return false;
2848 }
2849
2850 return true;
2851}
2852
2853/*
2854 * init_grouping_targets
2855 * Initialize the target for grouped paths (target) as well as the target
2856 * for paths that generate input for the grouped paths (agg_input).
2857 *
2858 * We also construct the list of SortGroupClauses and the list of grouping
2859 * expressions for the partial aggregation, and return them in *group_clause
2860 * and *group_exprs.
2861 *
2862 * Return true if the targets could be initialized, false otherwise.
2863 */
2864static bool
2866 PathTarget *target, PathTarget *agg_input,
2867 List **group_clauses, List **group_exprs)
2868{
2869 ListCell *lc;
2870 List *possibly_dependent = NIL;
2871 Index maxSortGroupRef;
2872
2873 /* Identify the max sortgroupref */
2874 maxSortGroupRef = 0;
2875 foreach(lc, root->processed_tlist)
2876 {
2877 Index ref = ((TargetEntry *) lfirst(lc))->ressortgroupref;
2878
2879 if (ref > maxSortGroupRef)
2880 maxSortGroupRef = ref;
2881 }
2882
2883 /*
2884 * At this point, all Vars from this relation that are needed by upper
2885 * joins or are required in the final targetlist should already be present
2886 * in its reltarget. Therefore, we can safely iterate over this
2887 * relation's reltarget->exprs to construct the PathTarget and grouping
2888 * clauses for the grouped paths.
2889 */
2890 foreach(lc, rel->reltarget->exprs)
2891 {
2892 Expr *expr = (Expr *) lfirst(lc);
2893 Index sortgroupref;
2894
2895 /*
2896 * Given that PlaceHolderVar currently prevents us from doing eager
2897 * aggregation, the source target cannot contain anything more complex
2898 * than a Var.
2899 */
2900 Assert(IsA(expr, Var));
2901
2902 /*
2903 * Get the sortgroupref of the expr if it is found among, or can be
2904 * deduced from, the original grouping expressions.
2905 */
2906 sortgroupref = get_expression_sortgroupref(root, expr);
2907 if (sortgroupref > 0)
2908 {
2909 SortGroupClause *sgc;
2910
2911 /* Find the matching SortGroupClause */
2912 sgc = get_sortgroupref_clause(sortgroupref, root->processed_groupClause);
2913 Assert(sgc->tleSortGroupRef <= maxSortGroupRef);
2914
2915 /*
2916 * If the target expression is to be used as a grouping key, it
2917 * should be emitted by the grouped paths that have been pushed
2918 * down to this relation level.
2919 */
2920 add_column_to_pathtarget(target, expr, sortgroupref);
2921
2922 /*
2923 * ... and it also should be emitted by the input paths.
2924 */
2925 add_column_to_pathtarget(agg_input, expr, sortgroupref);
2926
2927 /*
2928 * Record this SortGroupClause and grouping expression. Note that
2929 * this SortGroupClause might have already been recorded.
2930 */
2931 if (!list_member(*group_clauses, sgc))
2932 {
2933 *group_clauses = lappend(*group_clauses, sgc);
2934 *group_exprs = lappend(*group_exprs, expr);
2935 }
2936 }
2937 else if (is_var_needed_by_join(root, (Var *) expr, rel))
2938 {
2939 /*
2940 * The expression is needed for an upper join but is neither in
2941 * the GROUP BY clause nor derivable from it using EC (otherwise,
2942 * it would have already been included in the targets above). We
2943 * need to create a special SortGroupClause for this expression.
2944 *
2945 * It is important to include such expressions in the grouping
2946 * keys. This is essential to ensure that an aggregated row from
2947 * the partial aggregation matches the other side of the join if
2948 * and only if each row in the partial group does. This ensures
2949 * that all rows within the same partial group share the same
2950 * 'destiny', which is crucial for maintaining correctness.
2951 */
2952 SortGroupClause *sgc;
2953 TypeCacheEntry *tce;
2954 Oid equalimageproc;
2955
2956 /*
2957 * But first, check if equality implies image equality for this
2958 * expression. If not, we cannot use it as a grouping key. See
2959 * comments in create_grouping_expr_infos().
2960 */
2961 tce = lookup_type_cache(exprType((Node *) expr),
2963 if (!OidIsValid(tce->btree_opf) ||
2965 return false;
2966
2967 equalimageproc = get_opfamily_proc(tce->btree_opf,
2968 tce->btree_opintype,
2969 tce->btree_opintype,
2971 if (!OidIsValid(equalimageproc) ||
2972 !DatumGetBool(OidFunctionCall1Coll(equalimageproc,
2973 tce->typcollation,
2975 return false;
2976
2977 /* Create the SortGroupClause. */
2979
2980 /* Initialize the SortGroupClause. */
2981 sgc->tleSortGroupRef = ++maxSortGroupRef;
2983 false, true, false,
2984 &sgc->sortop, &sgc->eqop, NULL,
2985 &sgc->hashable);
2986
2987 /* This expression should be emitted by the grouped paths */
2988 add_column_to_pathtarget(target, expr, sgc->tleSortGroupRef);
2989
2990 /* ... and it also should be emitted by the input paths. */
2991 add_column_to_pathtarget(agg_input, expr, sgc->tleSortGroupRef);
2992
2993 /* Record this SortGroupClause and grouping expression */
2994 *group_clauses = lappend(*group_clauses, sgc);
2995 *group_exprs = lappend(*group_exprs, expr);
2996 }
2997 else if (is_var_in_aggref_only(root, (Var *) expr))
2998 {
2999 /*
3000 * The expression is referenced by an aggregate function pushed
3001 * down to this relation and does not appear elsewhere in the
3002 * targetlist or havingQual. Add it to 'agg_input' but not to
3003 * 'target'.
3004 */
3005 add_new_column_to_pathtarget(agg_input, expr);
3006 }
3007 else
3008 {
3009 /*
3010 * The expression may be functionally dependent on other
3011 * expressions in the target, but we cannot verify this until all
3012 * target expressions have been constructed.
3013 */
3014 possibly_dependent = lappend(possibly_dependent, expr);
3015 }
3016 }
3017
3018 /*
3019 * Now we can verify whether an expression is functionally dependent on
3020 * others.
3021 */
3022 foreach(lc, possibly_dependent)
3023 {
3024 Var *tvar;
3025 List *deps = NIL;
3026 RangeTblEntry *rte;
3027
3028 tvar = lfirst_node(Var, lc);
3029 rte = root->simple_rte_array[tvar->varno];
3030
3031 if (check_functional_grouping(rte->relid, tvar->varno,
3032 tvar->varlevelsup,
3033 target->exprs, &deps))
3034 {
3035 /*
3036 * The expression is functionally dependent on other target
3037 * expressions, so it can be included in the targets. Since it
3038 * will not be used as a grouping key, a sortgroupref is not
3039 * needed for it.
3040 */
3041 add_new_column_to_pathtarget(target, (Expr *) tvar);
3042 add_new_column_to_pathtarget(agg_input, (Expr *) tvar);
3043 }
3044 else
3045 {
3046 /*
3047 * We may arrive here with a grouping expression that is proven
3048 * redundant by EquivalenceClass processing, such as 't1.a' in the
3049 * query below.
3050 *
3051 * select max(t1.c) from t t1, t t2 where t1.a = 1 group by t1.a,
3052 * t1.b;
3053 *
3054 * For now we just give up in this case.
3055 */
3056 return false;
3057 }
3058 }
3059
3060 return true;
3061}
3062
3063/*
3064 * is_var_in_aggref_only
3065 * Check whether the given Var appears in aggregate expressions and not
3066 * elsewhere in the targetlist or havingQual.
3067 */
3068static bool
3070{
3071 ListCell *lc;
3072
3073 /*
3074 * Search the list of aggregate expressions for the Var.
3075 */
3076 foreach(lc, root->agg_clause_list)
3077 {
3078 AggClauseInfo *ac_info = lfirst_node(AggClauseInfo, lc);
3079 List *vars;
3080
3081 Assert(IsA(ac_info->aggref, Aggref));
3082
3083 if (!bms_is_member(var->varno, ac_info->agg_eval_at))
3084 continue;
3085
3086 vars = pull_var_clause((Node *) ac_info->aggref,
3090
3091 if (list_member(vars, var))
3092 {
3093 list_free(vars);
3094 break;
3095 }
3096
3097 list_free(vars);
3098 }
3099
3100 return (lc != NULL && !list_member(root->tlist_vars, var));
3101}
3102
3103/*
3104 * is_var_needed_by_join
3105 * Check if the given Var is needed by joins above the current rel.
3106 */
3107static bool
3109{
3110 Relids relids;
3111 int attno;
3112 RelOptInfo *baserel;
3113
3114 /*
3115 * Note that when checking if the Var is needed by joins above, we want to
3116 * exclude cases where the Var is only needed in the final targetlist. So
3117 * include "relation 0" in the check.
3118 */
3119 relids = bms_copy(rel->relids);
3120 relids = bms_add_member(relids, 0);
3121
3122 baserel = find_base_rel(root, var->varno);
3123 attno = var->varattno - baserel->min_attr;
3124
3125 return bms_nonempty_difference(baserel->attr_needed[attno], relids);
3126}
3127
3128/*
3129 * get_expression_sortgroupref
3130 * Return the sortgroupref of the given "expr" if it is found among the
3131 * original grouping expressions, or is known equal to any of the original
3132 * grouping expressions due to equivalence relationships. Return 0 if no
3133 * match is found.
3134 */
3135static Index
3137{
3138 ListCell *lc;
3139
3140 Assert(IsA(expr, Var));
3141
3142 foreach(lc, root->group_expr_list)
3143 {
3145 ListCell *lc1;
3146
3147 Assert(IsA(ge_info->expr, Var));
3148 Assert(ge_info->sortgroupref > 0);
3149
3150 if (equal(expr, ge_info->expr))
3151 return ge_info->sortgroupref;
3152
3153 if (ge_info->ec == NULL ||
3154 !bms_is_member(((Var *) expr)->varno, ge_info->ec->ec_relids))
3155 continue;
3156
3157 /*
3158 * Scan the EquivalenceClass, looking for a match to the given
3159 * expression. We ignore child members here.
3160 */
3161 foreach(lc1, ge_info->ec->ec_members)
3162 {
3164
3165 /* Child members should not exist in ec_members */
3166 Assert(!em->em_is_child);
3167
3168 if (equal(expr, em->em_expr))
3169 return ge_info->sortgroupref;
3170 }
3171 }
3172
3173 /* no match is found */
3174 return 0;
3175}
double min_eager_agg_group_size
Definition: allpaths.c:84
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:200
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, RelOptInfo *childrel, RelOptInfo *parentrel)
Definition: appendinfo.c:592
Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:625
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:1436
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:142
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
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:1446
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:228
int64_t int64
Definition: c.h:540
int32_t int32
Definition: c.h:539
uint32_t uint32
Definition: c.h:543
unsigned int Index
Definition: c.h:624
#define OidIsValid(objectId)
Definition: c.h:779
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:763
double get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, List *param_clauses)
Definition: costsize.c:5388
double get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, List *restrict_clauses)
Definition: costsize.c:5469
void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: costsize.c:5437
PathTarget * set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
Definition: costsize.c:6376
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:952
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:358
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
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:2648
List * generate_join_implied_equalities_for_ecs(PlannerInfo *root, List *eclasses, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
Definition: equivclass.c:1650
void add_child_join_rel_equivalences(PlannerInfo *root, int nappinfos, AppendRelInfo **appinfos, RelOptInfo *parent_joinrel, RelOptInfo *child_joinrel)
Definition: equivclass.c:2941
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
Definition: equivclass.c:1550
bool has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1)
Definition: equivclass.c:3446
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
Datum OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
Definition: fmgr.c:1412
Assert(PointerIsAligned(start, uint64))
@ 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:838
void mark_dummy_rel(RelOptInfo *rel)
Definition: joinrels.c:1513
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
void list_free(List *list)
Definition: list.c:1546
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
bool list_member(const List *list, const void *datum)
Definition: list.c:661
List * list_append_unique_ptr(List *list, void *datum)
Definition: list.c:1356
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:889
bool op_strict(Oid opno)
Definition: lsyscache.c:1644
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:168
List * get_mergejoin_opfamilies(Oid opno)
Definition: lsyscache.c:435
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition: lsyscache.c:68
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:311
void * palloc0(Size size)
Definition: mcxt.c:1395
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
Oid GetUserId(void)
Definition: miscinit.c:469
#define BTEQUALIMAGE_PROC
Definition: nbtree.h:720
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:164
#define copyObject(obj)
Definition: nodes.h:232
#define nodeTag(nodeptr)
Definition: nodes.h:139
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:348
@ AGGSPLIT_INITIAL_SERIAL
Definition: nodes.h:389
#define makeNode(_type_)
Definition: nodes.h:161
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
JoinType
Definition: nodes.h:298
@ JOIN_SEMI
Definition: nodes.h:317
@ JOIN_FULL
Definition: nodes.h:305
@ JOIN_INNER
Definition: nodes.h:303
@ JOIN_LEFT
Definition: nodes.h:304
@ JOIN_ANTI
Definition: nodes.h:318
#define PVC_RECURSE_AGGREGATES
Definition: optimizer.h:186
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:190
#define PVC_RECURSE_WINDOWFUNCS
Definition: optimizer.h:188
#define repalloc0_array(pointer, type, oldcount, count)
Definition: palloc.h:109
void get_sort_group_operators(Oid argtype, bool needLT, bool needEQ, bool needGT, Oid *ltOpr, Oid *eqOpr, Oid *gtOpr, bool *isHashable)
Definition: parse_oper.c:181
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ PARTITION_STRATEGY_HASH
Definition: parsenodes.h:902
@ RTE_JOIN
Definition: parsenodes.h:1045
@ RTE_CTE
Definition: parsenodes.h:1049
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1050
@ RTE_VALUES
Definition: parsenodes.h:1048
@ RTE_SUBQUERY
Definition: parsenodes.h:1044
@ RTE_RESULT
Definition: parsenodes.h:1051
@ RTE_FUNCTION
Definition: parsenodes.h:1046
@ RTE_TABLEFUNC
Definition: parsenodes.h:1047
@ RTE_RELATION
Definition: parsenodes.h:1043
bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel)
Definition: pathkeys.c:2291
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
Definition: pathnodes.h:2949
#define IS_DUMMY_REL(r)
Definition: pathnodes.h:2194
#define IS_PARTITIONED_REL(rel)
Definition: pathnodes.h:1135
#define IS_GROUPED_REL(rel)
Definition: pathnodes.h:1161
#define PATH_REQ_OUTER(path)
Definition: pathnodes.h:1917
Bitmapset * Relids
Definition: pathnodes.h:30
UpperRelationKind
Definition: pathnodes.h:70
@ RELOPT_BASEREL
Definition: pathnodes.h:883
@ RELOPT_OTHER_MEMBER_REL
Definition: pathnodes.h:885
@ RELOPT_UPPER_REL
Definition: pathnodes.h:887
@ RELOPT_JOINREL
Definition: pathnodes.h:884
@ RELOPT_OTHER_JOINREL
Definition: pathnodes.h:886
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:910
void * arg
#define PARTITION_MAX_KEYS
bool check_functional_grouping(Oid relid, Index varno, Index varlevelsup, List *grouping_columns, List **constraintDeps)
#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:124
void mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
Definition: planner.c:5762
static bool DatumGetBool(Datum X)
Definition: postgres.h:100
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
char * c
#define ROWID_VAR
Definition: primnodes.h:245
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:2113
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:529
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:108
static void set_joinrel_partition_key_exprs(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype)
Definition: relnode.c:2482
ParamPathInfo * get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
Definition: relnode.c:1978
static bool init_grouping_targets(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, PathTarget *agg_input, List **group_clauses, List **group_exprs)
Definition: relnode.c:2865
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, bool can_null)
Definition: relnode.c:1223
RelOptInfo * build_grouped_rel(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:484
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:1001
static bool have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *rel1, RelOptInfo *rel2, JoinType jointype, List *restrictlist)
Definition: relnode.c:2186
RelOptInfo * find_base_rel_noerr(PlannerInfo *root, int relid)
Definition: relnode.c:551
Relids min_join_parameterization(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:1145
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Definition: relnode.c:642
static void build_join_rel_hash(PlannerInfo *root)
Definition: relnode.c:601
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:1781
static bool eager_aggregation_possible_for_relation(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:2785
Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:1631
void expand_planner_arrays(PlannerInfo *root, int add_size)
Definition: relnode.c:177
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
Definition: relnode.c:1667
RelOptInfo * build_simple_grouped_rel(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:433
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1581
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:780
static void build_child_join_reltarget(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, int nappinfos, AppendRelInfo **appinfos)
Definition: relnode.c:2626
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:206
static List * build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
Definition: relnode.c:1408
RelAggInfo * create_rel_agg_info(PlannerInfo *root, RelOptInfo *rel, bool calculate_grouped_rows)
Definition: relnode.c:2655
static int match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel, bool strict_op)
Definition: relnode.c:2433
ParamPathInfo * find_param_path_info(RelOptInfo *rel, Relids required_outer)
Definition: relnode.c:2011
static void set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:704
struct JoinHashEntry JoinHashEntry
static void build_joinrel_joinlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:1445
static Index get_expression_sortgroupref(PlannerInfo *root, Expr *expr)
Definition: relnode.c:3136
Bitmapset * get_param_path_clause_serials(Path *path)
Definition: relnode.c:2032
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
Definition: relnode.c:742
RelOptInfo * find_base_rel_ignore_join(PlannerInfo *root, int relid)
Definition: relnode.c:569
static List * subbuild_joinrel_joinlist(RelOptInfo *joinrel, List *joininfo_list, List *new_joininfo)
Definition: relnode.c:1529
static List * subbuild_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel, Relids both_input_relids, List *new_restrictlist)
Definition: relnode.c:1463
static bool is_var_in_aggref_only(PlannerInfo *root, Var *var)
Definition: relnode.c:3069
static bool is_var_needed_by_join(PlannerInfo *root, Var *var, RelOptInfo *rel)
Definition: relnode.c:3108
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)
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo)
Definition: selfuncs.c:3768
Size add_size(Size s1, Size s2)
Definition: shmem.c:494
#define HTEqualStrategyNumber
Definition: stratnum.h:41
Relids agg_eval_at
Definition: pathnodes.h:3376
Aggref * aggref
Definition: pathnodes.h:3373
List * subpaths
Definition: pathnodes.h:2180
Index child_relid
Definition: pathnodes.h:3193
Index parent_relid
Definition: pathnodes.h:3192
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:222
Relids join_relids
Definition: relnode.c:46
RelOptInfo * join_rel
Definition: relnode.c:47
Path * outerjoinpath
Definition: pathnodes.h:2296
Path * innerjoinpath
Definition: pathnodes.h:2297
List * joinrestrictinfo
Definition: pathnodes.h:2299
Definition: pg_list.h:54
Definition: nodes.h:135
Oid opno
Definition: primnodes.h:850
List * args
Definition: primnodes.h:868
Cardinality ppi_rows
Definition: pathnodes.h:1827
List * ppi_clauses
Definition: pathnodes.h:1828
Bitmapset * ppi_serials
Definition: pathnodes.h:1829
Relids ppi_req_outer
Definition: pathnodes.h:1826
List * exprs
Definition: pathnodes.h:1780
QualCost cost
Definition: pathnodes.h:1786
Relids ph_needed
Definition: pathnodes.h:3317
Relids phnullingrels
Definition: pathnodes.h:3019
Cost per_tuple
Definition: pathnodes.h:48
Cost startup
Definition: pathnodes.h:47
JoinType jointype
Definition: parsenodes.h:1182
RTEKind rtekind
Definition: parsenodes.h:1078
Relids apply_agg_at
Definition: pathnodes.h:1206
List * group_exprs
Definition: pathnodes.h:1203
bool agg_useful
Definition: pathnodes.h:1212
List * group_clauses
Definition: pathnodes.h:1201
struct PathTarget * agg_input
Definition: pathnodes.h:1198
Cardinality grouped_rows
Definition: pathnodes.h:1209
struct PathTarget * target
Definition: pathnodes.h:1195
List * baserestrictinfo
Definition: pathnodes.h:1046
bool consider_param_startup
Definition: pathnodes.h:941
List * subplan_params
Definition: pathnodes.h:1005
List * ppilist
Definition: pathnodes.h:955
bool useridiscurrent
Definition: pathnodes.h:1019
uint32 amflags
Definition: pathnodes.h:1009
List * joininfo
Definition: pathnodes.h:1052
Bitmapset * notnullattnums
Definition: pathnodes.h:987
List * partition_qual
Definition: pathnodes.h:1096
Relids relids
Definition: pathnodes.h:927
struct PathTarget * reltarget
Definition: pathnodes.h:949
Index relid
Definition: pathnodes.h:973
List * statlist
Definition: pathnodes.h:997
List * lateral_vars
Definition: pathnodes.h:991
struct RelAggInfo * agg_info
Definition: pathnodes.h:1066
List * unique_for_rels
Definition: pathnodes.h:1028
List * unique_pathkeys
Definition: pathnodes.h:1038
Cardinality tuples
Definition: pathnodes.h:1000
bool consider_parallel
Definition: pathnodes.h:943
Relids top_parent_relids
Definition: pathnodes.h:1078
bool partbounds_merged
Definition: pathnodes.h:1094
BlockNumber pages
Definition: pathnodes.h:999
Relids lateral_relids
Definition: pathnodes.h:968
List * cheapest_parameterized_paths
Definition: pathnodes.h:959
List * pathlist
Definition: pathnodes.h:954
RelOptKind reloptkind
Definition: pathnodes.h:921
List * indexlist
Definition: pathnodes.h:995
Relids lateral_referencers
Definition: pathnodes.h:993
struct Path * cheapest_startup_path
Definition: pathnodes.h:957
QualCost baserestrictcost
Definition: pathnodes.h:1048
struct Path * cheapest_total_path
Definition: pathnodes.h:958
List * unique_groupclause
Definition: pathnodes.h:1040
struct RelOptInfo * grouped_rel
Definition: pathnodes.h:1068
List * non_unique_for_rels
Definition: pathnodes.h:1030
Bitmapset * eclass_indexes
Definition: pathnodes.h:1003
Relids all_partrels
Definition: pathnodes.h:1110
Relids direct_lateral_relids
Definition: pathnodes.h:966
bool has_eclass_joins
Definition: pathnodes.h:1054
Oid serverid
Definition: pathnodes.h:1015
bool consider_startup
Definition: pathnodes.h:939
Bitmapset * live_parts
Definition: pathnodes.h:1108
int rel_parallel_workers
Definition: pathnodes.h:1007
bool consider_partitionwise_join
Definition: pathnodes.h:1060
List * partial_pathlist
Definition: pathnodes.h:956
PlannerInfo * subroot
Definition: pathnodes.h:1004
AttrNumber max_attr
Definition: pathnodes.h:981
Relids nulling_relids
Definition: pathnodes.h:989
Index baserestrict_min_security
Definition: pathnodes.h:1050
double allvisfrac
Definition: pathnodes.h:1001
struct RelOptInfo * unique_rel
Definition: pathnodes.h:1036
Cardinality rows
Definition: pathnodes.h:933
AttrNumber min_attr
Definition: pathnodes.h:979
RTEKind rtekind
Definition: pathnodes.h:977
Relids required_relids
Definition: pathnodes.h:2823
int rinfo_serial
Definition: pathnodes.h:2864
Relids incompatible_relids
Definition: pathnodes.h:2826
Expr * clause
Definition: pathnodes.h:2792
bool has_clone
Definition: pathnodes.h:2804
Index tleSortGroupRef
Definition: parsenodes.h:1469
Relids commute_above_r
Definition: pathnodes.h:3124
Relids syn_lefthand
Definition: pathnodes.h:3119
JoinType jointype
Definition: pathnodes.h:3121
Relids syn_righthand
Definition: pathnodes.h:3120
Oid btree_opintype
Definition: typcache.h:59
Oid typcollation
Definition: typcache.h:48
Definition: primnodes.h:262
AttrNumber varattno
Definition: primnodes.h:274
int varno
Definition: primnodes.h:269
Index varlevelsup
Definition: primnodes.h:294
Definition: regcomp.c:282
SortGroupClause * get_sortgroupref_clause(Index sortref, List *clauses)
Definition: tlist.c:422
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:681
void add_new_column_to_pathtarget(PathTarget *target, Expr *expr)
Definition: tlist.c:741
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:695
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_BTREE_OPFAMILY
Definition: typcache.h:147
List * pull_var_clause(Node *node, int flags)
Definition: var.c:653