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