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