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-2018, 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 "optimizer/clauses.h"
21 #include "optimizer/cost.h"
22 #include "optimizer/pathnode.h"
23 #include "optimizer/paths.h"
24 #include "optimizer/placeholder.h"
25 #include "optimizer/plancat.h"
26 #include "optimizer/prep.h"
27 #include "optimizer/restrictinfo.h"
28 #include "optimizer/tlist.h"
30 #include "utils/hsearch.h"
31 
32 
33 typedef struct JoinHashEntry
34 {
35  Relids join_relids; /* hash key --- MUST BE FIRST */
38 
39 static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
40  RelOptInfo *input_rel);
42  RelOptInfo *joinrel,
43  RelOptInfo *outer_rel,
44  RelOptInfo *inner_rel);
45 static void build_joinrel_joinlist(RelOptInfo *joinrel,
46  RelOptInfo *outer_rel,
47  RelOptInfo *inner_rel);
49  List *joininfo_list,
50  List *new_restrictlist);
52  List *joininfo_list,
53  List *new_joininfo);
54 static void set_foreign_rel_properties(RelOptInfo *joinrel,
55  RelOptInfo *outer_rel, RelOptInfo *inner_rel);
56 static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel);
57 static void build_joinrel_partition_info(RelOptInfo *joinrel,
58  RelOptInfo *outer_rel, RelOptInfo *inner_rel,
59  List *restrictlist, JoinType jointype);
60 
61 
62 /*
63  * setup_simple_rel_arrays
64  * Prepare the arrays we use for quickly accessing base relations.
65  */
66 void
68 {
69  Index rti;
70  ListCell *lc;
71 
72  /* Arrays are accessed using RT indexes (1..N) */
73  root->simple_rel_array_size = list_length(root->parse->rtable) + 1;
74 
75  /* simple_rel_array is initialized to all NULLs */
76  root->simple_rel_array = (RelOptInfo **)
77  palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *));
78 
79  /* simple_rte_array is an array equivalent of the rtable list */
80  root->simple_rte_array = (RangeTblEntry **)
81  palloc0(root->simple_rel_array_size * sizeof(RangeTblEntry *));
82  rti = 1;
83  foreach(lc, root->parse->rtable)
84  {
85  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
86 
87  root->simple_rte_array[rti++] = rte;
88  }
89 }
90 
91 /*
92  * build_simple_rel
93  * Construct a new RelOptInfo for a base relation or 'other' relation.
94  */
95 RelOptInfo *
96 build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
97 {
98  RelOptInfo *rel;
99  RangeTblEntry *rte;
100 
101  /* Rel should not exist already */
102  Assert(relid > 0 && relid < root->simple_rel_array_size);
103  if (root->simple_rel_array[relid] != NULL)
104  elog(ERROR, "rel %d already exists", relid);
105 
106  /* Fetch RTE for relation */
107  rte = root->simple_rte_array[relid];
108  Assert(rte != NULL);
109 
110  rel = makeNode(RelOptInfo);
112  rel->relids = bms_make_singleton(relid);
113  rel->rows = 0;
114  /* cheap startup cost is interesting iff not all tuples to be retrieved */
115  rel->consider_startup = (root->tuple_fraction > 0);
116  rel->consider_param_startup = false; /* might get changed later */
117  rel->consider_parallel = false; /* might get changed later */
119  rel->pathlist = NIL;
120  rel->ppilist = NIL;
121  rel->partial_pathlist = NIL;
122  rel->cheapest_startup_path = NULL;
123  rel->cheapest_total_path = NULL;
124  rel->cheapest_unique_path = NULL;
126  rel->direct_lateral_relids = NULL;
127  rel->lateral_relids = NULL;
128  rel->relid = relid;
129  rel->rtekind = rte->rtekind;
130  /* min_attr, max_attr, attr_needed, attr_widths are set below */
131  rel->lateral_vars = NIL;
132  rel->lateral_referencers = NULL;
133  rel->indexlist = NIL;
134  rel->statlist = NIL;
135  rel->pages = 0;
136  rel->tuples = 0;
137  rel->allvisfrac = 0;
138  rel->subroot = NULL;
139  rel->subplan_params = NIL;
140  rel->rel_parallel_workers = -1; /* set up in get_relation_info */
141  rel->serverid = InvalidOid;
142  rel->userid = rte->checkAsUser;
143  rel->useridiscurrent = false;
144  rel->fdwroutine = NULL;
145  rel->fdw_private = NULL;
146  rel->unique_for_rels = NIL;
147  rel->non_unique_for_rels = NIL;
148  rel->baserestrictinfo = NIL;
149  rel->baserestrictcost.startup = 0;
150  rel->baserestrictcost.per_tuple = 0;
151  rel->baserestrict_min_security = UINT_MAX;
152  rel->joininfo = NIL;
153  rel->has_eclass_joins = false;
154  rel->part_scheme = NULL;
155  rel->nparts = 0;
156  rel->boundinfo = NULL;
157  rel->partition_qual = NIL;
158  rel->part_rels = NULL;
159  rel->partexprs = NULL;
160  rel->nullable_partexprs = NULL;
162 
163  /*
164  * Pass top parent's relids down the inheritance hierarchy. If the parent
165  * has top_parent_relids set, it's a direct or an indirect child of the
166  * top parent indicated by top_parent_relids. By extension this child is
167  * also an indirect child of that parent.
168  */
169  if (parent)
170  {
171  if (parent->top_parent_relids)
172  rel->top_parent_relids = parent->top_parent_relids;
173  else
174  rel->top_parent_relids = bms_copy(parent->relids);
175  }
176  else
177  rel->top_parent_relids = NULL;
178 
179  /* Check type of rtable entry */
180  switch (rte->rtekind)
181  {
182  case RTE_RELATION:
183  /* Table --- retrieve statistics from the system catalogs */
184  get_relation_info(root, rte->relid, rte->inh, rel);
185  break;
186  case RTE_SUBQUERY:
187  case RTE_FUNCTION:
188  case RTE_TABLEFUNC:
189  case RTE_VALUES:
190  case RTE_CTE:
191  case RTE_NAMEDTUPLESTORE:
192 
193  /*
194  * Subquery, function, tablefunc, values list, CTE, or ENR --- set
195  * up attr range and arrays
196  *
197  * Note: 0 is included in range to support whole-row Vars
198  */
199  rel->min_attr = 0;
200  rel->max_attr = list_length(rte->eref->colnames);
201  rel->attr_needed = (Relids *)
202  palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
203  rel->attr_widths = (int32 *)
204  palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
205  break;
206  default:
207  elog(ERROR, "unrecognized RTE kind: %d",
208  (int) rte->rtekind);
209  break;
210  }
211 
212  /* Save the finished struct in the query's simple_rel_array */
213  root->simple_rel_array[relid] = rel;
214 
215  /*
216  * This is a convenient spot at which to note whether rels participating
217  * in the query have any securityQuals attached. If so, increase
218  * root->qual_security_level to ensure it's larger than the maximum
219  * security level needed for securityQuals.
220  */
221  if (rte->securityQuals)
223  list_length(rte->securityQuals));
224 
225  /*
226  * If this rel is an appendrel parent, recurse to build "other rel"
227  * RelOptInfos for its children. They are "other rels" because they are
228  * not in the main join tree, but we will need RelOptInfos to plan access
229  * to them.
230  */
231  if (rte->inh)
232  {
233  ListCell *l;
234  int nparts = rel->nparts;
235  int cnt_parts = 0;
236 
237  if (nparts > 0)
238  rel->part_rels = (RelOptInfo **)
239  palloc(sizeof(RelOptInfo *) * nparts);
240 
241  foreach(l, root->append_rel_list)
242  {
243  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
244  RelOptInfo *childrel;
245 
246  /* append_rel_list contains all append rels; ignore others */
247  if (appinfo->parent_relid != relid)
248  continue;
249 
250  childrel = build_simple_rel(root, appinfo->child_relid,
251  rel);
252 
253  /* Nothing more to do for an unpartitioned table. */
254  if (!rel->part_scheme)
255  continue;
256 
257  /*
258  * The order of partition OIDs in append_rel_list is the same as
259  * the order in the PartitionDesc, so the order of part_rels will
260  * also match the PartitionDesc. See expand_partitioned_rtentry.
261  */
262  Assert(cnt_parts < nparts);
263  rel->part_rels[cnt_parts] = childrel;
264  cnt_parts++;
265  }
266 
267  /* We should have seen all the child partitions. */
268  Assert(cnt_parts == nparts);
269  }
270 
271  return rel;
272 }
273 
274 /*
275  * find_base_rel
276  * Find a base or other relation entry, which must already exist.
277  */
278 RelOptInfo *
279 find_base_rel(PlannerInfo *root, int relid)
280 {
281  RelOptInfo *rel;
282 
283  Assert(relid > 0);
284 
285  if (relid < root->simple_rel_array_size)
286  {
287  rel = root->simple_rel_array[relid];
288  if (rel)
289  return rel;
290  }
291 
292  elog(ERROR, "no relation entry for relid %d", relid);
293 
294  return NULL; /* keep compiler quiet */
295 }
296 
297 /*
298  * build_join_rel_hash
299  * Construct the auxiliary hash table for join relations.
300  */
301 static void
303 {
304  HTAB *hashtab;
305  HASHCTL hash_ctl;
306  ListCell *l;
307 
308  /* Create the hash table */
309  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
310  hash_ctl.keysize = sizeof(Relids);
311  hash_ctl.entrysize = sizeof(JoinHashEntry);
312  hash_ctl.hash = bitmap_hash;
313  hash_ctl.match = bitmap_match;
314  hash_ctl.hcxt = CurrentMemoryContext;
315  hashtab = hash_create("JoinRelHashTable",
316  256L,
317  &hash_ctl,
319 
320  /* Insert all the already-existing joinrels */
321  foreach(l, root->join_rel_list)
322  {
323  RelOptInfo *rel = (RelOptInfo *) lfirst(l);
324  JoinHashEntry *hentry;
325  bool found;
326 
327  hentry = (JoinHashEntry *) hash_search(hashtab,
328  &(rel->relids),
329  HASH_ENTER,
330  &found);
331  Assert(!found);
332  hentry->join_rel = rel;
333  }
334 
335  root->join_rel_hash = hashtab;
336 }
337 
338 /*
339  * find_join_rel
340  * Returns relation entry corresponding to 'relids' (a set of RT indexes),
341  * or NULL if none exists. This is for join relations.
342  */
343 RelOptInfo *
345 {
346  /*
347  * Switch to using hash lookup when list grows "too long". The threshold
348  * is arbitrary and is known only here.
349  */
350  if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)
351  build_join_rel_hash(root);
352 
353  /*
354  * Use either hashtable lookup or linear search, as appropriate.
355  *
356  * Note: the seemingly redundant hashkey variable is used to avoid taking
357  * the address of relids; unless the compiler is exceedingly smart, doing
358  * so would force relids out of a register and thus probably slow down the
359  * list-search case.
360  */
361  if (root->join_rel_hash)
362  {
363  Relids hashkey = relids;
364  JoinHashEntry *hentry;
365 
366  hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
367  &hashkey,
368  HASH_FIND,
369  NULL);
370  if (hentry)
371  return hentry->join_rel;
372  }
373  else
374  {
375  ListCell *l;
376 
377  foreach(l, root->join_rel_list)
378  {
379  RelOptInfo *rel = (RelOptInfo *) lfirst(l);
380 
381  if (bms_equal(rel->relids, relids))
382  return rel;
383  }
384  }
385 
386  return NULL;
387 }
388 
389 /*
390  * set_foreign_rel_properties
391  * Set up foreign-join fields if outer and inner relation are foreign
392  * tables (or joins) belonging to the same server and assigned to the same
393  * user to check access permissions as.
394  *
395  * In addition to an exact match of userid, we allow the case where one side
396  * has zero userid (implying current user) and the other side has explicit
397  * userid that happens to equal the current user; but in that case, pushdown of
398  * the join is only valid for the current user. The useridiscurrent field
399  * records whether we had to make such an assumption for this join or any
400  * sub-join.
401  *
402  * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
403  * called for the join relation.
404  *
405  */
406 static void
408  RelOptInfo *inner_rel)
409 {
410  if (OidIsValid(outer_rel->serverid) &&
411  inner_rel->serverid == outer_rel->serverid)
412  {
413  if (inner_rel->userid == outer_rel->userid)
414  {
415  joinrel->serverid = outer_rel->serverid;
416  joinrel->userid = outer_rel->userid;
417  joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
418  joinrel->fdwroutine = outer_rel->fdwroutine;
419  }
420  else if (!OidIsValid(inner_rel->userid) &&
421  outer_rel->userid == GetUserId())
422  {
423  joinrel->serverid = outer_rel->serverid;
424  joinrel->userid = outer_rel->userid;
425  joinrel->useridiscurrent = true;
426  joinrel->fdwroutine = outer_rel->fdwroutine;
427  }
428  else if (!OidIsValid(outer_rel->userid) &&
429  inner_rel->userid == GetUserId())
430  {
431  joinrel->serverid = outer_rel->serverid;
432  joinrel->userid = inner_rel->userid;
433  joinrel->useridiscurrent = true;
434  joinrel->fdwroutine = outer_rel->fdwroutine;
435  }
436  }
437 }
438 
439 /*
440  * add_join_rel
441  * Add given join relation to the list of join relations in the given
442  * PlannerInfo. Also add it to the auxiliary hashtable if there is one.
443  */
444 static void
446 {
447  /* GEQO requires us to append the new joinrel to the end of the list! */
448  root->join_rel_list = lappend(root->join_rel_list, joinrel);
449 
450  /* store it into the auxiliary hashtable if there is one. */
451  if (root->join_rel_hash)
452  {
453  JoinHashEntry *hentry;
454  bool found;
455 
456  hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
457  &(joinrel->relids),
458  HASH_ENTER,
459  &found);
460  Assert(!found);
461  hentry->join_rel = joinrel;
462  }
463 }
464 
465 /*
466  * build_join_rel
467  * Returns relation entry corresponding to the union of two given rels,
468  * creating a new relation entry if none already exists.
469  *
470  * 'joinrelids' is the Relids set that uniquely identifies the join
471  * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
472  * joined
473  * 'sjinfo': join context info
474  * 'restrictlist_ptr': result variable. If not NULL, *restrictlist_ptr
475  * receives the list of RestrictInfo nodes that apply to this
476  * particular pair of joinable relations.
477  *
478  * restrictlist_ptr makes the routine's API a little grotty, but it saves
479  * duplicated calculation of the restrictlist...
480  */
481 RelOptInfo *
483  Relids joinrelids,
484  RelOptInfo *outer_rel,
485  RelOptInfo *inner_rel,
486  SpecialJoinInfo *sjinfo,
487  List **restrictlist_ptr)
488 {
489  RelOptInfo *joinrel;
490  List *restrictlist;
491 
492  /* This function should be used only for join between parents. */
493  Assert(!IS_OTHER_REL(outer_rel) && !IS_OTHER_REL(inner_rel));
494 
495  /*
496  * See if we already have a joinrel for this set of base rels.
497  */
498  joinrel = find_join_rel(root, joinrelids);
499 
500  if (joinrel)
501  {
502  /*
503  * Yes, so we only need to figure the restrictlist for this particular
504  * pair of component relations.
505  */
506  if (restrictlist_ptr)
507  *restrictlist_ptr = build_joinrel_restrictlist(root,
508  joinrel,
509  outer_rel,
510  inner_rel);
511  return joinrel;
512  }
513 
514  /*
515  * Nope, so make one.
516  */
517  joinrel = makeNode(RelOptInfo);
518  joinrel->reloptkind = RELOPT_JOINREL;
519  joinrel->relids = bms_copy(joinrelids);
520  joinrel->rows = 0;
521  /* cheap startup cost is interesting iff not all tuples to be retrieved */
522  joinrel->consider_startup = (root->tuple_fraction > 0);
523  joinrel->consider_param_startup = false;
524  joinrel->consider_parallel = false;
525  joinrel->reltarget = create_empty_pathtarget();
526  joinrel->pathlist = NIL;
527  joinrel->ppilist = NIL;
528  joinrel->partial_pathlist = NIL;
529  joinrel->cheapest_startup_path = NULL;
530  joinrel->cheapest_total_path = NULL;
531  joinrel->cheapest_unique_path = NULL;
533  /* init direct_lateral_relids from children; we'll finish it up below */
534  joinrel->direct_lateral_relids =
535  bms_union(outer_rel->direct_lateral_relids,
536  inner_rel->direct_lateral_relids);
537  joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids,
538  outer_rel, inner_rel);
539  joinrel->relid = 0; /* indicates not a baserel */
540  joinrel->rtekind = RTE_JOIN;
541  joinrel->min_attr = 0;
542  joinrel->max_attr = 0;
543  joinrel->attr_needed = NULL;
544  joinrel->attr_widths = NULL;
545  joinrel->lateral_vars = NIL;
546  joinrel->lateral_referencers = NULL;
547  joinrel->indexlist = NIL;
548  joinrel->statlist = NIL;
549  joinrel->pages = 0;
550  joinrel->tuples = 0;
551  joinrel->allvisfrac = 0;
552  joinrel->subroot = NULL;
553  joinrel->subplan_params = NIL;
554  joinrel->rel_parallel_workers = -1;
555  joinrel->serverid = InvalidOid;
556  joinrel->userid = InvalidOid;
557  joinrel->useridiscurrent = false;
558  joinrel->fdwroutine = NULL;
559  joinrel->fdw_private = NULL;
560  joinrel->unique_for_rels = NIL;
561  joinrel->non_unique_for_rels = NIL;
562  joinrel->baserestrictinfo = NIL;
563  joinrel->baserestrictcost.startup = 0;
564  joinrel->baserestrictcost.per_tuple = 0;
565  joinrel->baserestrict_min_security = UINT_MAX;
566  joinrel->joininfo = NIL;
567  joinrel->has_eclass_joins = false;
568  joinrel->top_parent_relids = NULL;
569  joinrel->part_scheme = NULL;
570  joinrel->nparts = 0;
571  joinrel->boundinfo = NULL;
572  joinrel->partition_qual = NIL;
573  joinrel->part_rels = NULL;
574  joinrel->partexprs = NULL;
575  joinrel->nullable_partexprs = NULL;
576  joinrel->partitioned_child_rels = NIL;
577 
578  /* Compute information relevant to the foreign relations. */
579  set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
580 
581  /*
582  * Create a new tlist containing just the vars that need to be output from
583  * this join (ie, are needed for higher joinclauses or final output).
584  *
585  * NOTE: the tlist order for a join rel will depend on which pair of outer
586  * and inner rels we first try to build it from. But the contents should
587  * be the same regardless.
588  */
589  build_joinrel_tlist(root, joinrel, outer_rel);
590  build_joinrel_tlist(root, joinrel, inner_rel);
591  add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel);
592 
593  /*
594  * add_placeholders_to_joinrel also took care of adding the ph_lateral
595  * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
596  * now we can finish computing that. This is much like the computation of
597  * the transitively-closed lateral_relids in min_join_parameterization,
598  * except that here we *do* have to consider the added PHVs.
599  */
600  joinrel->direct_lateral_relids =
601  bms_del_members(joinrel->direct_lateral_relids, joinrel->relids);
602  if (bms_is_empty(joinrel->direct_lateral_relids))
603  joinrel->direct_lateral_relids = NULL;
604 
605  /*
606  * Construct restrict and join clause lists for the new joinrel. (The
607  * caller might or might not need the restrictlist, but I need it anyway
608  * for set_joinrel_size_estimates().)
609  */
610  restrictlist = build_joinrel_restrictlist(root, joinrel,
611  outer_rel, inner_rel);
612  if (restrictlist_ptr)
613  *restrictlist_ptr = restrictlist;
614  build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
615 
616  /*
617  * This is also the right place to check whether the joinrel has any
618  * pending EquivalenceClass joins.
619  */
620  joinrel->has_eclass_joins = has_relevant_eclass_joinclause(root, joinrel);
621 
622  /* Store the partition information. */
623  build_joinrel_partition_info(joinrel, outer_rel, inner_rel, restrictlist,
624  sjinfo->jointype);
625 
626  /*
627  * Set estimates of the joinrel's size.
628  */
629  set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
630  sjinfo, restrictlist);
631 
632  /*
633  * Set the consider_parallel flag if this joinrel could potentially be
634  * scanned within a parallel worker. If this flag is false for either
635  * inner_rel or outer_rel, then it must be false for the joinrel also.
636  * Even if both are true, there might be parallel-restricted expressions
637  * in the targetlist or quals.
638  *
639  * Note that if there are more than two rels in this relation, they could
640  * be divided between inner_rel and outer_rel in any arbitrary way. We
641  * assume this doesn't matter, because we should hit all the same baserels
642  * and joinclauses while building up to this joinrel no matter which we
643  * take; therefore, we should make the same decision here however we get
644  * here.
645  */
646  if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
647  is_parallel_safe(root, (Node *) restrictlist) &&
648  is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
649  joinrel->consider_parallel = true;
650 
651  /* Add the joinrel to the PlannerInfo. */
652  add_join_rel(root, joinrel);
653 
654  /*
655  * Also, if dynamic-programming join search is active, add the new joinrel
656  * to the appropriate sublist. Note: you might think the Assert on number
657  * of members should be for equality, but some of the level 1 rels might
658  * have been joinrels already, so we can only assert <=.
659  */
660  if (root->join_rel_level)
661  {
662  Assert(root->join_cur_level > 0);
663  Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
664  root->join_rel_level[root->join_cur_level] =
665  lappend(root->join_rel_level[root->join_cur_level], joinrel);
666  }
667 
668  return joinrel;
669 }
670 
671 /*
672  * build_child_join_rel
673  * Builds RelOptInfo representing join between given two child relations.
674  *
675  * 'outer_rel' and 'inner_rel' are the RelOptInfos of child relations being
676  * joined
677  * 'parent_joinrel' is the RelOptInfo representing the join between parent
678  * relations. Some of the members of new RelOptInfo are produced by
679  * translating corresponding members of this RelOptInfo
680  * 'sjinfo': child-join context info
681  * 'restrictlist': list of RestrictInfo nodes that apply to this particular
682  * pair of joinable relations
683  * 'jointype' is the join type (inner, left, full, etc)
684  */
685 RelOptInfo *
687  RelOptInfo *inner_rel, RelOptInfo *parent_joinrel,
688  List *restrictlist, SpecialJoinInfo *sjinfo,
689  JoinType jointype)
690 {
691  RelOptInfo *joinrel = makeNode(RelOptInfo);
692  AppendRelInfo **appinfos;
693  int nappinfos;
694 
695  /* Only joins between "other" relations land here. */
696  Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
697 
698  joinrel->reloptkind = RELOPT_OTHER_JOINREL;
699  joinrel->relids = bms_union(outer_rel->relids, inner_rel->relids);
700  joinrel->rows = 0;
701  /* cheap startup cost is interesting iff not all tuples to be retrieved */
702  joinrel->consider_startup = (root->tuple_fraction > 0);
703  joinrel->consider_param_startup = false;
704  joinrel->consider_parallel = false;
705  joinrel->reltarget = create_empty_pathtarget();
706  joinrel->pathlist = NIL;
707  joinrel->ppilist = NIL;
708  joinrel->partial_pathlist = NIL;
709  joinrel->cheapest_startup_path = NULL;
710  joinrel->cheapest_total_path = NULL;
711  joinrel->cheapest_unique_path = NULL;
713  joinrel->direct_lateral_relids = NULL;
714  joinrel->lateral_relids = NULL;
715  joinrel->relid = 0; /* indicates not a baserel */
716  joinrel->rtekind = RTE_JOIN;
717  joinrel->min_attr = 0;
718  joinrel->max_attr = 0;
719  joinrel->attr_needed = NULL;
720  joinrel->attr_widths = NULL;
721  joinrel->lateral_vars = NIL;
722  joinrel->lateral_referencers = NULL;
723  joinrel->indexlist = NIL;
724  joinrel->pages = 0;
725  joinrel->tuples = 0;
726  joinrel->allvisfrac = 0;
727  joinrel->subroot = NULL;
728  joinrel->subplan_params = NIL;
729  joinrel->serverid = InvalidOid;
730  joinrel->userid = InvalidOid;
731  joinrel->useridiscurrent = false;
732  joinrel->fdwroutine = NULL;
733  joinrel->fdw_private = NULL;
734  joinrel->baserestrictinfo = NIL;
735  joinrel->baserestrictcost.startup = 0;
736  joinrel->baserestrictcost.per_tuple = 0;
737  joinrel->joininfo = NIL;
738  joinrel->has_eclass_joins = false;
739  joinrel->top_parent_relids = NULL;
740  joinrel->part_scheme = NULL;
741  joinrel->nparts = 0;
742  joinrel->boundinfo = NULL;
743  joinrel->partition_qual = NIL;
744  joinrel->part_rels = NULL;
745  joinrel->partexprs = NULL;
746  joinrel->nullable_partexprs = NULL;
747  joinrel->partitioned_child_rels = NIL;
748 
749  joinrel->top_parent_relids = bms_union(outer_rel->top_parent_relids,
750  inner_rel->top_parent_relids);
751 
752  /* Compute information relevant to foreign relations. */
753  set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
754 
755  /* Build targetlist */
756  build_joinrel_tlist(root, joinrel, outer_rel);
757  build_joinrel_tlist(root, joinrel, inner_rel);
758  /* Add placeholder variables. */
759  add_placeholders_to_child_joinrel(root, joinrel, parent_joinrel);
760 
761  /* Construct joininfo list. */
762  appinfos = find_appinfos_by_relids(root, joinrel->relids, &nappinfos);
763  joinrel->joininfo = (List *) adjust_appendrel_attrs(root,
764  (Node *) parent_joinrel->joininfo,
765  nappinfos,
766  appinfos);
767  pfree(appinfos);
768 
769  /*
770  * Lateral relids referred in child join will be same as that referred in
771  * the parent relation. Throw any partial result computed while building
772  * the targetlist.
773  */
775  bms_free(joinrel->lateral_relids);
776  joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
777  joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
778 
779  /*
780  * If the parent joinrel has pending equivalence classes, so does the
781  * child.
782  */
783  joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
784 
785  /* Is the join between partitions itself partitioned? */
786  build_joinrel_partition_info(joinrel, outer_rel, inner_rel, restrictlist,
787  jointype);
788 
789  /* Child joinrel is parallel safe if parent is parallel safe. */
790  joinrel->consider_parallel = parent_joinrel->consider_parallel;
791 
792 
793  /* Set estimates of the child-joinrel's size. */
794  set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
795  sjinfo, restrictlist);
796 
797  /* We build the join only once. */
798  Assert(!find_join_rel(root, joinrel->relids));
799 
800  /* Add the relation to the PlannerInfo. */
801  add_join_rel(root, joinrel);
802 
803  return joinrel;
804 }
805 
806 /*
807  * min_join_parameterization
808  *
809  * Determine the minimum possible parameterization of a joinrel, that is, the
810  * set of other rels it contains LATERAL references to. We save this value in
811  * the join's RelOptInfo. This function is split out of build_join_rel()
812  * because join_is_legal() needs the value to check a prospective join.
813  */
814 Relids
816  Relids joinrelids,
817  RelOptInfo *outer_rel,
818  RelOptInfo *inner_rel)
819 {
820  Relids result;
821 
822  /*
823  * Basically we just need the union of the inputs' lateral_relids, less
824  * whatever is already in the join.
825  *
826  * It's not immediately obvious that this is a valid way to compute the
827  * result, because it might seem that we're ignoring possible lateral refs
828  * of PlaceHolderVars that are due to be computed at the join but not in
829  * either input. However, because create_lateral_join_info() already
830  * charged all such PHV refs to each member baserel of the join, they'll
831  * be accounted for already in the inputs' lateral_relids. Likewise, we
832  * do not need to worry about doing transitive closure here, because that
833  * was already accounted for in the original baserel lateral_relids.
834  */
835  result = bms_union(outer_rel->lateral_relids, inner_rel->lateral_relids);
836  result = bms_del_members(result, joinrelids);
837 
838  /* Maintain invariant that result is exactly NULL if empty */
839  if (bms_is_empty(result))
840  result = NULL;
841 
842  return result;
843 }
844 
845 /*
846  * build_joinrel_tlist
847  * Builds a join relation's target list from an input relation.
848  * (This is invoked twice to handle the two input relations.)
849  *
850  * The join's targetlist includes all Vars of its member relations that
851  * will still be needed above the join. This subroutine adds all such
852  * Vars from the specified input rel's tlist to the join rel's tlist.
853  *
854  * We also compute the expected width of the join's output, making use
855  * of data that was cached at the baserel level by set_rel_width().
856  */
857 static void
859  RelOptInfo *input_rel)
860 {
861  Relids relids;
862  ListCell *vars;
863 
864  /* attrs_needed refers to parent relids and not those of a child. */
865  if (joinrel->top_parent_relids)
866  relids = joinrel->top_parent_relids;
867  else
868  relids = joinrel->relids;
869 
870  foreach(vars, input_rel->reltarget->exprs)
871  {
872  Var *var = (Var *) lfirst(vars);
873  RelOptInfo *baserel;
874  int ndx;
875 
876  /*
877  * Ignore PlaceHolderVars in the input tlists; we'll make our own
878  * decisions about whether to copy them.
879  */
880  if (IsA(var, PlaceHolderVar))
881  continue;
882 
883  /*
884  * Otherwise, anything in a baserel or joinrel targetlist ought to be
885  * a Var. Children of a partitioned table may have ConvertRowtypeExpr
886  * translating whole-row Var of a child to that of the parent.
887  * Children of an inherited table or subquery child rels can not
888  * directly participate in a join, so other kinds of nodes here.
889  */
890  if (IsA(var, Var))
891  {
892  baserel = find_base_rel(root, var->varno);
893  ndx = var->varattno - baserel->min_attr;
894  }
895  else if (IsA(var, ConvertRowtypeExpr))
896  {
897  ConvertRowtypeExpr *child_expr = (ConvertRowtypeExpr *) var;
898  Var *childvar = (Var *) child_expr->arg;
899 
900  /*
901  * Child's whole-row references are converted to look like those
902  * of parent using ConvertRowtypeExpr. There can be as many
903  * ConvertRowtypeExpr decorations as the depth of partition tree.
904  * The argument to the deepest ConvertRowtypeExpr is expected to
905  * be a whole-row reference of the child.
906  */
907  while (IsA(childvar, ConvertRowtypeExpr))
908  {
909  child_expr = (ConvertRowtypeExpr *) childvar;
910  childvar = (Var *) child_expr->arg;
911  }
912  Assert(IsA(childvar, Var) &&childvar->varattno == 0);
913 
914  baserel = find_base_rel(root, childvar->varno);
915  ndx = 0 - baserel->min_attr;
916  }
917  else
918  elog(ERROR, "unexpected node type in rel targetlist: %d",
919  (int) nodeTag(var));
920 
921 
922  /* Is the target expression still needed above this joinrel? */
923  if (bms_nonempty_difference(baserel->attr_needed[ndx], relids))
924  {
925  /* Yup, add it to the output */
926  joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs, var);
927 
928  /*
929  * Vars have cost zero, so no need to adjust reltarget->cost. Even
930  * if it's a ConvertRowtypeExpr, it will be computed only for the
931  * base relation, costing nothing for a join.
932  */
933  joinrel->reltarget->width += baserel->attr_widths[ndx];
934  }
935  }
936 }
937 
938 /*
939  * build_joinrel_restrictlist
940  * build_joinrel_joinlist
941  * These routines build lists of restriction and join clauses for a
942  * join relation from the joininfo lists of the relations it joins.
943  *
944  * These routines are separate because the restriction list must be
945  * built afresh for each pair of input sub-relations we consider, whereas
946  * the join list need only be computed once for any join RelOptInfo.
947  * The join list is fully determined by the set of rels making up the
948  * joinrel, so we should get the same results (up to ordering) from any
949  * candidate pair of sub-relations. But the restriction list is whatever
950  * is not handled in the sub-relations, so it depends on which
951  * sub-relations are considered.
952  *
953  * If a join clause from an input relation refers to base rels still not
954  * present in the joinrel, then it is still a join clause for the joinrel;
955  * we put it into the joininfo list for the joinrel. Otherwise,
956  * the clause is now a restrict clause for the joined relation, and we
957  * return it to the caller of build_joinrel_restrictlist() to be stored in
958  * join paths made from this pair of sub-relations. (It will not need to
959  * be considered further up the join tree.)
960  *
961  * In many case we will find the same RestrictInfos in both input
962  * relations' joinlists, so be careful to eliminate duplicates.
963  * Pointer equality should be a sufficient test for dups, since all
964  * the various joinlist entries ultimately refer to RestrictInfos
965  * pushed into them by distribute_restrictinfo_to_rels().
966  *
967  * 'joinrel' is a join relation node
968  * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
969  * to form joinrel.
970  *
971  * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
972  * whereas build_joinrel_joinlist() stores its results in the joinrel's
973  * joininfo list. One or the other must accept each given clause!
974  *
975  * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
976  * up to the join relation. I believe this is no longer necessary, because
977  * RestrictInfo nodes are no longer context-dependent. Instead, just include
978  * the original nodes in the lists made for the join relation.
979  */
980 static List *
982  RelOptInfo *joinrel,
983  RelOptInfo *outer_rel,
984  RelOptInfo *inner_rel)
985 {
986  List *result;
987 
988  /*
989  * Collect all the clauses that syntactically belong at this level,
990  * eliminating any duplicates (important since we will see many of the
991  * same clauses arriving from both input relations).
992  */
993  result = subbuild_joinrel_restrictlist(joinrel, outer_rel->joininfo, NIL);
994  result = subbuild_joinrel_restrictlist(joinrel, inner_rel->joininfo, result);
995 
996  /*
997  * Add on any clauses derived from EquivalenceClasses. These cannot be
998  * redundant with the clauses in the joininfo lists, so don't bother
999  * checking.
1000  */
1001  result = list_concat(result,
1003  joinrel->relids,
1004  outer_rel->relids,
1005  inner_rel));
1006 
1007  return result;
1008 }
1009 
1010 static void
1012  RelOptInfo *outer_rel,
1013  RelOptInfo *inner_rel)
1014 {
1015  List *result;
1016 
1017  /*
1018  * Collect all the clauses that syntactically belong above this level,
1019  * eliminating any duplicates (important since we will see many of the
1020  * same clauses arriving from both input relations).
1021  */
1022  result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL);
1023  result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result);
1024 
1025  joinrel->joininfo = result;
1026 }
1027 
1028 static List *
1030  List *joininfo_list,
1031  List *new_restrictlist)
1032 {
1033  ListCell *l;
1034 
1035  foreach(l, joininfo_list)
1036  {
1037  RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1038 
1039  if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1040  {
1041  /*
1042  * This clause becomes a restriction clause for the joinrel, since
1043  * it refers to no outside rels. Add it to the list, being
1044  * careful to eliminate duplicates. (Since RestrictInfo nodes in
1045  * different joinlists will have been multiply-linked rather than
1046  * copied, pointer equality should be a sufficient test.)
1047  */
1048  new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
1049  }
1050  else
1051  {
1052  /*
1053  * This clause is still a join clause at this level, so we ignore
1054  * it in this routine.
1055  */
1056  }
1057  }
1058 
1059  return new_restrictlist;
1060 }
1061 
1062 static List *
1064  List *joininfo_list,
1065  List *new_joininfo)
1066 {
1067  ListCell *l;
1068 
1069  /* Expected to be called only for join between parent relations. */
1070  Assert(joinrel->reloptkind == RELOPT_JOINREL);
1071 
1072  foreach(l, joininfo_list)
1073  {
1074  RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1075 
1076  if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1077  {
1078  /*
1079  * This clause becomes a restriction clause for the joinrel, since
1080  * it refers to no outside rels. So we can ignore it in this
1081  * routine.
1082  */
1083  }
1084  else
1085  {
1086  /*
1087  * This clause is still a join clause at this level, so add it to
1088  * the new joininfo list, being careful to eliminate duplicates.
1089  * (Since RestrictInfo nodes in different joinlists will have been
1090  * multiply-linked rather than copied, pointer equality should be
1091  * a sufficient test.)
1092  */
1093  new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
1094  }
1095  }
1096 
1097  return new_joininfo;
1098 }
1099 
1100 
1101 /*
1102  * build_empty_join_rel
1103  * Build a dummy join relation describing an empty set of base rels.
1104  *
1105  * This is used for queries with empty FROM clauses, such as "SELECT 2+2" or
1106  * "INSERT INTO foo VALUES(...)". We don't try very hard to make the empty
1107  * joinrel completely valid, since no real planning will be done with it ---
1108  * we just need it to carry a simple Result path out of query_planner().
1109  */
1110 RelOptInfo *
1112 {
1113  RelOptInfo *joinrel;
1114 
1115  /* The dummy join relation should be the only one ... */
1116  Assert(root->join_rel_list == NIL);
1117 
1118  joinrel = makeNode(RelOptInfo);
1119  joinrel->reloptkind = RELOPT_JOINREL;
1120  joinrel->relids = NULL; /* empty set */
1121  joinrel->rows = 1; /* we produce one row for such cases */
1122  joinrel->rtekind = RTE_JOIN;
1123  joinrel->reltarget = create_empty_pathtarget();
1124 
1125  root->join_rel_list = lappend(root->join_rel_list, joinrel);
1126 
1127  return joinrel;
1128 }
1129 
1130 
1131 /*
1132  * fetch_upper_rel
1133  * Build a RelOptInfo describing some post-scan/join query processing,
1134  * or return a pre-existing one if somebody already built it.
1135  *
1136  * An "upper" relation is identified by an UpperRelationKind and a Relids set.
1137  * The meaning of the Relids set is not specified here, and very likely will
1138  * vary for different relation kinds.
1139  *
1140  * Most of the fields in an upper-level RelOptInfo are not used and are not
1141  * set here (though makeNode should ensure they're zeroes). We basically only
1142  * care about fields that are of interest to add_path() and set_cheapest().
1143  */
1144 RelOptInfo *
1146 {
1147  RelOptInfo *upperrel;
1148  ListCell *lc;
1149 
1150  /*
1151  * For the moment, our indexing data structure is just a List for each
1152  * relation kind. If we ever get so many of one kind that this stops
1153  * working well, we can improve it. No code outside this function should
1154  * assume anything about how to find a particular upperrel.
1155  */
1156 
1157  /* If we already made this upperrel for the query, return it */
1158  foreach(lc, root->upper_rels[kind])
1159  {
1160  upperrel = (RelOptInfo *) lfirst(lc);
1161 
1162  if (bms_equal(upperrel->relids, relids))
1163  return upperrel;
1164  }
1165 
1166  upperrel = makeNode(RelOptInfo);
1167  upperrel->reloptkind = RELOPT_UPPER_REL;
1168  upperrel->relids = bms_copy(relids);
1169 
1170  /* cheap startup cost is interesting iff not all tuples to be retrieved */
1171  upperrel->consider_startup = (root->tuple_fraction > 0);
1172  upperrel->consider_param_startup = false;
1173  upperrel->consider_parallel = false; /* might get changed later */
1174  upperrel->reltarget = create_empty_pathtarget();
1175  upperrel->pathlist = NIL;
1176  upperrel->cheapest_startup_path = NULL;
1177  upperrel->cheapest_total_path = NULL;
1178  upperrel->cheapest_unique_path = NULL;
1179  upperrel->cheapest_parameterized_paths = NIL;
1180 
1181  root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel);
1182 
1183  return upperrel;
1184 }
1185 
1186 
1187 /*
1188  * find_childrel_appendrelinfo
1189  * Get the AppendRelInfo associated with an appendrel child rel.
1190  *
1191  * This search could be eliminated by storing a link in child RelOptInfos,
1192  * but for now it doesn't seem performance-critical. (Also, it might be
1193  * difficult to maintain such a link during mutation of the append_rel_list.)
1194  */
1195 AppendRelInfo *
1197 {
1198  Index relid = rel->relid;
1199  ListCell *lc;
1200 
1201  /* Should only be called on child rels */
1203 
1204  foreach(lc, root->append_rel_list)
1205  {
1206  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
1207 
1208  if (appinfo->child_relid == relid)
1209  return appinfo;
1210  }
1211  /* should have found the entry ... */
1212  elog(ERROR, "child rel %d not found in append_rel_list", relid);
1213  return NULL; /* not reached */
1214 }
1215 
1216 
1217 /*
1218  * find_childrel_parents
1219  * Compute the set of parent relids of an appendrel child rel.
1220  *
1221  * Since appendrels can be nested, a child could have multiple levels of
1222  * appendrel ancestors. This function computes a Relids set of all the
1223  * parent relation IDs.
1224  */
1225 Relids
1227 {
1228  Relids result = NULL;
1229 
1231 
1232  do
1233  {
1234  AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel);
1235  Index prelid = appinfo->parent_relid;
1236 
1237  result = bms_add_member(result, prelid);
1238 
1239  /* traverse up to the parent rel, loop if it's also a child rel */
1240  rel = find_base_rel(root, prelid);
1241  } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
1242 
1243  Assert(rel->reloptkind == RELOPT_BASEREL);
1244 
1245  return result;
1246 }
1247 
1248 
1249 /*
1250  * get_baserel_parampathinfo
1251  * Get the ParamPathInfo for a parameterized path for a base relation,
1252  * constructing one if we don't have one already.
1253  *
1254  * This centralizes estimating the rowcounts for parameterized paths.
1255  * We need to cache those to be sure we use the same rowcount for all paths
1256  * of the same parameterization for a given rel. This is also a convenient
1257  * place to determine which movable join clauses the parameterized path will
1258  * be responsible for evaluating.
1259  */
1260 ParamPathInfo *
1262  Relids required_outer)
1263 {
1264  ParamPathInfo *ppi;
1265  Relids joinrelids;
1266  List *pclauses;
1267  double rows;
1268  ListCell *lc;
1269 
1270  /* Unparameterized paths have no ParamPathInfo */
1271  if (bms_is_empty(required_outer))
1272  return NULL;
1273 
1274  Assert(!bms_overlap(baserel->relids, required_outer));
1275 
1276  /* If we already have a PPI for this parameterization, just return it */
1277  if ((ppi = find_param_path_info(baserel, required_outer)))
1278  return ppi;
1279 
1280  /*
1281  * Identify all joinclauses that are movable to this base rel given this
1282  * parameterization.
1283  */
1284  joinrelids = bms_union(baserel->relids, required_outer);
1285  pclauses = NIL;
1286  foreach(lc, baserel->joininfo)
1287  {
1288  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1289 
1290  if (join_clause_is_movable_into(rinfo,
1291  baserel->relids,
1292  joinrelids))
1293  pclauses = lappend(pclauses, rinfo);
1294  }
1295 
1296  /*
1297  * Add in joinclauses generated by EquivalenceClasses, too. (These
1298  * necessarily satisfy join_clause_is_movable_into.)
1299  */
1300  pclauses = list_concat(pclauses,
1302  joinrelids,
1303  required_outer,
1304  baserel));
1305 
1306  /* Estimate the number of rows returned by the parameterized scan */
1307  rows = get_parameterized_baserel_size(root, baserel, pclauses);
1308 
1309  /* And now we can build the ParamPathInfo */
1310  ppi = makeNode(ParamPathInfo);
1311  ppi->ppi_req_outer = required_outer;
1312  ppi->ppi_rows = rows;
1313  ppi->ppi_clauses = pclauses;
1314  baserel->ppilist = lappend(baserel->ppilist, ppi);
1315 
1316  return ppi;
1317 }
1318 
1319 /*
1320  * get_joinrel_parampathinfo
1321  * Get the ParamPathInfo for a parameterized path for a join relation,
1322  * constructing one if we don't have one already.
1323  *
1324  * This centralizes estimating the rowcounts for parameterized paths.
1325  * We need to cache those to be sure we use the same rowcount for all paths
1326  * of the same parameterization for a given rel. This is also a convenient
1327  * place to determine which movable join clauses the parameterized path will
1328  * be responsible for evaluating.
1329  *
1330  * outer_path and inner_path are a pair of input paths that can be used to
1331  * construct the join, and restrict_clauses is the list of regular join
1332  * clauses (including clauses derived from EquivalenceClasses) that must be
1333  * applied at the join node when using these inputs.
1334  *
1335  * Unlike the situation for base rels, the set of movable join clauses to be
1336  * enforced at a join varies with the selected pair of input paths, so we
1337  * must calculate that and pass it back, even if we already have a matching
1338  * ParamPathInfo. We handle this by adding any clauses moved down to this
1339  * join to *restrict_clauses, which is an in/out parameter. (The addition
1340  * is done in such a way as to not modify the passed-in List structure.)
1341  *
1342  * Note: when considering a nestloop join, the caller must have removed from
1343  * restrict_clauses any movable clauses that are themselves scheduled to be
1344  * pushed into the right-hand path. We do not do that here since it's
1345  * unnecessary for other join types.
1346  */
1347 ParamPathInfo *
1349  Path *outer_path,
1350  Path *inner_path,
1351  SpecialJoinInfo *sjinfo,
1352  Relids required_outer,
1353  List **restrict_clauses)
1354 {
1355  ParamPathInfo *ppi;
1356  Relids join_and_req;
1357  Relids outer_and_req;
1358  Relids inner_and_req;
1359  List *pclauses;
1360  List *eclauses;
1361  List *dropped_ecs;
1362  double rows;
1363  ListCell *lc;
1364 
1365  /* Unparameterized paths have no ParamPathInfo or extra join clauses */
1366  if (bms_is_empty(required_outer))
1367  return NULL;
1368 
1369  Assert(!bms_overlap(joinrel->relids, required_outer));
1370 
1371  /*
1372  * Identify all joinclauses that are movable to this join rel given this
1373  * parameterization. These are the clauses that are movable into this
1374  * join, but not movable into either input path. Treat an unparameterized
1375  * input path as not accepting parameterized clauses (because it won't,
1376  * per the shortcut exit above), even though the joinclause movement rules
1377  * might allow the same clauses to be moved into a parameterized path for
1378  * that rel.
1379  */
1380  join_and_req = bms_union(joinrel->relids, required_outer);
1381  if (outer_path->param_info)
1382  outer_and_req = bms_union(outer_path->parent->relids,
1383  PATH_REQ_OUTER(outer_path));
1384  else
1385  outer_and_req = NULL; /* outer path does not accept parameters */
1386  if (inner_path->param_info)
1387  inner_and_req = bms_union(inner_path->parent->relids,
1388  PATH_REQ_OUTER(inner_path));
1389  else
1390  inner_and_req = NULL; /* inner path does not accept parameters */
1391 
1392  pclauses = NIL;
1393  foreach(lc, joinrel->joininfo)
1394  {
1395  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1396 
1397  if (join_clause_is_movable_into(rinfo,
1398  joinrel->relids,
1399  join_and_req) &&
1401  outer_path->parent->relids,
1402  outer_and_req) &&
1404  inner_path->parent->relids,
1405  inner_and_req))
1406  pclauses = lappend(pclauses, rinfo);
1407  }
1408 
1409  /* Consider joinclauses generated by EquivalenceClasses, too */
1410  eclauses = generate_join_implied_equalities(root,
1411  join_and_req,
1412  required_outer,
1413  joinrel);
1414  /* We only want ones that aren't movable to lower levels */
1415  dropped_ecs = NIL;
1416  foreach(lc, eclauses)
1417  {
1418  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1419 
1420  /*
1421  * In principle, join_clause_is_movable_into() should accept anything
1422  * returned by generate_join_implied_equalities(); but because its
1423  * analysis is only approximate, sometimes it doesn't. So we
1424  * currently cannot use this Assert; instead just assume it's okay to
1425  * apply the joinclause at this level.
1426  */
1427 #ifdef NOT_USED
1429  joinrel->relids,
1430  join_and_req));
1431 #endif
1432  if (join_clause_is_movable_into(rinfo,
1433  outer_path->parent->relids,
1434  outer_and_req))
1435  continue; /* drop if movable into LHS */
1436  if (join_clause_is_movable_into(rinfo,
1437  inner_path->parent->relids,
1438  inner_and_req))
1439  {
1440  /* drop if movable into RHS, but remember EC for use below */
1441  Assert(rinfo->left_ec == rinfo->right_ec);
1442  dropped_ecs = lappend(dropped_ecs, rinfo->left_ec);
1443  continue;
1444  }
1445  pclauses = lappend(pclauses, rinfo);
1446  }
1447 
1448  /*
1449  * EquivalenceClasses are harder to deal with than we could wish, because
1450  * of the fact that a given EC can generate different clauses depending on
1451  * context. Suppose we have an EC {X.X, Y.Y, Z.Z} where X and Y are the
1452  * LHS and RHS of the current join and Z is in required_outer, and further
1453  * suppose that the inner_path is parameterized by both X and Z. The code
1454  * above will have produced either Z.Z = X.X or Z.Z = Y.Y from that EC,
1455  * and in the latter case will have discarded it as being movable into the
1456  * RHS. However, the EC machinery might have produced either Y.Y = X.X or
1457  * Y.Y = Z.Z as the EC enforcement clause within the inner_path; it will
1458  * not have produced both, and we can't readily tell from here which one
1459  * it did pick. If we add no clause to this join, we'll end up with
1460  * insufficient enforcement of the EC; either Z.Z or X.X will fail to be
1461  * constrained to be equal to the other members of the EC. (When we come
1462  * to join Z to this X/Y path, we will certainly drop whichever EC clause
1463  * is generated at that join, so this omission won't get fixed later.)
1464  *
1465  * To handle this, for each EC we discarded such a clause from, try to
1466  * generate a clause connecting the required_outer rels to the join's LHS
1467  * ("Z.Z = X.X" in the terms of the above example). If successful, and if
1468  * the clause can't be moved to the LHS, add it to the current join's
1469  * restriction clauses. (If an EC cannot generate such a clause then it
1470  * has nothing that needs to be enforced here, while if the clause can be
1471  * moved into the LHS then it should have been enforced within that path.)
1472  *
1473  * Note that we don't need similar processing for ECs whose clause was
1474  * considered to be movable into the LHS, because the LHS can't refer to
1475  * the RHS so there is no comparable ambiguity about what it might
1476  * actually be enforcing internally.
1477  */
1478  if (dropped_ecs)
1479  {
1480  Relids real_outer_and_req;
1481 
1482  real_outer_and_req = bms_union(outer_path->parent->relids,
1483  required_outer);
1484  eclauses =
1486  dropped_ecs,
1487  real_outer_and_req,
1488  required_outer,
1489  outer_path->parent);
1490  foreach(lc, eclauses)
1491  {
1492  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1493 
1494  /* As above, can't quite assert this here */
1495 #ifdef NOT_USED
1497  outer_path->parent->relids,
1498  real_outer_and_req));
1499 #endif
1500  if (!join_clause_is_movable_into(rinfo,
1501  outer_path->parent->relids,
1502  outer_and_req))
1503  pclauses = lappend(pclauses, rinfo);
1504  }
1505  }
1506 
1507  /*
1508  * Now, attach the identified moved-down clauses to the caller's
1509  * restrict_clauses list. By using list_concat in this order, we leave
1510  * the original list structure of restrict_clauses undamaged.
1511  */
1512  *restrict_clauses = list_concat(pclauses, *restrict_clauses);
1513 
1514  /* If we already have a PPI for this parameterization, just return it */
1515  if ((ppi = find_param_path_info(joinrel, required_outer)))
1516  return ppi;
1517 
1518  /* Estimate the number of rows returned by the parameterized join */
1519  rows = get_parameterized_joinrel_size(root, joinrel,
1520  outer_path,
1521  inner_path,
1522  sjinfo,
1523  *restrict_clauses);
1524 
1525  /*
1526  * And now we can build the ParamPathInfo. No point in saving the
1527  * input-pair-dependent clause list, though.
1528  *
1529  * Note: in GEQO mode, we'll be called in a temporary memory context, but
1530  * the joinrel structure is there too, so no problem.
1531  */
1532  ppi = makeNode(ParamPathInfo);
1533  ppi->ppi_req_outer = required_outer;
1534  ppi->ppi_rows = rows;
1535  ppi->ppi_clauses = NIL;
1536  joinrel->ppilist = lappend(joinrel->ppilist, ppi);
1537 
1538  return ppi;
1539 }
1540 
1541 /*
1542  * get_appendrel_parampathinfo
1543  * Get the ParamPathInfo for a parameterized path for an append relation.
1544  *
1545  * For an append relation, the rowcount estimate will just be the sum of
1546  * the estimates for its children. However, we still need a ParamPathInfo
1547  * to flag the fact that the path requires parameters. So this just creates
1548  * a suitable struct with zero ppi_rows (and no ppi_clauses either, since
1549  * the Append node isn't responsible for checking quals).
1550  */
1551 ParamPathInfo *
1552 get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
1553 {
1554  ParamPathInfo *ppi;
1555 
1556  /* Unparameterized paths have no ParamPathInfo */
1557  if (bms_is_empty(required_outer))
1558  return NULL;
1559 
1560  Assert(!bms_overlap(appendrel->relids, required_outer));
1561 
1562  /* If we already have a PPI for this parameterization, just return it */
1563  if ((ppi = find_param_path_info(appendrel, required_outer)))
1564  return ppi;
1565 
1566  /* Else build the ParamPathInfo */
1567  ppi = makeNode(ParamPathInfo);
1568  ppi->ppi_req_outer = required_outer;
1569  ppi->ppi_rows = 0;
1570  ppi->ppi_clauses = NIL;
1571  appendrel->ppilist = lappend(appendrel->ppilist, ppi);
1572 
1573  return ppi;
1574 }
1575 
1576 /*
1577  * Returns a ParamPathInfo for the parameterization given by required_outer, if
1578  * already available in the given rel. Returns NULL otherwise.
1579  */
1580 ParamPathInfo *
1582 {
1583  ListCell *lc;
1584 
1585  foreach(lc, rel->ppilist)
1586  {
1587  ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
1588 
1589  if (bms_equal(ppi->ppi_req_outer, required_outer))
1590  return ppi;
1591  }
1592 
1593  return NULL;
1594 }
1595 
1596 /*
1597  * build_joinrel_partition_info
1598  * If the two relations have same partitioning scheme, their join may be
1599  * partitioned and will follow the same partitioning scheme as the joining
1600  * relations. Set the partition scheme and partition key expressions in
1601  * the join relation.
1602  */
1603 static void
1605  RelOptInfo *inner_rel, List *restrictlist,
1606  JoinType jointype)
1607 {
1608  int partnatts;
1609  int cnt;
1610  PartitionScheme part_scheme;
1611 
1612  /* Nothing to do if partitionwise join technique is disabled. */
1614  {
1615  Assert(!IS_PARTITIONED_REL(joinrel));
1616  return;
1617  }
1618 
1619  /*
1620  * We can only consider this join as an input to further partitionwise
1621  * joins if (a) the input relations are partitioned, (b) the partition
1622  * schemes match, and (c) we can identify an equi-join between the
1623  * partition keys. Note that if it were possible for
1624  * have_partkey_equi_join to return different answers for the same joinrel
1625  * depending on which join ordering we try first, this logic would break.
1626  * That shouldn't happen, though, because of the way the query planner
1627  * deduces implied equalities and reorders the joins. Please see
1628  * optimizer/README for details.
1629  */
1630  if (!IS_PARTITIONED_REL(outer_rel) || !IS_PARTITIONED_REL(inner_rel) ||
1631  outer_rel->part_scheme != inner_rel->part_scheme ||
1632  !have_partkey_equi_join(joinrel, outer_rel, inner_rel,
1633  jointype, restrictlist))
1634  {
1635  Assert(!IS_PARTITIONED_REL(joinrel));
1636  return;
1637  }
1638 
1639  part_scheme = outer_rel->part_scheme;
1640 
1641  Assert(REL_HAS_ALL_PART_PROPS(outer_rel) &&
1642  REL_HAS_ALL_PART_PROPS(inner_rel));
1643 
1644  /*
1645  * For now, our partition matching algorithm can match partitions only
1646  * when the partition bounds of the joining relations are exactly same.
1647  * So, bail out otherwise.
1648  */
1649  if (outer_rel->nparts != inner_rel->nparts ||
1650  !partition_bounds_equal(part_scheme->partnatts,
1651  part_scheme->parttyplen,
1652  part_scheme->parttypbyval,
1653  outer_rel->boundinfo, inner_rel->boundinfo))
1654  {
1655  Assert(!IS_PARTITIONED_REL(joinrel));
1656  return;
1657  }
1658 
1659  /*
1660  * This function will be called only once for each joinrel, hence it
1661  * should not have partition scheme, partition bounds, partition key
1662  * expressions and array for storing child relations set.
1663  */
1664  Assert(!joinrel->part_scheme && !joinrel->partexprs &&
1665  !joinrel->nullable_partexprs && !joinrel->part_rels &&
1666  !joinrel->boundinfo);
1667 
1668  /*
1669  * Join relation is partitioned using the same partitioning scheme as the
1670  * joining relations and has same bounds.
1671  */
1672  joinrel->part_scheme = part_scheme;
1673  joinrel->boundinfo = outer_rel->boundinfo;
1674  partnatts = joinrel->part_scheme->partnatts;
1675  joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
1676  joinrel->nullable_partexprs =
1677  (List **) palloc0(sizeof(List *) * partnatts);
1678  joinrel->nparts = outer_rel->nparts;
1679  joinrel->part_rels =
1680  (RelOptInfo **) palloc0(sizeof(RelOptInfo *) * joinrel->nparts);
1681 
1682 
1683  /*
1684  * Construct partition keys for the join.
1685  *
1686  * An INNER join between two partitioned relations can be regarded as
1687  * partitioned by either key expression. For example, A INNER JOIN B ON
1688  * A.a = B.b can be regarded as partitioned on A.a or on B.b; they are
1689  * equivalent.
1690  *
1691  * For a SEMI or ANTI join, the result can only be regarded as being
1692  * partitioned in the same manner as the outer side, since the inner
1693  * columns are not retained.
1694  *
1695  * An OUTER join like (A LEFT JOIN B ON A.a = B.b) may produce rows with
1696  * B.b NULL. These rows may not fit the partitioning conditions imposed on
1697  * B.b. Hence, strictly speaking, the join is not partitioned by B.b and
1698  * thus partition keys of an OUTER join should include partition key
1699  * expressions from the OUTER side only. However, because all
1700  * commonly-used comparison operators are strict, the presence of nulls on
1701  * the outer side doesn't cause any problem; they can't match anything at
1702  * future join levels anyway. Therefore, we track two sets of
1703  * expressions: those that authentically partition the relation
1704  * (partexprs) and those that partition the relation with the exception
1705  * that extra nulls may be present (nullable_partexprs). When the
1706  * comparison operator is strict, the latter is just as good as the
1707  * former.
1708  */
1709  for (cnt = 0; cnt < partnatts; cnt++)
1710  {
1711  List *outer_expr;
1712  List *outer_null_expr;
1713  List *inner_expr;
1714  List *inner_null_expr;
1715  List *partexpr = NIL;
1716  List *nullable_partexpr = NIL;
1717 
1718  outer_expr = list_copy(outer_rel->partexprs[cnt]);
1719  outer_null_expr = list_copy(outer_rel->nullable_partexprs[cnt]);
1720  inner_expr = list_copy(inner_rel->partexprs[cnt]);
1721  inner_null_expr = list_copy(inner_rel->nullable_partexprs[cnt]);
1722 
1723  switch (jointype)
1724  {
1725  case JOIN_INNER:
1726  partexpr = list_concat(outer_expr, inner_expr);
1727  nullable_partexpr = list_concat(outer_null_expr,
1728  inner_null_expr);
1729  break;
1730 
1731  case JOIN_SEMI:
1732  case JOIN_ANTI:
1733  partexpr = outer_expr;
1734  nullable_partexpr = outer_null_expr;
1735  break;
1736 
1737  case JOIN_LEFT:
1738  partexpr = outer_expr;
1739  nullable_partexpr = list_concat(inner_expr,
1740  outer_null_expr);
1741  nullable_partexpr = list_concat(nullable_partexpr,
1742  inner_null_expr);
1743  break;
1744 
1745  case JOIN_FULL:
1746  nullable_partexpr = list_concat(outer_expr,
1747  inner_expr);
1748  nullable_partexpr = list_concat(nullable_partexpr,
1749  outer_null_expr);
1750  nullable_partexpr = list_concat(nullable_partexpr,
1751  inner_null_expr);
1752  break;
1753 
1754  default:
1755  elog(ERROR, "unrecognized join type: %d", (int) jointype);
1756 
1757  }
1758 
1759  joinrel->partexprs[cnt] = partexpr;
1760  joinrel->nullable_partexprs[cnt] = nullable_partexpr;
1761  }
1762 }
bool has_eclass_joins
Definition: relation.h:678
struct Path * cheapest_unique_path
Definition: relation.h:631
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
ParamPathInfo * find_param_path_info(RelOptInfo *rel, Relids required_outer)
Definition: relnode.c:1581
int join_cur_level
Definition: relation.h:240
List * unique_for_rels
Definition: relation.h:667
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Query * parse
Definition: relation.h:169
List * statlist
Definition: relation.h:650
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:133
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
Definition: relnode.c:1261
RelOptKind reloptkind
Definition: relation.h:609
Relids * attr_needed
Definition: relation.h:645
Relids required_relids
Definition: relation.h:1898
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
List * colnames
Definition: primnodes.h:44
MemoryContext hcxt
Definition: hsearch.h:78
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Definition: relnode.c:344
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:1348
Oid GetUserId(void)
Definition: miscinit.c:379
static List * subbuild_joinrel_restrictlist(RelOptInfo *joinrel, List *joininfo_list, List *new_restrictlist)
Definition: relnode.c:1029
void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: costsize.c:4375
struct Path * cheapest_startup_path
Definition: relation.h:629
Oid userid
Definition: relation.h:660
Relids join_relids
Definition: relnode.c:35
List * securityQuals
Definition: parsenodes.h:1075
double tuples
Definition: relation.h:652
List * baserestrictinfo
Definition: relation.h:672
#define IS_PARTITIONED_REL(rel)
Definition: relation.h:706
bool consider_param_startup
Definition: relation.h:619
ParamPathInfo * param_info
Definition: relation.h:1081
Size entrysize
Definition: hsearch.h:73
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:517
List * partial_pathlist
Definition: relation.h:628
#define IS_OTHER_REL(rel)
Definition: relation.h:600
#define MemSet(start, val, len)
Definition: c.h:908
AttrNumber varattno
Definition: primnodes.h:169
List * join_rel_list
Definition: relation.h:229
List * list_concat(List *list1, List *list2)
Definition: list.c:321
EquivalenceClass * right_ec
Definition: relation.h:1929
List * cheapest_parameterized_paths
Definition: relation.h:632
Index baserestrict_min_security
Definition: relation.h:674
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
bool useridiscurrent
Definition: relation.h:661
UpperRelationKind
Definition: relation.h:72
List ** nullable_partexprs
Definition: relation.h:691
Definition: primnodes.h:164
#define OidIsValid(objectId)
Definition: c.h:605
void add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: placeholder.c:412
Cost startup
Definition: relation.h:46
double allvisfrac
Definition: relation.h:653
signed int int32
Definition: c.h:313
JoinType
Definition: nodes.h:681
struct RelOptInfo ** simple_rel_array
Definition: relation.h:193
AppendRelInfo * find_childrel_appendrelinfo(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:1196
PlannerInfo * subroot
Definition: relation.h:654
bool consider_startup
Definition: relation.h:618
Definition: dynahash.c:208
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:1088
Relids lateral_relids
Definition: relation.h:637
Cost per_tuple
Definition: relation.h:47
static void set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:407
double tuple_fraction
Definition: relation.h:306
struct JoinHashEntry JoinHashEntry
uint32 bitmap_hash(const void *key, Size keysize)
Definition: hashfn.c:76
void pfree(void *pointer)
Definition: mcxt.c:1031
List ** partexprs
Definition: relation.h:690
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel)
Definition: relnode.c:858
List * list_append_unique_ptr(List *list, void *datum)
Definition: list.c:975
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
Definition: equivclass.c:1071
Relids min_join_parameterization(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:815
RelOptInfo * build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel, RelOptInfo *parent_joinrel, List *restrictlist, SpecialJoinInfo *sjinfo, JoinType jointype)
Definition: relnode.c:686
int16 * parttyplen
Definition: relation.h:371
RelOptInfo * parent
Definition: relation.h:1078
RelOptInfo * join_rel
Definition: relnode.c:36
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:374
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1145
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:671
double get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, List *restrict_clauses)
Definition: costsize.c:4407
struct Path * cheapest_total_path
Definition: relation.h:630
static List * build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:981
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:245
List * joininfo
Definition: relation.h:676
struct FdwRoutine * fdwroutine
Definition: relation.h:663
int nparts
Definition: relation.h:685
#define REL_HAS_ALL_PART_PROPS(rel)
Definition: relation.h:714
Relids relids
Definition: relation.h:612
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:96
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
int bitmap_match(const void *key1, const void *key2, Size keysize)
Definition: hashfn.c:86
bool has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1)
Definition: equivclass.c:2397
int simple_rel_array_size
Definition: relation.h:194
List * non_unique_for_rels
Definition: relation.h:669
bool join_clause_is_movable_into(RestrictInfo *rinfo, Relids currentrelids, Relids current_and_outer)
Definition: restrictinfo.c:511
List * ppilist
Definition: relation.h:627
Index relid
Definition: relation.h:640
Bitmapset * Relids
Definition: relation.h:29
List * lappend(List *list, void *datum)
Definition: list.c:128
RangeTblEntry ** simple_rte_array
Definition: relation.h:202
Relids lateral_referencers
Definition: relation.h:648
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:2047
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
Index varno
Definition: primnodes.h:167
Oid serverid
Definition: relation.h:659
List * exprs
Definition: relation.h:1008
Relids direct_lateral_relids
Definition: relation.h:636
void * palloc0(Size size)
Definition: mcxt.c:955
List * generate_join_implied_equalities_for_ecs(PlannerInfo *root, List *eclasses, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
Definition: equivclass.c:1088
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
int rel_parallel_workers
Definition: relation.h:656
List * append_rel_list
Definition: relation.h:266
double get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, List *param_clauses)
Definition: costsize.c:4325
struct PartitionBoundInfoData * boundinfo
Definition: relation.h:686
Size keysize
Definition: hsearch.h:72
RelOptInfo * build_join_rel(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List **restrictlist_ptr)
Definition: relnode.c:482
unsigned int Index
Definition: c.h:442
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2618
HashCompareFunc match
Definition: hsearch.h:75
RTEKind rtekind
Definition: relation.h:642
Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:1226
List * indexlist
Definition: relation.h:649
double rows
Definition: relation.h:615
#define InvalidOid
Definition: postgres_ext.h:36
static void build_join_rel_hash(PlannerInfo *root)
Definition: relnode.c:302
void * fdw_private
Definition: relation.h:664
void bms_free(Bitmapset *a)
Definition: bitmapset.c:267
#define Max(x, y)
Definition: c.h:851
#define makeNode(_type_)
Definition: nodes.h:565
BlockNumber pages
Definition: relation.h:651
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
RelOptInfo * build_empty_join_rel(PlannerInfo *root)
Definition: relnode.c:1111
List ** join_rel_level
Definition: relation.h:239
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:67
List * lateral_vars
Definition: relation.h:647
#define HASH_COMPARE
Definition: hsearch.h:90
#define PATH_REQ_OUTER(path)
Definition: relation.h:1097
JoinType jointype
Definition: relation.h:2070
void add_placeholders_to_child_joinrel(PlannerInfo *root, RelOptInfo *childrel, RelOptInfo *parentrel)
Definition: placeholder.c:474
List * ppi_clauses
Definition: relation.h:1039
struct RelOptInfo ** part_rels
Definition: relation.h:688
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
bool enable_partitionwise_join
Definition: costsize.c:137
static int list_length(const List *l)
Definition: pg_list.h:89
struct HTAB * join_rel_hash
Definition: relation.h:230
Index qual_security_level
Definition: relation.h:309
bool consider_parallel
Definition: relation.h:620
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
#define nodeTag(nodeptr)
Definition: nodes.h:522
bool have_partkey_equi_join(RelOptInfo *joinrel, RelOptInfo *rel1, RelOptInfo *rel2, JoinType jointype, List *restrictlist)
Definition: joinrels.c:1418
double ppi_rows
Definition: relation.h:1038
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:955
RTEKind rtekind
Definition: parsenodes.h:962
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:509
List * partitioned_child_rels
Definition: relation.h:692
AttrNumber max_attr
Definition: relation.h:644
void * palloc(Size size)
Definition: mcxt.c:924
EquivalenceClass * left_ec
Definition: relation.h:1928
static List * subbuild_joinrel_joinlist(RelOptInfo *joinrel, List *joininfo_list, List *new_joininfo)
Definition: relnode.c:1063
bool partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval, PartitionBoundInfo b1, PartitionBoundInfo b2)
Definition: partbounds.c:104
static void build_joinrel_partition_info(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, List *restrictlist, JoinType jointype)
Definition: relnode.c:1604
PartitionScheme part_scheme
Definition: relation.h:684
List * pathlist
Definition: relation.h:626
Relids ppi_req_outer
Definition: relation.h:1037
#define elog
Definition: elog.h:219
Index child_relid
Definition: relation.h:2125
ParamPathInfo * get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
Definition: relnode.c:1552
Alias * eref
Definition: parsenodes.h:1066
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:279
List * partition_qual
Definition: relation.h:687
Index parent_relid
Definition: relation.h:2124
int32 * attr_widths
Definition: relation.h:646
Definition: regcomp.c:224
Definition: pg_list.h:45
struct PathTarget * reltarget
Definition: relation.h:623
QualCost baserestrictcost
Definition: relation.h:673
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
Definition: relnode.c:445
List * subplan_params
Definition: relation.h:655
static void build_joinrel_joinlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:1011
void get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel)
Definition: plancat.c:108
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:153
Relids top_parent_relids
Definition: relation.h:681
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:560
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89
List * upper_rels[UPPERREL_FINAL+1]
Definition: relation.h:287
AttrNumber min_attr
Definition: relation.h:643