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