PostgreSQL Source Code git master
Loading...
Searching...
No Matches
analyzejoins.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * analyzejoins.c
4 * Routines for simplifying joins after initial query analysis
5 *
6 * While we do a great deal of join simplification in prep/prepjointree.c,
7 * certain optimizations cannot be performed at that stage for lack of
8 * detailed information about the query. The routines here are invoked
9 * after initsplan.c has done its work, and can do additional join removal
10 * and simplification steps based on the information extracted. The penalty
11 * is that we have to work harder to clean up after ourselves when we modify
12 * the query, since the derived data structures have to be updated too.
13 *
14 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
15 * Portions Copyright (c) 1994, Regents of the University of California
16 *
17 *
18 * IDENTIFICATION
19 * src/backend/optimizer/plan/analyzejoins.c
20 *
21 *-------------------------------------------------------------------------
22 */
23#include "postgres.h"
24
25#include "catalog/pg_class.h"
26#include "nodes/nodeFuncs.h"
27#include "optimizer/joininfo.h"
28#include "optimizer/optimizer.h"
29#include "optimizer/pathnode.h"
30#include "optimizer/paths.h"
32#include "optimizer/planmain.h"
34#include "parser/parse_agg.h"
36#include "utils/lsyscache.h"
37
38/*
39 * Utility structure. A sorting procedure is needed to simplify the search
40 * of SJE-candidate baserels referencing the same database relation. Having
41 * collected all baserels from the query jointree, the planner sorts them
42 * according to the reloid value, groups them with the next pass and attempts
43 * to remove self-joins.
44 *
45 * Preliminary sorting prevents quadratic behavior that can be harmful in the
46 * case of numerous joins.
47 */
48typedef struct
49{
50 int relid;
53
55
56/* local functions */
58static void remove_leftjoinrel_from_query(PlannerInfo *root, int relid,
59 SpecialJoinInfo *sjinfo);
60static void remove_rel_from_query(PlannerInfo *root, int relid,
61 int subst, SpecialJoinInfo *sjinfo,
64 int relid, int ojrelid);
66 int relid, int ojrelid);
67static Node *remove_rel_from_phvs(Node *node, int relid, int ojrelid);
69static List *remove_rel_from_joinlist(List *joinlist, int relid, int *nremoved);
72 List *clause_list, List **extra_clauses);
76 Relids outerrelids,
77 RelOptInfo *innerrel,
78 JoinType jointype,
79 List *restrictlist,
80 List **extra_clauses);
81static int self_join_candidates_cmp(const void *a, const void *b);
82static bool replace_relid_callback(Node *node,
83 ChangeVarNodes_context *context);
84
85
86/*
87 * remove_useless_joins
88 * Check for relations that don't actually need to be joined at all,
89 * and remove them from the query.
90 *
91 * We are passed the current joinlist and return the updated list. Other
92 * data structures that have to be updated are accessible via "root".
93 */
94List *
96{
97 ListCell *lc;
98
99 /*
100 * We are only interested in relations that are left-joined to, so we can
101 * scan the join_info_list to find them easily.
102 */
103restart:
104 foreach(lc, root->join_info_list)
105 {
107 int innerrelid;
108 int nremoved;
109
110 /* Skip if not removable */
111 if (!join_is_removable(root, sjinfo))
112 continue;
113
114 /*
115 * Currently, join_is_removable can only succeed when the sjinfo's
116 * righthand is a single baserel. Remove that rel from the query and
117 * joinlist.
118 */
120
122
123 /* We verify that exactly one reference gets removed from joinlist */
124 nremoved = 0;
126 if (nremoved != 1)
127 elog(ERROR, "failed to find relation %d in joinlist", innerrelid);
128
129 /*
130 * We can delete this SpecialJoinInfo from the list too, since it's no
131 * longer of interest. (Since we'll restart the foreach loop
132 * immediately, we don't bother with foreach_delete_current.)
133 */
134 root->join_info_list = list_delete_cell(root->join_info_list, lc);
135
136 /*
137 * Restart the scan. This is necessary to ensure we find all
138 * removable joins independently of ordering of the join_info_list
139 * (note that removal of attr_needed bits may make a join appear
140 * removable that did not before).
141 */
142 goto restart;
143 }
144
145 return joinlist;
146}
147
148/*
149 * join_is_removable
150 * Check whether we need not perform this special join at all, because
151 * it will just duplicate its left input.
152 *
153 * This is true for a left join for which the join condition cannot match
154 * more than one inner-side row. (There are other possibly interesting
155 * cases, but we don't have the infrastructure to prove them.) We also
156 * have to check that the inner side doesn't generate any variables needed
157 * above the join.
158 */
159static bool
161{
162 int innerrelid;
163 RelOptInfo *innerrel;
167 ListCell *l;
168 int attroff;
169
170 /*
171 * Must be a left join to a single baserel, else we aren't going to be
172 * able to do anything with it.
173 */
174 if (sjinfo->jointype != JOIN_LEFT)
175 return false;
176
178 return false;
179
180 /*
181 * Never try to eliminate a left join to the query result rel. Although
182 * the case is syntactically impossible in standard SQL, MERGE will build
183 * a join tree that looks exactly like that.
184 */
185 if (innerrelid == root->parse->resultRelation)
186 return false;
187
188 innerrel = find_base_rel(root, innerrelid);
189
190 /*
191 * Before we go to the effort of checking whether any innerrel variables
192 * are needed above the join, make a quick check to eliminate cases in
193 * which we will surely be unable to prove uniqueness of the innerrel.
194 */
195 if (!rel_supports_distinctness(root, innerrel))
196 return false;
197
198 /* Compute the relid set for the join we are considering */
200 Assert(sjinfo->ojrelid != 0);
203
204 /*
205 * We can't remove the join if any inner-rel attributes are used above the
206 * join. Here, "above" the join includes pushed-down conditions, so we
207 * should reject if attr_needed includes the OJ's own relid; therefore,
208 * compare to inputrelids not joinrelids.
209 *
210 * As a micro-optimization, it seems better to start with max_attr and
211 * count down rather than starting with min_attr and counting up, on the
212 * theory that the system attributes are somewhat less likely to be wanted
213 * and should be tested last.
214 */
215 for (attroff = innerrel->max_attr - innerrel->min_attr;
216 attroff >= 0;
217 attroff--)
218 {
219 if (!bms_is_subset(innerrel->attr_needed[attroff], inputrelids))
220 return false;
221 }
222
223 /*
224 * Similarly check that the inner rel isn't needed by any PlaceHolderVars
225 * that will be used above the join. The PHV case is a little bit more
226 * complicated, because PHVs may have been assigned a ph_eval_at location
227 * that includes the innerrel, yet their contained expression might not
228 * actually reference the innerrel (it could be just a constant, for
229 * instance). If such a PHV is due to be evaluated above the join then it
230 * needn't prevent join removal.
231 */
232 foreach(l, root->placeholder_list)
233 {
235
236 if (bms_overlap(phinfo->ph_lateral, innerrel->relids))
237 return false; /* it references innerrel laterally */
238 if (!bms_overlap(phinfo->ph_eval_at, innerrel->relids))
239 continue; /* it definitely doesn't reference innerrel */
240 if (bms_is_subset(phinfo->ph_needed, inputrelids))
241 continue; /* PHV is not used above the join */
242 if (!bms_is_member(sjinfo->ojrelid, phinfo->ph_eval_at))
243 return false; /* it has to be evaluated below the join */
244
245 /*
246 * We need to be sure there will still be a place to evaluate the PHV
247 * if we remove the join, ie that ph_eval_at wouldn't become empty.
248 */
249 if (!bms_overlap(sjinfo->min_lefthand, phinfo->ph_eval_at))
250 return false; /* there isn't any other place to eval PHV */
251 /* Check contained expression last, since this is a bit expensive */
252 if (bms_overlap(pull_varnos(root, (Node *) phinfo->ph_var->phexpr),
253 innerrel->relids))
254 return false; /* contained expression references innerrel */
255 }
256
257 /*
258 * Search for mergejoinable clauses that constrain the inner rel against
259 * either the outer rel or a pseudoconstant. If an operator is
260 * mergejoinable then it behaves like equality for some btree opclass, so
261 * it's what we want. The mergejoinability test also eliminates clauses
262 * containing volatile functions, which we couldn't depend on.
263 */
264 foreach(l, innerrel->joininfo)
265 {
267
268 /*
269 * If the current join commutes with some other outer join(s) via
270 * outer join identity 3, there will be multiple clones of its join
271 * clauses in the joininfo list. We want to consider only the
272 * has_clone form of such clauses. Processing more than one form
273 * would be wasteful, and also some of the others would confuse the
274 * RINFO_IS_PUSHED_DOWN test below.
275 */
276 if (restrictinfo->is_clone)
277 continue; /* ignore it */
278
279 /*
280 * If it's not a join clause for this outer join, we can't use it.
281 * Note that if the clause is pushed-down, then it is logically from
282 * above the outer join, even if it references no other rels (it might
283 * be from WHERE, for example).
284 */
286 continue; /* ignore; not useful here */
287
288 /* Ignore if it's not a mergejoinable clause */
289 if (!restrictinfo->can_join ||
290 restrictinfo->mergeopfamilies == NIL)
291 continue; /* not mergejoinable */
292
293 /*
294 * Check if the clause has the form "outer op inner" or "inner op
295 * outer", and if so mark which side is inner.
296 */
298 innerrel->relids))
299 continue; /* no good for these input relations */
300
301 /* OK, add to list */
303 }
304
305 /*
306 * Now that we have the relevant equality join clauses, try to prove the
307 * innerrel distinct.
308 */
309 if (rel_is_distinct_for(root, innerrel, clause_list, NULL))
310 return true;
311
312 /*
313 * Some day it would be nice to check for other methods of establishing
314 * distinctness.
315 */
316 return false;
317}
318
319/*
320 * Remove the target relid and references to the target join from the
321 * planner's data structures, having determined that there is no need
322 * to include them in the query.
323 *
324 * We are not terribly thorough here. We only bother to update parts of
325 * the planner's data structures that will actually be consulted later.
326 */
327static void
329 SpecialJoinInfo *sjinfo)
330{
331 RelOptInfo *rel = find_base_rel(root, relid);
332 int ojrelid = sjinfo->ojrelid;
336 ListCell *l;
337
338 /* Compute the relid set for the join we are considering */
340 Assert(ojrelid != 0);
342
343 remove_rel_from_query(root, relid, -1, sjinfo, joinrelids);
344
345 /*
346 * Remove any joinquals referencing the rel from the joininfo lists.
347 *
348 * In some cases, a joinqual has to be put back after deleting its
349 * reference to the target rel. This can occur for pseudoconstant and
350 * outerjoin-delayed quals, which can get marked as requiring the rel in
351 * order to force them to be evaluated at or above the join. We can't
352 * just discard them, though. Only quals that logically belonged to the
353 * outer join being discarded should be removed from the query.
354 *
355 * We might encounter a qual that is a clone of a deletable qual with some
356 * outer-join relids added (see deconstruct_distribute_oj_quals). To
357 * ensure we get rid of such clones as well, add the relids of all OJs
358 * commutable with this one to the set we test against for
359 * pushed-down-ness.
360 */
362 sjinfo->commute_above_r);
364 sjinfo->commute_below_l);
365
366 /*
367 * We must make a copy of the rel's old joininfo list before starting the
368 * loop, because otherwise remove_join_clause_from_rels would destroy the
369 * list while we're scanning it.
370 */
372 foreach(l, joininfos)
373 {
374 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
375
377
379 {
380 /*
381 * There might be references to relid or ojrelid in the
382 * RestrictInfo's relid sets, as a consequence of PHVs having had
383 * ph_eval_at sets that include those. We already checked above
384 * that any such PHV is safe (and updated its ph_eval_at), so we
385 * can just drop those references.
386 */
387 remove_rel_from_restrictinfo(rinfo, relid, ojrelid);
388
389 /*
390 * Cross-check that the clause itself does not reference the
391 * target rel or join.
392 */
393#ifdef USE_ASSERT_CHECKING
394 {
396 (Node *) rinfo->clause);
397
400 }
401#endif
402 /* Now throw it back into the joininfo lists */
404 }
405 }
406
407 /*
408 * There may be references to the rel in root->fkey_list, but if so,
409 * match_foreign_keys_to_quals() will get rid of them.
410 */
411
412 /*
413 * Now remove the rel from the baserel array to prevent it from being
414 * referenced again. (We can't do this earlier because
415 * remove_join_clause_from_rels will touch it.)
416 */
417 root->simple_rel_array[relid] = NULL;
418 root->simple_rte_array[relid] = NULL;
419
420 /* And nuke the RelOptInfo, just in case there's another access path */
421 pfree(rel);
422
423 /*
424 * Now repeat construction of attr_needed bits coming from all other
425 * sources.
426 */
431}
432
433/*
434 * Remove the target relid and references to the target join from the
435 * planner's data structures, having determined that there is no need
436 * to include them in the query. Optionally replace references to the
437 * removed relid with subst if this is a self-join removal.
438 *
439 * This function serves as the common infrastructure for left-join removal
440 * and self-join elimination. It is intentionally scoped to update only the
441 * shared planner data structures that are universally affected by relation
442 * removal. Each specific caller remains responsible for updating any
443 * remaining data structures required by its unique removal logic.
444 *
445 * The specific type of removal being performed is dictated by the combination
446 * of the sjinfo and subst parameters. A non-NULL sjinfo indicates left-join
447 * removal. When sjinfo is NULL, a positive subst value indicates self-join
448 * elimination (where references are replaced with subst).
449 */
450static void
452 int subst, SpecialJoinInfo *sjinfo,
454{
455 int ojrelid = sjinfo ? sjinfo->ojrelid : 0;
456 Index rti;
457 ListCell *l;
458 bool is_outer_join = (sjinfo != NULL);
459 bool is_self_join = (!is_outer_join && subst > 0);
460
462 Assert(!is_outer_join || ojrelid > 0);
464
465 /*
466 * Update all_baserels and related relid sets.
467 */
468 root->all_baserels = adjust_relid_set(root->all_baserels, relid, subst);
469 root->all_query_rels = adjust_relid_set(root->all_query_rels, relid, subst);
470
471 if (is_outer_join)
472 {
473 root->outer_join_rels = bms_del_member(root->outer_join_rels, ojrelid);
474 root->all_query_rels = bms_del_member(root->all_query_rels, ojrelid);
475 }
476
477 /*
478 * Likewise remove references from SpecialJoinInfo data structures.
479 *
480 * This is relevant in case the relation we're deleting is part of the
481 * relid sets of special joins: those sets have to be adjusted. If we are
482 * removing an outer join, the RHS of the target outer join will be made
483 * empty here, but that's OK since the caller will delete that
484 * SpecialJoinInfo entirely.
485 */
486 foreach(l, root->join_info_list)
487 {
489
490 /*
491 * initsplan.c is fairly cavalier about allowing SpecialJoinInfos'
492 * lefthand/righthand relid sets to be shared with other data
493 * structures. Ensure that we don't modify the original relid sets.
494 * (The commute_xxx sets are always per-SpecialJoinInfo though.)
495 */
496 sjinf->min_lefthand = bms_copy(sjinf->min_lefthand);
497 sjinf->min_righthand = bms_copy(sjinf->min_righthand);
498 sjinf->syn_lefthand = bms_copy(sjinf->syn_lefthand);
499 sjinf->syn_righthand = bms_copy(sjinf->syn_righthand);
500
501 /* Now adjust relid bit in the sets: */
502 sjinf->min_lefthand = adjust_relid_set(sjinf->min_lefthand, relid, subst);
503 sjinf->min_righthand = adjust_relid_set(sjinf->min_righthand, relid, subst);
504 sjinf->syn_lefthand = adjust_relid_set(sjinf->syn_lefthand, relid, subst);
505 sjinf->syn_righthand = adjust_relid_set(sjinf->syn_righthand, relid, subst);
506
507 if (is_outer_join)
508 {
509 /* Remove ojrelid bit from the sets: */
510 sjinf->min_lefthand = bms_del_member(sjinf->min_lefthand, ojrelid);
511 sjinf->min_righthand = bms_del_member(sjinf->min_righthand, ojrelid);
512 sjinf->syn_lefthand = bms_del_member(sjinf->syn_lefthand, ojrelid);
513 sjinf->syn_righthand = bms_del_member(sjinf->syn_righthand, ojrelid);
514 /* relid cannot appear in these fields, but ojrelid can: */
515 sjinf->commute_above_l = bms_del_member(sjinf->commute_above_l, ojrelid);
516 sjinf->commute_above_r = bms_del_member(sjinf->commute_above_r, ojrelid);
517 sjinf->commute_below_l = bms_del_member(sjinf->commute_below_l, ojrelid);
518 sjinf->commute_below_r = bms_del_member(sjinf->commute_below_r, ojrelid);
519 }
520 else
521 {
522 /*
523 * For self-join removal, replace relid references in
524 * semi_rhs_exprs.
525 */
526 ChangeVarNodesExtended((Node *) sjinf->semi_rhs_exprs, relid, subst,
528 }
529 }
530
531 /*
532 * Likewise remove references from PlaceHolderVar data structures,
533 * removing any no-longer-needed placeholders entirely. We only remove
534 * PHVs for left-join removal. With self-join elimination, PHVs already
535 * get moved to the remaining relation, where they might still be needed.
536 * It might also happen that we skip the removal of some PHVs that could
537 * be removed. However, the overhead of extra PHVs is small compared to
538 * the complexity of analysis needed to remove them.
539 *
540 * Removal is a bit trickier than it might seem: we can remove PHVs that
541 * are used at the target rel and/or in the join qual, but not those that
542 * are used at join partner rels or above the join. It's not that easy to
543 * distinguish PHVs used at partner rels from those used in the join qual,
544 * since they will both have ph_needed sets that are subsets of
545 * joinrelids. However, a PHV used at a partner rel could not have the
546 * target rel in ph_eval_at, so we check that while deciding whether to
547 * remove or just update the PHV. There is no corresponding test in
548 * join_is_removable because it doesn't need to distinguish those cases.
549 */
550 foreach(l, root->placeholder_list)
551 {
553
554 Assert(!is_outer_join || !bms_is_member(relid, phinfo->ph_lateral));
555
556 if (is_outer_join &&
557 bms_is_subset(phinfo->ph_needed, joinrelids) &&
558 bms_is_member(relid, phinfo->ph_eval_at) &&
559 !bms_is_member(ojrelid, phinfo->ph_eval_at))
560 {
561 root->placeholder_list = foreach_delete_current(root->placeholder_list,
562 l);
563 root->placeholder_array[phinfo->phid] = NULL;
564 }
565 else
566 {
567 PlaceHolderVar *phv = phinfo->ph_var;
568
569 phinfo->ph_eval_at = adjust_relid_set(phinfo->ph_eval_at, relid, subst);
570 if (is_outer_join)
571 phinfo->ph_eval_at = bms_del_member(phinfo->ph_eval_at, ojrelid);
572 Assert(!bms_is_empty(phinfo->ph_eval_at)); /* checked previously */
573
574 /* Reduce ph_needed to contain only "relation 0"; see below */
575 if (bms_is_member(0, phinfo->ph_needed))
576 phinfo->ph_needed = bms_make_singleton(0);
577 else
578 phinfo->ph_needed = NULL;
579
580 phv->phrels = adjust_relid_set(phv->phrels, relid, subst);
581 if (is_outer_join)
582 phv->phrels = bms_del_member(phv->phrels, ojrelid);
583 Assert(!bms_is_empty(phv->phrels));
584
585 /*
586 * For self-join removal, update Var nodes within the PHV's
587 * expression to reference the replacement relid, and adjust
588 * ph_lateral for the relid substitution. (For left-join removal,
589 * we're removing rather than replacing, and any surviving PHV
590 * shouldn't reference the removed rel in its expression. Also,
591 * relid can't appear in ph_lateral for outer joins.)
592 */
593 if (is_self_join)
594 {
595 ChangeVarNodesExtended((Node *) phv->phexpr, relid, subst, 0,
597 phinfo->ph_lateral = adjust_relid_set(phinfo->ph_lateral, relid, subst);
598
599 /*
600 * ph_lateral might contain rels mentioned in ph_eval_at after
601 * the replacement, remove them.
602 */
603 phinfo->ph_lateral = bms_difference(phinfo->ph_lateral, phinfo->ph_eval_at);
604 /* ph_lateral might or might not be empty */
605 }
606
607 Assert(phv->phnullingrels == NULL); /* no need to adjust */
608 }
609 }
610
611 /*
612 * Likewise remove references from EquivalenceClasses.
613 *
614 * For self-join removal, the caller has already updated the
615 * EquivalenceClasses, so we can skip this step.
616 */
617 if (is_outer_join)
618 {
619 foreach(l, root->eq_classes)
620 {
622
623 remove_rel_from_eclass(root, ec, relid, ojrelid);
624 }
625 }
626
627 /*
628 * Finally, we must prepare for the caller to recompute per-Var
629 * attr_needed and per-PlaceHolderVar ph_needed relid sets. These have to
630 * be known accurately, else we may fail to remove other now-removable
631 * joins. Because the caller removes the join clause(s) associated with
632 * the removed join, Vars that were formerly needed may no longer be.
633 *
634 * The actual reconstruction of these relid sets is performed by the
635 * specific caller. Here, we simply clear out the existing attr_needed
636 * sets (we already did this above for ph_needed) to ensure they are
637 * rebuilt from scratch. We can cheat to one small extent: we can avoid
638 * re-examining the targetlist and HAVING qual by preserving "relation 0"
639 * bits from the existing relid sets. This is safe because we'd never
640 * remove such references.
641 *
642 * Additionally, if we are performing self-join elimination, we must
643 * replace references to the removed relid with subst within the
644 * lateral_vars lists.
645 *
646 * Also, for left-join removal, we strip the removed rel and join from any
647 * PlaceHolderVar embedded in the surviving rels' restriction clauses (see
648 * remove_rel_from_phvs); we needn't bother with the rel being removed,
649 * nor when the query has no PlaceHolderVars.
650 */
651 for (rti = 1; rti < root->simple_rel_array_size; rti++)
652 {
653 RelOptInfo *otherrel = root->simple_rel_array[rti];
654 int attroff;
655
656 /* there may be empty slots corresponding to non-baserel RTEs */
657 if (otherrel == NULL)
658 continue;
659
660 Assert(otherrel->relid == rti); /* sanity check on array */
661
662 for (attroff = otherrel->max_attr - otherrel->min_attr;
663 attroff >= 0;
664 attroff--)
665 {
666 if (bms_is_member(0, otherrel->attr_needed[attroff]))
667 otherrel->attr_needed[attroff] = bms_make_singleton(0);
668 else
669 otherrel->attr_needed[attroff] = NULL;
670 }
671
672 if (is_self_join)
673 ChangeVarNodesExtended((Node *) otherrel->lateral_vars, relid,
674 subst, 0, replace_relid_callback);
675
676 if (is_outer_join && rti != relid && root->glob->lastPHId != 0)
677 {
678 foreach_node(RestrictInfo, rinfo, otherrel->baserestrictinfo)
679 {
680 rinfo->clause = (Expr *)
681 remove_rel_from_phvs((Node *) rinfo->clause, relid, ojrelid);
682 }
683 }
684 }
685}
686
687/*
688 * Remove any references to relid or ojrelid from the RestrictInfo.
689 *
690 * We only bother to clean out bits in the RestrictInfo's various relid sets,
691 * not nullingrel bits in contained Vars and PHVs. (This might have to be
692 * improved sometime.) However, if the RestrictInfo contains an OR clause
693 * we have to also clean up the sub-clauses.
694 */
695static void
696remove_rel_from_restrictinfo(RestrictInfo *rinfo, int relid, int ojrelid)
697{
698 /*
699 * initsplan.c is fairly cavalier about allowing RestrictInfos to share
700 * relid sets with other RestrictInfos, and SpecialJoinInfos too. Make
701 * sure this RestrictInfo has its own relid sets before we modify them.
702 * (In present usage, clause_relids is probably not shared, but
703 * required_relids could be; let's not assume anything.)
704 */
705 rinfo->clause_relids = bms_copy(rinfo->clause_relids);
706 rinfo->clause_relids = bms_del_member(rinfo->clause_relids, relid);
707 rinfo->clause_relids = bms_del_member(rinfo->clause_relids, ojrelid);
708 /* Likewise for required_relids */
710 rinfo->required_relids = bms_del_member(rinfo->required_relids, relid);
711 rinfo->required_relids = bms_del_member(rinfo->required_relids, ojrelid);
712 /* Likewise for incompatible_relids */
716 /* Likewise for outer_relids */
717 rinfo->outer_relids = bms_copy(rinfo->outer_relids);
718 rinfo->outer_relids = bms_del_member(rinfo->outer_relids, relid);
719 rinfo->outer_relids = bms_del_member(rinfo->outer_relids, ojrelid);
720 /* Likewise for left_relids */
721 rinfo->left_relids = bms_copy(rinfo->left_relids);
722 rinfo->left_relids = bms_del_member(rinfo->left_relids, relid);
723 rinfo->left_relids = bms_del_member(rinfo->left_relids, ojrelid);
724 /* Likewise for right_relids */
725 rinfo->right_relids = bms_copy(rinfo->right_relids);
726 rinfo->right_relids = bms_del_member(rinfo->right_relids, relid);
727 rinfo->right_relids = bms_del_member(rinfo->right_relids, ojrelid);
728
729 /* If it's an OR, recurse to clean up sub-clauses */
730 if (restriction_is_or_clause(rinfo))
731 {
732 ListCell *lc;
733
734 Assert(is_orclause(rinfo->orclause));
735 foreach(lc, ((BoolExpr *) rinfo->orclause)->args)
736 {
737 Node *orarg = (Node *) lfirst(lc);
738
739 /* OR arguments should be ANDs or sub-RestrictInfos */
740 if (is_andclause(orarg))
741 {
742 List *andargs = ((BoolExpr *) orarg)->args;
743 ListCell *lc2;
744
745 foreach(lc2, andargs)
746 {
748
749 remove_rel_from_restrictinfo(rinfo2, relid, ojrelid);
750 }
751 }
752 else
753 {
755
756 remove_rel_from_restrictinfo(rinfo2, relid, ojrelid);
757 }
758 }
759 }
760}
761
762/*
763 * Remove any references to relid or ojrelid from the EquivalenceClass.
764 *
765 * We fix the EC and EM relid sets to ensure that implied join equalities will
766 * be generated at the appropriate join level(s). We also strip the removed
767 * rel from PlaceHolderVars embedded in member expressions; a member's
768 * em_relids reflects ph_eval_at rather than the PHV's phrels, so the latter
769 * can still mention the removed rel even when em_relids does not. Like
770 * remove_rel_from_restrictinfo, we don't bother with nullingrel bits in
771 * contained plain Vars.
772 */
773static void
775 int relid, int ojrelid)
776{
777 ListCell *lc;
778
779 /*
780 * Strip the removed rel/join from PlaceHolderVars in member expressions.
781 * This is needed even when the EC's relids don't mention the removed rel.
782 * Plain Vars and Consts can't contain a PlaceHolderVar, so skip them.
783 */
784 if (root->glob->lastPHId != 0)
785 {
787 {
788 if (!IsA(em->em_expr, Var) && !IsA(em->em_expr, Const))
789 em->em_expr = (Expr *)
790 remove_rel_from_phvs((Node *) em->em_expr, relid, ojrelid);
791 }
792 }
793
794 if (!bms_is_member(relid, ec->ec_relids) &&
795 !bms_is_member(ojrelid, ec->ec_relids))
796 return;
797
798 /* Fix up the EC's overall relids */
799 ec->ec_relids = bms_del_member(ec->ec_relids, relid);
800 ec->ec_relids = bms_del_member(ec->ec_relids, ojrelid);
801
802 /*
803 * We don't expect any EC child members to exist at this point. Ensure
804 * that's the case, otherwise, we might be getting asked to do something
805 * this function hasn't been coded for.
806 */
808
809 /*
810 * Fix up the member expressions. Any non-const member that ends with
811 * empty em_relids must be a Var or PHV of the removed relation. We don't
812 * need it anymore, so we can drop it.
813 */
814 foreach(lc, ec->ec_members)
815 {
817
818 if (bms_is_member(relid, cur_em->em_relids) ||
819 bms_is_member(ojrelid, cur_em->em_relids))
820 {
821 Assert(!cur_em->em_is_const);
822 /* em_relids is likely to be shared with some RestrictInfo */
823 cur_em->em_relids = bms_copy(cur_em->em_relids);
824 cur_em->em_relids = bms_del_member(cur_em->em_relids, relid);
825 cur_em->em_relids = bms_del_member(cur_em->em_relids, ojrelid);
826 if (bms_is_empty(cur_em->em_relids))
828 }
829 }
830
831 /* Fix up the source clauses, in case we can re-use them later */
832 foreach(lc, ec->ec_sources)
833 {
834 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
835
836 remove_rel_from_restrictinfo(rinfo, relid, ojrelid);
837 }
838
839 /*
840 * Rather than expend code on fixing up any already-derived clauses, just
841 * drop them. (At this point, any such clauses would be base restriction
842 * clauses, which we'd not need anymore anyway.)
843 */
845}
846
847/*
848 * Remove any references to the specified RT index(es) from the phrels (and
849 * phnullingrels) of every PlaceHolderVar in the given expression.
850 *
851 * remove_rel_from_query() fixes up the relid sets of RestrictInfos and
852 * EquivalenceMembers, but not the PlaceHolderVars embedded in their
853 * expressions. That's normally fine, but such an expression may later be
854 * translated for an appendrel child and have its relids recomputed by
855 * pull_varnos(). A leftover removed relid in phrels would then make
856 * pull_varnos() reference a nonexistent rel, so we strip it here to match the
857 * canonical PlaceHolderVar.
858 */
859static Node *
860remove_rel_from_phvs(Node *node, int relid, int ojrelid)
861{
863
865}
866
867static Node *
869{
870 if (node == NULL)
871 return NULL;
872 if (IsA(node, PlaceHolderVar))
873 {
876
877 /* Upper-level PlaceHolderVars should be long gone at this point */
878 Assert(phv->phlevelsup == 0);
879
880 /* Copy the PlaceHolderVar and mutate what's below ... */
881 phv = (PlaceHolderVar *)
884 removable);
885
886 /*
887 * ... then strip the removed rels from its relid sets.
888 *
889 * If stripping would empty phrels, the PHV is evaluated only at the
890 * removed relation(s); it then belongs to an EquivalenceMember that
891 * the caller drops immediately afterwards. Leave such a PHV
892 * untouched rather than build one with empty phrels, which the rest
893 * of the planner assumes never occurs.
894 */
897 {
898 phv->phrels = newphrels;
899 phv->phnullingrels = bms_difference(phv->phnullingrels,
900 removable);
901 }
902
903 return (Node *) phv;
904 }
905 return expression_tree_mutator(node,
907 removable);
908}
909
910/*
911 * Remove any occurrences of the target relid from a joinlist structure.
912 *
913 * It's easiest to build a whole new list structure, so we handle it that
914 * way. Efficiency is not a big deal here.
915 *
916 * *nremoved is incremented by the number of occurrences removed (there
917 * should be exactly one, but the caller checks that).
918 */
919static List *
921{
922 List *result = NIL;
923 ListCell *jl;
924
925 foreach(jl, joinlist)
926 {
927 Node *jlnode = (Node *) lfirst(jl);
928
929 if (IsA(jlnode, RangeTblRef))
930 {
931 int varno = ((RangeTblRef *) jlnode)->rtindex;
932
933 if (varno == relid)
934 (*nremoved)++;
935 else
937 }
938 else if (IsA(jlnode, List))
939 {
940 /* Recurse to handle subproblem */
941 List *sublist;
942
944 relid, nremoved);
945 /* Avoid including empty sub-lists in the result */
946 if (sublist)
948 }
949 else
950 {
951 elog(ERROR, "unrecognized joinlist node type: %d",
952 (int) nodeTag(jlnode));
953 }
954 }
955
956 return result;
957}
958
959
960/*
961 * reduce_unique_semijoins
962 * Check for semijoins that can be simplified to plain inner joins
963 * because the inner relation is provably unique for the join clauses.
964 *
965 * Ideally this would happen during reduce_outer_joins, but we don't have
966 * enough information at that point.
967 *
968 * To perform the strength reduction when applicable, we need only delete
969 * the semijoin's SpecialJoinInfo from root->join_info_list. (We don't
970 * bother fixing the join type attributed to it in the query jointree,
971 * since that won't be consulted again.)
972 */
973void
975{
976 ListCell *lc;
977
978 /*
979 * Scan the join_info_list to find semijoins.
980 */
981 foreach(lc, root->join_info_list)
982 {
984 int innerrelid;
985 RelOptInfo *innerrel;
987 List *restrictlist;
988
989 /*
990 * Must be a semijoin to a single baserel, else we aren't going to be
991 * able to do anything with it.
992 */
993 if (sjinfo->jointype != JOIN_SEMI)
994 continue;
995
997 continue;
998
999 innerrel = find_base_rel(root, innerrelid);
1000
1001 /*
1002 * Before we trouble to run generate_join_implied_equalities, make a
1003 * quick check to eliminate cases in which we will surely be unable to
1004 * prove uniqueness of the innerrel.
1005 */
1006 if (!rel_supports_distinctness(root, innerrel))
1007 continue;
1008
1009 /* Compute the relid set for the join we are considering */
1010 joinrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
1011 Assert(sjinfo->ojrelid == 0); /* SEMI joins don't have RT indexes */
1012
1013 /*
1014 * Since we're only considering a single-rel RHS, any join clauses it
1015 * has must be clauses linking it to the semijoin's min_lefthand. We
1016 * can also consider EC-derived join clauses.
1017 */
1018 restrictlist =
1020 joinrelids,
1021 sjinfo->min_lefthand,
1022 innerrel,
1023 NULL),
1024 innerrel->joininfo);
1025
1026 /* Test whether the innerrel is unique for those clauses. */
1028 joinrelids, sjinfo->min_lefthand, innerrel,
1029 JOIN_SEMI, restrictlist, true))
1030 continue;
1031
1032 /* OK, remove the SpecialJoinInfo from the list. */
1033 root->join_info_list = foreach_delete_current(root->join_info_list, lc);
1034 }
1035}
1036
1037
1038/*
1039 * rel_supports_distinctness
1040 * Could the relation possibly be proven distinct on some set of columns?
1041 *
1042 * This is effectively a pre-checking function for rel_is_distinct_for().
1043 * It must return true if rel_is_distinct_for() could possibly return true
1044 * with this rel, but it should not expend a lot of cycles. The idea is
1045 * that callers can avoid doing possibly-expensive processing to compute
1046 * rel_is_distinct_for()'s argument lists if the call could not possibly
1047 * succeed.
1048 */
1049static bool
1051{
1052 /* We only know about baserels ... */
1053 if (rel->reloptkind != RELOPT_BASEREL)
1054 return false;
1055 if (rel->rtekind == RTE_RELATION)
1056 {
1057 /*
1058 * For a plain relation, we only know how to prove uniqueness by
1059 * reference to unique indexes. Make sure there's at least one
1060 * suitable unique index. It must be immediately enforced, and not a
1061 * partial index. (Keep these conditions in sync with
1062 * relation_has_unique_index_for!)
1063 */
1064 ListCell *lc;
1065
1066 foreach(lc, rel->indexlist)
1067 {
1069
1070 if (ind->unique && ind->immediate && ind->indpred == NIL)
1071 return true;
1072 }
1073 }
1074 else if (rel->rtekind == RTE_SUBQUERY)
1075 {
1076 Query *subquery = root->simple_rte_array[rel->relid]->subquery;
1077
1078 /* Check if the subquery has any qualities that support distinctness */
1079 if (query_supports_distinctness(subquery))
1080 return true;
1081 }
1082 /* We have no proof rules for any other rtekinds. */
1083 return false;
1084}
1085
1086/*
1087 * rel_is_distinct_for
1088 * Does the relation return only distinct rows according to clause_list?
1089 *
1090 * clause_list is a list of join restriction clauses involving this rel and
1091 * some other one. Return true if no two rows emitted by this rel could
1092 * possibly join to the same row of the other rel.
1093 *
1094 * The caller must have already determined that each condition is a
1095 * mergejoinable equality with an expression in this relation on one side, and
1096 * an expression not involving this relation on the other. The transient
1097 * outer_is_left flag is used to identify which side references this relation:
1098 * left side if outer_is_left is false, right side if it is true.
1099 *
1100 * Note that the passed-in clause_list may be destructively modified! This
1101 * is OK for current uses, because the clause_list is built by the caller for
1102 * the sole purpose of passing to this function.
1103 *
1104 * (*extra_clauses) to be set to the right sides of baserestrictinfo clauses,
1105 * looking like "x = const" if distinctness is derived from such clauses, not
1106 * joininfo clauses. Pass NULL to the extra_clauses if this value is not
1107 * needed.
1108 */
1109static bool
1111 List **extra_clauses)
1112{
1113 /*
1114 * We could skip a couple of tests here if we assume all callers checked
1115 * rel_supports_distinctness first, but it doesn't seem worth taking any
1116 * risk for.
1117 */
1118 if (rel->reloptkind != RELOPT_BASEREL)
1119 return false;
1120 if (rel->rtekind == RTE_RELATION)
1121 {
1122 /*
1123 * Examine the indexes to see if we have a matching unique index.
1124 * relation_has_unique_index_for automatically adds any usable
1125 * restriction clauses for the rel, so we needn't do that here.
1126 */
1127 if (relation_has_unique_index_for(root, rel, clause_list, extra_clauses))
1128 return true;
1129 }
1130 else if (rel->rtekind == RTE_SUBQUERY)
1131 {
1132 Index relid = rel->relid;
1133 Query *subquery = root->simple_rte_array[relid]->subquery;
1135 ListCell *l;
1136
1137 /*
1138 * Build the argument list for query_is_distinct_for: a list of
1139 * DistinctColInfo entries, each holding an output column number that
1140 * the query needs to be distinct over, the equality operator that the
1141 * column needs to be distinct according to, and that operator's input
1142 * collation. The collation matters because the subquery's own
1143 * DISTINCT / GROUP BY / set-op proves uniqueness under its own
1144 * collation, which need not agree with the operator's.
1145 *
1146 * (XXX we are not considering restriction clauses attached to the
1147 * subquery; is that worth doing?)
1148 */
1149 foreach(l, clause_list)
1150 {
1152 OpExpr *opexpr;
1153 Var *var;
1155
1156 /*
1157 * The caller's mergejoinability test should have selected only
1158 * OpExprs. The operator might be a cross-type operator and thus
1159 * not exactly the same operator the subquery would consider;
1160 * that's all right since query_is_distinct_for can resolve such
1161 * cases.
1162 */
1163 opexpr = castNode(OpExpr, rinfo->clause);
1164
1165 /* caller identified the inner side for us */
1166 if (rinfo->outer_is_left)
1167 var = (Var *) get_rightop(rinfo->clause);
1168 else
1169 var = (Var *) get_leftop(rinfo->clause);
1170
1171 /*
1172 * We may ignore any RelabelType node above the operand. (There
1173 * won't be more than one, since eval_const_expressions() has been
1174 * applied already.)
1175 */
1176 if (var && IsA(var, RelabelType))
1177 var = (Var *) ((RelabelType *) var)->arg;
1178
1179 /*
1180 * If inner side isn't a Var referencing a subquery output column,
1181 * this clause doesn't help us.
1182 */
1183 if (!var || !IsA(var, Var) ||
1184 var->varno != relid || var->varlevelsup != 0)
1185 continue;
1186
1187 dcinfo = palloc(sizeof(DistinctColInfo));
1188 dcinfo->colno = var->varattno;
1189 dcinfo->opid = opexpr->opno;
1190 dcinfo->collid = opexpr->inputcollid;
1192 }
1193
1194 if (query_is_distinct_for(subquery, distinct_cols))
1195 return true;
1196 }
1197 return false;
1198}
1199
1200
1201/*
1202 * query_supports_distinctness - could the query possibly be proven distinct
1203 * on some set of output columns?
1204 *
1205 * This is effectively a pre-checking function for query_is_distinct_for().
1206 * It must return true if query_is_distinct_for() could possibly return true
1207 * with this query, but it should not expend a lot of cycles. The idea is
1208 * that callers can avoid doing possibly-expensive processing to compute
1209 * query_is_distinct_for()'s argument lists if the call could not possibly
1210 * succeed.
1211 */
1212bool
1214{
1215 /* SRFs break distinctness except with DISTINCT, see below */
1216 if (query->hasTargetSRFs && query->distinctClause == NIL)
1217 return false;
1218
1219 /* check for features we can prove distinctness with */
1220 if (query->distinctClause != NIL ||
1221 query->groupClause != NIL ||
1222 query->groupingSets != NIL ||
1223 query->hasAggs ||
1224 query->havingQual ||
1225 query->setOperations)
1226 return true;
1227
1228 return false;
1229}
1230
1231/*
1232 * query_is_distinct_for - does query never return duplicates of the
1233 * specified columns?
1234 *
1235 * query is a not-yet-planned subquery (in current usage, it's always from
1236 * a subquery RTE, which the planner avoids scribbling on).
1237 *
1238 * distinct_cols is a list of DistinctColInfo, one per requested output column.
1239 * Each entry names the subquery output column number we want distinct, the
1240 * upper-level equality operator we'll compare values with, and that operator's
1241 * input collation. We are interested in whether rows consisting of just these
1242 * columns are certain to be distinct.
1243 *
1244 * "Distinctness" is defined according to whether the corresponding upper-level
1245 * equality operators would think the values are distinct. (Note: each opid
1246 * could be a cross-type operator, and thus not exactly the equality operator
1247 * that the subquery would use itself. We use equality_ops_are_compatible() to
1248 * check compatibility. That looks at opfamily membership for index AMs that
1249 * have declared that they support consistent equality semantics within an
1250 * opfamily, and so should give trustworthy answers for all operators that we
1251 * might need to deal with here.)
1252 *
1253 * The collid must also agree on equality with the collation the subquery's own
1254 * DISTINCT/GROUP BY/set-op uses to deduplicate the column, else the subquery's
1255 * distinctness does not carry over to the caller's equality semantics. Two
1256 * collations agree on equality if they match or if both are deterministic (in
1257 * which case both reduce equality to byte-equality; see CREATE COLLATION).
1258 */
1259bool
1261{
1262 ListCell *l;
1264
1265 /*
1266 * DISTINCT (including DISTINCT ON) guarantees uniqueness if all the
1267 * columns in the DISTINCT clause appear in colnos and operator semantics
1268 * match. This is true even if there are SRFs in the DISTINCT columns or
1269 * elsewhere in the tlist.
1270 */
1271 if (query->distinctClause)
1272 {
1273 foreach(l, query->distinctClause)
1274 {
1277 query->targetList);
1278
1280 if (dcinfo == NULL ||
1281 !equality_ops_are_compatible(dcinfo->opid, sgc->eqop) ||
1283 exprCollation((Node *) tle->expr)))
1284 break; /* exit early if no match */
1285 }
1286 if (l == NULL) /* had matches for all? */
1287 return true;
1288 }
1289
1290 /*
1291 * Otherwise, a set-returning function in the query's targetlist can
1292 * result in returning duplicate rows, despite any grouping that might
1293 * occur before tlist evaluation. (If all tlist SRFs are within GROUP BY
1294 * columns, it would be safe because they'd be expanded before grouping.
1295 * But it doesn't currently seem worth the effort to check for that.)
1296 */
1297 if (query->hasTargetSRFs)
1298 return false;
1299
1300 /*
1301 * Similarly, GROUP BY without GROUPING SETS guarantees uniqueness if all
1302 * the grouped columns appear in colnos and operator semantics match.
1303 */
1304 if (query->groupClause && !query->groupingSets)
1305 {
1306 foreach(l, query->groupClause)
1307 {
1310 query->targetList);
1311
1313 if (dcinfo == NULL ||
1314 !equality_ops_are_compatible(dcinfo->opid, sgc->eqop) ||
1316 exprCollation((Node *) tle->expr)))
1317 break; /* exit early if no match */
1318 }
1319 if (l == NULL) /* had matches for all? */
1320 return true;
1321 }
1322 else if (query->groupingSets)
1323 {
1324 List *gsets;
1325
1326 /*
1327 * If we have grouping sets with expressions, we probably don't have
1328 * uniqueness and analysis would be hard. Punt.
1329 */
1330 if (query->groupClause)
1331 return false;
1332
1333 /*
1334 * If we have no groupClause (therefore no grouping expressions), we
1335 * might have one or many empty grouping sets. If there's just one,
1336 * or if the DISTINCT clause is used on the GROUP BY, then we're
1337 * returning only one row and are certainly unique. But otherwise, we
1338 * know we're certainly not unique.
1339 */
1340 if (query->groupDistinct)
1341 return true;
1342
1343 gsets = expand_grouping_sets(query->groupingSets, false, -1);
1344
1345 return (list_length(gsets) == 1);
1346 }
1347 else
1348 {
1349 /*
1350 * If we have no GROUP BY, but do have aggregates or HAVING, then the
1351 * result is at most one row so it's surely unique, for any operators.
1352 */
1353 if (query->hasAggs || query->havingQual)
1354 return true;
1355 }
1356
1357 /*
1358 * UNION, INTERSECT, EXCEPT guarantee uniqueness of the whole output row,
1359 * except with ALL.
1360 */
1361 if (query->setOperations)
1362 {
1364
1365 Assert(topop->op != SETOP_NONE);
1366
1367 if (!topop->all)
1368 {
1369 ListCell *lg;
1370
1371 /* We're good if all the nonjunk output columns are in colnos */
1372 lg = list_head(topop->groupClauses);
1373 foreach(l, query->targetList)
1374 {
1377
1378 if (tle->resjunk)
1379 continue; /* ignore resjunk columns */
1380
1381 /* non-resjunk columns should have grouping clauses */
1382 Assert(lg != NULL);
1384 lg = lnext(topop->groupClauses, lg);
1385
1387 if (dcinfo == NULL ||
1388 !equality_ops_are_compatible(dcinfo->opid, sgc->eqop) ||
1390 exprCollation((Node *) tle->expr)))
1391 break; /* exit early if no match */
1392 }
1393 if (l == NULL) /* had matches for all? */
1394 return true;
1395 }
1396 }
1397
1398 /*
1399 * XXX Are there any other cases in which we can easily see the result
1400 * must be distinct?
1401 *
1402 * If you do add more smarts to this function, be sure to update
1403 * query_supports_distinctness() to match.
1404 */
1405
1406 return false;
1407}
1408
1409/*
1410 * distinct_col_search - subroutine for query_is_distinct_for
1411 *
1412 * If colno matches the colno field of an entry in distinct_cols, return a
1413 * pointer to that entry; else return NULL. (Ordinarily distinct_cols would
1414 * not contain duplicate colnos, but if it does, we arbitrarily select the
1415 * first match.)
1416 */
1417static DistinctColInfo *
1419{
1421 {
1422 if (dcinfo->colno == colno)
1423 return dcinfo;
1424 }
1425
1426 return NULL;
1427}
1428
1429
1430/*
1431 * innerrel_is_unique
1432 * Check if the innerrel provably contains at most one tuple matching any
1433 * tuple from the outerrel, based on join clauses in the 'restrictlist'.
1434 *
1435 * We need an actual RelOptInfo for the innerrel, but it's sufficient to
1436 * identify the outerrel by its Relids. This asymmetry supports use of this
1437 * function before joinrels have been built. (The caller is expected to
1438 * also supply the joinrelids, just to save recalculating that.)
1439 *
1440 * The proof must be made based only on clauses that will be "joinquals"
1441 * rather than "otherquals" at execution. For an inner join there's no
1442 * difference; but if the join is outer, we must ignore pushed-down quals,
1443 * as those will become "otherquals". Note that this means the answer might
1444 * vary depending on whether IS_OUTER_JOIN(jointype); since we cache the
1445 * answer without regard to that, callers must take care not to call this
1446 * with jointypes that would be classified differently by IS_OUTER_JOIN().
1447 *
1448 * The actual proof is undertaken by is_innerrel_unique_for(); this function
1449 * is a frontend that is mainly concerned with caching the answers.
1450 * In particular, the force_cache argument allows overriding the internal
1451 * heuristic about whether to cache negative answers; it should be "true"
1452 * if making an inquiry that is not part of the normal bottom-up join search
1453 * sequence.
1454 */
1455bool
1458 Relids outerrelids,
1459 RelOptInfo *innerrel,
1460 JoinType jointype,
1461 List *restrictlist,
1462 bool force_cache)
1463{
1464 return innerrel_is_unique_ext(root, joinrelids, outerrelids, innerrel,
1465 jointype, restrictlist, force_cache, NULL);
1466}
1467
1468/*
1469 * innerrel_is_unique_ext
1470 * Do the same as innerrel_is_unique(), but also set to (*extra_clauses)
1471 * additional clauses from a baserestrictinfo list used to prove the
1472 * uniqueness.
1473 *
1474 * A non-NULL extra_clauses indicates that we're checking for self-join and
1475 * correspondingly dealing with filtered clauses.
1476 */
1477bool
1480 Relids outerrelids,
1481 RelOptInfo *innerrel,
1482 JoinType jointype,
1483 List *restrictlist,
1484 bool force_cache,
1485 List **extra_clauses)
1486{
1488 ListCell *lc;
1490 List *outer_exprs = NIL;
1491 bool self_join = (extra_clauses != NULL);
1492
1493 /* Certainly can't prove uniqueness when there are no joinclauses */
1494 if (restrictlist == NIL)
1495 return false;
1496
1497 /*
1498 * Make a quick check to eliminate cases in which we will surely be unable
1499 * to prove uniqueness of the innerrel.
1500 */
1501 if (!rel_supports_distinctness(root, innerrel))
1502 return false;
1503
1504 /*
1505 * Query the cache to see if we've managed to prove that innerrel is
1506 * unique for any subset of this outerrel. For non-self-join search, we
1507 * don't need an exact match, as extra outerrels can't make the innerrel
1508 * any less unique (or more formally, the restrictlist for a join to a
1509 * superset outerrel must be a superset of the conditions we successfully
1510 * used before). For self-join search, we require an exact match of
1511 * outerrels because we need extra clauses to be valid for our case. Also,
1512 * for self-join checking we've filtered the clauses list. Thus, we can
1513 * match only the result cached for a self-join search for another
1514 * self-join check.
1515 */
1516 foreach(lc, innerrel->unique_for_rels)
1517 {
1519
1520 if ((!self_join && bms_is_subset(uniqueRelInfo->outerrelids, outerrelids)) ||
1521 (self_join && bms_equal(uniqueRelInfo->outerrelids, outerrelids) &&
1522 uniqueRelInfo->self_join))
1523 {
1524 if (extra_clauses)
1525 *extra_clauses = uniqueRelInfo->extra_clauses;
1526 return true; /* Success! */
1527 }
1528 }
1529
1530 /*
1531 * Conversely, we may have already determined that this outerrel, or some
1532 * superset thereof, cannot prove this innerrel to be unique.
1533 */
1534 foreach(lc, innerrel->non_unique_for_rels)
1535 {
1536 Relids unique_for_rels = (Relids) lfirst(lc);
1537
1538 if (bms_is_subset(outerrelids, unique_for_rels))
1539 return false;
1540 }
1541
1542 /* No cached information, so try to make the proof. */
1543 if (is_innerrel_unique_for(root, joinrelids, outerrelids, innerrel,
1544 jointype, restrictlist,
1545 self_join ? &outer_exprs : NULL))
1546 {
1547 /*
1548 * Cache the positive result for future probes, being sure to keep it
1549 * in the planner_cxt even if we are working in GEQO.
1550 *
1551 * Note: one might consider trying to isolate the minimal subset of
1552 * the outerrels that proved the innerrel unique. But it's not worth
1553 * the trouble, because the planner builds up joinrels incrementally
1554 * and so we'll see the minimally sufficient outerrels before any
1555 * supersets of them anyway.
1556 */
1557 old_context = MemoryContextSwitchTo(root->planner_cxt);
1559 uniqueRelInfo->outerrelids = bms_copy(outerrelids);
1560 uniqueRelInfo->self_join = self_join;
1561 uniqueRelInfo->extra_clauses = outer_exprs;
1562 innerrel->unique_for_rels = lappend(innerrel->unique_for_rels,
1565
1566 if (extra_clauses)
1567 *extra_clauses = outer_exprs;
1568 return true; /* Success! */
1569 }
1570 else
1571 {
1572 /*
1573 * None of the join conditions for outerrel proved innerrel unique, so
1574 * we can safely reject this outerrel or any subset of it in future
1575 * checks.
1576 *
1577 * However, in normal planning mode, caching this knowledge is totally
1578 * pointless; it won't be queried again, because we build up joinrels
1579 * from smaller to larger. It's only useful when using GEQO or
1580 * another planner extension that attempts planning multiple times.
1581 *
1582 * Also, allow callers to override that heuristic and force caching;
1583 * that's useful for reduce_unique_semijoins, which calls here before
1584 * the normal join search starts.
1585 */
1586 if (force_cache || root->assumeReplanning)
1587 {
1588 old_context = MemoryContextSwitchTo(root->planner_cxt);
1589 innerrel->non_unique_for_rels =
1590 lappend(innerrel->non_unique_for_rels,
1591 bms_copy(outerrelids));
1593 }
1594
1595 return false;
1596 }
1597}
1598
1599/*
1600 * is_innerrel_unique_for
1601 * Check if the innerrel provably contains at most one tuple matching any
1602 * tuple from the outerrel, based on join clauses in the 'restrictlist'.
1603 */
1604static bool
1607 Relids outerrelids,
1608 RelOptInfo *innerrel,
1609 JoinType jointype,
1610 List *restrictlist,
1611 List **extra_clauses)
1612{
1613 List *clause_list = NIL;
1614 ListCell *lc;
1615
1616 /*
1617 * Search for mergejoinable clauses that constrain the inner rel against
1618 * the outer rel. If an operator is mergejoinable then it behaves like
1619 * equality for some btree opclass, so it's what we want. The
1620 * mergejoinability test also eliminates clauses containing volatile
1621 * functions, which we couldn't depend on.
1622 */
1623 foreach(lc, restrictlist)
1624 {
1626
1627 /*
1628 * As noted above, if it's a pushed-down clause and we're at an outer
1629 * join, we can't use it.
1630 */
1631 if (IS_OUTER_JOIN(jointype) &&
1633 continue;
1634
1635 /* Ignore if it's not a mergejoinable clause */
1636 if (!restrictinfo->can_join ||
1637 restrictinfo->mergeopfamilies == NIL)
1638 continue; /* not mergejoinable */
1639
1640 /*
1641 * Check if the clause has the form "outer op inner" or "inner op
1642 * outer", and if so mark which side is inner.
1643 */
1644 if (!clause_sides_match_join(restrictinfo, outerrelids,
1645 innerrel->relids))
1646 continue; /* no good for these input relations */
1647
1648 /* OK, add to the list */
1650 }
1651
1652 /* Let rel_is_distinct_for() do the hard work */
1653 return rel_is_distinct_for(root, innerrel, clause_list, extra_clauses);
1654}
1655
1656/*
1657 * Update EC members to point to the remaining relation instead of the removed
1658 * one, removing duplicates.
1659 *
1660 * Restriction clauses for base relations are already distributed to
1661 * the respective baserestrictinfo lists (see
1662 * generate_implied_equalities_for_column). The above code has already processed
1663 * this list and updated these clauses to reference the remaining
1664 * relation, so that we can skip them here based on their relids.
1665 *
1666 * Likewise, we have already processed the join clauses that join the
1667 * removed relation to the remaining one.
1668 *
1669 * Finally, there might be join clauses tying the removed relation to
1670 * some third relation. We can't just delete the source clauses and
1671 * regenerate them from the EC because the corresponding equality
1672 * operators might be missing (see the handling of ec_broken).
1673 * Therefore, we will update the references in the source clauses.
1674 *
1675 * Derived clauses can be generated again, so it is simpler just to
1676 * delete them.
1677 */
1678static void
1679update_eclasses(EquivalenceClass *ec, int from, int to)
1680{
1681 List *new_members = NIL;
1682 List *new_sources = NIL;
1683
1684 /*
1685 * We don't expect any EC child members to exist at this point. Ensure
1686 * that's the case, otherwise, we might be getting asked to do something
1687 * this function hasn't been coded for.
1688 */
1689 Assert(ec->ec_childmembers == NULL);
1690
1692 {
1693 bool is_redundant = false;
1694
1695 if (!bms_is_member(from, em->em_relids))
1696 {
1698 continue;
1699 }
1700
1701 em->em_relids = adjust_relid_set(em->em_relids, from, to);
1702 em->em_jdomain->jd_relids = adjust_relid_set(em->em_jdomain->jd_relids, from, to);
1703
1704 /* We only process inner joins */
1705 ChangeVarNodesExtended((Node *) em->em_expr, from, to, 0,
1707
1709 {
1710 if (!equal(em->em_relids, other->em_relids))
1711 continue;
1712
1713 if (equal(em->em_expr, other->em_expr))
1714 {
1715 is_redundant = true;
1716 break;
1717 }
1718 }
1719
1720 if (!is_redundant)
1722 }
1723
1724 list_free(ec->ec_members);
1725 ec->ec_members = new_members;
1726
1728
1729 /* Update EC source expressions */
1731 {
1732 bool is_redundant = false;
1733
1734 if (!bms_is_member(from, rinfo->required_relids))
1735 {
1737 continue;
1738 }
1739
1740 ChangeVarNodesExtended((Node *) rinfo, from, to, 0,
1742
1743 /*
1744 * After switching the clause to the remaining relation, check it for
1745 * redundancy with existing ones. We don't have to check for
1746 * redundancy with derived clauses, because we've just deleted them.
1747 */
1749 {
1750 if (!equal(rinfo->clause_relids, other->clause_relids))
1751 continue;
1752
1753 if (equal(rinfo->clause, other->clause))
1754 {
1755 is_redundant = true;
1756 break;
1757 }
1758 }
1759
1760 if (!is_redundant)
1762 }
1763
1764 list_free(ec->ec_sources);
1765 ec->ec_sources = new_sources;
1766 ec->ec_relids = adjust_relid_set(ec->ec_relids, from, to);
1767}
1768
1769/*
1770 * "Logically" compares two RestrictInfo's ignoring the 'rinfo_serial' field,
1771 * which makes almost every RestrictInfo unique. This type of comparison is
1772 * useful when removing duplicates while moving RestrictInfo's from removed
1773 * relation to remaining relation during self-join elimination.
1774 *
1775 * XXX: In the future, we might remove the 'rinfo_serial' field completely and
1776 * get rid of this function.
1777 */
1778static bool
1780{
1781 int saved_rinfo_serial = a->rinfo_serial;
1782 bool result;
1783
1784 a->rinfo_serial = b->rinfo_serial;
1785 result = equal(a, b);
1786 a->rinfo_serial = saved_rinfo_serial;
1787
1788 return result;
1789}
1790
1791/*
1792 * This function adds all non-redundant clauses to the keeping relation
1793 * during self-join elimination. That is a contradictory operation. On the
1794 * one hand, we reduce the length of the `restrict` lists, which can
1795 * impact planning or executing time. Additionally, we improve the
1796 * accuracy of cardinality estimation. On the other hand, it is one more
1797 * place that can make planning time much longer in specific cases. It
1798 * would have been better to avoid calling the equal() function here, but
1799 * it's the only way to detect duplicated inequality expressions.
1800 *
1801 * (*keep_rinfo_list) is given by pointer because it might be altered by
1802 * distribute_restrictinfo_to_rels().
1803 */
1804static void
1809{
1811 {
1812 bool is_redundant = false;
1813
1814 Assert(!bms_is_member(removed_relid, rinfo->required_relids));
1815
1817 {
1818 if (!bms_equal(src->clause_relids, rinfo->clause_relids))
1819 /* Can't compare trivially different clauses */
1820 continue;
1821
1822 if (src == rinfo ||
1823 (rinfo->parent_ec != NULL &&
1824 src->parent_ec == rinfo->parent_ec) ||
1826 {
1827 is_redundant = true;
1828 break;
1829 }
1830 }
1831 if (!is_redundant)
1833 }
1834}
1835
1836/*
1837 * A custom callback for ChangeVarNodesExtended() providing Self-join
1838 * elimination (SJE) related functionality
1839 *
1840 * SJE needs to skip the RangeTblRef node type. During SJE's last
1841 * step, remove_rel_from_joinlist() removes remaining RangeTblRefs
1842 * with target relid. If ChangeVarNodes() replaces the target relid
1843 * before, remove_rel_from_joinlist() would fail to identify the nodes
1844 * to delete.
1845 *
1846 * SJE also needs to change the relids within RestrictInfo's.
1847 */
1848static bool
1850{
1851 if (IsA(node, RangeTblRef))
1852 {
1853 return true;
1854 }
1855 else if (IsA(node, RestrictInfo))
1856 {
1857 RestrictInfo *rinfo = (RestrictInfo *) node;
1858 int relid = -1;
1859 bool is_req_equal =
1860 (rinfo->required_relids == rinfo->clause_relids);
1862 (bms_membership(rinfo->clause_relids) == BMS_MULTIPLE);
1863
1864 /*
1865 * Recurse down into clauses if the target relation is present in
1866 * clause_relids or required_relids. We must check required_relids
1867 * because the relation not present in clause_relids might still be
1868 * present somewhere in orclause.
1869 */
1870 if (bms_is_member(context->rt_index, rinfo->clause_relids) ||
1871 bms_is_member(context->rt_index, rinfo->required_relids))
1872 {
1874
1875 ChangeVarNodesWalkExpression((Node *) rinfo->clause, context);
1876 ChangeVarNodesWalkExpression((Node *) rinfo->orclause, context);
1877
1878 new_clause_relids = adjust_relid_set(rinfo->clause_relids,
1879 context->rt_index,
1880 context->new_index);
1881
1882 /*
1883 * Incrementally adjust num_base_rels based on the change of
1884 * clause_relids, which could contain both base relids and
1885 * outer-join relids. This operation is legal until we remove
1886 * only baserels.
1887 */
1888 rinfo->num_base_rels -= bms_num_members(rinfo->clause_relids) -
1890
1891 rinfo->clause_relids = new_clause_relids;
1892 rinfo->left_relids =
1893 adjust_relid_set(rinfo->left_relids, context->rt_index, context->new_index);
1894 rinfo->right_relids =
1895 adjust_relid_set(rinfo->right_relids, context->rt_index, context->new_index);
1896 }
1897
1898 if (is_req_equal)
1899 rinfo->required_relids = rinfo->clause_relids;
1900 else
1901 rinfo->required_relids =
1902 adjust_relid_set(rinfo->required_relids, context->rt_index, context->new_index);
1903
1904 rinfo->outer_relids =
1905 adjust_relid_set(rinfo->outer_relids, context->rt_index, context->new_index);
1906 rinfo->incompatible_relids =
1907 adjust_relid_set(rinfo->incompatible_relids, context->rt_index, context->new_index);
1908
1909 if (rinfo->mergeopfamilies &&
1910 bms_get_singleton_member(rinfo->clause_relids, &relid) &&
1912 relid == context->new_index && IsA(rinfo->clause, OpExpr))
1913 {
1914 Expr *leftOp;
1915 Expr *rightOp;
1916
1917 leftOp = (Expr *) get_leftop(rinfo->clause);
1918 rightOp = (Expr *) get_rightop(rinfo->clause);
1919
1920 /*
1921 * For self-join elimination, changing varnos could transform
1922 * "t1.a = t2.a" into "t1.a = t1.a". That is always true as long
1923 * as "t1.a" is not null. We use equal() to check for such a
1924 * case, and then we replace the qual with a check for not null
1925 * (NullTest).
1926 */
1927 if (leftOp != NULL && equal(leftOp, rightOp))
1928 {
1930
1931 ntest->arg = leftOp;
1932 ntest->nulltesttype = IS_NOT_NULL;
1933 ntest->argisrow = false;
1934 ntest->location = -1;
1935 rinfo->clause = (Expr *) ntest;
1936 rinfo->mergeopfamilies = NIL;
1937 rinfo->left_em = NULL;
1938 rinfo->right_em = NULL;
1939 }
1940 Assert(rinfo->orclause == NULL);
1941 }
1942 return true;
1943 }
1944
1945 return false;
1946}
1947
1948/*
1949 * Remove a relation after we have proven that it participates only in an
1950 * unneeded unique self-join.
1951 *
1952 * Replace any links in planner info structures.
1953 *
1954 * Transfer join and restriction clauses from the removed relation to the
1955 * remaining one. We change the Vars of the clause to point to the
1956 * remaining relation instead of the removed one. The clauses that require
1957 * a subset of joinrelids become restriction clauses of the remaining
1958 * relation, and others remain join clauses. We append them to
1959 * baserestrictinfo and joininfo, respectively, trying not to introduce
1960 * duplicates.
1961 *
1962 * We also have to process the 'joinclauses' list here, because it
1963 * contains EC-derived join clauses which must become filter clauses. It
1964 * is not enough to just correct the ECs because the EC-derived
1965 * restrictions are generated before join removal (see
1966 * generate_base_implied_equalities).
1967 *
1968 * NOTE: Remember to keep the code in sync with PlannerInfo to be sure all
1969 * cached relids and relid bitmapsets can be correctly cleaned during the
1970 * self-join elimination procedure.
1971 */
1972static void
1975 List *restrictlist)
1976{
1977 List *joininfos;
1978 ListCell *lc;
1979 int i;
1982
1983 Assert(toKeep->relid > 0);
1984 Assert(toRemove->relid > 0);
1985
1986 /*
1987 * Replace the index of the removing table with the keeping one. The
1988 * technique of removing/distributing restrictinfo is used here to attach
1989 * just appeared (for keeping relation) join clauses and avoid adding
1990 * duplicates of those that already exist in the joininfo list.
1991 */
1992 joininfos = list_copy(toRemove->joininfo);
1994 {
1995 remove_join_clause_from_rels(root, rinfo, rinfo->required_relids);
1996 ChangeVarNodesExtended((Node *) rinfo, toRemove->relid, toKeep->relid,
1998
1999 if (bms_membership(rinfo->required_relids) == BMS_MULTIPLE)
2001 else
2003 }
2004
2005 /*
2006 * Concatenate restrictlist to the list of base restrictions of the
2007 * removing table just to simplify the replacement procedure: all of them
2008 * weren't connected to any keeping relations and need to be added to some
2009 * rels.
2010 */
2011 toRemove->baserestrictinfo = list_concat(toRemove->baserestrictinfo,
2012 restrictlist);
2013 foreach_node(RestrictInfo, rinfo, toRemove->baserestrictinfo)
2014 {
2015 ChangeVarNodesExtended((Node *) rinfo, toRemove->relid, toKeep->relid,
2017
2018 if (bms_membership(rinfo->required_relids) == BMS_MULTIPLE)
2020 else
2022 }
2023
2024 /*
2025 * Now, add all non-redundant clauses to the keeping relation.
2026 */
2028 &toKeep->baserestrictinfo, toRemove->relid);
2030 &toKeep->joininfo, toRemove->relid);
2031
2034
2035 /*
2036 * Arrange equivalence classes, mentioned removing a table, with the
2037 * keeping one: varno of removing table should be replaced in members and
2038 * sources lists. Also, remove duplicated elements if this replacement
2039 * procedure created them.
2040 */
2041 i = -1;
2042 while ((i = bms_next_member(toRemove->eclass_indexes, i)) >= 0)
2043 {
2044 EquivalenceClass *ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
2045
2046 update_eclasses(ec, toRemove->relid, toKeep->relid);
2047 toKeep->eclass_indexes = bms_add_member(toKeep->eclass_indexes, i);
2048 }
2049
2050 /*
2051 * Transfer the targetlist and attr_needed flags.
2052 */
2053
2054 foreach(lc, toRemove->reltarget->exprs)
2055 {
2056 Node *node = lfirst(lc);
2057
2058 ChangeVarNodesExtended(node, toRemove->relid, toKeep->relid, 0,
2060 if (!list_member(toKeep->reltarget->exprs, node))
2061 toKeep->reltarget->exprs = lappend(toKeep->reltarget->exprs, node);
2062 }
2063
2064 for (i = toKeep->min_attr; i <= toKeep->max_attr; i++)
2065 {
2066 int attno = i - toKeep->min_attr;
2067
2068 toRemove->attr_needed[attno] = adjust_relid_set(toRemove->attr_needed[attno],
2069 toRemove->relid, toKeep->relid);
2070 toKeep->attr_needed[attno] = bms_add_members(toKeep->attr_needed[attno],
2071 toRemove->attr_needed[attno]);
2072 }
2073
2074 /*
2075 * If the removed relation has a row mark, transfer it to the remaining
2076 * one.
2077 *
2078 * If both rels have row marks, just keep the one corresponding to the
2079 * remaining relation because we verified earlier that they have the same
2080 * strength.
2081 */
2082 if (rmark)
2083 {
2084 if (kmark)
2085 {
2086 Assert(kmark->markType == rmark->markType);
2087
2088 root->rowMarks = list_delete_ptr(root->rowMarks, rmark);
2089 }
2090 else
2091 {
2092 /* Shouldn't have inheritance children here. */
2093 Assert(rmark->rti == rmark->prti);
2094
2095 rmark->rti = rmark->prti = toKeep->relid;
2096 }
2097 }
2098
2099 /*
2100 * Replace varno in all the query structures, except nodes RangeTblRef
2101 * otherwise later remove_rel_from_joinlist will yield errors.
2102 */
2103 ChangeVarNodesExtended((Node *) root->parse, toRemove->relid, toKeep->relid,
2105
2106 /* Replace links in the planner info */
2108
2109 /* Replace varno in the fully-processed targetlist */
2110 ChangeVarNodesExtended((Node *) root->processed_tlist, toRemove->relid,
2111 toKeep->relid, 0, replace_relid_callback);
2112
2113 /*
2114 * No need to touch all_result_relids or leaf_result_relids: at this point
2115 * those sets contain only parse->resultRelation; inheritance children
2116 * have not been added yet; that happens later in add_other_rels_to_query.
2117 * And remove_self_joins_recurse rejects parse->resultRelation as an SJE
2118 * candidate to preserve the EPQ mechanism. So toRemove->relid cannot be
2119 * a member.
2120 */
2121 Assert(!bms_is_member(toRemove->relid, root->all_result_relids));
2122 Assert(!bms_is_member(toRemove->relid, root->leaf_result_relids));
2123
2124 /*
2125 * There may be references to the rel in root->fkey_list, but if so,
2126 * match_foreign_keys_to_quals() will get rid of them.
2127 */
2128
2129 /*
2130 * Finally, remove the rel from the baserel array to prevent it from being
2131 * referenced again. (We can't do this earlier because
2132 * remove_join_clause_from_rels will touch it.)
2133 */
2134 root->simple_rel_array[toRemove->relid] = NULL;
2135 root->simple_rte_array[toRemove->relid] = NULL;
2136
2137 /* And nuke the RelOptInfo, just in case there's another access path. */
2138 pfree(toRemove);
2139
2140
2141 /*
2142 * Now repeat construction of attr_needed bits coming from all other
2143 * sources.
2144 */
2149}
2150
2151/*
2152 * split_selfjoin_quals
2153 * Processes 'joinquals' by building two lists: one containing the quals
2154 * where the columns/exprs are on either side of the join match and
2155 * another one containing the remaining quals.
2156 *
2157 * 'joinquals' must only contain quals for a RTE_RELATION being joined to
2158 * itself.
2159 */
2160static void
2162 List **otherjoinquals, int from, int to)
2163{
2164 List *sjoinquals = NIL;
2165 List *ojoinquals = NIL;
2166
2168 {
2169 OpExpr *expr;
2170 Node *leftexpr;
2171 Node *rightexpr;
2172
2173 /* In general, clause looks like F(arg1) = G(arg2) */
2174 if (!rinfo->mergeopfamilies ||
2175 bms_num_members(rinfo->clause_relids) != 2 ||
2176 bms_membership(rinfo->left_relids) != BMS_SINGLETON ||
2177 bms_membership(rinfo->right_relids) != BMS_SINGLETON)
2178 {
2179 ojoinquals = lappend(ojoinquals, rinfo);
2180 continue;
2181 }
2182
2183 expr = (OpExpr *) rinfo->clause;
2184
2185 if (!IsA(expr, OpExpr) || list_length(expr->args) != 2)
2186 {
2187 ojoinquals = lappend(ojoinquals, rinfo);
2188 continue;
2189 }
2190
2191 leftexpr = get_leftop(rinfo->clause);
2192 rightexpr = copyObject(get_rightop(rinfo->clause));
2193
2195 leftexpr = (Node *) ((RelabelType *) leftexpr)->arg;
2197 rightexpr = (Node *) ((RelabelType *) rightexpr)->arg;
2198
2199 /*
2200 * Quite an expensive operation, narrowing the use case. For example,
2201 * when we have cast of the same var to different (but compatible)
2202 * types.
2203 */
2205 bms_singleton_member(rinfo->right_relids),
2206 bms_singleton_member(rinfo->left_relids), 0,
2208
2209 if (equal(leftexpr, rightexpr))
2210 sjoinquals = lappend(sjoinquals, rinfo);
2211 else
2212 ojoinquals = lappend(ojoinquals, rinfo);
2213 }
2214
2217}
2218
2219/*
2220 * Check for a case when uniqueness is at least partly derived from a
2221 * baserestrictinfo clause. In this case, we have a chance to return only
2222 * one row (if such clauses on both sides of SJ are equal) or nothing (if they
2223 * are different).
2224 */
2225static bool
2227 Index relid)
2228{
2230 {
2231 Expr *clause;
2232 Node *iclause;
2233 Node *c1;
2234 bool matched = false;
2235
2236 Assert(outer->relid > 0 && relid > 0);
2237
2238 /* Only filters like f(R.x1,...,R.xN) == expr we should consider. */
2239 Assert(bms_is_empty(rinfo->left_relids) ^
2240 bms_is_empty(rinfo->right_relids));
2241
2242 clause = (Expr *) copyObject(rinfo->clause);
2243 ChangeVarNodesExtended((Node *) clause, relid, outer->relid, 0,
2245
2246 iclause = bms_is_empty(rinfo->left_relids) ? get_rightop(clause) :
2247 get_leftop(clause);
2248 c1 = bms_is_empty(rinfo->left_relids) ? get_leftop(clause) :
2249 get_rightop(clause);
2250
2251 /*
2252 * Compare these left and right sides with the corresponding sides of
2253 * the outer's filters. If no one is detected - return immediately.
2254 */
2256 {
2257 Node *oclause;
2258 Node *c2;
2259
2260 if (orinfo->mergeopfamilies == NIL)
2261 /* Don't consider clauses that aren't similar to 'F(X)=G(Y)' */
2262 continue;
2263
2264 Assert(is_opclause(orinfo->clause));
2265
2266 oclause = bms_is_empty(orinfo->left_relids) ?
2267 get_rightop(orinfo->clause) : get_leftop(orinfo->clause);
2268 c2 = (bms_is_empty(orinfo->left_relids) ?
2269 get_leftop(orinfo->clause) : get_rightop(orinfo->clause));
2270
2271 if (equal(iclause, oclause) && equal(c1, c2))
2272 {
2273 matched = true;
2274 break;
2275 }
2276 }
2277
2278 if (!matched)
2279 return false;
2280 }
2281
2282 return true;
2283}
2284
2285/*
2286 * Find and remove unique self-joins in a group of base relations that have
2287 * the same Oid.
2288 *
2289 * Returns a set of relids that were removed.
2290 */
2291static Relids
2293{
2294 Relids result = NULL;
2295 int k; /* Index of kept relation */
2296 int r = -1; /* Index of removed relation */
2297
2298 while ((r = bms_next_member(relids, r)) > 0)
2299 {
2300 RelOptInfo *rrel = root->simple_rel_array[r];
2301
2302 k = r;
2303
2304 while ((k = bms_next_member(relids, k)) > 0)
2305 {
2307 RelOptInfo *krel = root->simple_rel_array[k];
2308 List *restrictlist;
2311 ListCell *lc;
2312 bool jinfo_check = true;
2315 List *uclauses = NIL;
2316
2317 /* A sanity check: the relations have the same Oid. */
2318 Assert(root->simple_rte_array[k]->relid ==
2319 root->simple_rte_array[r]->relid);
2320
2321 /*
2322 * It is impossible to eliminate the join of two relations if they
2323 * belong to different rules of order. Otherwise, the planner
2324 * can't find any variants of the correct query plan.
2325 */
2326 foreach(lc, root->join_info_list)
2327 {
2329
2330 if ((bms_is_member(k, info->syn_lefthand) ^
2331 bms_is_member(r, info->syn_lefthand)) ||
2332 (bms_is_member(k, info->syn_righthand) ^
2333 bms_is_member(r, info->syn_righthand)))
2334 {
2335 jinfo_check = false;
2336 break;
2337 }
2338 }
2339 if (!jinfo_check)
2340 continue;
2341
2342 /*
2343 * Check Row Marks equivalence. We can't remove the join if the
2344 * relations have row marks of different strength (e.g., one is
2345 * locked FOR UPDATE, and another just has ROW_MARK_REFERENCE for
2346 * EvalPlanQual rechecking).
2347 */
2348 foreach(lc, root->rowMarks)
2349 {
2351
2352 if (rowMark->rti == r)
2353 {
2354 Assert(rmark == NULL);
2355 rmark = rowMark;
2356 }
2357 else if (rowMark->rti == k)
2358 {
2359 Assert(kmark == NULL);
2360 kmark = rowMark;
2361 }
2362
2363 if (kmark && rmark)
2364 break;
2365 }
2366 if (kmark && rmark && kmark->markType != rmark->markType)
2367 continue;
2368
2369 /*
2370 * We only deal with base rels here, so their relids bitset
2371 * contains only one member -- their relid.
2372 */
2375
2376 /*
2377 * PHVs should not impose any constraints on removing self-joins.
2378 */
2379
2380 /*
2381 * At this stage, joininfo lists of inner and outer can contain
2382 * only clauses required for a superior outer join that can't
2383 * influence this optimization. So, we can avoid to call the
2384 * build_joinrel_restrictlist() routine.
2385 */
2387 rrel->relids,
2388 krel, NULL);
2389 if (restrictlist == NIL)
2390 continue;
2391
2392 /*
2393 * Process restrictlist to separate the self-join quals from the
2394 * other quals. e.g., "x = x" goes to selfjoinquals and "a = b" to
2395 * otherjoinquals.
2396 */
2397 split_selfjoin_quals(root, restrictlist, &selfjoinquals,
2398 &otherjoinquals, rrel->relid, krel->relid);
2399
2400 Assert(list_length(restrictlist) ==
2402
2403 /*
2404 * To enable SJE for the only degenerate case without any self
2405 * join clauses at all, add baserestrictinfo to this list. The
2406 * degenerate case works only if both sides have the same clause.
2407 * So doesn't matter which side to add.
2408 */
2409 selfjoinquals = list_concat(selfjoinquals, krel->baserestrictinfo);
2410
2411 /*
2412 * Determine if the rrel can duplicate outer rows. We must bypass
2413 * the unique rel cache here since we're possibly using a subset
2414 * of join quals. We can use 'force_cache' == true when all join
2415 * quals are self-join quals. Otherwise, we could end up putting
2416 * false negatives in the cache.
2417 */
2421 &uclauses))
2422 continue;
2423
2424 /*
2425 * 'uclauses' is the copy of outer->baserestrictinfo that are
2426 * associated with an index. We proved by matching selfjoinquals
2427 * to a unique index that the outer relation has at most one
2428 * matching row for each inner row. Sometimes that is not enough.
2429 * e.g. "WHERE s1.b = s2.b AND s1.a = 1 AND s2.a = 2" when the
2430 * unique index is (a,b). Having non-empty uclauses, we must
2431 * validate that the inner baserestrictinfo contains the same
2432 * expressions, or we won't match the same row on each side of the
2433 * join.
2434 */
2435 if (!match_unique_clauses(root, rrel, uclauses, krel->relid))
2436 continue;
2437
2438 /*
2439 * Remove rrel RelOptInfo from the planner structures and the
2440 * corresponding row mark.
2441 */
2442 remove_self_join_rel(root, kmark, rmark, krel, rrel, restrictlist);
2443
2445
2446 /* We have removed the outer relation, try the next one. */
2447 break;
2448 }
2449 }
2450
2451 return result;
2452}
2453
2454/*
2455 * Gather indexes of base relations from the joinlist and try to eliminate self
2456 * joins.
2457 */
2458static Relids
2460{
2461 ListCell *jl;
2462 Relids relids = NULL;
2464 int i;
2465 int j;
2466 int numRels;
2467
2468 /* Collect indexes of base relations of the join tree */
2469 foreach(jl, joinlist)
2470 {
2471 Node *jlnode = (Node *) lfirst(jl);
2472
2473 if (IsA(jlnode, RangeTblRef))
2474 {
2475 int varno = ((RangeTblRef *) jlnode)->rtindex;
2476 RangeTblEntry *rte = root->simple_rte_array[varno];
2477
2478 /*
2479 * We only consider ordinary relations as candidates to be
2480 * removed, and these relations should not have TABLESAMPLE
2481 * clauses specified. Removing a relation with TABLESAMPLE clause
2482 * could potentially change the syntax of the query. Because of
2483 * UPDATE/DELETE EPQ mechanism, currently Query->resultRelation or
2484 * Query->mergeTargetRelation associated rel cannot be eliminated.
2485 */
2486 if (rte->rtekind == RTE_RELATION &&
2487 rte->relkind == RELKIND_RELATION &&
2488 rte->tablesample == NULL &&
2489 varno != root->parse->resultRelation &&
2490 varno != root->parse->mergeTargetRelation)
2491 {
2492 Assert(!bms_is_member(varno, relids));
2493 relids = bms_add_member(relids, varno);
2494 }
2495 }
2496 else if (IsA(jlnode, List))
2497 {
2498 /* Recursively go inside the sub-joinlist */
2500 toRemove);
2501 }
2502 else
2503 elog(ERROR, "unrecognized joinlist node type: %d",
2504 (int) nodeTag(jlnode));
2505 }
2506
2507 numRels = bms_num_members(relids);
2508
2509 /* Need at least two relations for the join */
2510 if (numRels < 2)
2511 return toRemove;
2512
2513 /*
2514 * In order to find relations with the same oid we first build an array of
2515 * candidates and then sort it by oid.
2516 */
2518 i = -1;
2519 j = 0;
2520 while ((i = bms_next_member(relids, i)) >= 0)
2521 {
2522 candidates[j].relid = i;
2523 candidates[j].reloid = root->simple_rte_array[i]->relid;
2524 j++;
2525 }
2526
2529
2530 /*
2531 * Iteratively form a group of relation indexes with the same oid and
2532 * launch the routine that detects self-joins in this group and removes
2533 * excessive range table entries.
2534 *
2535 * At the end of the iteration, exclude the group from the overall relids
2536 * list. So each next iteration of the cycle will involve less and less
2537 * value of relids.
2538 */
2539 i = 0;
2540 for (j = 1; j < numRels + 1; j++)
2541 {
2542 if (j == numRels || candidates[j].reloid != candidates[i].reloid)
2543 {
2544 if (j - i >= 2)
2545 {
2546 /* Create a group of relation indexes with the same oid */
2547 Relids group = NULL;
2549
2550 while (i < j)
2551 {
2552 group = bms_add_member(group, candidates[i].relid);
2553 i++;
2554 }
2555 relids = bms_del_members(relids, group);
2556
2557 /*
2558 * Try to remove self-joins from a group of identical entries.
2559 * Make the next attempt iteratively - if something is deleted
2560 * from a group, changes in clauses and equivalence classes
2561 * can give us a chance to find more candidates.
2562 */
2563 do
2564 {
2565 Assert(!bms_overlap(group, toRemove));
2568 group = bms_del_members(group, removed);
2569 } while (!bms_is_empty(removed) &&
2570 bms_membership(group) == BMS_MULTIPLE);
2572 bms_free(group);
2573 }
2574 else
2575 {
2576 /* Single relation, just remove it from the set */
2577 relids = bms_del_member(relids, candidates[i].relid);
2578 i = j;
2579 }
2580 }
2581 }
2582
2583 Assert(bms_is_empty(relids));
2584
2585 return toRemove;
2586}
2587
2588/*
2589 * Compare self-join candidates by their oids.
2590 */
2591static int
2592self_join_candidates_cmp(const void *a, const void *b)
2593{
2594 const SelfJoinCandidate *ca = (const SelfJoinCandidate *) a;
2595 const SelfJoinCandidate *cb = (const SelfJoinCandidate *) b;
2596
2597 if (ca->reloid != cb->reloid)
2598 return (ca->reloid < cb->reloid ? -1 : 1);
2599 else
2600 return 0;
2601}
2602
2603/*
2604 * Find and remove useless self joins.
2605 *
2606 * Search for joins where a relation is joined to itself. If the join clause
2607 * for each tuple from one side of the join is proven to match the same
2608 * physical row (or nothing) on the other side, that self-join can be
2609 * eliminated from the query. Suitable join clauses are assumed to be in the
2610 * form of X = X, and can be replaced with NOT NULL clauses.
2611 *
2612 * For the sake of simplicity, we don't apply this optimization to special
2613 * joins. Here is a list of what we could do in some particular cases:
2614 * 'a a1 semi join a a2': is reduced to inner by reduce_unique_semijoins,
2615 * and then removed normally.
2616 * 'a a1 anti join a a2': could simplify to a scan with 'outer quals AND
2617 * (IS NULL on join columns OR NOT inner quals)'.
2618 * 'a a1 left join a a2': could simplify to a scan like inner but without
2619 * NOT NULL conditions on join columns.
2620 * 'a a1 left join (a a2 join b)': can't simplify this, because join to b
2621 * can both remove rows and introduce duplicates.
2622 *
2623 * To search for removable joins, we order all the relations on their Oid,
2624 * go over each set with the same Oid, and consider each pair of relations
2625 * in this set.
2626 *
2627 * To remove the join, we mark one of the participating relations as dead
2628 * and rewrite all references to it to point to the remaining relation.
2629 * This includes modifying RestrictInfos, EquivalenceClasses, and
2630 * EquivalenceMembers. We also have to modify the row marks. The join clauses
2631 * of the removed relation become either restriction or join clauses, based on
2632 * whether they reference any relations not participating in the removed join.
2633 *
2634 * 'joinlist' is the top-level joinlist of the query. If it has any
2635 * references to the removed relations, we update them to point to the
2636 * remaining ones.
2637 */
2638List *
2640{
2642 int relid = -1;
2643
2646 return joinlist;
2647
2648 /*
2649 * Merge pairs of relations participated in self-join. Remove unnecessary
2650 * range table entries.
2651 */
2653
2654 if (unlikely(toRemove != NULL))
2655 {
2656 /* At the end, remove orphaned relation links */
2657 while ((relid = bms_next_member(toRemove, relid)) >= 0)
2658 {
2659 int nremoved = 0;
2660
2662 if (nremoved != 1)
2663 elog(ERROR, "failed to find relation %d in joinlist", relid);
2664 }
2665 }
2666
2667 return joinlist;
2668}
static int self_join_candidates_cmp(const void *a, const void *b)
static bool match_unique_clauses(PlannerInfo *root, RelOptInfo *outer, List *uclauses, Index relid)
static bool replace_relid_callback(Node *node, ChangeVarNodes_context *context)
static void split_selfjoin_quals(PlannerInfo *root, List *joinquals, List **selfjoinquals, List **otherjoinquals, int from, int to)
static void add_non_redundant_clauses(PlannerInfo *root, List *rinfo_candidates, List **keep_rinfo_list, Index removed_relid)
static Node * remove_rel_from_phvs_mutator(Node *node, Relids removable)
static Node * remove_rel_from_phvs(Node *node, int relid, int ojrelid)
bool innerrel_is_unique(PlannerInfo *root, Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache)
static List * remove_rel_from_joinlist(List *joinlist, int relid, int *nremoved)
static void remove_leftjoinrel_from_query(PlannerInfo *root, int relid, SpecialJoinInfo *sjinfo)
static Relids remove_self_joins_one_group(PlannerInfo *root, Relids relids)
List * remove_useless_joins(PlannerInfo *root, List *joinlist)
static bool is_innerrel_unique_for(PlannerInfo *root, Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, List **extra_clauses)
static bool rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list, List **extra_clauses)
bool innerrel_is_unique_ext(PlannerInfo *root, Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache, List **extra_clauses)
static DistinctColInfo * distinct_col_search(int colno, List *distinct_cols)
List * remove_useless_self_joins(PlannerInfo *root, List *joinlist)
bool query_supports_distinctness(Query *query)
static void update_eclasses(EquivalenceClass *ec, int from, int to)
static bool restrict_infos_logically_equal(RestrictInfo *a, RestrictInfo *b)
static Relids remove_self_joins_recurse(PlannerInfo *root, List *joinlist, Relids toRemove)
static bool join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
static void remove_rel_from_query(PlannerInfo *root, int relid, int subst, SpecialJoinInfo *sjinfo, Relids joinrelids)
void reduce_unique_semijoins(PlannerInfo *root)
bool enable_self_join_elimination
static void remove_rel_from_restrictinfo(RestrictInfo *rinfo, int relid, int ojrelid)
static bool rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel)
static void remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark, RelOptInfo *toKeep, RelOptInfo *toRemove, List *restrictlist)
static void remove_rel_from_eclass(PlannerInfo *root, EquivalenceClass *ec, int relid, int ojrelid)
bool query_is_distinct_for(Query *query, List *distinct_cols)
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:346
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:216
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:142
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1290
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1145
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:852
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:412
int bms_singleton_member(const Bitmapset *a)
Definition bitmapset.c:665
void bms_free(Bitmapset *a)
Definition bitmapset.c:239
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:744
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:901
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:765
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:575
bool bms_get_singleton_member(const Bitmapset *a, int *member)
Definition bitmapset.c:708
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:122
#define bms_is_empty(a)
Definition bitmapset.h:118
@ BMS_SINGLETON
Definition bitmapset.h:72
@ BMS_MULTIPLE
Definition bitmapset.h:73
#define Assert(condition)
Definition c.h:943
#define unlikely(x)
Definition c.h:438
unsigned int Index
Definition c.h:698
uint32 result
Datum arg
Definition elog.c:1323
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
void rebuild_eclass_attr_needed(PlannerInfo *root)
void ec_clear_derived_clauses(EquivalenceClass *ec)
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
#define palloc_array(type, count)
Definition fe_memutils.h:91
bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List **extra_clauses)
Definition indxpath.c:4144
void rebuild_lateral_attr_needed(PlannerInfo *root)
Definition initsplan.c:1245
void distribute_restrictinfo_to_rels(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition initsplan.c:3629
void rebuild_joinclause_attr_needed(PlannerInfo *root)
Definition initsplan.c:3961
int b
Definition isn.c:74
int a
Definition isn.c:73
int j
Definition isn.c:78
int i
Definition isn.c:77
void remove_join_clause_from_rels(PlannerInfo *root, RestrictInfo *restrictinfo, Relids join_relids)
Definition joininfo.c:161
List * list_delete_ptr(List *list, void *datum)
Definition list.c:872
List * lappend(List *list, void *datum)
Definition list.c:339
List * list_concat(List *list1, const List *list2)
Definition list.c:561
List * list_delete_cell(List *list, ListCell *cell)
Definition list.c:841
List * list_copy(const List *oldlist)
Definition list.c:1573
void list_free(List *list)
Definition list.c:1546
bool list_member(const List *list, const void *datum)
Definition list.c:661
bool collations_agree_on_equality(Oid coll1, Oid coll2)
Definition lsyscache.c:947
bool equality_ops_are_compatible(Oid opno1, Oid opno2)
Definition lsyscache.c:834
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc(Size size)
Definition mcxt.c:1390
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
#define expression_tree_mutator(n, m, c)
Definition nodeFuncs.h:155
static bool is_andclause(const void *clause)
Definition nodeFuncs.h:107
static bool is_orclause(const void *clause)
Definition nodeFuncs.h:116
static Node * get_rightop(const void *clause)
Definition nodeFuncs.h:95
static bool is_opclause(const void *clause)
Definition nodeFuncs.h:76
static Node * get_leftop(const void *clause)
Definition nodeFuncs.h:83
#define IsA(nodeptr, _type_)
Definition nodes.h:162
#define copyObject(obj)
Definition nodes.h:230
#define nodeTag(nodeptr)
Definition nodes.h:137
#define IS_OUTER_JOIN(jointype)
Definition nodes.h:346
#define makeNode(_type_)
Definition nodes.h:159
#define castNode(_type_, nodeptr)
Definition nodes.h:180
JoinType
Definition nodes.h:296
@ JOIN_SEMI
Definition nodes.h:315
@ JOIN_INNER
Definition nodes.h:301
@ JOIN_LEFT
Definition nodes.h:302
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
List * expand_grouping_sets(List *groupingSets, bool groupDistinct, int limit)
Definition parse_agg.c:2019
@ SETOP_NONE
@ RTE_SUBQUERY
@ RTE_RELATION
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
Definition pathnodes.h:3058
Bitmapset * Relids
Definition pathnodes.h:103
@ RELOPT_BASEREL
Definition pathnodes.h:977
#define lfirst(lc)
Definition pg_list.h:172
#define lfirst_node(type, lc)
Definition pg_list.h:176
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define foreach_delete_current(lst, var_or_cell)
Definition pg_list.h:423
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
#define linitial(l)
Definition pg_list.h:178
#define foreach_node(type, var, lst)
Definition pg_list.h:528
static ListCell * list_head(const List *l)
Definition pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition pg_list.h:375
void rebuild_placeholder_attr_needed(PlannerInfo *root)
#define qsort(a, b, c, d)
Definition port.h:496
unsigned int Oid
static int fb(int x)
@ IS_NOT_NULL
Definition primnodes.h:1973
tree ctl root
Definition radixtree.h:1857
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition relnode.c:544
bool restriction_is_or_clause(RestrictInfo *restrictinfo)
static bool clause_sides_match_join(RestrictInfo *rinfo, Relids outerrelids, Relids innerrelids)
bool ChangeVarNodesWalkExpression(Node *node, ChangeVarNodes_context *context)
Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid)
void ChangeVarNodesExtended(Node *node, int rt_index, int new_index, int sublevels_up, ChangeVarNodes_callback callback)
List ** ec_childmembers
Definition pathnodes.h:1663
Definition pg_list.h:54
Definition nodes.h:133
Oid opno
Definition primnodes.h:835
List * args
Definition primnodes.h:853
bool groupDistinct
Definition parsenodes.h:222
Node * setOperations
Definition parsenodes.h:241
List * groupClause
Definition parsenodes.h:221
Node * havingQual
Definition parsenodes.h:227
List * targetList
Definition parsenodes.h:203
List * groupingSets
Definition parsenodes.h:225
List * distinctClause
Definition parsenodes.h:231
List * baserestrictinfo
Definition pathnodes.h:1142
List * joininfo
Definition pathnodes.h:1148
Relids relids
Definition pathnodes.h:1021
Index relid
Definition pathnodes.h:1069
List * unique_for_rels
Definition pathnodes.h:1124
RelOptKind reloptkind
Definition pathnodes.h:1015
List * indexlist
Definition pathnodes.h:1091
List * non_unique_for_rels
Definition pathnodes.h:1126
AttrNumber max_attr
Definition pathnodes.h:1077
AttrNumber min_attr
Definition pathnodes.h:1075
RTEKind rtekind
Definition pathnodes.h:1073
Relids required_relids
Definition pathnodes.h:2932
Relids outer_relids
Definition pathnodes.h:2938
Relids incompatible_relids
Definition pathnodes.h:2935
Expr * clause
Definition pathnodes.h:2901
Relids commute_above_r
Definition pathnodes.h:3233
Relids syn_lefthand
Definition pathnodes.h:3228
Relids min_righthand
Definition pathnodes.h:3227
JoinType jointype
Definition pathnodes.h:3230
Relids commute_below_l
Definition pathnodes.h:3234
Relids min_lefthand
Definition pathnodes.h:3226
Relids syn_righthand
Definition pathnodes.h:3229
AttrNumber varattno
Definition primnodes.h:275
int varno
Definition primnodes.h:270
Index varlevelsup
Definition primnodes.h:295
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition tlist.c:376
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition var.c:114