Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * initsplan.c
4 : : * Target list, group by, qualification, joininfo initialization routines
5 : : *
6 : : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : *
10 : : * IDENTIFICATION
11 : : * src/backend/optimizer/plan/initsplan.c
12 : : *
13 : : *-------------------------------------------------------------------------
14 : : */
15 : : #include "postgres.h"
16 : :
17 : : #include "access/nbtree.h"
18 : : #include "catalog/pg_constraint.h"
19 : : #include "catalog/pg_type.h"
20 : : #include "nodes/makefuncs.h"
21 : : #include "nodes/nodeFuncs.h"
22 : : #include "optimizer/clauses.h"
23 : : #include "optimizer/cost.h"
24 : : #include "optimizer/inherit.h"
25 : : #include "optimizer/joininfo.h"
26 : : #include "optimizer/optimizer.h"
27 : : #include "optimizer/pathnode.h"
28 : : #include "optimizer/paths.h"
29 : : #include "optimizer/placeholder.h"
30 : : #include "optimizer/planmain.h"
31 : : #include "optimizer/planner.h"
32 : : #include "optimizer/restrictinfo.h"
33 : : #include "parser/analyze.h"
34 : : #include "rewrite/rewriteManip.h"
35 : : #include "utils/lsyscache.h"
36 : : #include "utils/rel.h"
37 : : #include "utils/typcache.h"
38 : :
39 : : /* These parameters are set by GUC */
40 : : int from_collapse_limit;
41 : : int join_collapse_limit;
42 : :
43 : :
44 : : /*
45 : : * deconstruct_jointree requires multiple passes over the join tree, because we
46 : : * need to finish computing JoinDomains before we start distributing quals.
47 : : * As long as we have to do that, other information such as the relevant
48 : : * qualscopes might as well be computed in the first pass too.
49 : : *
50 : : * deconstruct_recurse recursively examines the join tree and builds a List
51 : : * (in depth-first traversal order) of JoinTreeItem structs, which are then
52 : : * processed iteratively by deconstruct_distribute. If there are outer
53 : : * joins, non-degenerate outer join clauses are processed in a third pass
54 : : * deconstruct_distribute_oj_quals.
55 : : *
56 : : * The JoinTreeItem structs themselves can be freed at the end of
57 : : * deconstruct_jointree, but do not modify or free their substructure,
58 : : * as the relid sets may also be pointed to by RestrictInfo and
59 : : * SpecialJoinInfo nodes.
60 : : */
61 : : typedef struct JoinTreeItem
62 : : {
63 : : /* Fields filled during deconstruct_recurse: */
64 : : Node *jtnode; /* jointree node to examine */
65 : : JoinDomain *jdomain; /* join domain for its ON/WHERE clauses */
66 : : struct JoinTreeItem *jti_parent; /* JoinTreeItem for this node's
67 : : * parent, or NULL if it's the top */
68 : : Relids qualscope; /* base+OJ Relids syntactically included in
69 : : * this jointree node */
70 : : Relids inner_join_rels; /* base+OJ Relids syntactically included
71 : : * in inner joins appearing at or below
72 : : * this jointree node */
73 : : Relids left_rels; /* if join node, Relids of the left side */
74 : : Relids right_rels; /* if join node, Relids of the right side */
75 : : Relids nonnullable_rels; /* if outer join, Relids of the
76 : : * non-nullable side */
77 : : /* Fields filled during deconstruct_distribute: */
78 : : SpecialJoinInfo *sjinfo; /* if outer join, its SpecialJoinInfo */
79 : : List *oj_joinclauses; /* outer join quals not yet distributed */
80 : : List *lateral_clauses; /* quals postponed from children due to
81 : : * lateral references */
82 : : } JoinTreeItem;
83 : :
84 : :
85 : : static bool is_partial_agg_memory_risky(PlannerInfo *root);
86 : : static void create_agg_clause_infos(PlannerInfo *root);
87 : : static void create_grouping_expr_infos(PlannerInfo *root);
88 : : static EquivalenceClass *get_eclass_for_sortgroupclause(PlannerInfo *root,
89 : : SortGroupClause *sgc,
90 : : Expr *expr);
91 : : static void extract_lateral_references(PlannerInfo *root, RelOptInfo *brel,
92 : : Index rtindex);
93 : : static List *deconstruct_recurse(PlannerInfo *root, Node *jtnode,
94 : : JoinDomain *parent_domain,
95 : : JoinTreeItem *parent_jtitem,
96 : : List **item_list);
97 : : static void deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem);
98 : : static void process_security_barrier_quals(PlannerInfo *root,
99 : : int rti, JoinTreeItem *jtitem);
100 : : static void mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid,
101 : : Relids lower_rels);
102 : : static SpecialJoinInfo *make_outerjoininfo(PlannerInfo *root,
103 : : Relids left_rels, Relids right_rels,
104 : : Relids inner_join_rels,
105 : : JoinType jointype, Index ojrelid,
106 : : List *clause);
107 : : static void compute_semijoin_info(PlannerInfo *root, SpecialJoinInfo *sjinfo,
108 : : List *clause);
109 : : static void deconstruct_distribute_oj_quals(PlannerInfo *root,
110 : : List *jtitems,
111 : : JoinTreeItem *jtitem);
112 : : static void distribute_quals_to_rels(PlannerInfo *root, List *clauses,
113 : : JoinTreeItem *jtitem,
114 : : SpecialJoinInfo *sjinfo,
115 : : Index security_level,
116 : : Relids qualscope,
117 : : Relids ojscope,
118 : : Relids outerjoin_nonnullable,
119 : : Relids incompatible_relids,
120 : : bool allow_equivalence,
121 : : bool has_clone,
122 : : bool is_clone,
123 : : List **postponed_oj_qual_list);
124 : : static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
125 : : JoinTreeItem *jtitem,
126 : : SpecialJoinInfo *sjinfo,
127 : : Index security_level,
128 : : Relids qualscope,
129 : : Relids ojscope,
130 : : Relids outerjoin_nonnullable,
131 : : Relids incompatible_relids,
132 : : bool allow_equivalence,
133 : : bool has_clone,
134 : : bool is_clone,
135 : : List **postponed_oj_qual_list);
136 : : static bool check_redundant_nullability_qual(PlannerInfo *root, Node *clause);
137 : : static Relids get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids);
138 : : static void check_mergejoinable(RestrictInfo *restrictinfo);
139 : : static void check_hashjoinable(RestrictInfo *restrictinfo);
140 : : static void check_memoizable(RestrictInfo *restrictinfo);
141 : :
142 : :
143 : : /*****************************************************************************
144 : : *
145 : : * JOIN TREES
146 : : *
147 : : *****************************************************************************/
148 : :
149 : : /*
150 : : * add_base_rels_to_query
151 : : *
152 : : * Scan the query's jointree and create baserel RelOptInfos for all
153 : : * the base relations (e.g., table, subquery, and function RTEs)
154 : : * appearing in the jointree.
155 : : *
156 : : * The initial invocation must pass root->parse->jointree as the value of
157 : : * jtnode. Internally, the function recurses through the jointree.
158 : : *
159 : : * At the end of this process, there should be one baserel RelOptInfo for
160 : : * every non-join RTE that is used in the query. Some of the baserels
161 : : * may be appendrel parents, which will require additional "otherrel"
162 : : * RelOptInfos for their member rels, but those are added later.
163 : : */
164 : : void
7500 tgl@sss.pgh.pa.us 165 :CBC 475621 : add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
166 : : {
9227 167 [ - + ]: 475621 : if (jtnode == NULL)
8372 tgl@sss.pgh.pa.us 168 :UBC 0 : return;
9210 tgl@sss.pgh.pa.us 169 [ + + ]:CBC 475621 : if (IsA(jtnode, RangeTblRef))
170 : : {
171 : 247264 : int varno = ((RangeTblRef *) jtnode)->rtindex;
172 : :
3180 rhaas@postgresql.org 173 : 247264 : (void) build_simple_rel(root, varno, NULL);
174 : : }
9210 tgl@sss.pgh.pa.us 175 [ + + ]: 228357 : else if (IsA(jtnode, FromExpr))
176 : : {
177 : 177689 : FromExpr *f = (FromExpr *) jtnode;
178 : : ListCell *l;
179 : :
180 [ + - + + : 380759 : foreach(l, f->fromlist)
+ + ]
8372 181 : 203079 : add_base_rels_to_query(root, lfirst(l));
182 : : }
9227 183 [ + - ]: 50668 : else if (IsA(jtnode, JoinExpr))
184 : : {
185 : 50668 : JoinExpr *j = (JoinExpr *) jtnode;
186 : :
8372 187 : 50668 : add_base_rels_to_query(root, j->larg);
188 : 50668 : add_base_rels_to_query(root, j->rarg);
189 : : }
190 : : else
8181 tgl@sss.pgh.pa.us 191 [ # # ]:UBC 0 : elog(ERROR, "unrecognized node type: %d",
192 : : (int) nodeTag(jtnode));
193 : : }
194 : :
195 : : /*
196 : : * add_other_rels_to_query
197 : : * create "otherrel" RelOptInfos for the children of appendrel baserels
198 : : *
199 : : * At the end of this process, there should be RelOptInfos for all relations
200 : : * that will be scanned by the query.
201 : : */
202 : : void
2458 tgl@sss.pgh.pa.us 203 :CBC 171197 : add_other_rels_to_query(PlannerInfo *root)
204 : : {
205 : : int rti;
206 : :
207 [ + + ]: 524238 : for (rti = 1; rti < root->simple_rel_array_size; rti++)
208 : : {
209 : 353042 : RelOptInfo *rel = root->simple_rel_array[rti];
210 : 353042 : RangeTblEntry *rte = root->simple_rte_array[rti];
211 : :
212 : : /* there may be empty slots corresponding to non-baserel RTEs */
213 [ + + ]: 353042 : if (rel == NULL)
214 : 81698 : continue;
215 : :
216 : : /* Ignore any "otherrels" that were already added. */
217 [ + + ]: 271344 : if (rel->reloptkind != RELOPT_BASEREL)
218 : 29784 : continue;
219 : :
220 : : /* If it's marked as inheritable, look for children. */
221 [ + + ]: 241560 : if (rte->inh)
2454 222 : 11261 : expand_inherited_rtentry(root, rel, rte, rti);
223 : : }
2458 224 : 171196 : }
225 : :
226 : :
227 : : /*****************************************************************************
228 : : *
229 : : * TARGET LISTS
230 : : *
231 : : *****************************************************************************/
232 : :
233 : : /*
234 : : * build_base_rel_tlists
235 : : * Add targetlist entries for each var needed in the query's final tlist
236 : : * (and HAVING clause, if any) to the appropriate base relations.
237 : : *
238 : : * We mark such vars as needed by "relation 0" to ensure that they will
239 : : * propagate up through all join plan steps.
240 : : */
241 : : void
7500 242 : 171212 : build_base_rel_tlists(PlannerInfo *root, List *final_tlist)
243 : : {
6086 244 : 171212 : List *tlist_vars = pull_var_clause((Node *) final_tlist,
245 : : PVC_RECURSE_AGGREGATES |
246 : : PVC_RECURSE_WINDOWFUNCS |
247 : : PVC_INCLUDE_PLACEHOLDERS);
248 : :
8207 249 [ + + ]: 171212 : if (tlist_vars != NIL)
250 : : {
1218 251 : 159389 : add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0));
7871 neilc@samurai.com 252 : 159389 : list_free(tlist_vars);
253 : : }
254 : :
255 : : /*
256 : : * If there's a HAVING clause, we'll need the Vars it uses, too. Note
257 : : * that HAVING can contain Aggrefs but not WindowFuncs.
258 : : */
3632 tgl@sss.pgh.pa.us 259 [ + + ]: 171212 : if (root->parse->havingQual)
260 : : {
261 : 466 : List *having_vars = pull_var_clause(root->parse->havingQual,
262 : : PVC_RECURSE_AGGREGATES |
263 : : PVC_INCLUDE_PLACEHOLDERS);
264 : :
265 [ + + ]: 466 : if (having_vars != NIL)
266 : : {
267 : 406 : add_vars_to_targetlist(root, having_vars,
268 : : bms_make_singleton(0));
269 : 406 : list_free(having_vars);
270 : : }
271 : : }
8681 272 : 171212 : }
273 : :
274 : : /*
275 : : * add_vars_to_targetlist
276 : : * For each variable appearing in the list, add it to the owning
277 : : * relation's targetlist if not already present, and mark the variable
278 : : * as being needed for the indicated join (or for final output if
279 : : * where_needed includes "relation 0").
280 : : *
281 : : * The list may also contain PlaceHolderVars. These don't necessarily
282 : : * have a single owning relation; we keep their attr_needed info in
283 : : * root->placeholder_list instead. Find or create the associated
284 : : * PlaceHolderInfo entry, and update its ph_needed.
285 : : *
286 : : * See also add_vars_to_attr_needed.
287 : : */
288 : : void
5244 289 : 328264 : add_vars_to_targetlist(PlannerInfo *root, List *vars,
290 : : Relids where_needed)
291 : : {
292 : : ListCell *temp;
293 : :
8207 294 [ - + ]: 328264 : Assert(!bms_is_empty(where_needed));
295 : :
8681 296 [ + + + + : 1165244 : foreach(temp, vars)
+ + ]
297 : : {
6266 298 : 836980 : Node *node = (Node *) lfirst(temp);
299 : :
300 [ + + ]: 836980 : if (IsA(node, Var))
301 : : {
302 : 835390 : Var *var = (Var *) node;
303 : 835390 : RelOptInfo *rel = find_base_rel(root, var->varno);
304 : 835390 : int attno = var->varattno;
305 : :
4505 306 [ + + ]: 835390 : if (bms_is_subset(where_needed, rel->relids))
307 : 704 : continue;
6266 308 [ + - - + ]: 834686 : Assert(attno >= rel->min_attr && attno <= rel->max_attr);
309 : 834686 : attno -= rel->min_attr;
310 [ + + ]: 834686 : if (rel->attr_needed[attno] == NULL)
311 : : {
312 : : /*
313 : : * Variable not yet requested, so add to rel's targetlist.
314 : : *
315 : : * The value available at the rel's scan level has not been
316 : : * nulled by any outer join, so drop its varnullingrels.
317 : : * (We'll put those back as we climb up the join tree.)
318 : : */
1052 319 : 630720 : var = copyObject(var);
320 : 630720 : var->varnullingrels = NULL;
321 : 630720 : rel->reltarget->exprs = lappend(rel->reltarget->exprs, var);
322 : : /* reltarget cost and width will be computed later */
323 : : }
6266 324 : 834686 : rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
325 : : where_needed);
326 : : }
327 [ + - ]: 1590 : else if (IsA(node, PlaceHolderVar))
328 : : {
329 : 1590 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
1218 330 : 1590 : PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
331 : :
6266 332 : 1590 : phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
333 : : where_needed);
334 : : }
335 : : else
6266 tgl@sss.pgh.pa.us 336 [ # # ]:UBC 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
337 : : }
8681 tgl@sss.pgh.pa.us 338 :CBC 328264 : }
339 : :
340 : : /*
341 : : * add_vars_to_attr_needed
342 : : * This does a subset of what add_vars_to_targetlist does: it just
343 : : * updates attr_needed for Vars and ph_needed for PlaceHolderVars.
344 : : * We assume the Vars are already in their relations' targetlists.
345 : : *
346 : : * This is used to rebuild attr_needed/ph_needed sets after removal
347 : : * of a useless outer join. The removed join clause might have been
348 : : * the only upper-level use of some other relation's Var, in which
349 : : * case we can reduce that Var's attr_needed and thereby possibly
350 : : * open the door to further join removals. But we can't tell that
351 : : * without tedious reconstruction of the attr_needed data.
352 : : *
353 : : * Note that if a Var's attr_needed is successfully reduced to empty,
354 : : * it will still be in the relation's targetlist even though we do
355 : : * not really need the scan plan node to emit it. The extra plan
356 : : * inefficiency seems tiny enough to not be worth spending planner
357 : : * cycles to get rid of it.
358 : : */
359 : : void
446 360 : 6591 : add_vars_to_attr_needed(PlannerInfo *root, List *vars,
361 : : Relids where_needed)
362 : : {
363 : : ListCell *temp;
364 : :
365 [ - + ]: 6591 : Assert(!bms_is_empty(where_needed));
366 : :
367 [ + + + + : 15351 : foreach(temp, vars)
+ + ]
368 : : {
369 : 8760 : Node *node = (Node *) lfirst(temp);
370 : :
371 [ + + ]: 8760 : if (IsA(node, Var))
372 : : {
373 : 8712 : Var *var = (Var *) node;
374 : 8712 : RelOptInfo *rel = find_base_rel(root, var->varno);
375 : 8712 : int attno = var->varattno;
376 : :
377 [ + + ]: 8712 : if (bms_is_subset(where_needed, rel->relids))
378 : 428 : continue;
379 [ + - - + ]: 8284 : Assert(attno >= rel->min_attr && attno <= rel->max_attr);
380 : 8284 : attno -= rel->min_attr;
381 : 8284 : rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
382 : : where_needed);
383 : : }
384 [ + - ]: 48 : else if (IsA(node, PlaceHolderVar))
385 : : {
386 : 48 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
387 : 48 : PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
388 : :
389 : 48 : phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
390 : : where_needed);
391 : : }
392 : : else
446 tgl@sss.pgh.pa.us 393 [ # # ]:UBC 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
394 : : }
446 tgl@sss.pgh.pa.us 395 :CBC 6591 : }
396 : :
397 : : /*****************************************************************************
398 : : *
399 : : * GROUP BY
400 : : *
401 : : *****************************************************************************/
402 : :
403 : : /*
404 : : * remove_useless_groupby_columns
405 : : * Remove any columns in the GROUP BY clause that are redundant due to
406 : : * being functionally dependent on other GROUP BY columns.
407 : : *
408 : : * Since some other DBMSes do not allow references to ungrouped columns, it's
409 : : * not unusual to find all columns listed in GROUP BY even though listing the
410 : : * primary-key columns, or columns of a unique constraint would be sufficient.
411 : : * Deleting such excess columns avoids redundant sorting or hashing work, so
412 : : * it's worth doing.
413 : : *
414 : : * Relcache invalidations will ensure that cached plans become invalidated
415 : : * when the underlying supporting indexes are dropped or if a column's NOT
416 : : * NULL attribute is removed.
417 : : */
418 : : void
370 drowley@postgresql.o 419 : 171197 : remove_useless_groupby_columns(PlannerInfo *root)
420 : : {
421 : 171197 : Query *parse = root->parse;
422 : : Bitmapset **groupbyattnos;
423 : : Bitmapset **surplusvars;
424 : 171197 : bool tryremove = false;
425 : : ListCell *lc;
426 : : int relid;
427 : :
428 : : /* No chance to do anything if there are less than two GROUP BY items */
429 [ + + ]: 171197 : if (list_length(root->processed_groupClause) < 2)
430 : 170132 : return;
431 : :
432 : : /* Don't fiddle with the GROUP BY clause if the query has grouping sets */
433 [ + + ]: 1065 : if (parse->groupingSets)
434 : 343 : return;
435 : :
436 : : /*
437 : : * Scan the GROUP BY clause to find GROUP BY items that are simple Vars.
438 : : * Fill groupbyattnos[k] with a bitmapset of the column attnos of RTE k
439 : : * that are GROUP BY items.
440 : : */
7 michael@paquier.xyz 441 :GNC 722 : groupbyattnos = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
370 drowley@postgresql.o 442 [ + - + + :CBC 2612 : foreach(lc, root->processed_groupClause)
+ + ]
443 : : {
444 : 1890 : SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
445 : 1890 : TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList);
446 : 1890 : Var *var = (Var *) tle->expr;
447 : :
448 : : /*
449 : : * Ignore non-Vars and Vars from other query levels.
450 : : *
451 : : * XXX in principle, stable expressions containing Vars could also be
452 : : * removed, if all the Vars are functionally dependent on other GROUP
453 : : * BY items. But it's not clear that such cases occur often enough to
454 : : * be worth troubling over.
455 : : */
456 [ + + ]: 1890 : if (!IsA(var, Var) ||
457 [ - + ]: 1485 : var->varlevelsup > 0)
458 : 405 : continue;
459 : :
460 : : /* OK, remember we have this Var */
461 : 1485 : relid = var->varno;
462 [ - + ]: 1485 : Assert(relid <= list_length(parse->rtable));
463 : :
464 : : /*
465 : : * If this isn't the first column for this relation then we now have
466 : : * multiple columns. That means there might be some that can be
467 : : * removed.
468 : : */
469 : 1485 : tryremove |= !bms_is_empty(groupbyattnos[relid]);
470 : 1485 : groupbyattnos[relid] = bms_add_member(groupbyattnos[relid],
471 : 1485 : var->varattno - FirstLowInvalidHeapAttributeNumber);
472 : : }
473 : :
474 : : /*
475 : : * No Vars or didn't find multiple Vars for any relation in the GROUP BY?
476 : : * If so, nothing can be removed, so don't waste more effort trying.
477 : : */
478 [ + + ]: 722 : if (!tryremove)
479 : 227 : return;
480 : :
481 : : /*
482 : : * Consider each relation and see if it is possible to remove some of its
483 : : * Vars from GROUP BY. For simplicity and speed, we do the actual removal
484 : : * in a separate pass. Here, we just fill surplusvars[k] with a bitmapset
485 : : * of the column attnos of RTE k that are removable GROUP BY items.
486 : : */
487 : 495 : surplusvars = NULL; /* don't allocate array unless required */
488 : 495 : relid = 0;
489 [ + - + + : 2074 : foreach(lc, parse->rtable)
+ + ]
490 : : {
491 : 1579 : RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc);
492 : : RelOptInfo *rel;
493 : : Bitmapset *relattnos;
494 : 1579 : Bitmapset *best_keycolumns = NULL;
495 : 1579 : int32 best_nkeycolumns = PG_INT32_MAX;
496 : :
497 : 1579 : relid++;
498 : :
499 : : /* Only plain relations could have primary-key constraints */
500 [ + + ]: 1579 : if (rte->rtekind != RTE_RELATION)
501 : 803 : continue;
502 : :
503 : : /*
504 : : * We must skip inheritance parent tables as some of the child rels
505 : : * may cause duplicate rows. This cannot happen with partitioned
506 : : * tables, however.
507 : : */
508 [ + + + + ]: 776 : if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
509 : 9 : continue;
510 : :
511 : : /* Nothing to do unless this rel has multiple Vars in GROUP BY */
512 : 767 : relattnos = groupbyattnos[relid];
513 [ + + ]: 767 : if (bms_membership(relattnos) != BMS_MULTIPLE)
514 : 290 : continue;
515 : :
516 : 477 : rel = root->simple_rel_array[relid];
517 : :
518 : : /*
519 : : * Now check each index for this relation to see if there are any with
520 : : * columns which are a proper subset of the grouping columns for this
521 : : * relation.
522 : : */
523 [ + + + + : 1477 : foreach_node(IndexOptInfo, index, rel->indexlist)
+ + ]
524 : : {
525 : : Bitmapset *ind_attnos;
526 : : bool nulls_check_ok;
527 : :
528 : : /*
529 : : * Skip any non-unique and deferrable indexes. Predicate indexes
530 : : * have not been checked yet, so we must skip those too as the
531 : : * predOK check that's done later might fail.
532 : : */
533 [ + + + + : 523 : if (!index->unique || !index->immediate || index->indpred != NIL)
- + ]
534 : 205 : continue;
535 : :
536 : : /* For simplicity, we currently don't support expression indexes */
537 [ - + ]: 318 : if (index->indexprs != NIL)
370 drowley@postgresql.o 538 :UBC 0 : continue;
539 : :
370 drowley@postgresql.o 540 :CBC 318 : ind_attnos = NULL;
541 : 318 : nulls_check_ok = true;
542 [ + + ]: 802 : for (int i = 0; i < index->nkeycolumns; i++)
543 : : {
544 : : /*
545 : : * We must insist that the index columns are all defined NOT
546 : : * NULL otherwise duplicate NULLs could exist. However, we
547 : : * can relax this check when the index is defined with NULLS
548 : : * NOT DISTINCT as there can only be 1 NULL row, therefore
549 : : * functional dependency on the unique columns is maintained,
550 : : * despite the NULL.
551 : : */
552 [ + + ]: 487 : if (!index->nullsnotdistinct &&
553 [ + + ]: 484 : !bms_is_member(index->indexkeys[i],
554 : 484 : rel->notnullattnums))
555 : : {
556 : 3 : nulls_check_ok = false;
557 : 3 : break;
558 : : }
559 : :
560 : : ind_attnos =
561 : 484 : bms_add_member(ind_attnos,
562 : 484 : index->indexkeys[i] -
563 : : FirstLowInvalidHeapAttributeNumber);
564 : : }
565 : :
566 [ + + ]: 318 : if (!nulls_check_ok)
567 : 3 : continue;
568 : :
569 : : /*
570 : : * Skip any indexes where the indexed columns aren't a proper
571 : : * subset of the GROUP BY.
572 : : */
573 [ + + ]: 315 : if (bms_subset_compare(ind_attnos, relattnos) != BMS_SUBSET1)
574 : 145 : continue;
575 : :
576 : : /*
577 : : * Record the attribute numbers from the index with the fewest
578 : : * columns. This allows the largest number of columns to be
579 : : * removed from the GROUP BY clause. In the future, we may wish
580 : : * to consider using the narrowest set of columns and looking at
581 : : * pg_statistic.stawidth as it might be better to use an index
582 : : * with, say two INT4s, rather than, say, one long varlena column.
583 : : */
584 [ + + ]: 170 : if (index->nkeycolumns < best_nkeycolumns)
585 : : {
586 : 161 : best_keycolumns = ind_attnos;
587 : 161 : best_nkeycolumns = index->nkeycolumns;
588 : : }
589 : : }
590 : :
591 : : /* Did we find a suitable index? */
592 [ + + ]: 477 : if (!bms_is_empty(best_keycolumns))
593 : : {
594 : : /*
595 : : * To easily remember whether we've found anything to do, we don't
596 : : * allocate the surplusvars[] array until we find something.
597 : : */
598 [ + + ]: 161 : if (surplusvars == NULL)
7 michael@paquier.xyz 599 :GNC 158 : surplusvars = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
600 : :
601 : : /* Remember the attnos of the removable columns */
370 drowley@postgresql.o 602 :CBC 161 : surplusvars[relid] = bms_difference(relattnos, best_keycolumns);
603 : : }
604 : : }
605 : :
606 : : /*
607 : : * If we found any surplus Vars, build a new GROUP BY clause without them.
608 : : * (Note: this may leave some TLEs with unreferenced ressortgroupref
609 : : * markings, but that's harmless.)
610 : : */
611 [ + + ]: 495 : if (surplusvars != NULL)
612 : : {
613 : 158 : List *new_groupby = NIL;
614 : :
615 [ + - + + : 649 : foreach(lc, root->processed_groupClause)
+ + ]
616 : : {
617 : 491 : SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
618 : 491 : TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList);
619 : 491 : Var *var = (Var *) tle->expr;
620 : :
621 : : /*
622 : : * New list must include non-Vars, outer Vars, and anything not
623 : : * marked as surplus.
624 : : */
625 [ + - ]: 491 : if (!IsA(var, Var) ||
626 [ + - ]: 491 : var->varlevelsup > 0 ||
627 [ + + ]: 491 : !bms_is_member(var->varattno - FirstLowInvalidHeapAttributeNumber,
628 : 491 : surplusvars[var->varno]))
629 : 309 : new_groupby = lappend(new_groupby, sgc);
630 : : }
631 : :
632 : 158 : root->processed_groupClause = new_groupby;
633 : : }
634 : : }
635 : :
636 : : /*
637 : : * setup_eager_aggregation
638 : : * Check if eager aggregation is applicable, and if so collect suitable
639 : : * aggregate expressions and grouping expressions in the query.
640 : : */
641 : : void
70 rguo@postgresql.org 642 :GNC 171197 : setup_eager_aggregation(PlannerInfo *root)
643 : : {
644 : : /*
645 : : * Don't apply eager aggregation if disabled by user.
646 : : */
647 [ + + ]: 171197 : if (!enable_eager_aggregate)
648 : 240 : return;
649 : :
650 : : /*
651 : : * Don't apply eager aggregation if there are no available GROUP BY
652 : : * clauses.
653 : : */
654 [ + + ]: 170957 : if (!root->processed_groupClause)
655 : 168829 : return;
656 : :
657 : : /*
658 : : * For now we don't try to support grouping sets.
659 : : */
660 [ + + ]: 2128 : if (root->parse->groupingSets)
661 : 389 : return;
662 : :
663 : : /*
664 : : * For now we don't try to support DISTINCT or ORDER BY aggregates.
665 : : */
666 [ + + ]: 1739 : if (root->numOrderedAggs > 0)
667 : 96 : return;
668 : :
669 : : /*
670 : : * If there are any aggregates that do not support partial mode, or any
671 : : * partial aggregates that are non-serializable, do not apply eager
672 : : * aggregation.
673 : : */
674 [ + + - + ]: 1643 : if (root->hasNonPartialAggs || root->hasNonSerialAggs)
675 : 77 : return;
676 : :
677 : : /*
678 : : * We don't try to apply eager aggregation if there are set-returning
679 : : * functions in targetlist.
680 : : */
681 [ + + ]: 1566 : if (root->parse->hasTargetSRFs)
682 : 36 : return;
683 : :
684 : : /*
685 : : * Eager aggregation only makes sense if there are multiple base rels in
686 : : * the query.
687 : : */
688 [ + + ]: 1530 : if (bms_membership(root->all_baserels) != BMS_MULTIPLE)
689 : 1036 : return;
690 : :
691 : : /*
692 : : * Don't apply eager aggregation if any aggregate poses a risk of
693 : : * excessive memory usage during partial aggregation.
694 : : */
695 [ + + ]: 494 : if (is_partial_agg_memory_risky(root))
696 : 1 : return;
697 : :
698 : : /*
699 : : * Collect aggregate expressions and plain Vars that appear in the
700 : : * targetlist and havingQual.
701 : : */
702 : 493 : create_agg_clause_infos(root);
703 : :
704 : : /*
705 : : * If there are no suitable aggregate expressions, we cannot apply eager
706 : : * aggregation.
707 : : */
708 [ + + ]: 493 : if (root->agg_clause_list == NIL)
709 : 163 : return;
710 : :
711 : : /*
712 : : * Collect grouping expressions that appear in grouping clauses.
713 : : */
714 : 330 : create_grouping_expr_infos(root);
715 : : }
716 : :
717 : : /*
718 : : * is_partial_agg_memory_risky
719 : : * Check if any aggregate poses a risk of excessive memory usage during
720 : : * partial aggregation.
721 : : *
722 : : * We check if any aggregate has a negative aggtransspace value, which
723 : : * indicates that its transition state data can grow unboundedly in size.
724 : : * Applying eager aggregation in such cases risks high memory usage since
725 : : * partial aggregation results might be stored in join hash tables or
726 : : * materialized nodes.
727 : : */
728 : : static bool
729 : 494 : is_partial_agg_memory_risky(PlannerInfo *root)
730 : : {
731 : : ListCell *lc;
732 : :
733 [ + + + + : 953 : foreach(lc, root->aggtransinfos)
+ + ]
734 : : {
735 : 460 : AggTransInfo *transinfo = lfirst_node(AggTransInfo, lc);
736 : :
737 [ + + ]: 460 : if (transinfo->aggtransspace < 0)
738 : 1 : return true;
739 : : }
740 : :
741 : 493 : return false;
742 : : }
743 : :
744 : : /*
745 : : * create_agg_clause_infos
746 : : * Search the targetlist and havingQual for Aggrefs and plain Vars, and
747 : : * create an AggClauseInfo for each Aggref node.
748 : : */
749 : : static void
750 : 493 : create_agg_clause_infos(PlannerInfo *root)
751 : : {
752 : : List *tlist_exprs;
753 : 493 : List *agg_clause_list = NIL;
754 : 493 : List *tlist_vars = NIL;
755 : 493 : Relids aggregate_relids = NULL;
756 : 493 : bool eager_agg_applicable = true;
757 : : ListCell *lc;
758 : :
759 [ - + ]: 493 : Assert(root->agg_clause_list == NIL);
760 [ - + ]: 493 : Assert(root->tlist_vars == NIL);
761 : :
762 : 493 : tlist_exprs = pull_var_clause((Node *) root->processed_tlist,
763 : : PVC_INCLUDE_AGGREGATES |
764 : : PVC_RECURSE_WINDOWFUNCS |
765 : : PVC_RECURSE_PLACEHOLDERS);
766 : :
767 : : /*
768 : : * Aggregates within the HAVING clause need to be processed in the same
769 : : * way as those in the targetlist. Note that HAVING can contain Aggrefs
770 : : * but not WindowFuncs.
771 : : */
772 [ + + ]: 493 : if (root->parse->havingQual != NULL)
773 : : {
774 : : List *having_exprs;
775 : :
776 : 29 : having_exprs = pull_var_clause((Node *) root->parse->havingQual,
777 : : PVC_INCLUDE_AGGREGATES |
778 : : PVC_RECURSE_PLACEHOLDERS);
779 [ + - ]: 29 : if (having_exprs != NIL)
780 : : {
781 : 29 : tlist_exprs = list_concat(tlist_exprs, having_exprs);
782 : 29 : list_free(having_exprs);
783 : : }
784 : : }
785 : :
786 [ + - + + : 2188 : foreach(lc, tlist_exprs)
+ + ]
787 : : {
788 : 1719 : Expr *expr = (Expr *) lfirst(lc);
789 : : Aggref *aggref;
790 : : Relids agg_eval_at;
791 : : AggClauseInfo *ac_info;
792 : :
793 : : /* For now we don't try to support GROUPING() expressions */
794 [ - + ]: 1719 : if (IsA(expr, GroupingFunc))
795 : : {
70 rguo@postgresql.org 796 :UNC 0 : eager_agg_applicable = false;
797 : 0 : break;
798 : : }
799 : :
800 : : /* Collect plain Vars for future reference */
70 rguo@postgresql.org 801 [ + + ]:GNC 1719 : if (IsA(expr, Var))
802 : : {
803 : 1257 : tlist_vars = list_append_unique(tlist_vars, expr);
804 : 1257 : continue;
805 : : }
806 : :
807 : 462 : aggref = castNode(Aggref, expr);
808 : :
809 [ - + ]: 462 : Assert(aggref->aggorder == NIL);
810 [ - + ]: 462 : Assert(aggref->aggdistinct == NIL);
811 : :
812 : : /*
813 : : * If there are any securityQuals, do not try to apply eager
814 : : * aggregation if any non-leakproof aggregate functions are present.
815 : : * This is overly strict, but for now...
816 : : */
817 [ - + ]: 462 : if (root->qual_security_level > 0 &&
70 rguo@postgresql.org 818 [ # # ]:UNC 0 : !get_func_leakproof(aggref->aggfnoid))
819 : : {
820 : 0 : eager_agg_applicable = false;
821 : 0 : break;
822 : : }
823 : :
70 rguo@postgresql.org 824 :GNC 462 : agg_eval_at = pull_varnos(root, (Node *) aggref);
825 : :
826 : : /*
827 : : * If all base relations in the query are referenced by aggregate
828 : : * functions, then eager aggregation is not applicable.
829 : : */
830 : 462 : aggregate_relids = bms_add_members(aggregate_relids, agg_eval_at);
831 [ + + ]: 462 : if (bms_is_subset(root->all_baserels, aggregate_relids))
832 : : {
833 : 24 : eager_agg_applicable = false;
834 : 24 : break;
835 : : }
836 : :
837 : : /* OK, create the AggClauseInfo node */
838 : 438 : ac_info = makeNode(AggClauseInfo);
839 : 438 : ac_info->aggref = aggref;
840 : 438 : ac_info->agg_eval_at = agg_eval_at;
841 : :
842 : : /* ... and add it to the list */
843 : 438 : agg_clause_list = list_append_unique(agg_clause_list, ac_info);
844 : : }
845 : :
846 : 493 : list_free(tlist_exprs);
847 : :
848 [ + + ]: 493 : if (eager_agg_applicable)
849 : : {
850 : 469 : root->agg_clause_list = agg_clause_list;
851 : 469 : root->tlist_vars = tlist_vars;
852 : : }
853 : : else
854 : : {
855 : 24 : list_free_deep(agg_clause_list);
856 : 24 : list_free(tlist_vars);
857 : : }
858 : 493 : }
859 : :
860 : : /*
861 : : * create_grouping_expr_infos
862 : : * Create a GroupingExprInfo for each expression usable as grouping key.
863 : : *
864 : : * If any grouping expression is not suitable, we will just return with
865 : : * root->group_expr_list being NIL.
866 : : */
867 : : static void
868 : 330 : create_grouping_expr_infos(PlannerInfo *root)
869 : : {
870 : 330 : List *exprs = NIL;
871 : 330 : List *sortgrouprefs = NIL;
872 : 330 : List *ecs = NIL;
873 : : ListCell *lc,
874 : : *lc1,
875 : : *lc2,
876 : : *lc3;
877 : :
878 [ - + ]: 330 : Assert(root->group_expr_list == NIL);
879 : :
880 [ + - + + : 656 : foreach(lc, root->processed_groupClause)
+ + ]
881 : : {
882 : 359 : SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
883 : 359 : TargetEntry *tle = get_sortgroupclause_tle(sgc, root->processed_tlist);
884 : : TypeCacheEntry *tce;
885 : : Oid equalimageproc;
886 : :
887 [ - + ]: 359 : Assert(tle->ressortgroupref > 0);
888 : :
889 : : /*
890 : : * For now we only support plain Vars as grouping expressions.
891 : : */
892 [ + + ]: 359 : if (!IsA(tle->expr, Var))
893 : 33 : return;
894 : :
895 : : /*
896 : : * Eager aggregation is only possible if equality implies image
897 : : * equality for each grouping key. Otherwise, placing keys with
898 : : * different byte images into the same group may result in the loss of
899 : : * information that could be necessary to evaluate upper qual clauses.
900 : : *
901 : : * For instance, the NUMERIC data type is not supported, as values
902 : : * that are considered equal by the equality operator (e.g., 0 and
903 : : * 0.0) can have different scales.
904 : : */
905 : 329 : tce = lookup_type_cache(exprType((Node *) tle->expr),
906 : : TYPECACHE_BTREE_OPFAMILY);
907 [ + - ]: 329 : if (!OidIsValid(tce->btree_opf) ||
908 [ - + ]: 329 : !OidIsValid(tce->btree_opintype))
70 rguo@postgresql.org 909 :UNC 0 : return;
910 : :
70 rguo@postgresql.org 911 :GNC 329 : equalimageproc = get_opfamily_proc(tce->btree_opf,
912 : : tce->btree_opintype,
913 : : tce->btree_opintype,
914 : : BTEQUALIMAGE_PROC);
915 [ + + ]: 329 : if (!OidIsValid(equalimageproc) ||
916 [ - + ]: 326 : !DatumGetBool(OidFunctionCall1Coll(equalimageproc,
917 : : tce->typcollation,
918 : : ObjectIdGetDatum(tce->btree_opintype))))
919 : 3 : return;
920 : :
921 : 326 : exprs = lappend(exprs, tle->expr);
922 : 326 : sortgrouprefs = lappend_int(sortgrouprefs, tle->ressortgroupref);
923 : 326 : ecs = lappend(ecs, get_eclass_for_sortgroupclause(root, sgc, tle->expr));
924 : : }
925 : :
926 : : /*
927 : : * Construct a GroupingExprInfo for each expression.
928 : : */
929 [ + - + + : 617 : forthree(lc1, exprs, lc2, sortgrouprefs, lc3, ecs)
+ - + + +
- + + + +
+ - + - +
+ ]
930 : : {
931 : 320 : Expr *expr = (Expr *) lfirst(lc1);
932 : 320 : int sortgroupref = lfirst_int(lc2);
933 : 320 : EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc3);
934 : : GroupingExprInfo *ge_info;
935 : :
936 : 320 : ge_info = makeNode(GroupingExprInfo);
937 : 320 : ge_info->expr = (Expr *) copyObject(expr);
938 : 320 : ge_info->sortgroupref = sortgroupref;
939 : 320 : ge_info->ec = ec;
940 : :
941 : 320 : root->group_expr_list = lappend(root->group_expr_list, ge_info);
942 : : }
943 : : }
944 : :
945 : : /*
946 : : * get_eclass_for_sortgroupclause
947 : : * Given a group clause and an expression, find an existing equivalence
948 : : * class that the expression is a member of; return NULL if none.
949 : : */
950 : : static EquivalenceClass *
951 : 326 : get_eclass_for_sortgroupclause(PlannerInfo *root, SortGroupClause *sgc,
952 : : Expr *expr)
953 : : {
954 : : Oid opfamily,
955 : : opcintype,
956 : : collation;
957 : : CompareType cmptype;
958 : : Oid equality_op;
959 : : List *opfamilies;
960 : :
961 : : /* Punt if the group clause is not sortable */
962 [ - + ]: 326 : if (!OidIsValid(sgc->sortop))
70 rguo@postgresql.org 963 :UNC 0 : return NULL;
964 : :
965 : : /* Find the operator in pg_amop --- failure shouldn't happen */
70 rguo@postgresql.org 966 [ - + ]:GNC 326 : if (!get_ordering_op_properties(sgc->sortop,
967 : : &opfamily, &opcintype, &cmptype))
70 rguo@postgresql.org 968 [ # # ]:UNC 0 : elog(ERROR, "operator %u is not a valid ordering operator",
969 : : sgc->sortop);
970 : :
971 : : /* Because SortGroupClause doesn't carry collation, consult the expr */
70 rguo@postgresql.org 972 :GNC 326 : collation = exprCollation((Node *) expr);
973 : :
974 : : /*
975 : : * EquivalenceClasses need to contain opfamily lists based on the family
976 : : * membership of mergejoinable equality operators, which could belong to
977 : : * more than one opfamily. So we have to look up the opfamily's equality
978 : : * operator and get its membership.
979 : : */
980 : 326 : equality_op = get_opfamily_member_for_cmptype(opfamily,
981 : : opcintype,
982 : : opcintype,
983 : : COMPARE_EQ);
984 [ - + ]: 326 : if (!OidIsValid(equality_op)) /* shouldn't happen */
70 rguo@postgresql.org 985 [ # # ]:UNC 0 : elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
986 : : COMPARE_EQ, opcintype, opcintype, opfamily);
70 rguo@postgresql.org 987 :GNC 326 : opfamilies = get_mergejoin_opfamilies(equality_op);
988 [ - + ]: 326 : if (!opfamilies) /* certainly should find some */
70 rguo@postgresql.org 989 [ # # ]:UNC 0 : elog(ERROR, "could not find opfamilies for equality operator %u",
990 : : equality_op);
991 : :
992 : : /* Now find a matching EquivalenceClass */
70 rguo@postgresql.org 993 :GNC 326 : return get_eclass_for_sort_expr(root, expr, opfamilies, opcintype,
994 : : collation, sgc->tleSortGroupRef,
995 : : NULL, false);
996 : : }
997 : :
998 : : /*****************************************************************************
999 : : *
1000 : : * LATERAL REFERENCES
1001 : : *
1002 : : *****************************************************************************/
1003 : :
1004 : : /*
1005 : : * find_lateral_references
1006 : : * For each LATERAL subquery, extract all its references to Vars and
1007 : : * PlaceHolderVars of the current query level, and make sure those values
1008 : : * will be available for evaluation of the subquery.
1009 : : *
1010 : : * While later planning steps ensure that the Var/PHV source rels are on the
1011 : : * outside of nestloops relative to the LATERAL subquery, we also need to
1012 : : * ensure that the Vars/PHVs propagate up to the nestloop join level; this
1013 : : * means setting suitable where_needed values for them.
1014 : : *
1015 : : * Note that this only deals with lateral references in unflattened LATERAL
1016 : : * subqueries. When we flatten a LATERAL subquery, its lateral references
1017 : : * become plain Vars in the parent query, but they may have to be wrapped in
1018 : : * PlaceHolderVars if they need to be forced NULL by outer joins that don't
1019 : : * also null the LATERAL subquery. That's all handled elsewhere.
1020 : : *
1021 : : * This has to run before deconstruct_jointree, since it might result in
1022 : : * creation of PlaceHolderInfos.
1023 : : */
1024 : : void
4861 tgl@sss.pgh.pa.us 1025 :CBC 171197 : find_lateral_references(PlannerInfo *root)
1026 : : {
1027 : : Index rti;
1028 : :
1029 : : /* We need do nothing if the query contains no LATERAL RTEs */
1030 [ + + ]: 171197 : if (!root->hasLateralRTEs)
1031 : 165980 : return;
1032 : :
1033 : : /*
1034 : : * Examine all baserels (the rel array has been set up by now).
1035 : : */
1036 [ + + ]: 20605 : for (rti = 1; rti < root->simple_rel_array_size; rti++)
1037 : : {
1038 : 15388 : RelOptInfo *brel = root->simple_rel_array[rti];
1039 : :
1040 : : /* there may be empty slots corresponding to non-baserel RTEs */
1041 [ + + ]: 15388 : if (brel == NULL)
1042 : 3506 : continue;
1043 : :
3101 1044 [ - + ]: 11882 : Assert(brel->relid == rti); /* sanity check on array */
1045 : :
1046 : : /*
1047 : : * This bit is less obvious than it might look. We ignore appendrel
1048 : : * otherrels and consider only their parent baserels. In a case where
1049 : : * a LATERAL-containing UNION ALL subquery was pulled up, it is the
1050 : : * otherrel that is actually going to be in the plan. However, we
1051 : : * want to mark all its lateral references as needed by the parent,
1052 : : * because it is the parent's relid that will be used for join
1053 : : * planning purposes. And the parent's RTE will contain all the
1054 : : * lateral references we need to know, since the pulled-up member is
1055 : : * nothing but a copy of parts of the original RTE's subquery. We
1056 : : * could visit the parent's children instead and transform their
1057 : : * references back to the parent's relid, but it would be much more
1058 : : * complicated for no real gain. (Important here is that the child
1059 : : * members have not yet received any processing beyond being pulled
1060 : : * up.) Similarly, in appendrels created by inheritance expansion,
1061 : : * it's sufficient to look at the parent relation.
1062 : : */
1063 : :
1064 : : /* ignore RTEs that are "other rels" */
4861 1065 [ - + ]: 11882 : if (brel->reloptkind != RELOPT_BASEREL)
4861 tgl@sss.pgh.pa.us 1066 :UBC 0 : continue;
1067 : :
4861 tgl@sss.pgh.pa.us 1068 :CBC 11882 : extract_lateral_references(root, brel, rti);
1069 : : }
1070 : : }
1071 : :
1072 : : static void
1073 : 11882 : extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex)
1074 : : {
4880 1075 : 11882 : RangeTblEntry *rte = root->simple_rte_array[rtindex];
1076 : : List *vars;
1077 : : List *newvars;
1078 : : Relids where_needed;
1079 : : ListCell *lc;
1080 : :
1081 : : /* No cross-references are possible if it's not LATERAL */
1082 [ + + ]: 11882 : if (!rte->lateral)
1083 : 6984 : return;
1084 : :
1085 : : /* Fetch the appropriate variables */
3798 1086 [ + + ]: 4898 : if (rte->rtekind == RTE_RELATION)
1087 : 18 : vars = pull_vars_of_level((Node *) rte->tablesample, 0);
1088 [ + + ]: 4880 : else if (rte->rtekind == RTE_SUBQUERY)
4880 1089 : 400 : vars = pull_vars_of_level((Node *) rte->subquery, 1);
1090 [ + + ]: 4480 : else if (rte->rtekind == RTE_FUNCTION)
4409 1091 : 4327 : vars = pull_vars_of_level((Node *) rte->functions, 0);
3206 alvherre@alvh.no-ip. 1092 [ + + ]: 153 : else if (rte->rtekind == RTE_TABLEFUNC)
1093 : 117 : vars = pull_vars_of_level((Node *) rte->tablefunc, 0);
4875 tgl@sss.pgh.pa.us 1094 [ + - ]: 36 : else if (rte->rtekind == RTE_VALUES)
1095 : 36 : vars = pull_vars_of_level((Node *) rte->values_lists, 0);
1096 : : else
1097 : : {
4861 tgl@sss.pgh.pa.us 1098 :UBC 0 : Assert(false);
1099 : : return; /* keep compiler quiet */
1100 : : }
1101 : :
4861 tgl@sss.pgh.pa.us 1102 [ + + ]:CBC 4898 : if (vars == NIL)
1103 : 50 : return; /* nothing to do */
1104 : :
1105 : : /* Copy each Var (or PlaceHolderVar) and adjust it to match our level */
4880 1106 : 4848 : newvars = NIL;
1107 [ + - + + : 10153 : foreach(lc, vars)
+ + ]
1108 : : {
4585 bruce@momjian.us 1109 : 5305 : Node *node = (Node *) lfirst(lc);
1110 : :
4861 tgl@sss.pgh.pa.us 1111 : 5305 : node = copyObject(node);
1112 [ + + ]: 5305 : if (IsA(node, Var))
1113 : : {
4585 bruce@momjian.us 1114 : 5242 : Var *var = (Var *) node;
1115 : :
1116 : : /* Adjustment is easy since it's just one node */
4861 tgl@sss.pgh.pa.us 1117 : 5242 : var->varlevelsup = 0;
1118 : : }
1119 [ + - ]: 63 : else if (IsA(node, PlaceHolderVar))
1120 : : {
1121 : 63 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
4585 bruce@momjian.us 1122 : 63 : int levelsup = phv->phlevelsup;
1123 : :
1124 : : /* Have to work harder to adjust the contained expression too */
4861 tgl@sss.pgh.pa.us 1125 [ + + ]: 63 : if (levelsup != 0)
1126 : 45 : IncrementVarSublevelsUp(node, -levelsup, 0);
1127 : :
1128 : : /*
1129 : : * If we pulled the PHV out of a subquery RTE, its expression
1130 : : * needs to be preprocessed. subquery_planner() already did this
1131 : : * for level-zero PHVs in function and values RTEs, though.
1132 : : */
1133 [ + + ]: 63 : if (levelsup > 0)
1134 : 45 : phv->phexpr = preprocess_phv_expression(root, phv->phexpr);
1135 : : }
1136 : : else
4869 tgl@sss.pgh.pa.us 1137 :UBC 0 : Assert(false);
4861 tgl@sss.pgh.pa.us 1138 :CBC 5305 : newvars = lappend(newvars, node);
1139 : : }
1140 : :
1141 : 4848 : list_free(vars);
1142 : :
1143 : : /*
1144 : : * We mark the Vars as being "needed" at the LATERAL RTE. This is a bit
1145 : : * of a cheat: a more formal approach would be to mark each one as needed
1146 : : * at the join of the LATERAL RTE with its source RTE. But it will work,
1147 : : * and it's much less tedious than computing a separate where_needed for
1148 : : * each Var.
1149 : : */
4880 1150 : 4848 : where_needed = bms_make_singleton(rtindex);
1151 : :
1152 : : /*
1153 : : * Push Vars into their source relations' targetlists, and PHVs into
1154 : : * root->placeholder_list.
1155 : : */
1218 1156 : 4848 : add_vars_to_targetlist(root, newvars, where_needed);
1157 : :
1158 : : /*
1159 : : * Remember the lateral references for rebuild_lateral_attr_needed and
1160 : : * create_lateral_join_info.
1161 : : */
4861 1162 : 4848 : brel->lateral_vars = newvars;
1163 : : }
1164 : :
1165 : : /*
1166 : : * rebuild_lateral_attr_needed
1167 : : * Put back attr_needed bits for Vars/PHVs needed for lateral references.
1168 : : *
1169 : : * This is used to rebuild attr_needed/ph_needed sets after removal of a
1170 : : * useless outer join. It should match what find_lateral_references did,
1171 : : * except that we call add_vars_to_attr_needed not add_vars_to_targetlist.
1172 : : */
1173 : : void
446 1174 : 5695 : rebuild_lateral_attr_needed(PlannerInfo *root)
1175 : : {
1176 : : Index rti;
1177 : :
1178 : : /* We need do nothing if the query contains no LATERAL RTEs */
1179 [ + + ]: 5695 : if (!root->hasLateralRTEs)
1180 : 5370 : return;
1181 : :
1182 : : /* Examine the same baserels that find_lateral_references did */
1183 [ + + ]: 3366 : for (rti = 1; rti < root->simple_rel_array_size; rti++)
1184 : : {
1185 : 3041 : RelOptInfo *brel = root->simple_rel_array[rti];
1186 : : Relids where_needed;
1187 : :
1188 [ + + ]: 3041 : if (brel == NULL)
1189 : 2167 : continue;
1190 [ - + ]: 874 : if (brel->reloptkind != RELOPT_BASEREL)
446 tgl@sss.pgh.pa.us 1191 :UBC 0 : continue;
1192 : :
1193 : : /*
1194 : : * We don't need to repeat all of extract_lateral_references, since it
1195 : : * kindly saved the extracted Vars/PHVs in lateral_vars.
1196 : : */
446 tgl@sss.pgh.pa.us 1197 [ + + ]:CBC 874 : if (brel->lateral_vars == NIL)
1198 : 706 : continue;
1199 : :
1200 : 168 : where_needed = bms_make_singleton(rti);
1201 : :
1202 : 168 : add_vars_to_attr_needed(root, brel->lateral_vars, where_needed);
1203 : : }
1204 : : }
1205 : :
1206 : : /*
1207 : : * create_lateral_join_info
1208 : : * Fill in the per-base-relation direct_lateral_relids, lateral_relids
1209 : : * and lateral_referencers sets.
1210 : : */
1211 : : void
4861 1212 : 171197 : create_lateral_join_info(PlannerInfo *root)
1213 : : {
3659 1214 : 171197 : bool found_laterals = false;
1215 : : Index rti;
1216 : : ListCell *lc;
1217 : :
1218 : : /* We need do nothing if the query contains no LATERAL RTEs */
4861 1219 [ + + ]: 171197 : if (!root->hasLateralRTEs)
1220 : 165980 : return;
1221 : :
1222 : : /* We'll need to have the ph_eval_at values for PlaceHolderVars */
1047 1223 [ - + ]: 5217 : Assert(root->placeholdersFrozen);
1224 : :
1225 : : /*
1226 : : * Examine all baserels (the rel array has been set up by now).
1227 : : */
4861 1228 [ + + ]: 20605 : for (rti = 1; rti < root->simple_rel_array_size; rti++)
1229 : : {
1230 : 15388 : RelOptInfo *brel = root->simple_rel_array[rti];
1231 : : Relids lateral_relids;
1232 : :
1233 : : /* there may be empty slots corresponding to non-baserel RTEs */
1234 [ + + ]: 15388 : if (brel == NULL)
1235 : 3831 : continue;
1236 : :
3101 1237 [ - + ]: 11557 : Assert(brel->relid == rti); /* sanity check on array */
1238 : :
1239 : : /* ignore RTEs that are "other rels" */
4861 1240 [ - + ]: 11557 : if (brel->reloptkind != RELOPT_BASEREL)
4861 tgl@sss.pgh.pa.us 1241 :UBC 0 : continue;
1242 : :
4861 tgl@sss.pgh.pa.us 1243 :CBC 11557 : lateral_relids = NULL;
1244 : :
1245 : : /* consider each laterally-referenced Var or PHV */
1246 [ + + + + : 16778 : foreach(lc, brel->lateral_vars)
+ + ]
1247 : : {
4585 bruce@momjian.us 1248 : 5221 : Node *node = (Node *) lfirst(lc);
1249 : :
4861 tgl@sss.pgh.pa.us 1250 [ + + ]: 5221 : if (IsA(node, Var))
1251 : : {
4585 bruce@momjian.us 1252 : 5158 : Var *var = (Var *) node;
1253 : :
3659 tgl@sss.pgh.pa.us 1254 : 5158 : found_laterals = true;
4861 1255 : 5158 : lateral_relids = bms_add_member(lateral_relids,
1256 : : var->varno);
1257 : : }
1258 [ + - ]: 63 : else if (IsA(node, PlaceHolderVar))
1259 : : {
1260 : 63 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
1218 1261 : 63 : PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
1262 : :
3659 1263 : 63 : found_laterals = true;
4861 1264 : 63 : lateral_relids = bms_add_members(lateral_relids,
1265 : 63 : phinfo->ph_eval_at);
1266 : : }
1267 : : else
4861 tgl@sss.pgh.pa.us 1268 :UBC 0 : Assert(false);
1269 : : }
1270 : :
1271 : : /* We now have all the simple lateral refs from this rel */
3659 tgl@sss.pgh.pa.us 1272 :CBC 11557 : brel->direct_lateral_relids = lateral_relids;
1273 : 11557 : brel->lateral_relids = bms_copy(lateral_relids);
1274 : : }
1275 : :
1276 : : /*
1277 : : * Now check for lateral references within PlaceHolderVars, and mark their
1278 : : * eval_at rels as having lateral references to the source rels.
1279 : : *
1280 : : * For a PHV that is due to be evaluated at a baserel, mark its source(s)
1281 : : * as direct lateral dependencies of the baserel (adding onto the ones
1282 : : * recorded above). If it's due to be evaluated at a join, mark its
1283 : : * source(s) as indirect lateral dependencies of each baserel in the join,
1284 : : * ie put them into lateral_relids but not direct_lateral_relids. This is
1285 : : * appropriate because we can't put any such baserel on the outside of a
1286 : : * join to one of the PHV's lateral dependencies, but on the other hand we
1287 : : * also can't yet join it directly to the dependency.
1288 : : */
4505 1289 [ + + + + : 5512 : foreach(lc, root->placeholder_list)
+ + ]
1290 : : {
1291 : 295 : PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
1292 : 295 : Relids eval_at = phinfo->ph_eval_at;
1293 : : Relids lateral_refs;
1294 : : int varno;
1295 : :
3659 1296 [ + + ]: 295 : if (phinfo->ph_lateral == NULL)
1297 : 164 : continue; /* PHV is uninteresting if no lateral refs */
1298 : :
1299 : 131 : found_laterals = true;
1300 : :
1301 : : /*
1302 : : * Include only baserels not outer joins in the evaluation sites'
1303 : : * lateral relids. This avoids problems when outer join order gets
1304 : : * rearranged, and it should still ensure that the lateral values are
1305 : : * available when needed.
1306 : : */
911 1307 : 131 : lateral_refs = bms_intersect(phinfo->ph_lateral, root->all_baserels);
1308 [ - + ]: 131 : Assert(!bms_is_empty(lateral_refs));
1309 : :
3659 1310 [ + + ]: 131 : if (bms_get_singleton_member(eval_at, &varno))
1311 : : {
1312 : : /* Evaluation site is a baserel */
1313 : 98 : RelOptInfo *brel = find_base_rel(root, varno);
1314 : :
1315 : 98 : brel->direct_lateral_relids =
1316 : 98 : bms_add_members(brel->direct_lateral_relids,
1317 : : lateral_refs);
1318 : 98 : brel->lateral_relids =
1319 : 98 : bms_add_members(brel->lateral_relids,
1320 : : lateral_refs);
1321 : : }
1322 : : else
1323 : : {
1324 : : /* Evaluation site is a join */
1325 : 33 : varno = -1;
1326 [ + + ]: 99 : while ((varno = bms_next_member(eval_at, varno)) >= 0)
1327 : : {
1052 1328 : 66 : RelOptInfo *brel = find_base_rel_ignore_join(root, varno);
1329 : :
1330 [ - + ]: 66 : if (brel == NULL)
1052 tgl@sss.pgh.pa.us 1331 :UBC 0 : continue; /* ignore outer joins in eval_at */
3659 tgl@sss.pgh.pa.us 1332 :CBC 66 : brel->lateral_relids = bms_add_members(brel->lateral_relids,
1333 : : lateral_refs);
1334 : : }
1335 : : }
1336 : : }
1337 : :
1338 : : /*
1339 : : * If we found no actual lateral references, we're done; but reset the
1340 : : * hasLateralRTEs flag to avoid useless work later.
1341 : : */
1342 [ + + ]: 5217 : if (!found_laterals)
1343 : : {
1344 : 367 : root->hasLateralRTEs = false;
4505 1345 : 367 : return;
1346 : : }
1347 : :
1348 : : /*
1349 : : * Calculate the transitive closure of the lateral_relids sets, so that
1350 : : * they describe both direct and indirect lateral references. If relation
1351 : : * X references Y laterally, and Y references Z laterally, then we will
1352 : : * have to scan X on the inside of a nestloop with Z, so for all intents
1353 : : * and purposes X is laterally dependent on Z too.
1354 : : *
1355 : : * This code is essentially Warshall's algorithm for transitive closure.
1356 : : * The outer loop considers each baserel, and propagates its lateral
1357 : : * dependencies to those baserels that have a lateral dependency on it.
1358 : : */
1359 [ + + ]: 17826 : for (rti = 1; rti < root->simple_rel_array_size; rti++)
1360 : : {
1361 : 12976 : RelOptInfo *brel = root->simple_rel_array[rti];
1362 : : Relids outer_lateral_relids;
1363 : : Index rti2;
1364 : :
3659 1365 [ + + - + ]: 12976 : if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
4505 1366 : 2175 : continue;
1367 : :
1368 : : /* need not consider baserel further if it has no lateral refs */
3659 1369 : 10801 : outer_lateral_relids = brel->lateral_relids;
1370 [ + + ]: 10801 : if (outer_lateral_relids == NULL)
4505 1371 : 5873 : continue;
1372 : :
1373 : : /* else scan all baserels */
3659 1374 [ + + ]: 18396 : for (rti2 = 1; rti2 < root->simple_rel_array_size; rti2++)
1375 : : {
1376 : 13468 : RelOptInfo *brel2 = root->simple_rel_array[rti2];
1377 : :
1378 [ + + - + ]: 13468 : if (brel2 == NULL || brel2->reloptkind != RELOPT_BASEREL)
1379 : 2382 : continue;
1380 : :
1381 : : /* if brel2 has lateral ref to brel, propagate brel's refs */
1382 [ + + ]: 11086 : if (bms_is_member(rti, brel2->lateral_relids))
1383 : 36 : brel2->lateral_relids = bms_add_members(brel2->lateral_relids,
1384 : : outer_lateral_relids);
1385 : : }
1386 : : }
1387 : :
1388 : : /*
1389 : : * Now that we've identified all lateral references, mark each baserel
1390 : : * with the set of relids of rels that reference it laterally (possibly
1391 : : * indirectly) --- that is, the inverse mapping of lateral_relids.
1392 : : */
1393 [ + + ]: 17826 : for (rti = 1; rti < root->simple_rel_array_size; rti++)
1394 : : {
1395 : 12976 : RelOptInfo *brel = root->simple_rel_array[rti];
1396 : : Relids lateral_relids;
1397 : : int rti2;
1398 : :
1399 [ + + - + ]: 12976 : if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
1400 : 2175 : continue;
1401 : :
1402 : : /* Nothing to do at rels with no lateral refs */
1403 : 10801 : lateral_relids = brel->lateral_relids;
1021 1404 [ + + ]: 10801 : if (bms_is_empty(lateral_relids))
3659 1405 : 5873 : continue;
1406 : :
1407 : : /* No rel should have a lateral dependency on itself */
1408 [ - + ]: 4928 : Assert(!bms_is_member(rti, lateral_relids));
1409 : :
1410 : : /* Mark this rel's referencees */
1411 : 4928 : rti2 = -1;
1412 [ + + ]: 9991 : while ((rti2 = bms_next_member(lateral_relids, rti2)) >= 0)
1413 : : {
1414 : 5063 : RelOptInfo *brel2 = root->simple_rel_array[rti2];
1415 : :
1052 1416 [ + + ]: 5063 : if (brel2 == NULL)
1417 : 6 : continue; /* must be an OJ */
1418 : :
1419 [ - + ]: 5057 : Assert(brel2->reloptkind == RELOPT_BASEREL);
3659 1420 : 5057 : brel2->lateral_referencers =
1421 : 5057 : bms_add_member(brel2->lateral_referencers, rti);
1422 : : }
1423 : : }
1424 : : }
1425 : :
1426 : :
1427 : : /*****************************************************************************
1428 : : *
1429 : : * JOIN TREE PROCESSING
1430 : : *
1431 : : *****************************************************************************/
1432 : :
1433 : : /*
1434 : : * deconstruct_jointree
1435 : : * Recursively scan the query's join tree for WHERE and JOIN/ON qual
1436 : : * clauses, and add these to the appropriate restrictinfo and joininfo
1437 : : * lists belonging to base RelOptInfos. Also, add SpecialJoinInfo nodes
1438 : : * to root->join_info_list for any outer joins appearing in the query tree.
1439 : : * Return a "joinlist" data structure showing the join order decisions
1440 : : * that need to be made by make_one_rel().
1441 : : *
1442 : : * The "joinlist" result is a list of items that are either RangeTblRef
1443 : : * jointree nodes or sub-joinlists. All the items at the same level of
1444 : : * joinlist must be joined in an order to be determined by make_one_rel()
1445 : : * (note that legal orders may be constrained by SpecialJoinInfo nodes).
1446 : : * A sub-joinlist represents a subproblem to be planned separately. Currently
1447 : : * sub-joinlists arise only from FULL OUTER JOIN or when collapsing of
1448 : : * subproblems is stopped by join_collapse_limit or from_collapse_limit.
1449 : : */
1450 : : List *
7302 1451 : 171197 : deconstruct_jointree(PlannerInfo *root)
1452 : : {
1453 : : List *result;
1454 : : JoinDomain *top_jdomain;
1052 1455 : 171197 : List *item_list = NIL;
1456 : : ListCell *lc;
1457 : :
1458 : : /*
1459 : : * After this point, no more PlaceHolderInfos may be made, because
1460 : : * make_outerjoininfo requires all active placeholders to be present in
1461 : : * root->placeholder_list while we crawl up the join tree.
1462 : : */
1218 1463 : 171197 : root->placeholdersFrozen = true;
1464 : :
1465 : : /* Fetch the already-created top-level join domain for the query */
1052 1466 : 171197 : top_jdomain = linitial_node(JoinDomain, root->join_domains);
1467 : 171197 : top_jdomain->jd_relids = NULL; /* filled during deconstruct_recurse */
1468 : :
1469 : : /* Start recursion at top of jointree */
7302 1470 [ + - - + ]: 171197 : Assert(root->parse->jointree != NULL &&
1471 : : IsA(root->parse->jointree, FromExpr));
1472 : :
1473 : : /* These are filled as we scan the jointree */
1052 1474 : 171197 : root->all_baserels = NULL;
1475 : 171197 : root->outer_join_rels = NULL;
1476 : :
1477 : : /* Perform the initial scan of the jointree */
1478 : 171197 : result = deconstruct_recurse(root, (Node *) root->parse->jointree,
1479 : : top_jdomain, NULL,
1480 : : &item_list);
1481 : :
1482 : : /* Now we can form the value of all_query_rels, too */
1483 : 171197 : root->all_query_rels = bms_union(root->all_baserels, root->outer_join_rels);
1484 : :
1485 : : /* ... which should match what we computed for the top join domain */
1486 [ - + ]: 171197 : Assert(bms_equal(root->all_query_rels, top_jdomain->jd_relids));
1487 : :
1488 : : /* Now scan all the jointree nodes again, and distribute quals */
1489 [ + - + + : 646800 : foreach(lc, item_list)
+ + ]
1490 : : {
1491 : 475603 : JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc);
1492 : :
1047 1493 : 475603 : deconstruct_distribute(root, jtitem);
1494 : : }
1495 : :
1496 : : /*
1497 : : * If there were any special joins then we may have some postponed LEFT
1498 : : * JOIN clauses to deal with.
1499 : : */
1052 1500 [ + + ]: 171197 : if (root->join_info_list)
1501 : : {
1502 [ + - + + : 130225 : foreach(lc, item_list)
+ + ]
1503 : : {
1504 : 110447 : JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc);
1505 : :
1506 [ + + ]: 110447 : if (jtitem->oj_joinclauses != NIL)
1507 : 21226 : deconstruct_distribute_oj_quals(root, item_list, jtitem);
1508 : : }
1509 : : }
1510 : :
1511 : : /* Don't need the JoinTreeItems any more */
1512 : 171197 : list_free_deep(item_list);
1513 : :
4503 1514 : 171197 : return result;
1515 : : }
1516 : :
1517 : : /*
1518 : : * deconstruct_recurse
1519 : : * One recursion level of deconstruct_jointree's initial jointree scan.
1520 : : *
1521 : : * jtnode is the jointree node to examine, and parent_domain is the
1522 : : * enclosing join domain. (We must add all base+OJ relids appearing
1523 : : * here or below to parent_domain.) parent_jtitem is the JoinTreeItem
1524 : : * for the parent jointree node, or NULL at the top of the recursion.
1525 : : *
1526 : : * item_list is an in/out parameter: we add a JoinTreeItem struct to
1527 : : * that list for each jointree node, in depth-first traversal order.
1528 : : * (Hence, after each call, the last list item corresponds to its jtnode.)
1529 : : *
1530 : : * Return value is the appropriate joinlist for this jointree node.
1531 : : */
1532 : : static List *
1052 1533 : 475603 : deconstruct_recurse(PlannerInfo *root, Node *jtnode,
1534 : : JoinDomain *parent_domain,
1535 : : JoinTreeItem *parent_jtitem,
1536 : : List **item_list)
1537 : : {
1538 : : List *joinlist;
1539 : : JoinTreeItem *jtitem;
1540 : :
1541 [ - + ]: 475603 : Assert(jtnode != NULL);
1542 : :
1543 : : /* Make the new JoinTreeItem, but don't add it to item_list yet */
1544 : 475603 : jtitem = palloc0_object(JoinTreeItem);
1545 : 475603 : jtitem->jtnode = jtnode;
1047 1546 : 475603 : jtitem->jti_parent = parent_jtitem;
1547 : :
9210 1548 [ + + ]: 475603 : if (IsA(jtnode, RangeTblRef))
1549 : : {
1550 : 247255 : int varno = ((RangeTblRef *) jtnode)->rtindex;
1551 : :
1552 : : /* Fill all_baserels as we encounter baserel jointree nodes */
1052 1553 : 247255 : root->all_baserels = bms_add_member(root->all_baserels, varno);
1554 : : /* This node belongs to parent_domain */
1555 : 247255 : jtitem->jdomain = parent_domain;
1556 : 247255 : parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
1557 : : varno);
1558 : : /* qualscope is just the one RTE */
1559 : 247255 : jtitem->qualscope = bms_make_singleton(varno);
1560 : : /* A single baserel does not create an inner join */
1561 : 247255 : jtitem->inner_join_rels = NULL;
7302 1562 : 247255 : joinlist = list_make1(jtnode);
1563 : : }
9210 1564 [ + + ]: 228348 : else if (IsA(jtnode, FromExpr))
1565 : : {
1566 : 177680 : FromExpr *f = (FromExpr *) jtnode;
1567 : : int remaining;
1568 : : ListCell *l;
1569 : :
1570 : : /* This node belongs to parent_domain, as do its children */
1052 1571 : 177680 : jtitem->jdomain = parent_domain;
1572 : :
1573 : : /*
1574 : : * Recurse to handle child nodes, and compute output joinlist. We
1575 : : * collapse subproblems into a single joinlist whenever the resulting
1576 : : * joinlist wouldn't exceed from_collapse_limit members. Also, always
1577 : : * collapse one-element subproblems, since that won't lengthen the
1578 : : * joinlist anyway.
1579 : : */
1580 : 177680 : jtitem->qualscope = NULL;
1581 : 177680 : jtitem->inner_join_rels = NULL;
7302 1582 : 177680 : joinlist = NIL;
1583 : 177680 : remaining = list_length(f->fromlist);
9210 1584 [ + - + + : 380750 : foreach(l, f->fromlist)
+ + ]
1585 : : {
1586 : : JoinTreeItem *sub_item;
1587 : : List *sub_joinlist;
1588 : : int sub_members;
1589 : :
7302 1590 : 203070 : sub_joinlist = deconstruct_recurse(root, lfirst(l),
1591 : : parent_domain,
1592 : : jtitem,
1593 : : item_list);
1052 1594 : 203070 : sub_item = (JoinTreeItem *) llast(*item_list);
1595 : 406140 : jtitem->qualscope = bms_add_members(jtitem->qualscope,
1596 : 203070 : sub_item->qualscope);
1597 : 203070 : jtitem->inner_join_rels = sub_item->inner_join_rels;
7302 1598 : 203070 : sub_members = list_length(sub_joinlist);
1599 : 203070 : remaining--;
1600 [ + + ]: 203070 : if (sub_members <= 1 ||
1601 [ + + ]: 32913 : list_length(joinlist) + sub_members + remaining <= from_collapse_limit)
1602 : 203064 : joinlist = list_concat(joinlist, sub_joinlist);
1603 : : else
1604 : 6 : joinlist = lappend(joinlist, sub_joinlist);
1605 : : }
1606 : :
1607 : : /*
1608 : : * A FROM with more than one list element is an inner join subsuming
1609 : : * all below it, so we should report inner_join_rels = qualscope. If
1610 : : * there was exactly one element, we should (and already did) report
1611 : : * whatever its inner_join_rels were. If there were no elements (is
1612 : : * that still possible?) the initialization before the loop fixed it.
1613 : : */
6683 1614 [ + + ]: 177680 : if (list_length(f->fromlist) > 1)
1052 1615 : 22888 : jtitem->inner_join_rels = jtitem->qualscope;
1616 : : }
9227 1617 [ + - ]: 50668 : else if (IsA(jtnode, JoinExpr))
1618 : : {
1619 : 50668 : JoinExpr *j = (JoinExpr *) jtnode;
1620 : : JoinDomain *child_domain,
1621 : : *fj_domain;
1622 : : JoinTreeItem *left_item,
1623 : : *right_item;
1624 : : List *leftjoinlist,
1625 : : *rightjoinlist;
1626 : :
1627 [ + + + + : 50668 : switch (j->jointype)
- ]
1628 : : {
1629 : 23528 : case JOIN_INNER:
1630 : : /* This node belongs to parent_domain, as do its children */
1052 1631 : 23528 : jtitem->jdomain = parent_domain;
1632 : : /* Recurse */
7302 1633 : 23528 : leftjoinlist = deconstruct_recurse(root, j->larg,
1634 : : parent_domain,
1635 : : jtitem,
1636 : : item_list);
1052 1637 : 23528 : left_item = (JoinTreeItem *) llast(*item_list);
7302 1638 : 23528 : rightjoinlist = deconstruct_recurse(root, j->rarg,
1639 : : parent_domain,
1640 : : jtitem,
1641 : : item_list);
1052 1642 : 23528 : right_item = (JoinTreeItem *) llast(*item_list);
1643 : : /* Compute qualscope etc */
1644 : 47056 : jtitem->qualscope = bms_union(left_item->qualscope,
1645 : 23528 : right_item->qualscope);
1646 : 23528 : jtitem->inner_join_rels = jtitem->qualscope;
1647 : 23528 : jtitem->left_rels = left_item->qualscope;
1648 : 23528 : jtitem->right_rels = right_item->qualscope;
1649 : : /* Inner join adds no restrictions for quals */
1650 : 23528 : jtitem->nonnullable_rels = NULL;
9227 1651 : 23528 : break;
1652 : 24052 : case JOIN_LEFT:
1653 : : case JOIN_ANTI:
1654 : : /* Make new join domain for my quals and the RHS */
1052 1655 : 24052 : child_domain = makeNode(JoinDomain);
1656 : 24052 : child_domain->jd_relids = NULL; /* filled by recursion */
1657 : 24052 : root->join_domains = lappend(root->join_domains, child_domain);
1658 : 24052 : jtitem->jdomain = child_domain;
1659 : : /* Recurse */
7302 1660 : 24052 : leftjoinlist = deconstruct_recurse(root, j->larg,
1661 : : parent_domain,
1662 : : jtitem,
1663 : : item_list);
1052 1664 : 24052 : left_item = (JoinTreeItem *) llast(*item_list);
7302 1665 : 24052 : rightjoinlist = deconstruct_recurse(root, j->rarg,
1666 : : child_domain,
1667 : : jtitem,
1668 : : item_list);
1052 1669 : 24052 : right_item = (JoinTreeItem *) llast(*item_list);
1670 : : /* Compute join domain contents, qualscope etc */
1671 : 24052 : parent_domain->jd_relids =
1672 : 24052 : bms_add_members(parent_domain->jd_relids,
1673 : 24052 : child_domain->jd_relids);
1674 : 48104 : jtitem->qualscope = bms_union(left_item->qualscope,
1675 : 24052 : right_item->qualscope);
1676 : : /* caution: ANTI join derived from SEMI will lack rtindex */
1677 [ + + ]: 24052 : if (j->rtindex != 0)
1678 : : {
1679 : 22664 : parent_domain->jd_relids =
1680 : 22664 : bms_add_member(parent_domain->jd_relids,
1681 : : j->rtindex);
1682 : 22664 : jtitem->qualscope = bms_add_member(jtitem->qualscope,
1683 : : j->rtindex);
1684 : 22664 : root->outer_join_rels = bms_add_member(root->outer_join_rels,
1685 : : j->rtindex);
1686 : 22664 : mark_rels_nulled_by_join(root, j->rtindex,
1687 : : right_item->qualscope);
1688 : : }
1689 : 48104 : jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
1690 : 24052 : right_item->inner_join_rels);
1691 : 24052 : jtitem->left_rels = left_item->qualscope;
1692 : 24052 : jtitem->right_rels = right_item->qualscope;
1693 : 24052 : jtitem->nonnullable_rels = left_item->qualscope;
9227 1694 : 24052 : break;
6139 1695 : 2571 : case JOIN_SEMI:
1696 : : /* This node belongs to parent_domain, as do its children */
1052 1697 : 2571 : jtitem->jdomain = parent_domain;
1698 : : /* Recurse */
6139 1699 : 2571 : leftjoinlist = deconstruct_recurse(root, j->larg,
1700 : : parent_domain,
1701 : : jtitem,
1702 : : item_list);
1052 1703 : 2571 : left_item = (JoinTreeItem *) llast(*item_list);
6139 1704 : 2571 : rightjoinlist = deconstruct_recurse(root, j->rarg,
1705 : : parent_domain,
1706 : : jtitem,
1707 : : item_list);
1052 1708 : 2571 : right_item = (JoinTreeItem *) llast(*item_list);
1709 : : /* Compute qualscope etc */
1710 : 5142 : jtitem->qualscope = bms_union(left_item->qualscope,
1711 : 2571 : right_item->qualscope);
1712 : : /* SEMI join never has rtindex, so don't add to anything */
1713 [ - + ]: 2571 : Assert(j->rtindex == 0);
1714 : 5142 : jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
1715 : 2571 : right_item->inner_join_rels);
1716 : 2571 : jtitem->left_rels = left_item->qualscope;
1717 : 2571 : jtitem->right_rels = right_item->qualscope;
1718 : : /* Semi join adds no restrictions for quals */
1719 : 2571 : jtitem->nonnullable_rels = NULL;
6139 1720 : 2571 : break;
9227 1721 : 517 : case JOIN_FULL:
1722 : : /* The FULL JOIN's quals need their very own domain */
1052 1723 : 517 : fj_domain = makeNode(JoinDomain);
1724 : 517 : root->join_domains = lappend(root->join_domains, fj_domain);
1725 : 517 : jtitem->jdomain = fj_domain;
1726 : : /* Recurse, giving each side its own join domain */
1727 : 517 : child_domain = makeNode(JoinDomain);
1728 : 517 : child_domain->jd_relids = NULL; /* filled by recursion */
1729 : 517 : root->join_domains = lappend(root->join_domains, child_domain);
7302 1730 : 517 : leftjoinlist = deconstruct_recurse(root, j->larg,
1731 : : child_domain,
1732 : : jtitem,
1733 : : item_list);
1052 1734 : 517 : left_item = (JoinTreeItem *) llast(*item_list);
1735 : 517 : fj_domain->jd_relids = bms_copy(child_domain->jd_relids);
1736 : 517 : child_domain = makeNode(JoinDomain);
1737 : 517 : child_domain->jd_relids = NULL; /* filled by recursion */
1738 : 517 : root->join_domains = lappend(root->join_domains, child_domain);
7302 1739 : 517 : rightjoinlist = deconstruct_recurse(root, j->rarg,
1740 : : child_domain,
1741 : : jtitem,
1742 : : item_list);
1052 1743 : 517 : right_item = (JoinTreeItem *) llast(*item_list);
1744 : : /* Compute qualscope etc */
1745 : 1034 : fj_domain->jd_relids = bms_add_members(fj_domain->jd_relids,
1746 : 517 : child_domain->jd_relids);
1747 : 1034 : parent_domain->jd_relids = bms_add_members(parent_domain->jd_relids,
1748 : 517 : fj_domain->jd_relids);
1749 : 1034 : jtitem->qualscope = bms_union(left_item->qualscope,
1750 : 517 : right_item->qualscope);
1751 [ - + ]: 517 : Assert(j->rtindex != 0);
1752 : 517 : parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
1753 : : j->rtindex);
1754 : 517 : jtitem->qualscope = bms_add_member(jtitem->qualscope,
1755 : : j->rtindex);
1756 : 517 : root->outer_join_rels = bms_add_member(root->outer_join_rels,
1757 : : j->rtindex);
1758 : 517 : mark_rels_nulled_by_join(root, j->rtindex,
1759 : : left_item->qualscope);
1760 : 517 : mark_rels_nulled_by_join(root, j->rtindex,
1761 : : right_item->qualscope);
1762 : 1034 : jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
1763 : 517 : right_item->inner_join_rels);
1764 : 517 : jtitem->left_rels = left_item->qualscope;
1765 : 517 : jtitem->right_rels = right_item->qualscope;
1766 : : /* each side is both outer and inner */
1767 : 517 : jtitem->nonnullable_rels = jtitem->qualscope;
9227 1768 : 517 : break;
9227 tgl@sss.pgh.pa.us 1769 :UBC 0 : default:
1770 : : /* JOIN_RIGHT was eliminated during reduce_outer_joins() */
8181 1771 [ # # ]: 0 : elog(ERROR, "unrecognized join type: %d",
1772 : : (int) j->jointype);
1773 : : leftjoinlist = rightjoinlist = NIL; /* keep compiler quiet */
1774 : : break;
1775 : : }
1776 : :
1777 : : /*
1778 : : * Compute the output joinlist. We fold subproblems together except
1779 : : * at a FULL JOIN or where join_collapse_limit would be exceeded.
1780 : : */
1052 tgl@sss.pgh.pa.us 1781 [ + + ]:CBC 50668 : if (j->jointype == JOIN_FULL)
1782 : : {
1783 : : /* force the join order exactly at this node */
1784 : 517 : joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist));
1785 : : }
1786 [ + + ]: 50151 : else if (list_length(leftjoinlist) + list_length(rightjoinlist) <=
1787 : : join_collapse_limit)
1788 : : {
1789 : : /* OK to combine subproblems */
1790 : 50067 : joinlist = list_concat(leftjoinlist, rightjoinlist);
1791 : : }
1792 : : else
1793 : : {
1794 : : /* can't combine, but needn't force join order above here */
1795 : : Node *leftpart,
1796 : : *rightpart;
1797 : :
1798 : : /* avoid creating useless 1-element sublists */
1799 [ + + ]: 84 : if (list_length(leftjoinlist) == 1)
1800 : 15 : leftpart = (Node *) linitial(leftjoinlist);
1801 : : else
1802 : 69 : leftpart = (Node *) leftjoinlist;
1803 [ + + ]: 84 : if (list_length(rightjoinlist) == 1)
1804 : 12 : rightpart = (Node *) linitial(rightjoinlist);
1805 : : else
1806 : 72 : rightpart = (Node *) rightjoinlist;
1807 : 84 : joinlist = list_make2(leftpart, rightpart);
1808 : : }
1809 : : }
1810 : : else
1811 : : {
1052 tgl@sss.pgh.pa.us 1812 [ # # ]:UBC 0 : elog(ERROR, "unrecognized node type: %d",
1813 : : (int) nodeTag(jtnode));
1814 : : joinlist = NIL; /* keep compiler quiet */
1815 : : }
1816 : :
1817 : : /* Finally, we can add the new JoinTreeItem to item_list */
1052 tgl@sss.pgh.pa.us 1818 :CBC 475603 : *item_list = lappend(*item_list, jtitem);
1819 : :
1820 : 475603 : return joinlist;
1821 : : }
1822 : :
1823 : : /*
1824 : : * deconstruct_distribute
1825 : : * Process one jointree node in phase 2 of deconstruct_jointree processing.
1826 : : *
1827 : : * Distribute quals of the node to appropriate restriction and join lists.
1828 : : * In addition, entries will be added to root->join_info_list for outer joins.
1829 : : */
1830 : : static void
1047 1831 : 475603 : deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem)
1832 : : {
1052 1833 : 475603 : Node *jtnode = jtitem->jtnode;
1834 : :
1835 [ + + ]: 475603 : if (IsA(jtnode, RangeTblRef))
1836 : : {
1837 : 247255 : int varno = ((RangeTblRef *) jtnode)->rtindex;
1838 : :
1839 : : /* Deal with any securityQuals attached to the RTE */
1840 [ + + ]: 247255 : if (root->qual_security_level > 0)
1841 : 1494 : process_security_barrier_quals(root,
1842 : : varno,
1843 : : jtitem);
1844 : : }
1845 [ + + ]: 228348 : else if (IsA(jtnode, FromExpr))
1846 : : {
1847 : 177680 : FromExpr *f = (FromExpr *) jtnode;
1848 : :
1849 : : /*
1850 : : * Process any lateral-referencing quals that were postponed to this
1851 : : * level by children.
1852 : : */
1047 1853 : 177680 : distribute_quals_to_rels(root, jtitem->lateral_clauses,
1854 : : jtitem,
1855 : : NULL,
1856 : : root->qual_security_level,
1857 : : jtitem->qualscope,
1858 : : NULL, NULL, NULL,
1859 : : true, false, false,
1860 : : NULL);
1861 : :
1862 : : /*
1863 : : * Now process the top-level quals.
1864 : : */
1052 1865 : 177680 : distribute_quals_to_rels(root, (List *) f->quals,
1866 : : jtitem,
1867 : : NULL,
1868 : : root->qual_security_level,
1869 : : jtitem->qualscope,
1870 : : NULL, NULL, NULL,
1871 : : true, false, false,
1872 : : NULL);
1873 : : }
1874 [ + - ]: 50668 : else if (IsA(jtnode, JoinExpr))
1875 : : {
1876 : 50668 : JoinExpr *j = (JoinExpr *) jtnode;
1877 : : Relids ojscope;
1878 : : List *my_quals;
1879 : : SpecialJoinInfo *sjinfo;
1880 : : List **postponed_oj_qual_list;
1881 : :
1882 : : /*
1883 : : * Include lateral-referencing quals postponed from children in
1884 : : * my_quals, so that they'll be handled properly in
1885 : : * make_outerjoininfo. (This is destructive to
1886 : : * jtitem->lateral_clauses, but we won't use that again.)
1887 : : */
1047 1888 : 50668 : my_quals = list_concat(jtitem->lateral_clauses,
1889 : 50668 : (List *) j->quals);
1890 : :
1891 : : /*
1892 : : * For an OJ, form the SpecialJoinInfo now, so that we can pass it to
1893 : : * distribute_qual_to_rels. We must compute its ojscope too.
1894 : : *
1895 : : * Semijoins are a bit of a hybrid: we build a SpecialJoinInfo, but we
1896 : : * want ojscope = NULL for distribute_qual_to_rels.
1897 : : */
7302 1898 [ + + ]: 50668 : if (j->jointype != JOIN_INNER)
1899 : : {
6334 1900 : 27140 : sjinfo = make_outerjoininfo(root,
1901 : : jtitem->left_rels,
1902 : : jtitem->right_rels,
1903 : : jtitem->inner_join_rels,
1904 : : j->jointype,
1052 1905 : 27140 : j->rtindex,
1906 : : my_quals);
1907 : 27140 : jtitem->sjinfo = sjinfo;
6139 1908 [ + + ]: 27140 : if (j->jointype == JOIN_SEMI)
1909 : 2571 : ojscope = NULL;
1910 : : else
1911 : 24569 : ojscope = bms_union(sjinfo->min_lefthand,
1912 : 24569 : sjinfo->min_righthand);
1913 : : }
1914 : : else
1915 : : {
6334 1916 : 23528 : sjinfo = NULL;
7302 1917 : 23528 : ojscope = NULL;
1918 : : }
1919 : :
1920 : : /*
1921 : : * If it's a left join with a join clause that is strict for the LHS,
1922 : : * then we need to postpone handling of any non-degenerate join
1923 : : * clauses, in case the join is able to commute with another left join
1924 : : * per identity 3. (Degenerate clauses need not be postponed, since
1925 : : * they will drop down below this join anyway.)
1926 : : */
1052 1927 [ + + + + ]: 50668 : if (j->jointype == JOIN_LEFT && sjinfo->lhs_strict)
1928 : : {
1929 : 21226 : postponed_oj_qual_list = &jtitem->oj_joinclauses;
1930 : :
1931 : : /*
1932 : : * Add back any commutable lower OJ relids that were removed from
1933 : : * min_lefthand or min_righthand, else the ojscope cross-check in
1934 : : * distribute_qual_to_rels will complain. Since we are postponing
1935 : : * processing of non-degenerate clauses, this addition doesn't
1936 : : * affect anything except that cross-check. Real clause
1937 : : * positioning decisions will be made later, when we revisit the
1938 : : * postponed clauses.
1939 : : */
945 1940 : 21226 : ojscope = bms_add_members(ojscope, sjinfo->commute_below_l);
1941 : 21226 : ojscope = bms_add_members(ojscope, sjinfo->commute_below_r);
1942 : : }
1943 : : else
1052 1944 : 29442 : postponed_oj_qual_list = NULL;
1945 : :
1946 : : /* Process the JOIN's qual clauses */
1947 : 50668 : distribute_quals_to_rels(root, my_quals,
1948 : : jtitem,
1949 : : sjinfo,
1950 : : root->qual_security_level,
1951 : : jtitem->qualscope,
1952 : : ojscope, jtitem->nonnullable_rels,
1953 : : NULL, /* incompatible_relids */
1954 : : true, /* allow_equivalence */
1955 : : false, false, /* not clones */
1956 : : postponed_oj_qual_list);
1957 : :
1958 : : /* And add the SpecialJoinInfo to join_info_list */
6334 1959 [ + + ]: 50668 : if (sjinfo)
1960 : 27140 : root->join_info_list = lappend(root->join_info_list, sjinfo);
1961 : : }
1962 : : else
1963 : : {
8181 tgl@sss.pgh.pa.us 1964 [ # # ]:UBC 0 : elog(ERROR, "unrecognized node type: %d",
1965 : : (int) nodeTag(jtnode));
1966 : : }
9227 tgl@sss.pgh.pa.us 1967 :CBC 475603 : }
1968 : :
1969 : : /*
1970 : : * process_security_barrier_quals
1971 : : * Transfer security-barrier quals into relation's baserestrictinfo list.
1972 : : *
1973 : : * The rewriter put any relevant security-barrier conditions into the RTE's
1974 : : * securityQuals field, but it's now time to copy them into the rel's
1975 : : * baserestrictinfo.
1976 : : *
1977 : : * In inheritance cases, we only consider quals attached to the parent rel
1978 : : * here; they will be valid for all children too, so it's okay to consider
1979 : : * them for purposes like equivalence class creation. Quals attached to
1980 : : * individual child rels will be dealt with during path creation.
1981 : : */
1982 : : static void
3255 1983 : 1494 : process_security_barrier_quals(PlannerInfo *root,
1984 : : int rti, JoinTreeItem *jtitem)
1985 : : {
1986 : 1494 : RangeTblEntry *rte = root->simple_rte_array[rti];
1987 : 1494 : Index security_level = 0;
1988 : : ListCell *lc;
1989 : :
1990 : : /*
1991 : : * Each element of the securityQuals list has been preprocessed into an
1992 : : * implicitly-ANDed list of clauses. All the clauses in a given sublist
1993 : : * should get the same security level, but successive sublists get higher
1994 : : * levels.
1995 : : */
1996 [ + + + + : 3059 : foreach(lc, rte->securityQuals)
+ + ]
1997 : : {
1998 : 1565 : List *qualset = (List *) lfirst(lc);
1999 : :
2000 : : /*
2001 : : * We cheat to the extent of passing ojscope = qualscope rather than
2002 : : * its more logical value of NULL. The only effect this has is to
2003 : : * force a Var-free qual to be evaluated at the rel rather than being
2004 : : * pushed up to top of tree, which we don't want.
2005 : : */
1052 2006 : 1565 : distribute_quals_to_rels(root, qualset,
2007 : : jtitem,
2008 : : NULL,
2009 : : security_level,
2010 : : jtitem->qualscope,
2011 : : jtitem->qualscope,
2012 : : NULL,
2013 : : NULL,
2014 : : true,
2015 : : false, false, /* not clones */
2016 : : NULL);
3255 2017 : 1565 : security_level++;
2018 : : }
2019 : :
2020 : : /* Assert that qual_security_level is higher than anything we just used */
2021 [ - + ]: 1494 : Assert(security_level <= root->qual_security_level);
2022 : 1494 : }
2023 : :
2024 : : /*
2025 : : * mark_rels_nulled_by_join
2026 : : * Fill RelOptInfo.nulling_relids of baserels nulled by this outer join
2027 : : *
2028 : : * Inputs:
2029 : : * ojrelid: RT index of the join RTE (must not be 0)
2030 : : * lower_rels: the base+OJ Relids syntactically below nullable side of join
2031 : : */
2032 : : static void
1052 2033 : 23698 : mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid,
2034 : : Relids lower_rels)
2035 : : {
2036 : 23698 : int relid = -1;
2037 : :
2038 [ + + ]: 48772 : while ((relid = bms_next_member(lower_rels, relid)) > 0)
2039 : : {
2040 : 25074 : RelOptInfo *rel = root->simple_rel_array[relid];
2041 : :
2042 : : /* ignore the RTE_GROUP RTE */
463 rguo@postgresql.org 2043 [ - + ]: 25074 : if (relid == root->group_rtindex)
463 rguo@postgresql.org 2044 :UBC 0 : continue;
2045 : :
1052 tgl@sss.pgh.pa.us 2046 [ + + ]:CBC 25074 : if (rel == NULL) /* must be an outer join */
2047 : : {
2048 [ - + ]: 385 : Assert(bms_is_member(relid, root->outer_join_rels));
2049 : 385 : continue;
2050 : : }
2051 : 24689 : rel->nulling_relids = bms_add_member(rel->nulling_relids, ojrelid);
2052 : : }
2053 : 23698 : }
2054 : :
2055 : : /*
2056 : : * make_outerjoininfo
2057 : : * Build a SpecialJoinInfo for the current outer join
2058 : : *
2059 : : * Inputs:
2060 : : * left_rels: the base+OJ Relids syntactically on outer side of join
2061 : : * right_rels: the base+OJ Relids syntactically on inner side of join
2062 : : * inner_join_rels: base+OJ Relids participating in inner joins below this one
2063 : : * jointype: what it says (must always be LEFT, FULL, SEMI, or ANTI)
2064 : : * ojrelid: RT index of the join RTE (0 for SEMI, which isn't in the RT list)
2065 : : * clause: the outer join's join condition (in implicit-AND format)
2066 : : *
2067 : : * The node should eventually be appended to root->join_info_list, but we
2068 : : * do not do that here.
2069 : : *
2070 : : * Note: we assume that this function is invoked bottom-up, so that
2071 : : * root->join_info_list already contains entries for all outer joins that are
2072 : : * syntactically below this one.
2073 : : */
2074 : : static SpecialJoinInfo *
7302 2075 : 27140 : make_outerjoininfo(PlannerInfo *root,
2076 : : Relids left_rels, Relids right_rels,
2077 : : Relids inner_join_rels,
2078 : : JoinType jointype, Index ojrelid,
2079 : : List *clause)
2080 : : {
6334 2081 : 27140 : SpecialJoinInfo *sjinfo = makeNode(SpecialJoinInfo);
2082 : : Relids clause_relids;
2083 : : Relids strict_relids;
2084 : : Relids min_lefthand;
2085 : : Relids min_righthand;
2086 : : Relids commute_below_l;
2087 : : Relids commute_below_r;
2088 : : ListCell *l;
2089 : :
2090 : : /*
2091 : : * We should not see RIGHT JOIN here because left/right were switched
2092 : : * earlier
2093 : : */
2094 [ - + ]: 27140 : Assert(jointype != JOIN_INNER);
2095 [ - + ]: 27140 : Assert(jointype != JOIN_RIGHT);
2096 : :
2097 : : /*
2098 : : * Presently the executor cannot support FOR [KEY] UPDATE/SHARE marking of
2099 : : * rels appearing on the nullable side of an outer join. (It's somewhat
2100 : : * unclear what that would mean, anyway: what should we mark when a result
2101 : : * row is generated from no element of the nullable relation?) So,
2102 : : * complain if any nullable rel is FOR [KEY] UPDATE/SHARE.
2103 : : *
2104 : : * You might be wondering why this test isn't made far upstream in the
2105 : : * parser. It's because the parser hasn't got enough info --- consider
2106 : : * FOR UPDATE applied to a view. Only after rewriting and flattening do
2107 : : * we know whether the view contains an outer join.
2108 : : *
2109 : : * We use the original RowMarkClause list here; the PlanRowMark list would
2110 : : * list everything.
2111 : : */
7040 2112 [ + + + + : 27162 : foreach(l, root->parse->rowMarks)
+ + ]
2113 : : {
2114 : 22 : RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2115 : :
2116 [ + - + + ]: 22 : if (bms_is_member(rc->rti, right_rels) ||
6334 2117 [ - + ]: 4 : (jointype == JOIN_FULL && bms_is_member(rc->rti, left_rels)))
7040 tgl@sss.pgh.pa.us 2118 [ # # ]:UBC 0 : ereport(ERROR,
2119 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2120 : : /*------
2121 : : translator: %s is a SQL row locking clause such as FOR UPDATE */
2122 : : errmsg("%s cannot be applied to the nullable side of an outer join",
2123 : : LCS_asString(rc->strength))));
2124 : : }
2125 : :
6334 tgl@sss.pgh.pa.us 2126 :CBC 27140 : sjinfo->syn_lefthand = left_rels;
2127 : 27140 : sjinfo->syn_righthand = right_rels;
2128 : 27140 : sjinfo->jointype = jointype;
1052 2129 : 27140 : sjinfo->ojrelid = ojrelid;
2130 : : /* these fields may get added to later: */
2131 : 27140 : sjinfo->commute_above_l = NULL;
2132 : 27140 : sjinfo->commute_above_r = NULL;
945 2133 : 27140 : sjinfo->commute_below_l = NULL;
2134 : 27140 : sjinfo->commute_below_r = NULL;
2135 : :
1791 2136 : 27140 : compute_semijoin_info(root, sjinfo, clause);
2137 : :
2138 : : /* If it's a full join, no need to be very smart */
6334 2139 [ + + ]: 27140 : if (jointype == JOIN_FULL)
2140 : : {
2141 : 517 : sjinfo->min_lefthand = bms_copy(left_rels);
2142 : 517 : sjinfo->min_righthand = bms_copy(right_rels);
3101 2143 : 517 : sjinfo->lhs_strict = false; /* don't care about this */
6334 2144 : 517 : return sjinfo;
2145 : : }
2146 : :
2147 : : /*
2148 : : * Retrieve all relids mentioned within the join clause.
2149 : : */
1791 2150 : 26623 : clause_relids = pull_varnos(root, (Node *) clause);
2151 : :
2152 : : /*
2153 : : * For which relids is the clause strict, ie, it cannot succeed if the
2154 : : * rel's columns are all NULL?
2155 : : */
6334 2156 : 26623 : strict_relids = find_nonnullable_rels((Node *) clause);
2157 : :
2158 : : /* Remember whether the clause is strict for any LHS relations */
2159 : 26623 : sjinfo->lhs_strict = bms_overlap(strict_relids, left_rels);
2160 : :
2161 : : /*
2162 : : * Required LHS always includes the LHS rels mentioned in the clause. We
2163 : : * may have to add more rels based on lower outer joins; see below.
2164 : : */
6683 2165 : 26623 : min_lefthand = bms_intersect(clause_relids, left_rels);
2166 : :
2167 : : /*
2168 : : * Similarly for required RHS. But here, we must also include any lower
2169 : : * inner joins, to ensure we don't try to commute with any of them.
2170 : : */
2171 : 26623 : min_righthand = bms_int_members(bms_union(clause_relids, inner_join_rels),
2172 : : right_rels);
2173 : :
2174 : : /*
2175 : : * Now check previous outer joins for ordering restrictions.
2176 : : *
2177 : : * commute_below_l and commute_below_r accumulate the relids of lower
2178 : : * outer joins that we think this one can commute with. These decisions
2179 : : * are just tentative within this loop, since we might find an
2180 : : * intermediate outer join that prevents commutation. Surviving relids
2181 : : * will get merged into the SpecialJoinInfo structs afterwards.
2182 : : */
1046 2183 : 26623 : commute_below_l = commute_below_r = NULL;
6334 2184 [ + + + + : 35484 : foreach(l, root->join_info_list)
+ + ]
2185 : : {
2186 : 8861 : SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l);
2187 : : bool have_unsafe_phvs;
2188 : :
2189 : : /*
2190 : : * A full join is an optimization barrier: we can't associate into or
2191 : : * out of it. Hence, if it overlaps either LHS or RHS of the current
2192 : : * rel, expand that side's min relset to cover the whole full join.
2193 : : */
2194 [ + + ]: 8861 : if (otherinfo->jointype == JOIN_FULL)
2195 : : {
1046 2196 [ - + ]: 32 : Assert(otherinfo->ojrelid != 0);
3527 2197 [ + + - + ]: 47 : if (bms_overlap(left_rels, otherinfo->syn_lefthand) ||
2198 : 15 : bms_overlap(left_rels, otherinfo->syn_righthand))
2199 : : {
2200 : 17 : min_lefthand = bms_add_members(min_lefthand,
2201 : 17 : otherinfo->syn_lefthand);
2202 : 17 : min_lefthand = bms_add_members(min_lefthand,
2203 : 17 : otherinfo->syn_righthand);
1046 2204 : 17 : min_lefthand = bms_add_member(min_lefthand,
2205 : 17 : otherinfo->ojrelid);
2206 : : }
3527 2207 [ + + - + ]: 49 : if (bms_overlap(right_rels, otherinfo->syn_lefthand) ||
2208 : 17 : bms_overlap(right_rels, otherinfo->syn_righthand))
2209 : : {
2210 : 15 : min_righthand = bms_add_members(min_righthand,
2211 : 15 : otherinfo->syn_lefthand);
2212 : 15 : min_righthand = bms_add_members(min_righthand,
2213 : 15 : otherinfo->syn_righthand);
1046 2214 : 15 : min_righthand = bms_add_member(min_righthand,
2215 : 15 : otherinfo->ojrelid);
2216 : : }
2217 : : /* Needn't do anything else with the full join */
7302 2218 : 32 : continue;
2219 : : }
2220 : :
2221 : : /*
2222 : : * If our join condition contains any PlaceHolderVars that need to be
2223 : : * evaluated above the lower OJ, then we can't commute with it.
2224 : : */
1052 2225 [ + + ]: 8829 : if (otherinfo->ojrelid != 0)
2226 : : have_unsafe_phvs =
2227 : 8652 : contain_placeholder_references_to(root,
2228 : : (Node *) clause,
2229 : 8652 : otherinfo->ojrelid);
2230 : : else
2231 : 177 : have_unsafe_phvs = false;
2232 : :
2233 : : /*
2234 : : * For a lower OJ in our LHS, if our join condition uses the lower
2235 : : * join's RHS and is not strict for that rel, we must preserve the
2236 : : * ordering of the two OJs, so add lower OJ's full syntactic relset to
2237 : : * min_lefthand. (We must use its full syntactic relset, not just its
2238 : : * min_lefthand + min_righthand. This is because there might be other
2239 : : * OJs below this one that this one can commute with, but we cannot
2240 : : * commute with them if we don't with this one.) Also, if we have
2241 : : * unsafe PHVs or the current join is a semijoin or antijoin, we must
2242 : : * preserve ordering regardless of strictness.
2243 : : *
2244 : : * Note: I believe we have to insist on being strict for at least one
2245 : : * rel in the lower OJ's min_righthand, not its whole syn_righthand.
2246 : : *
2247 : : * When we don't need to preserve ordering, check to see if outer join
2248 : : * identity 3 applies, and if so, remove the lower OJ's ojrelid from
2249 : : * our min_lefthand so that commutation is allowed.
2250 : : */
6137 2251 [ + + ]: 8829 : if (bms_overlap(left_rels, otherinfo->syn_righthand))
2252 : : {
2253 [ + + + + ]: 8403 : if (bms_overlap(clause_relids, otherinfo->syn_righthand) &&
1052 2254 [ + - ]: 2433 : (have_unsafe_phvs ||
2255 [ + - ]: 2433 : jointype == JOIN_SEMI || jointype == JOIN_ANTI ||
6137 2256 [ + + ]: 2433 : !bms_overlap(strict_relids, otherinfo->min_righthand)))
2257 : : {
2258 : : /* Preserve ordering */
2259 : 21 : min_lefthand = bms_add_members(min_lefthand,
2260 : 21 : otherinfo->syn_lefthand);
2261 : 21 : min_lefthand = bms_add_members(min_lefthand,
2262 : 21 : otherinfo->syn_righthand);
1052 2263 [ + - ]: 21 : if (otherinfo->ojrelid != 0)
2264 : 21 : min_lefthand = bms_add_member(min_lefthand,
2265 : 21 : otherinfo->ojrelid);
2266 : : }
2267 [ + + ]: 8382 : else if (jointype == JOIN_LEFT &&
2268 [ + + + + ]: 16124 : otherinfo->jointype == JOIN_LEFT &&
1041 2269 : 8061 : bms_overlap(strict_relids, otherinfo->min_righthand) &&
2270 [ + + ]: 2418 : !bms_overlap(clause_relids, otherinfo->syn_lefthand))
2271 : : {
2272 : : /* Identity 3 applies, so remove the ordering restriction */
1052 2273 : 2391 : min_lefthand = bms_del_member(min_lefthand, otherinfo->ojrelid);
2274 : : /* Record the (still tentative) commutability relationship */
2275 : : commute_below_l =
1046 2276 : 2391 : bms_add_member(commute_below_l, otherinfo->ojrelid);
2277 : : }
2278 : : }
2279 : :
2280 : : /*
2281 : : * For a lower OJ in our RHS, if our join condition does not use the
2282 : : * lower join's RHS and the lower OJ's join condition is strict, we
2283 : : * can interchange the ordering of the two OJs; otherwise we must add
2284 : : * the lower OJ's full syntactic relset to min_righthand.
2285 : : *
2286 : : * Also, if our join condition does not use the lower join's LHS
2287 : : * either, force the ordering to be preserved. Otherwise we can end
2288 : : * up with SpecialJoinInfos with identical min_righthands, which can
2289 : : * confuse join_is_legal (see discussion in backend/optimizer/README).
2290 : : *
2291 : : * Also, we must preserve ordering anyway if we have unsafe PHVs, or
2292 : : * if either this join or the lower OJ is a semijoin or antijoin.
2293 : : *
2294 : : * When we don't need to preserve ordering, check to see if outer join
2295 : : * identity 3 applies, and if so, remove the lower OJ's ojrelid from
2296 : : * our min_righthand so that commutation is allowed.
2297 : : */
6683 2298 [ + + ]: 8829 : if (bms_overlap(right_rels, otherinfo->syn_righthand))
2299 : : {
2300 [ + + ]: 383 : if (bms_overlap(clause_relids, otherinfo->syn_righthand) ||
3786 2301 [ + + + - ]: 359 : !bms_overlap(clause_relids, otherinfo->min_lefthand) ||
1052 2302 [ + + ]: 203 : have_unsafe_phvs ||
6068 2303 [ + + ]: 155 : jointype == JOIN_SEMI ||
3889 2304 : 152 : jointype == JOIN_ANTI ||
5993 2305 [ + + ]: 152 : otherinfo->jointype == JOIN_SEMI ||
6137 2306 [ + - ]: 122 : otherinfo->jointype == JOIN_ANTI ||
1052 2307 [ + + ]: 122 : !otherinfo->lhs_strict)
2308 : : {
2309 : : /* Preserve ordering */
6683 2310 : 273 : min_righthand = bms_add_members(min_righthand,
2311 : 273 : otherinfo->syn_lefthand);
2312 : 273 : min_righthand = bms_add_members(min_righthand,
2313 : 273 : otherinfo->syn_righthand);
1052 2314 [ + + ]: 273 : if (otherinfo->ojrelid != 0)
2315 : 195 : min_righthand = bms_add_member(min_righthand,
2316 : 195 : otherinfo->ojrelid);
2317 : : }
2318 [ + - ]: 110 : else if (jointype == JOIN_LEFT &&
2319 [ + - ]: 110 : otherinfo->jointype == JOIN_LEFT &&
2320 [ + - ]: 110 : otherinfo->lhs_strict)
2321 : : {
2322 : : /* Identity 3 applies, so remove the ordering restriction */
2323 : 110 : min_righthand = bms_del_member(min_righthand,
2324 : 110 : otherinfo->ojrelid);
2325 : : /* Record the (still tentative) commutability relationship */
2326 : : commute_below_r =
1046 2327 : 110 : bms_add_member(commute_below_r, otherinfo->ojrelid);
2328 : : }
2329 : : }
2330 : : }
2331 : :
2332 : : /*
2333 : : * Examine PlaceHolderVars. If a PHV is supposed to be evaluated within
2334 : : * this join's nullable side, then ensure that min_righthand contains the
2335 : : * full eval_at set of the PHV. This ensures that the PHV actually can be
2336 : : * evaluated within the RHS. Note that this works only because we should
2337 : : * already have determined the final eval_at level for any PHV
2338 : : * syntactically within this join.
2339 : : */
5559 2340 [ + + + + : 27341 : foreach(l, root->placeholder_list)
+ + ]
2341 : : {
2342 : 718 : PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
2343 : 718 : Relids ph_syn_level = phinfo->ph_var->phrels;
2344 : :
2345 : : /* Ignore placeholder if it didn't syntactically come from RHS */
2346 [ + + ]: 718 : if (!bms_is_subset(ph_syn_level, right_rels))
2347 : 260 : continue;
2348 : :
2349 : : /* Else, prevent join from being formed before we eval the PHV */
2350 : 458 : min_righthand = bms_add_members(min_righthand, phinfo->ph_eval_at);
2351 : : }
2352 : :
2353 : : /*
2354 : : * If we found nothing to put in min_lefthand, punt and make it the full
2355 : : * LHS, to avoid having an empty min_lefthand which will confuse later
2356 : : * processing. (We don't try to be smart about such cases, just correct.)
2357 : : * Likewise for min_righthand.
2358 : : */
6683 2359 [ + + ]: 26623 : if (bms_is_empty(min_lefthand))
2360 : 807 : min_lefthand = bms_copy(left_rels);
3786 2361 [ + + ]: 26623 : if (bms_is_empty(min_righthand))
2362 : 337 : min_righthand = bms_copy(right_rels);
2363 : :
2364 : : /* Now they'd better be nonempty */
6683 2365 [ - + ]: 26623 : Assert(!bms_is_empty(min_lefthand));
2366 [ - + ]: 26623 : Assert(!bms_is_empty(min_righthand));
2367 : : /* Shouldn't overlap either */
2368 [ - + ]: 26623 : Assert(!bms_overlap(min_lefthand, min_righthand));
2369 : :
6334 2370 : 26623 : sjinfo->min_lefthand = min_lefthand;
2371 : 26623 : sjinfo->min_righthand = min_righthand;
2372 : :
2373 : : /*
2374 : : * Now that we've identified the correct min_lefthand and min_righthand,
2375 : : * any commute_below_l or commute_below_r relids that have not gotten
2376 : : * added back into those sets (due to intervening outer joins) are indeed
2377 : : * commutable with this one.
2378 : : *
2379 : : * First, delete any subsequently-added-back relids (this is easier than
2380 : : * maintaining commute_below_l/r precisely through all the above).
2381 : : */
945 2382 : 26623 : commute_below_l = bms_del_members(commute_below_l, min_lefthand);
2383 : 26623 : commute_below_r = bms_del_members(commute_below_r, min_righthand);
2384 : :
2385 : : /* Anything left? */
1046 2386 [ + + + + ]: 26623 : if (commute_below_l || commute_below_r)
2387 : : {
2388 : : /* Yup, so we must update the derived data in the SpecialJoinInfos */
945 2389 : 2462 : sjinfo->commute_below_l = commute_below_l;
2390 : 2462 : sjinfo->commute_below_r = commute_below_r;
2391 [ + - + + : 5393 : foreach(l, root->join_info_list)
+ + ]
2392 : : {
2393 : 2931 : SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l);
2394 : :
2395 [ + + ]: 2931 : if (bms_is_member(otherinfo->ojrelid, commute_below_l))
2396 : 2391 : otherinfo->commute_above_l =
2397 : 2391 : bms_add_member(otherinfo->commute_above_l, ojrelid);
2398 [ + + ]: 540 : else if (bms_is_member(otherinfo->ojrelid, commute_below_r))
2399 : 95 : otherinfo->commute_above_r =
2400 : 95 : bms_add_member(otherinfo->commute_above_r, ojrelid);
2401 : : }
2402 : : }
2403 : :
6334 2404 : 26623 : return sjinfo;
2405 : : }
2406 : :
2407 : : /*
2408 : : * compute_semijoin_info
2409 : : * Fill semijoin-related fields of a new SpecialJoinInfo
2410 : : *
2411 : : * Note: this relies on only the jointype and syn_righthand fields of the
2412 : : * SpecialJoinInfo; the rest may not be set yet.
2413 : : */
2414 : : static void
1791 2415 : 27140 : compute_semijoin_info(PlannerInfo *root, SpecialJoinInfo *sjinfo, List *clause)
2416 : : {
2417 : : List *semi_operators;
2418 : : List *semi_rhs_exprs;
2419 : : bool all_btree;
2420 : : bool all_hash;
2421 : : ListCell *lc;
2422 : :
2423 : : /* Initialize semijoin-related fields in case we can't unique-ify */
3934 2424 : 27140 : sjinfo->semi_can_btree = false;
2425 : 27140 : sjinfo->semi_can_hash = false;
2426 : 27140 : sjinfo->semi_operators = NIL;
2427 : 27140 : sjinfo->semi_rhs_exprs = NIL;
2428 : :
2429 : : /* Nothing more to do if it's not a semijoin */
2430 [ + + ]: 27140 : if (sjinfo->jointype != JOIN_SEMI)
2431 : 24569 : return;
2432 : :
2433 : : /*
2434 : : * Look to see whether the semijoin's join quals consist of AND'ed
2435 : : * equality operators, with (only) RHS variables on only one side of each
2436 : : * one. If so, we can figure out how to enforce uniqueness for the RHS.
2437 : : *
2438 : : * Note that the input clause list is the list of quals that are
2439 : : * *syntactically* associated with the semijoin, which in practice means
2440 : : * the synthesized comparison list for an IN or the WHERE of an EXISTS.
2441 : : * Particularly in the latter case, it might contain clauses that aren't
2442 : : * *semantically* associated with the join, but refer to just one side or
2443 : : * the other. We can ignore such clauses here, as they will just drop
2444 : : * down to be processed within one side or the other. (It is okay to
2445 : : * consider only the syntactically-associated clauses here because for a
2446 : : * semijoin, no higher-level quals could refer to the RHS, and so there
2447 : : * can be no other quals that are semantically associated with this join.
2448 : : * We do things this way because it is useful to have the set of potential
2449 : : * unique-ification expressions before we can extract the list of quals
2450 : : * that are actually semantically associated with the particular join.)
2451 : : *
2452 : : * Note that the semi_operators list consists of the joinqual operators
2453 : : * themselves (but commuted if needed to put the RHS value on the right).
2454 : : * These could be cross-type operators, in which case the operator
2455 : : * actually needed for uniqueness is a related single-type operator. We
2456 : : * assume here that that operator will be available from the btree or hash
2457 : : * opclass when the time comes ... if not, create_unique_plan() will fail.
2458 : : */
2459 : 2571 : semi_operators = NIL;
2460 : 2571 : semi_rhs_exprs = NIL;
2461 : 2571 : all_btree = true;
2462 : 2571 : all_hash = enable_hashagg; /* don't consider hash if not enabled */
2463 [ + - + + : 5327 : foreach(lc, clause)
+ + ]
2464 : : {
2465 : 2813 : OpExpr *op = (OpExpr *) lfirst(lc);
2466 : : Oid opno;
2467 : : Node *left_expr;
2468 : : Node *right_expr;
2469 : : Relids left_varnos;
2470 : : Relids right_varnos;
2471 : : Relids all_varnos;
2472 : : Oid opinputtype;
2473 : :
2474 : : /* Is it a binary opclause? */
2475 [ + + - + ]: 5572 : if (!IsA(op, OpExpr) ||
2476 : 2759 : list_length(op->args) != 2)
2477 : : {
2478 : : /* No, but does it reference both sides? */
1791 2479 : 54 : all_varnos = pull_varnos(root, (Node *) op);
3934 2480 [ + + + + ]: 102 : if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
2481 : 48 : bms_is_subset(all_varnos, sjinfo->syn_righthand))
2482 : : {
2483 : : /*
2484 : : * Clause refers to only one rel, so ignore it --- unless it
2485 : : * contains volatile functions, in which case we'd better
2486 : : * punt.
2487 : : */
2488 [ - + ]: 48 : if (contain_volatile_functions((Node *) op))
2489 : 57 : return;
2490 : 48 : continue;
2491 : : }
2492 : : /* Non-operator clause referencing both sides, must punt */
2493 : 6 : return;
2494 : : }
2495 : :
2496 : : /* Extract data from binary opclause */
2497 : 2759 : opno = op->opno;
2498 : 2759 : left_expr = linitial(op->args);
2499 : 2759 : right_expr = lsecond(op->args);
1791 2500 : 2759 : left_varnos = pull_varnos(root, left_expr);
2501 : 2759 : right_varnos = pull_varnos(root, right_expr);
3934 2502 : 2759 : all_varnos = bms_union(left_varnos, right_varnos);
2503 : 2759 : opinputtype = exprType(left_expr);
2504 : :
2505 : : /* Does it reference both sides? */
2506 [ + + + + ]: 5508 : if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
2507 : 2749 : bms_is_subset(all_varnos, sjinfo->syn_righthand))
2508 : : {
2509 : : /*
2510 : : * Clause refers to only one rel, so ignore it --- unless it
2511 : : * contains volatile functions, in which case we'd better punt.
2512 : : */
2513 [ - + ]: 65 : if (contain_volatile_functions((Node *) op))
3934 tgl@sss.pgh.pa.us 2514 :UBC 0 : return;
3934 tgl@sss.pgh.pa.us 2515 :CBC 65 : continue;
2516 : : }
2517 : :
2518 : : /* check rel membership of arguments */
2519 [ + - + + ]: 5388 : if (!bms_is_empty(right_varnos) &&
2520 : 2694 : bms_is_subset(right_varnos, sjinfo->syn_righthand) &&
2521 [ + - ]: 2464 : !bms_overlap(left_varnos, sjinfo->syn_righthand))
2522 : : {
2523 : : /* typical case, right_expr is RHS variable */
2524 : : }
2525 [ + - + + ]: 460 : else if (!bms_is_empty(left_varnos) &&
2526 : 230 : bms_is_subset(left_varnos, sjinfo->syn_righthand) &&
2527 [ + - ]: 227 : !bms_overlap(right_varnos, sjinfo->syn_righthand))
2528 : : {
2529 : : /* flipped case, left_expr is RHS variable */
2530 : 227 : opno = get_commutator(opno);
2531 [ - + ]: 227 : if (!OidIsValid(opno))
3934 tgl@sss.pgh.pa.us 2532 :UBC 0 : return;
3934 tgl@sss.pgh.pa.us 2533 :CBC 227 : right_expr = left_expr;
2534 : : }
2535 : : else
2536 : : {
2537 : : /* mixed membership of args, punt */
2538 : 3 : return;
2539 : : }
2540 : :
2541 : : /* all operators must be btree equality or hash equality */
2542 [ + - ]: 2691 : if (all_btree)
2543 : : {
2544 : : /* oprcanmerge is considered a hint... */
2545 [ + + - + ]: 5334 : if (!op_mergejoinable(opno, opinputtype) ||
2546 : 2643 : get_mergejoin_opfamilies(opno) == NIL)
2547 : 48 : all_btree = false;
2548 : : }
2549 [ + + ]: 2691 : if (all_hash)
2550 : : {
2551 : : /* ... but oprcanhash had better be correct */
2552 [ + + ]: 2655 : if (!op_hashjoinable(opno, opinputtype))
2553 : 48 : all_hash = false;
2554 : : }
2555 [ + + + - ]: 2691 : if (!(all_btree || all_hash))
2556 : 48 : return;
2557 : :
2558 : : /* so far so good, keep building lists */
2559 : 2643 : semi_operators = lappend_oid(semi_operators, opno);
2560 : 2643 : semi_rhs_exprs = lappend(semi_rhs_exprs, copyObject(right_expr));
2561 : : }
2562 : :
2563 : : /* Punt if we didn't find at least one column to unique-ify */
2564 [ + + ]: 2514 : if (semi_rhs_exprs == NIL)
2565 : 6 : return;
2566 : :
2567 : : /*
2568 : : * The expressions we'd need to unique-ify mustn't be volatile.
2569 : : */
2570 [ - + ]: 2508 : if (contain_volatile_functions((Node *) semi_rhs_exprs))
3934 tgl@sss.pgh.pa.us 2571 :UBC 0 : return;
2572 : :
2573 : : /*
2574 : : * If we get here, we can unique-ify the semijoin's RHS using at least one
2575 : : * of sorting and hashing. Save the information about how to do that.
2576 : : */
3934 tgl@sss.pgh.pa.us 2577 :CBC 2508 : sjinfo->semi_can_btree = all_btree;
2578 : 2508 : sjinfo->semi_can_hash = all_hash;
2579 : 2508 : sjinfo->semi_operators = semi_operators;
2580 : 2508 : sjinfo->semi_rhs_exprs = semi_rhs_exprs;
2581 : : }
2582 : :
2583 : : /*
2584 : : * deconstruct_distribute_oj_quals
2585 : : * Adjust LEFT JOIN quals to be suitable for commuted-left-join cases,
2586 : : * then push them into the joinqual lists and EquivalenceClass structures.
2587 : : *
2588 : : * This runs immediately after we've completed the deconstruct_distribute scan.
2589 : : * jtitems contains all the JoinTreeItems (in depth-first order), and jtitem
2590 : : * is one that has postponed oj_joinclauses to deal with.
2591 : : */
2592 : : static void
1052 2593 : 21226 : deconstruct_distribute_oj_quals(PlannerInfo *root,
2594 : : List *jtitems,
2595 : : JoinTreeItem *jtitem)
2596 : : {
2597 : 21226 : SpecialJoinInfo *sjinfo = jtitem->sjinfo;
2598 : : Relids qualscope,
2599 : : ojscope,
2600 : : nonnullable_rels;
2601 : :
2602 : : /* Recompute syntactic and semantic scopes of this left join */
2603 : 21226 : qualscope = bms_union(sjinfo->syn_lefthand, sjinfo->syn_righthand);
2604 : 21226 : qualscope = bms_add_member(qualscope, sjinfo->ojrelid);
2605 : 21226 : ojscope = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
2606 : 21226 : nonnullable_rels = sjinfo->syn_lefthand;
2607 : :
2608 : : /*
2609 : : * If this join can commute with any other ones per outer-join identity 3,
2610 : : * and it is the one providing the join clause with flexible semantics,
2611 : : * then we have to generate variants of the join clause with different
2612 : : * nullingrels labeling. Otherwise, just push out the postponed clause
2613 : : * as-is.
2614 : : */
2615 [ - + ]: 21226 : Assert(sjinfo->lhs_strict); /* else we shouldn't be here */
945 2616 [ + + + + ]: 21226 : if (sjinfo->commute_above_r || sjinfo->commute_below_l)
1052 2617 : 2468 : {
2618 : : Relids joins_above;
2619 : : Relids joins_below;
2620 : : Relids incompatible_joins;
2621 : : Relids joins_so_far;
2622 : : List *quals;
2623 : : int save_last_rinfo_serial;
2624 : : ListCell *lc;
2625 : :
2626 : : /* Identify the outer joins this one commutes with */
2627 : 2468 : joins_above = sjinfo->commute_above_r;
945 2628 : 2468 : joins_below = sjinfo->commute_below_l;
2629 : :
2630 : : /*
2631 : : * Generate qual variants with different sets of nullingrels bits.
2632 : : *
2633 : : * We only need bit-sets that correspond to the successively less
2634 : : * deeply syntactically-nested subsets of this join and its
2635 : : * commutators. That's true first because obviously only those forms
2636 : : * of the Vars and PHVs could appear elsewhere in the query, and
2637 : : * second because the outer join identities do not provide a way to
2638 : : * re-order such joins in a way that would require different marking.
2639 : : * (That is, while the current join may commute with several others,
2640 : : * none of those others can commute with each other.) To visit the
2641 : : * interesting joins in syntactic nesting order, we rely on the
2642 : : * jtitems list to be ordered that way.
2643 : : *
2644 : : * We first strip out all the nullingrels bits corresponding to
2645 : : * commuting joins below this one, and then successively put them back
2646 : : * as we crawl up the join stack.
2647 : : */
1052 2648 : 2468 : quals = jtitem->oj_joinclauses;
2649 [ + + ]: 2468 : if (!bms_is_empty(joins_below))
2650 : 2373 : quals = (List *) remove_nulling_relids((Node *) quals,
2651 : : joins_below,
2652 : : NULL);
2653 : :
2654 : : /*
2655 : : * We'll need to mark the lower versions of the quals as not safe to
2656 : : * apply above not-yet-processed joins of the stack. This prevents
2657 : : * possibly applying a cloned qual at the wrong join level.
2658 : : */
937 2659 : 2468 : incompatible_joins = bms_union(joins_below, joins_above);
2660 : 2468 : incompatible_joins = bms_add_member(incompatible_joins,
2661 : 2468 : sjinfo->ojrelid);
2662 : :
2663 : : /*
2664 : : * Each time we produce RestrictInfo(s) from these quals, reset the
2665 : : * last_rinfo_serial counter, so that the RestrictInfos for the "same"
2666 : : * qual condition get identical serial numbers. (This relies on the
2667 : : * fact that we're not changing the qual list in any way that'd affect
2668 : : * the number of RestrictInfos built from it.) This'll allow us to
2669 : : * detect duplicative qual usage later.
2670 : : */
1052 2671 : 2468 : save_last_rinfo_serial = root->last_rinfo_serial;
2672 : :
2673 : 2468 : joins_so_far = NULL;
2674 [ + - + + : 21536 : foreach(lc, jtitems)
+ + ]
2675 : : {
2676 : 19068 : JoinTreeItem *otherjtitem = (JoinTreeItem *) lfirst(lc);
2677 : 19068 : SpecialJoinInfo *othersj = otherjtitem->sjinfo;
2678 : 19068 : bool below_sjinfo = false;
2679 : 19068 : bool above_sjinfo = false;
2680 : : Relids this_qualscope;
2681 : : Relids this_ojscope;
2682 : : bool allow_equivalence,
2683 : : has_clone,
2684 : : is_clone;
2685 : :
2686 [ + + ]: 19068 : if (othersj == NULL)
2687 : 13541 : continue; /* not an outer-join item, ignore */
2688 : :
2689 [ + + ]: 5527 : if (bms_is_member(othersj->ojrelid, joins_below))
2690 : : {
2691 : : /* othersj commutes with sjinfo from below left */
2692 : 2391 : below_sjinfo = true;
2693 : : }
2694 [ + + ]: 3136 : else if (othersj == sjinfo)
2695 : : {
2696 : : /* found our join in syntactic order */
2697 [ - + ]: 2468 : Assert(bms_equal(joins_so_far, joins_below));
2698 : : }
2699 [ + + ]: 668 : else if (bms_is_member(othersj->ojrelid, joins_above))
2700 : : {
2701 : : /* othersj commutes with sjinfo from above */
2702 : 95 : above_sjinfo = true;
2703 : : }
2704 : : else
2705 : : {
2706 : : /* othersj is not relevant, ignore */
2707 : 573 : continue;
2708 : : }
2709 : :
2710 : : /* Reset serial counter for this version of the quals */
2711 : 4954 : root->last_rinfo_serial = save_last_rinfo_serial;
2712 : :
2713 : : /*
2714 : : * When we are looking at joins above sjinfo, we are envisioning
2715 : : * pushing sjinfo to above othersj, so add othersj's nulling bit
2716 : : * before distributing the quals. We should add it to Vars coming
2717 : : * from the current join's LHS: we want to transform the second
2718 : : * form of OJ identity 3 to the first form, in which Vars of
2719 : : * relation B will appear nulled by the syntactically-upper OJ
2720 : : * within the Pbc clause, but those of relation C will not. (In
2721 : : * the notation used by optimizer/README, we're converting a qual
2722 : : * of the form Pbc to Pb*c.) Of course, we must also remove that
2723 : : * bit from the incompatible_joins value, else we'll make a qual
2724 : : * that can't be placed anywhere.
2725 : : */
2726 [ + + ]: 4954 : if (above_sjinfo)
2727 : : {
2728 : : quals = (List *)
2729 : 95 : add_nulling_relids((Node *) quals,
1041 2730 : 95 : sjinfo->syn_lefthand,
1052 2731 : 95 : bms_make_singleton(othersj->ojrelid));
937 2732 : 95 : incompatible_joins = bms_del_member(incompatible_joins,
2733 : 95 : othersj->ojrelid);
2734 : : }
2735 : :
2736 : : /* Compute qualscope and ojscope for this join level */
1052 2737 : 4954 : this_qualscope = bms_union(qualscope, joins_so_far);
2738 : 4954 : this_ojscope = bms_union(ojscope, joins_so_far);
2739 [ + + ]: 4954 : if (above_sjinfo)
2740 : : {
2741 : : /* othersj is not yet in joins_so_far, but we need it */
2742 : 95 : this_qualscope = bms_add_member(this_qualscope,
2743 : 95 : othersj->ojrelid);
2744 : 95 : this_ojscope = bms_add_member(this_ojscope,
2745 : 95 : othersj->ojrelid);
2746 : : /* sjinfo is in joins_so_far, and we don't want it */
2747 : 95 : this_ojscope = bms_del_member(this_ojscope,
2748 : 95 : sjinfo->ojrelid);
2749 : : }
2750 : :
2751 : : /*
2752 : : * We generate EquivalenceClasses only from the first form of the
2753 : : * quals, with the fewest nullingrels bits set. An EC made from
2754 : : * this version of the quals can be useful below the outer-join
2755 : : * nest, whereas versions with some nullingrels bits set would not
2756 : : * be. We cannot generate ECs from more than one version, or
2757 : : * we'll make nonsensical conclusions that Vars with nullingrels
2758 : : * bits set are equal to their versions without. Fortunately,
2759 : : * such ECs wouldn't be very useful anyway, because they'd equate
2760 : : * values not observable outside the join nest. (See
2761 : : * optimizer/README.)
2762 : : *
2763 : : * The first form of the quals is also the only one marked as
2764 : : * has_clone rather than is_clone.
2765 : : */
2766 : 4954 : allow_equivalence = (joins_so_far == NULL);
2767 : 4954 : has_clone = allow_equivalence;
2768 : 4954 : is_clone = !has_clone;
2769 : :
2770 : 4954 : distribute_quals_to_rels(root, quals,
2771 : : otherjtitem,
2772 : : sjinfo,
2773 : : root->qual_security_level,
2774 : : this_qualscope,
2775 : : this_ojscope, nonnullable_rels,
2776 : : bms_copy(incompatible_joins),
2777 : : allow_equivalence,
2778 : : has_clone,
2779 : : is_clone,
2780 : : NULL); /* no more postponement */
2781 : :
2782 : : /*
2783 : : * Adjust qual nulling bits for next level up, if needed. We
2784 : : * don't want to put sjinfo's own bit in at all, and if we're
2785 : : * above sjinfo then we did it already. Here, we should mark all
2786 : : * Vars coming from the lower join's RHS. (Again, we are
2787 : : * converting a qual of the form Pbc to Pb*c, but now we are
2788 : : * putting back bits that were there in the parser output and were
2789 : : * temporarily stripped above.) Update incompatible_joins too.
2790 : : */
2791 [ + + ]: 4954 : if (below_sjinfo)
2792 : : {
2793 : : quals = (List *)
2794 : 2391 : add_nulling_relids((Node *) quals,
1041 2795 : 2391 : othersj->syn_righthand,
1052 2796 : 2391 : bms_make_singleton(othersj->ojrelid));
937 2797 : 2391 : incompatible_joins = bms_del_member(incompatible_joins,
2798 : 2391 : othersj->ojrelid);
2799 : : }
2800 : :
2801 : : /* ... and track joins processed so far */
1052 2802 : 4954 : joins_so_far = bms_add_member(joins_so_far, othersj->ojrelid);
2803 : : }
2804 : : }
2805 : : else
2806 : : {
2807 : : /* No commutation possible, just process the postponed clauses */
2808 : 18758 : distribute_quals_to_rels(root, jtitem->oj_joinclauses,
2809 : : jtitem,
2810 : : sjinfo,
2811 : : root->qual_security_level,
2812 : : qualscope,
2813 : : ojscope, nonnullable_rels,
2814 : : NULL, /* incompatible_relids */
2815 : : true, /* allow_equivalence */
2816 : : false, false, /* not clones */
2817 : : NULL); /* no more postponement */
2818 : : }
2819 : 21226 : }
2820 : :
2821 : :
2822 : : /*****************************************************************************
2823 : : *
2824 : : * QUALIFICATIONS
2825 : : *
2826 : : *****************************************************************************/
2827 : :
2828 : : /*
2829 : : * distribute_quals_to_rels
2830 : : * Convenience routine to apply distribute_qual_to_rels to each element
2831 : : * of an AND'ed list of clauses.
2832 : : */
2833 : : static void
2834 : 431305 : distribute_quals_to_rels(PlannerInfo *root, List *clauses,
2835 : : JoinTreeItem *jtitem,
2836 : : SpecialJoinInfo *sjinfo,
2837 : : Index security_level,
2838 : : Relids qualscope,
2839 : : Relids ojscope,
2840 : : Relids outerjoin_nonnullable,
2841 : : Relids incompatible_relids,
2842 : : bool allow_equivalence,
2843 : : bool has_clone,
2844 : : bool is_clone,
2845 : : List **postponed_oj_qual_list)
2846 : : {
2847 : : ListCell *lc;
2848 : :
2849 [ + + + + : 735660 : foreach(lc, clauses)
+ + ]
2850 : : {
2851 : 304355 : Node *clause = (Node *) lfirst(lc);
2852 : :
2853 : 304355 : distribute_qual_to_rels(root, clause,
2854 : : jtitem,
2855 : : sjinfo,
2856 : : security_level,
2857 : : qualscope,
2858 : : ojscope,
2859 : : outerjoin_nonnullable,
2860 : : incompatible_relids,
2861 : : allow_equivalence,
2862 : : has_clone,
2863 : : is_clone,
2864 : : postponed_oj_qual_list);
2865 : : }
2866 : 431305 : }
2867 : :
2868 : : /*
2869 : : * distribute_qual_to_rels
2870 : : * Add clause information to either the baserestrictinfo or joininfo list
2871 : : * (depending on whether the clause is a join) of each base relation
2872 : : * mentioned in the clause. A RestrictInfo node is created and added to
2873 : : * the appropriate list for each rel. Alternatively, if the clause uses a
2874 : : * mergejoinable operator, enter its left- and right-side expressions into
2875 : : * the query's EquivalenceClasses.
2876 : : *
2877 : : * In some cases, quals will be added to parent jtitems' lateral_clauses
2878 : : * or to postponed_oj_qual_list instead of being processed right away.
2879 : : * These will be dealt with in later calls of deconstruct_distribute.
2880 : : *
2881 : : * 'clause': the qual clause to be distributed
2882 : : * 'jtitem': the JoinTreeItem for the containing jointree node
2883 : : * 'sjinfo': join's SpecialJoinInfo (NULL for an inner join or WHERE clause)
2884 : : * 'security_level': security_level to assign to the qual
2885 : : * 'qualscope': set of base+OJ rels the qual's syntactic scope covers
2886 : : * 'ojscope': NULL if not an outer-join qual, else the minimum set of base+OJ
2887 : : * rels needed to form this join
2888 : : * 'outerjoin_nonnullable': NULL if not an outer-join qual, else the set of
2889 : : * base+OJ rels appearing on the outer (nonnullable) side of the join
2890 : : * (for FULL JOIN this includes both sides of the join, and must in fact
2891 : : * equal qualscope)
2892 : : * 'incompatible_relids': the set of outer-join relid(s) that must not be
2893 : : * computed below this qual. We only bother to compute this for
2894 : : * "clone" quals, otherwise it can be left NULL.
2895 : : * 'allow_equivalence': true if it's okay to convert clause into an
2896 : : * EquivalenceClass
2897 : : * 'has_clone': has_clone property to assign to the qual
2898 : : * 'is_clone': is_clone property to assign to the qual
2899 : : * 'postponed_oj_qual_list': if not NULL, non-degenerate outer join clauses
2900 : : * should be added to this list instead of being processed (list entries
2901 : : * are just the bare clauses)
2902 : : *
2903 : : * 'qualscope' identifies what level of JOIN the qual came from syntactically.
2904 : : * 'ojscope' is needed if we decide to force the qual up to the outer-join
2905 : : * level, which will be ojscope not necessarily qualscope.
2906 : : *
2907 : : * At the time this is called, root->join_info_list must contain entries for
2908 : : * at least those special joins that are syntactically below this qual.
2909 : : * (We now need that only for detection of redundant IS NULL quals.)
2910 : : */
2911 : : static void
7500 2912 : 304355 : distribute_qual_to_rels(PlannerInfo *root, Node *clause,
2913 : : JoinTreeItem *jtitem,
2914 : : SpecialJoinInfo *sjinfo,
2915 : : Index security_level,
2916 : : Relids qualscope,
2917 : : Relids ojscope,
2918 : : Relids outerjoin_nonnullable,
2919 : : Relids incompatible_relids,
2920 : : bool allow_equivalence,
2921 : : bool has_clone,
2922 : : bool is_clone,
2923 : : List **postponed_oj_qual_list)
2924 : : {
2925 : : Relids relids;
2926 : : bool is_pushed_down;
7109 2927 : 304355 : bool pseudoconstant = false;
2928 : : bool maybe_equivalence;
2929 : : bool maybe_outer_join;
2930 : : RestrictInfo *restrictinfo;
2931 : :
2932 : : /*
2933 : : * Retrieve all relids mentioned within the clause.
2934 : : */
1791 2935 : 304355 : relids = pull_varnos(root, clause);
2936 : :
2937 : : /*
2938 : : * In ordinary SQL, a WHERE or JOIN/ON clause can't reference any rels
2939 : : * that aren't within its syntactic scope; however, if we pulled up a
2940 : : * LATERAL subquery then we might find such references in quals that have
2941 : : * been pulled up. We need to treat such quals as belonging to the join
2942 : : * level that includes every rel they reference. Although we could make
2943 : : * pull_up_subqueries() place such quals correctly to begin with, it's
2944 : : * easier to handle it here. When we find a clause that contains Vars
2945 : : * outside its syntactic scope, locate the nearest parent join level that
2946 : : * includes all the required rels and add the clause to that level's
2947 : : * lateral_clauses list. We'll process it when we reach that join level.
2948 : : */
4503 2949 [ + + ]: 304355 : if (!bms_is_subset(relids, qualscope))
2950 : : {
2951 : : JoinTreeItem *pitem;
2952 : :
2953 [ - + ]: 55 : Assert(root->hasLateralRTEs); /* shouldn't happen otherwise */
1052 2954 [ - + ]: 55 : Assert(sjinfo == NULL); /* mustn't postpone past outer join */
1047 2955 [ + - ]: 58 : for (pitem = jtitem->jti_parent; pitem; pitem = pitem->jti_parent)
2956 : : {
2957 [ + + ]: 58 : if (bms_is_subset(relids, pitem->qualscope))
2958 : : {
2959 : 55 : pitem->lateral_clauses = lappend(pitem->lateral_clauses,
2960 : : clause);
2961 : 214366 : return;
2962 : : }
2963 : :
2964 : : /*
2965 : : * We should not be postponing any quals past an outer join. If
2966 : : * this Assert fires, pull_up_subqueries() messed up.
2967 : : */
2968 [ - + ]: 3 : Assert(pitem->sjinfo == NULL);
2969 : : }
1047 tgl@sss.pgh.pa.us 2970 [ # # ]:UBC 0 : elog(ERROR, "failed to postpone qual containing lateral reference");
2971 : : }
2972 : :
2973 : : /*
2974 : : * If it's an outer-join clause, also check that relids is a subset of
2975 : : * ojscope. (This should not fail if the syntactic scope check passed.)
2976 : : */
7302 tgl@sss.pgh.pa.us 2977 [ + + - + ]:CBC 304300 : if (ojscope && !bms_is_subset(relids, ojscope))
6894 bruce@momjian.us 2978 [ # # ]:UBC 0 : elog(ERROR, "JOIN qualification cannot refer to other relations");
2979 : :
2980 : : /*
2981 : : * If the clause is variable-free, our normal heuristic for pushing it
2982 : : * down to just the mentioned rels doesn't work, because there are none.
2983 : : *
2984 : : * If the clause is an outer-join clause, we must force it to the OJ's
2985 : : * semantic level to preserve semantics.
2986 : : *
2987 : : * Otherwise, when the clause contains volatile functions, we force it to
2988 : : * be evaluated at its original syntactic level. This preserves the
2989 : : * expected semantics.
2990 : : *
2991 : : * When the clause contains no volatile functions either, it is actually a
2992 : : * pseudoconstant clause that will not change value during any one
2993 : : * execution of the plan, and hence can be used as a one-time qual in a
2994 : : * gating Result plan node. We put such a clause into the regular
2995 : : * RestrictInfo lists for the moment, but eventually createplan.c will
2996 : : * pull it out and make a gating Result node immediately above whatever
2997 : : * plan node the pseudoconstant clause is assigned to. It's usually best
2998 : : * to put a gating node as high in the plan tree as possible.
2999 : : */
8348 tgl@sss.pgh.pa.us 3000 [ + + ]:CBC 304300 : if (bms_is_empty(relids))
3001 : : {
7109 3002 [ + + ]: 5712 : if (ojscope)
3003 : : {
3004 : : /* clause is attached to outer join, eval it there */
6552 3005 : 202 : relids = bms_copy(ojscope);
3006 : : /* mustn't use as gating qual, so don't mark pseudoconstant */
3007 : : }
1052 3008 [ + + ]: 5510 : else if (contain_volatile_functions(clause))
3009 : : {
3010 : : /* eval at original syntactic level */
6552 3011 : 87 : relids = bms_copy(qualscope);
3012 : : /* again, can't mark pseudoconstant */
3013 : : }
3014 : : else
3015 : : {
3016 : : /*
3017 : : * If we are in the top-level join domain, we can push the qual to
3018 : : * the top of the plan tree. Otherwise, be conservative and eval
3019 : : * it at original syntactic level. (Ideally we'd push it to the
3020 : : * top of the current join domain in all cases, but that causes
3021 : : * problems if we later rearrange outer-join evaluation order.
3022 : : * Pseudoconstant quals below the top level are a pretty odd case,
3023 : : * so it's not clear that it's worth working hard on.)
3024 : : */
1029 3025 [ + + ]: 5423 : if (jtitem->jdomain == (JoinDomain *) linitial(root->join_domains))
3026 : 5393 : relids = bms_copy(jtitem->jdomain->jd_relids);
3027 : : else
3028 : 30 : relids = bms_copy(qualscope);
3029 : : /* mark as gating qual */
1052 3030 : 5423 : pseudoconstant = true;
3031 : : /* tell createplan.c to check for gating quals */
3032 : 5423 : root->hasPseudoConstantQuals = true;
3033 : : }
3034 : : }
3035 : :
3036 : : /*----------
3037 : : * Check to see if clause application must be delayed by outer-join
3038 : : * considerations.
3039 : : *
3040 : : * A word about is_pushed_down: we mark the qual as "pushed down" if
3041 : : * it is (potentially) applicable at a level different from its original
3042 : : * syntactic level. This flag is used to distinguish OUTER JOIN ON quals
3043 : : * from other quals pushed down to the same joinrel. The rules are:
3044 : : * WHERE quals and INNER JOIN quals: is_pushed_down = true.
3045 : : * Non-degenerate OUTER JOIN quals: is_pushed_down = false.
3046 : : * Degenerate OUTER JOIN quals: is_pushed_down = true.
3047 : : * A "degenerate" OUTER JOIN qual is one that doesn't mention the
3048 : : * non-nullable side, and hence can be pushed down into the nullable side
3049 : : * without changing the join result. It is correct to treat it as a
3050 : : * regular filter condition at the level where it is evaluated.
3051 : : *
3052 : : * Note: it is not immediately obvious that a simple boolean is enough
3053 : : * for this: if for some reason we were to attach a degenerate qual to
3054 : : * its original join level, it would need to be treated as an outer join
3055 : : * qual there. However, this cannot happen, because all the rels the
3056 : : * clause mentions must be in the outer join's min_righthand, therefore
3057 : : * the join it needs must be formed before the outer join; and we always
3058 : : * attach quals to the lowest level where they can be evaluated. But
3059 : : * if we were ever to re-introduce a mechanism for delaying evaluation
3060 : : * of "expensive" quals, this area would need work.
3061 : : *
3062 : : * Note: generally, use of is_pushed_down has to go through the macro
3063 : : * RINFO_IS_PUSHED_DOWN, because that flag alone is not always sufficient
3064 : : * to tell whether a clause must be treated as pushed-down in context.
3065 : : * This seems like another reason why it should perhaps be rethought.
3066 : : *----------
3067 : : */
1876 3068 [ + + ]: 304300 : if (bms_overlap(relids, outerjoin_nonnullable))
3069 : : {
3070 : : /*
3071 : : * The qual is attached to an outer join and mentions (some of the)
3072 : : * rels on the nonnullable side, so it's not degenerate. If the
3073 : : * caller wants to postpone handling such clauses, just add it to
3074 : : * postponed_oj_qual_list and return. (The work we've done up to here
3075 : : * will have to be redone later, but there's not much of it.)
3076 : : */
1052 3077 [ + + ]: 53225 : if (postponed_oj_qual_list != NULL)
3078 : : {
3079 : 23581 : *postponed_oj_qual_list = lappend(*postponed_oj_qual_list, clause);
3080 : 23581 : return;
3081 : : }
3082 : :
3083 : : /*
3084 : : * We can't use such a clause to deduce equivalence (the left and
3085 : : * right sides might be unequal above the join because one of them has
3086 : : * gone to NULL) ... but we might be able to use it for more limited
3087 : : * deductions, if it is mergejoinable. So consider adding it to the
3088 : : * lists of set-aside outer-join clauses.
3089 : : */
6552 3090 : 29644 : is_pushed_down = false;
6906 3091 : 29644 : maybe_equivalence = false;
6552 3092 : 29644 : maybe_outer_join = true;
3093 : :
3094 : : /*
3095 : : * Now force the qual to be evaluated exactly at the level of joining
3096 : : * corresponding to the outer join. We cannot let it get pushed down
3097 : : * into the nonnullable side, since then we'd produce no output rows,
3098 : : * rather than the intended single null-extended row, for any
3099 : : * nonnullable-side rows failing the qual.
3100 : : */
7302 3101 [ - + ]: 29644 : Assert(ojscope);
3102 : 29644 : relids = ojscope;
7109 3103 [ - + ]: 29644 : Assert(!pseudoconstant);
3104 : : }
3105 : : else
3106 : : {
3107 : : /*
3108 : : * Normal qual clause or degenerate outer-join clause. Either way, we
3109 : : * can mark it as pushed-down.
3110 : : */
6879 3111 : 251075 : is_pushed_down = true;
3112 : :
3113 : : /*
3114 : : * It's possible that this is an IS NULL clause that's redundant with
3115 : : * a lower antijoin; if so we can just discard it. We need not test
3116 : : * in any of the other cases, because this will only be possible for
3117 : : * pushed-down clauses.
3118 : : */
1052 3119 [ + + ]: 251075 : if (check_redundant_nullability_qual(root, clause))
3120 : 584 : return;
3121 : :
3122 : : /* Feed qual to the equivalence machinery, if allowed by caller */
3123 : 250491 : maybe_equivalence = allow_equivalence;
3124 : :
3125 : : /*
3126 : : * Since it doesn't mention the LHS, it's certainly not useful as a
3127 : : * set-aside OJ clause, even if it's in an OJ.
3128 : : */
7473 3129 : 250491 : maybe_outer_join = false;
3130 : : }
3131 : :
3132 : : /*
3133 : : * Build the RestrictInfo node itself.
3134 : : */
1791 3135 : 280135 : restrictinfo = make_restrictinfo(root,
3136 : : (Expr *) clause,
3137 : : is_pushed_down,
3138 : : has_clone,
3139 : : is_clone,
3140 : : pseudoconstant,
3141 : : security_level,
3142 : : relids,
3143 : : incompatible_relids,
3144 : : outerjoin_nonnullable);
3145 : :
3146 : : /*
3147 : : * If it's a join clause, add vars used in the clause to targetlists of
3148 : : * their relations, so that they will be emitted by the plan nodes that
3149 : : * scan those relations (else they won't be available at the join node!).
3150 : : *
3151 : : * Normally we mark the vars as needed at the join identified by "relids".
3152 : : * However, if this is a clone clause then ignore the outer-join relids in
3153 : : * that set. Otherwise, vars appearing in a cloned clause would end up
3154 : : * marked as having to propagate to the highest one of the commuting
3155 : : * joins, which would often be an overestimate. For such clauses, correct
3156 : : * var propagation is ensured by making ojscope include input rels from
3157 : : * both sides of the join.
3158 : : *
3159 : : * See also rebuild_joinclause_attr_needed, which has to partially repeat
3160 : : * this work after removal of an outer join.
3161 : : *
3162 : : * Note: if the clause gets absorbed into an EquivalenceClass then this
3163 : : * may be unnecessary, but for now we have to do it to cover the case
3164 : : * where the EC becomes ec_broken and we end up reinserting the original
3165 : : * clauses into the plan.
3166 : : */
6906 3167 [ + + ]: 280135 : if (bms_membership(relids) == BMS_MULTIPLE)
3168 : : {
5272 3169 : 82799 : List *vars = pull_var_clause(clause,
3170 : : PVC_RECURSE_AGGREGATES |
3171 : : PVC_RECURSE_WINDOWFUNCS |
3172 : : PVC_INCLUDE_PLACEHOLDERS);
3173 : : Relids where_needed;
3174 : :
1052 3175 [ + + ]: 82799 : if (is_clone)
3176 : 2697 : where_needed = bms_intersect(relids, root->all_baserels);
3177 : : else
3178 : 80102 : where_needed = relids;
3179 : 82799 : add_vars_to_targetlist(root, vars, where_needed);
6906 3180 : 82799 : list_free(vars);
3181 : : }
3182 : :
3183 : : /*
3184 : : * We check "mergejoinability" of every clause, not only join clauses,
3185 : : * because we want to know about equivalences between vars of the same
3186 : : * relation, or between vars and consts.
3187 : : */
3188 : 280135 : check_mergejoinable(restrictinfo);
3189 : :
3190 : : /*
3191 : : * If it is a true equivalence clause, send it to the EquivalenceClass
3192 : : * machinery. We do *not* attach it directly to any restriction or join
3193 : : * lists. The EC code will propagate it to the appropriate places later.
3194 : : *
3195 : : * If the clause has a mergejoinable operator, yet isn't an equivalence
3196 : : * because it is an outer-join clause, the EC code may still be able to do
3197 : : * something with it. We add it to appropriate lists for further
3198 : : * consideration later. Specifically:
3199 : : *
3200 : : * If it is a left or right outer-join qualification that relates the two
3201 : : * sides of the outer join (no funny business like leftvar1 = leftvar2 +
3202 : : * rightvar), we add it to root->left_join_clauses or
3203 : : * root->right_join_clauses according to which side the nonnullable
3204 : : * variable appears on.
3205 : : *
3206 : : * If it is a full outer-join qualification, we add it to
3207 : : * root->full_join_clauses. (Ideally we'd discard cases that aren't
3208 : : * leftvar = rightvar, as we do for left/right joins, but this routine
3209 : : * doesn't have the info needed to do that; and the current usage of the
3210 : : * full_join_clauses list doesn't require that, so it's not currently
3211 : : * worth complicating this routine's API to make it possible.)
3212 : : *
3213 : : * If none of the above hold, pass it off to
3214 : : * distribute_restrictinfo_to_rels().
3215 : : *
3216 : : * In all cases, it's important to initialize the left_ec and right_ec
3217 : : * fields of a mergejoinable clause, so that all possibly mergejoinable
3218 : : * expressions have representations in EquivalenceClasses. If
3219 : : * process_equivalence is successful, it will take care of that;
3220 : : * otherwise, we have to call initialize_mergeclause_eclasses to do it.
3221 : : */
3222 [ + + ]: 280135 : if (restrictinfo->mergeopfamilies)
3223 : : {
3224 [ + + ]: 190733 : if (maybe_equivalence)
3225 : : {
1047 3226 [ + + ]: 161845 : if (process_equivalence(root, &restrictinfo, jtitem->jdomain))
6906 3227 : 161714 : return;
3228 : : /* EC rejected it, so set left_ec/right_ec the hard way ... */
2992 3229 [ + + ]: 131 : if (restrictinfo->mergeopfamilies) /* EC might have changed this */
3230 : 104 : initialize_mergeclause_eclasses(root, restrictinfo);
3231 : : /* ... and fall through to distribute_restrictinfo_to_rels */
3232 : : }
7473 3233 [ + - + + ]: 28888 : else if (maybe_outer_join && restrictinfo->can_join)
3234 : : {
3235 : : /* we need to set up left_ec/right_ec the hard way */
5528 3236 : 28530 : initialize_mergeclause_eclasses(root, restrictinfo);
3237 : : /* now see if it should go to any outer-join lists */
1052 3238 [ - + ]: 28530 : Assert(sjinfo != NULL);
7473 3239 [ + + ]: 28530 : if (bms_is_subset(restrictinfo->left_relids,
3240 : 14087 : outerjoin_nonnullable) &&
3241 [ + + ]: 14087 : !bms_overlap(restrictinfo->right_relids,
3242 : : outerjoin_nonnullable))
3243 : : {
3244 : : /* we have outervar = innervar */
1052 3245 : 13437 : OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
3246 : :
3247 : 13437 : ojcinfo->rinfo = restrictinfo;
3248 : 13437 : ojcinfo->sjinfo = sjinfo;
7473 3249 : 13437 : root->left_join_clauses = lappend(root->left_join_clauses,
3250 : : ojcinfo);
6906 3251 : 13437 : return;
3252 : : }
3253 [ + + ]: 15093 : if (bms_is_subset(restrictinfo->right_relids,
6607 bruce@momjian.us 3254 : 15013 : outerjoin_nonnullable) &&
3255 [ + + ]: 15013 : !bms_overlap(restrictinfo->left_relids,
3256 : : outerjoin_nonnullable))
3257 : : {
3258 : : /* we have innervar = outervar */
1052 tgl@sss.pgh.pa.us 3259 : 14363 : OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
3260 : :
3261 : 14363 : ojcinfo->rinfo = restrictinfo;
3262 : 14363 : ojcinfo->sjinfo = sjinfo;
7473 3263 : 14363 : root->right_join_clauses = lappend(root->right_join_clauses,
3264 : : ojcinfo);
6906 3265 : 14363 : return;
3266 : : }
1052 3267 [ + + ]: 730 : if (sjinfo->jointype == JOIN_FULL)
3268 : : {
3269 : : /* FULL JOIN (above tests cannot match in this case) */
3270 : 632 : OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
3271 : :
3272 : 632 : ojcinfo->rinfo = restrictinfo;
3273 : 632 : ojcinfo->sjinfo = sjinfo;
7473 3274 : 632 : root->full_join_clauses = lappend(root->full_join_clauses,
3275 : : ojcinfo);
6906 3276 : 632 : return;
3277 : : }
3278 : : /* nope, so fall through to distribute_restrictinfo_to_rels */
3279 : : }
3280 : : else
3281 : : {
3282 : : /* we still need to set up left_ec/right_ec */
5528 3283 : 358 : initialize_mergeclause_eclasses(root, restrictinfo);
3284 : : }
3285 : : }
3286 : :
3287 : : /* No EC special case applies, so push it into the clause lists */
6906 3288 : 89989 : distribute_restrictinfo_to_rels(root, restrictinfo);
3289 : : }
3290 : :
3291 : : /*
3292 : : * check_redundant_nullability_qual
3293 : : * Check to see if the qual is an IS NULL qual that is redundant with
3294 : : * a lower JOIN_ANTI join.
3295 : : *
3296 : : * We want to suppress redundant IS NULL quals, not so much to save cycles
3297 : : * as to avoid generating bogus selectivity estimates for them. So if
3298 : : * redundancy is detected here, distribute_qual_to_rels() just throws away
3299 : : * the qual.
3300 : : */
3301 : : static bool
6334 3302 : 251075 : check_redundant_nullability_qual(PlannerInfo *root, Node *clause)
3303 : : {
3304 : : Var *forced_null_var;
3305 : : ListCell *lc;
3306 : :
3307 : : /* Check for IS NULL, and identify the Var forced to NULL */
3308 : 251075 : forced_null_var = find_forced_null_var(clause);
3309 [ + + ]: 251075 : if (forced_null_var == NULL)
3310 : 249711 : return false;
3311 : :
3312 : : /*
3313 : : * If the Var comes from the nullable side of a lower antijoin, the IS
3314 : : * NULL condition is necessarily true. If it's not nulled by anything,
3315 : : * there is no point in searching the join_info_list. Otherwise, we need
3316 : : * to find out whether the nulling rel is an antijoin.
3317 : : */
1052 3318 [ + + ]: 1364 : if (forced_null_var->varnullingrels == NULL)
3319 : 724 : return false;
3320 : :
6334 3321 [ + - + + : 718 : foreach(lc, root->join_info_list)
+ + ]
3322 : : {
3323 : 662 : SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
3324 : :
3325 : : /*
3326 : : * This test will not succeed if sjinfo->ojrelid is zero, which is
3327 : : * possible for an antijoin that was converted from a semijoin; but in
3328 : : * such a case the Var couldn't have come from its nullable side.
3329 : : */
1052 3330 [ + + + - : 1246 : if (sjinfo->jointype == JOIN_ANTI && sjinfo->ojrelid != 0 &&
+ - ]
3331 : 584 : bms_is_member(sjinfo->ojrelid, forced_null_var->varnullingrels))
6144 3332 : 584 : return true;
3333 : : }
3334 : :
3335 : 56 : return false;
3336 : : }
3337 : :
3338 : : /*
3339 : : * add_base_clause_to_rel
3340 : : * Add 'restrictinfo' as a baserestrictinfo to the base relation denoted
3341 : : * by 'relid'. We offer some simple prechecks to try to determine if the
3342 : : * qual is always true, in which case we ignore it rather than add it.
3343 : : * If we detect the qual is always false, we replace it with
3344 : : * constant-FALSE.
3345 : : */
3346 : : static void
694 drowley@postgresql.o 3347 : 206512 : add_base_clause_to_rel(PlannerInfo *root, Index relid,
3348 : : RestrictInfo *restrictinfo)
3349 : : {
3350 : 206512 : RelOptInfo *rel = find_base_rel(root, relid);
614 3351 : 206512 : RangeTblEntry *rte = root->simple_rte_array[relid];
3352 : :
694 3353 [ - + ]: 206512 : Assert(bms_membership(restrictinfo->required_relids) == BMS_SINGLETON);
3354 : :
3355 : : /*
3356 : : * For inheritance parent tables, we must always record the RestrictInfo
3357 : : * in baserestrictinfo as is. If we were to transform or skip adding it,
3358 : : * then the original wouldn't be available in apply_child_basequals. Since
3359 : : * there are two RangeTblEntries for inheritance parents, one with
3360 : : * inh==true and the other with inh==false, we're still able to apply this
3361 : : * optimization to the inh==false one. The inh==true one is what
3362 : : * apply_child_basequals() sees, whereas the inh==false one is what's used
3363 : : * for the scan node in the final plan.
3364 : : *
3365 : : * We make an exception to this for partitioned tables. For these, we
3366 : : * always apply the constant-TRUE and constant-FALSE transformations. A
3367 : : * qual which is either of these for a partitioned table must also be that
3368 : : * for all of its child partitions.
3369 : : */
614 3370 [ + + + + ]: 206512 : if (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE)
3371 : : {
3372 : : /* Don't add the clause if it is always true */
3373 [ + + ]: 205512 : if (restriction_is_always_true(root, restrictinfo))
3374 : 240 : return;
3375 : :
3376 : : /*
3377 : : * Substitute the origin qual with constant-FALSE if it is provably
3378 : : * always false.
3379 : : *
3380 : : * Note that we need to keep the same rinfo_serial, since it is in
3381 : : * practice the same condition. We also need to reset the
3382 : : * last_rinfo_serial counter, which is essential to ensure that the
3383 : : * RestrictInfos for the "same" qual condition get identical serial
3384 : : * numbers (see deconstruct_distribute_oj_quals).
3385 : : */
3386 [ - + ]: 205272 : if (restriction_is_always_false(root, restrictinfo))
3387 : : {
614 drowley@postgresql.o 3388 :LBC (21) : int save_rinfo_serial = restrictinfo->rinfo_serial;
404 rguo@postgresql.org 3389 : (21) : int save_last_rinfo_serial = root->last_rinfo_serial;
3390 : :
614 drowley@postgresql.o 3391 : (21) : restrictinfo = make_restrictinfo(root,
3392 : (21) : (Expr *) makeBoolConst(false, false),
3393 : (21) : restrictinfo->is_pushed_down,
3394 : (21) : restrictinfo->has_clone,
3395 : (21) : restrictinfo->is_clone,
3396 : (21) : restrictinfo->pseudoconstant,
3397 : : 0, /* security_level */
3398 : : restrictinfo->required_relids,
3399 : : restrictinfo->incompatible_relids,
3400 : : restrictinfo->outer_relids);
3401 : (21) : restrictinfo->rinfo_serial = save_rinfo_serial;
404 rguo@postgresql.org 3402 : (21) : root->last_rinfo_serial = save_last_rinfo_serial;
3403 : : }
3404 : : }
3405 : :
3406 : : /* Add clause to rel's restriction list */
694 drowley@postgresql.o 3407 :CBC 206272 : rel->baserestrictinfo = lappend(rel->baserestrictinfo, restrictinfo);
3408 : :
3409 : : /* Update security level info */
3410 : 206272 : rel->baserestrict_min_security = Min(rel->baserestrict_min_security,
3411 : : restrictinfo->security_level);
3412 : : }
3413 : :
3414 : : /*
3415 : : * restriction_is_always_true
3416 : : * Check to see if the RestrictInfo is always true.
3417 : : *
3418 : : * Currently we only check for NullTest quals and OR clauses that include
3419 : : * NullTest quals. We may extend it in the future.
3420 : : */
3421 : : bool
3422 : 265042 : restriction_is_always_true(PlannerInfo *root,
3423 : : RestrictInfo *restrictinfo)
3424 : : {
3425 : : /*
3426 : : * For a clone clause, we don't have a reliable way to determine if the
3427 : : * input expression of a NullTest is non-nullable: nullingrel bits in
3428 : : * clone clauses may not reflect reality, so we dare not draw conclusions
3429 : : * from clones about whether Vars are guaranteed not-null.
3430 : : */
288 rguo@postgresql.org 3431 [ + + + + ]: 265042 : if (restrictinfo->has_clone || restrictinfo->is_clone)
3432 : 5376 : return false;
3433 : :
3434 : : /* Check for NullTest qual */
694 drowley@postgresql.o 3435 [ + + ]: 259666 : if (IsA(restrictinfo->clause, NullTest))
3436 : : {
3437 : 5946 : NullTest *nulltest = (NullTest *) restrictinfo->clause;
3438 : :
3439 : : /* is this NullTest an IS_NOT_NULL qual? */
3440 [ + + ]: 5946 : if (nulltest->nulltesttype != IS_NOT_NULL)
3441 : 1537 : return false;
3442 : :
3443 : : /*
3444 : : * Empty rows can appear NULL in some contexts and NOT NULL in others,
3445 : : * so avoid this optimization for row expressions.
3446 : : */
254 bruce@momjian.us 3447 [ + + ]: 4409 : if (nulltest->argisrow)
3448 : 78 : return false;
3449 : :
20 drowley@postgresql.o 3450 :GNC 4331 : return expr_is_nonnullable(root, nulltest->arg, true);
3451 : : }
3452 : :
3453 : : /* If it's an OR, check its sub-clauses */
694 drowley@postgresql.o 3454 [ + + ]:CBC 253720 : if (restriction_is_or_clause(restrictinfo))
3455 : : {
3456 : : ListCell *lc;
3457 : :
3458 [ - + ]: 4695 : Assert(is_orclause(restrictinfo->orclause));
3459 : :
3460 : : /*
3461 : : * if any of the given OR branches is provably always true then the
3462 : : * entire condition is true.
3463 : : */
3464 [ + - + + : 15673 : foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
+ + ]
3465 : : {
3466 : 10978 : Node *orarg = (Node *) lfirst(lc);
3467 : :
3468 [ + + ]: 10978 : if (!IsA(orarg, RestrictInfo))
3469 : 1582 : continue;
3470 : :
3471 [ - + ]: 9396 : if (restriction_is_always_true(root, (RestrictInfo *) orarg))
694 drowley@postgresql.o 3472 :LBC (6) : return true;
3473 : : }
3474 : : }
3475 : :
694 drowley@postgresql.o 3476 :CBC 253720 : return false;
3477 : : }
3478 : :
3479 : : /*
3480 : : * restriction_is_always_false
3481 : : * Check to see if the RestrictInfo is always false.
3482 : : *
3483 : : * Currently we only check for NullTest quals and OR clauses that include
3484 : : * NullTest quals. We may extend it in the future.
3485 : : */
3486 : : bool
3487 : 259370 : restriction_is_always_false(PlannerInfo *root,
3488 : : RestrictInfo *restrictinfo)
3489 : : {
3490 : : /*
3491 : : * For a clone clause, we don't have a reliable way to determine if the
3492 : : * input expression of a NullTest is non-nullable: nullingrel bits in
3493 : : * clone clauses may not reflect reality, so we dare not draw conclusions
3494 : : * from clones about whether Vars are guaranteed not-null.
3495 : : */
288 rguo@postgresql.org 3496 [ + + + + ]: 259370 : if (restrictinfo->has_clone || restrictinfo->is_clone)
3497 : 5376 : return false;
3498 : :
3499 : : /* Check for NullTest qual */
694 drowley@postgresql.o 3500 [ + + ]: 253994 : if (IsA(restrictinfo->clause, NullTest))
3501 : : {
3502 : 5110 : NullTest *nulltest = (NullTest *) restrictinfo->clause;
3503 : :
3504 : : /* is this NullTest an IS_NULL qual? */
3505 [ + + ]: 5110 : if (nulltest->nulltesttype != IS_NULL)
3506 : 3783 : return false;
3507 : :
3508 : : /*
3509 : : * Empty rows can appear NULL in some contexts and NOT NULL in others,
3510 : : * so avoid this optimization for row expressions.
3511 : : */
254 bruce@momjian.us 3512 [ + + ]: 1327 : if (nulltest->argisrow)
3513 : 60 : return false;
3514 : :
20 drowley@postgresql.o 3515 :GNC 1267 : return expr_is_nonnullable(root, nulltest->arg, true);
3516 : : }
3517 : :
3518 : : /* If it's an OR, check its sub-clauses */
694 drowley@postgresql.o 3519 [ + + ]:CBC 248884 : if (restriction_is_or_clause(restrictinfo))
3520 : : {
3521 : : ListCell *lc;
3522 : :
3523 [ - + ]: 4695 : Assert(is_orclause(restrictinfo->orclause));
3524 : :
3525 : : /*
3526 : : * Currently, when processing OR expressions, we only return true when
3527 : : * all of the OR branches are always false. This could perhaps be
3528 : : * expanded to remove OR branches that are provably false. This may
3529 : : * be a useful thing to do as it could result in the OR being left
3530 : : * with a single arg. That's useful as it would allow the OR
3531 : : * condition to be replaced with its single argument which may allow
3532 : : * use of an index for faster filtering on the remaining condition.
3533 : : */
3534 [ + - + - : 4695 : foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
+ - ]
3535 : : {
3536 : 4695 : Node *orarg = (Node *) lfirst(lc);
3537 : :
3538 [ + + ]: 4695 : if (!IsA(orarg, RestrictInfo) ||
3539 [ + - ]: 3964 : !restriction_is_always_false(root, (RestrictInfo *) orarg))
3540 : 4695 : return false;
3541 : : }
694 drowley@postgresql.o 3542 :LBC (6) : return true;
3543 : : }
3544 : :
694 drowley@postgresql.o 3545 :CBC 244189 : return false;
3546 : : }
3547 : :
3548 : : /*
3549 : : * distribute_restrictinfo_to_rels
3550 : : * Push a completed RestrictInfo into the proper restriction or join
3551 : : * clause list(s).
3552 : : *
3553 : : * This is the last step of distribute_qual_to_rels() for ordinary qual
3554 : : * clauses. Clauses that are interesting for equivalence-class processing
3555 : : * are diverted to the EC machinery, but may ultimately get fed back here.
3556 : : */
3557 : : void
6906 tgl@sss.pgh.pa.us 3558 : 241709 : distribute_restrictinfo_to_rels(PlannerInfo *root,
3559 : : RestrictInfo *restrictinfo)
3560 : : {
3561 : 241709 : Relids relids = restrictinfo->required_relids;
3562 : :
750 drowley@postgresql.o 3563 [ + - ]: 241709 : if (!bms_is_empty(relids))
3564 : : {
3565 : : int relid;
3566 : :
3567 [ + + ]: 241709 : if (bms_get_singleton_member(relids, &relid))
3568 : : {
3569 : : /*
3570 : : * There is only one relation participating in the clause, so it
3571 : : * is a restriction clause for that relation.
3572 : : */
694 3573 : 206512 : add_base_clause_to_rel(root, relid, restrictinfo);
3574 : : }
3575 : : else
3576 : : {
3577 : : /*
3578 : : * The clause is a join clause, since there is more than one rel
3579 : : * in its relid set.
3580 : : */
3581 : :
3582 : : /*
3583 : : * Check for hashjoinable operators. (We don't bother setting the
3584 : : * hashjoin info except in true join clauses.)
3585 : : */
5466 tgl@sss.pgh.pa.us 3586 : 35197 : check_hashjoinable(restrictinfo);
3587 : :
3588 : : /*
3589 : : * Likewise, check if the clause is suitable to be used with a
3590 : : * Memoize node to cache inner tuples during a parameterized
3591 : : * nested loop.
3592 : : */
1617 drowley@postgresql.o 3593 : 35197 : check_memoizable(restrictinfo);
3594 : :
3595 : : /*
3596 : : * Add clause to the join lists of all the relevant relations.
3597 : : */
6906 tgl@sss.pgh.pa.us 3598 : 35197 : add_join_clause_to_rels(root, restrictinfo, relids);
3599 : : }
3600 : : }
3601 : : else
3602 : : {
3603 : : /*
3604 : : * clause references no rels, and therefore we have no place to attach
3605 : : * it. Shouldn't get here if callers are working properly.
3606 : : */
750 drowley@postgresql.o 3607 [ # # ]:UBC 0 : elog(ERROR, "cannot cope with variable-free clause");
3608 : : }
6906 tgl@sss.pgh.pa.us 3609 :CBC 241709 : }
3610 : :
3611 : : /*
3612 : : * process_implied_equality
3613 : : * Create a restrictinfo item that says "item1 op item2", and push it
3614 : : * into the appropriate lists. (In practice opno is always a btree
3615 : : * equality operator.)
3616 : : *
3617 : : * "qualscope" is the nominal syntactic level to impute to the restrictinfo.
3618 : : * This must contain at least all the rels used in the expressions, but it
3619 : : * is used only to set the qual application level when both exprs are
3620 : : * variable-free. (Hence, it should usually match the join domain in which
3621 : : * the clause applies.) Otherwise the qual is applied at the lowest join
3622 : : * level that provides all its variables.
3623 : : *
3624 : : * "security_level" is the security level to assign to the new restrictinfo.
3625 : : *
3626 : : * "both_const" indicates whether both items are known pseudo-constant;
3627 : : * in this case it is worth applying eval_const_expressions() in case we
3628 : : * can produce constant TRUE or constant FALSE. (Otherwise it's not,
3629 : : * because the expressions went through eval_const_expressions already.)
3630 : : *
3631 : : * Returns the generated RestrictInfo, if any. The result will be NULL
3632 : : * if both_const is true and we successfully reduced the clause to
3633 : : * constant TRUE.
3634 : : *
3635 : : * Note: this function will copy item1 and item2, but it is caller's
3636 : : * responsibility to make sure that the Relids parameters are fresh copies
3637 : : * not shared with other uses.
3638 : : *
3639 : : * Note: we do not do initialize_mergeclause_eclasses() here. It is
3640 : : * caller's responsibility that left_ec/right_ec be set as necessary.
3641 : : */
3642 : : RestrictInfo *
3643 : 18909 : process_implied_equality(PlannerInfo *root,
3644 : : Oid opno,
3645 : : Oid collation,
3646 : : Expr *item1,
3647 : : Expr *item2,
3648 : : Relids qualscope,
3649 : : Index security_level,
3650 : : bool both_const)
3651 : : {
3652 : : RestrictInfo *restrictinfo;
3653 : : Node *clause;
3654 : : Relids relids;
1876 3655 : 18909 : bool pseudoconstant = false;
3656 : :
3657 : : /*
3658 : : * Build the new clause. Copy to ensure it shares no substructure with
3659 : : * original (this is necessary in case there are subselects in there...)
3660 : : */
3661 : 18909 : clause = (Node *) make_opclause(opno,
3662 : : BOOLOID, /* opresulttype */
3663 : : false, /* opretset */
3664 : 18909 : copyObject(item1),
3665 : 18909 : copyObject(item2),
3666 : : InvalidOid,
3667 : : collation);
3668 : :
3669 : : /* If both constant, try to reduce to a boolean constant. */
6906 3670 [ + + ]: 18909 : if (both_const)
3671 : : {
1876 3672 : 66 : clause = eval_const_expressions(root, clause);
3673 : :
3674 : : /* If we produced const TRUE, just drop the clause */
6906 3675 [ + - + + ]: 66 : if (clause && IsA(clause, Const))
3676 : : {
6607 bruce@momjian.us 3677 : 63 : Const *cclause = (Const *) clause;
3678 : :
6906 tgl@sss.pgh.pa.us 3679 [ - + ]: 63 : Assert(cclause->consttype == BOOLOID);
3680 [ + - - + ]: 63 : if (!cclause->constisnull && DatumGetBool(cclause->constvalue))
1876 tgl@sss.pgh.pa.us 3681 :UBC 0 : return NULL;
3682 : : }
3683 : : }
3684 : :
3685 : : /*
3686 : : * The rest of this is a very cut-down version of distribute_qual_to_rels.
3687 : : * We can skip most of the work therein, but there are a couple of special
3688 : : * cases we still have to handle.
3689 : : *
3690 : : * Retrieve all relids mentioned within the possibly-simplified clause.
3691 : : */
1791 tgl@sss.pgh.pa.us 3692 :CBC 18909 : relids = pull_varnos(root, clause);
1876 3693 [ - + ]: 18909 : Assert(bms_is_subset(relids, qualscope));
3694 : :
3695 : : /*
3696 : : * If the clause is variable-free, our normal heuristic for pushing it
3697 : : * down to just the mentioned rels doesn't work, because there are none.
3698 : : * Apply it as a gating qual at the appropriate level (see comments for
3699 : : * get_join_domain_min_rels).
3700 : : */
3701 [ + + ]: 18909 : if (bms_is_empty(relids))
3702 : : {
3703 : : /* eval at join domain's safe level */
1029 3704 : 66 : relids = get_join_domain_min_rels(root, qualscope);
3705 : : /* mark as gating qual */
1052 3706 : 66 : pseudoconstant = true;
3707 : : /* tell createplan.c to check for gating quals */
3708 : 66 : root->hasPseudoConstantQuals = true;
3709 : : }
3710 : :
3711 : : /*
3712 : : * Build the RestrictInfo node itself.
3713 : : */
1791 3714 : 18909 : restrictinfo = make_restrictinfo(root,
3715 : : (Expr *) clause,
3716 : : true, /* is_pushed_down */
3717 : : false, /* !has_clone */
3718 : : false, /* !is_clone */
3719 : : pseudoconstant,
3720 : : security_level,
3721 : : relids,
3722 : : NULL, /* incompatible_relids */
3723 : : NULL); /* outer_relids */
3724 : :
3725 : : /*
3726 : : * If it's a join clause, add vars used in the clause to targetlists of
3727 : : * their relations, so that they will be emitted by the plan nodes that
3728 : : * scan those relations (else they won't be available at the join node!).
3729 : : *
3730 : : * Typically, we'd have already done this when the component expressions
3731 : : * were first seen by distribute_qual_to_rels; but it is possible that
3732 : : * some of the Vars could have missed having that done because they only
3733 : : * appeared in single-relation clauses originally. So do it here for
3734 : : * safety.
3735 : : *
3736 : : * See also rebuild_joinclause_attr_needed, which has to partially repeat
3737 : : * this work after removal of an outer join. (Since we will put this
3738 : : * clause into the joininfo lists, that function needn't do any extra work
3739 : : * to find it.)
3740 : : */
1876 3741 [ + + ]: 18909 : if (bms_membership(relids) == BMS_MULTIPLE)
3742 : : {
3743 : 30 : List *vars = pull_var_clause(clause,
3744 : : PVC_RECURSE_AGGREGATES |
3745 : : PVC_RECURSE_WINDOWFUNCS |
3746 : : PVC_INCLUDE_PLACEHOLDERS);
3747 : :
1218 3748 : 30 : add_vars_to_targetlist(root, vars, relids);
1876 3749 : 30 : list_free(vars);
3750 : : }
3751 : :
3752 : : /*
3753 : : * Check mergejoinability. This will usually succeed, since the op came
3754 : : * from an EquivalenceClass; but we could have reduced the original clause
3755 : : * to a constant.
3756 : : */
3757 : 18909 : check_mergejoinable(restrictinfo);
3758 : :
3759 : : /*
3760 : : * Note we don't do initialize_mergeclause_eclasses(); the caller can
3761 : : * handle that much more cheaply than we can. It's okay to call
3762 : : * distribute_restrictinfo_to_rels() before that happens.
3763 : : */
3764 : :
3765 : : /*
3766 : : * Push the new clause into all the appropriate restrictinfo lists.
3767 : : */
3768 : 18909 : distribute_restrictinfo_to_rels(root, restrictinfo);
3769 : :
3770 : 18909 : return restrictinfo;
3771 : : }
3772 : :
3773 : : /*
3774 : : * build_implied_join_equality --- build a RestrictInfo for a derived equality
3775 : : *
3776 : : * This overlaps the functionality of process_implied_equality(), but we
3777 : : * must not push the RestrictInfo into the joininfo tree.
3778 : : *
3779 : : * Note: this function will copy item1 and item2, but it is caller's
3780 : : * responsibility to make sure that the Relids parameters are fresh copies
3781 : : * not shared with other uses.
3782 : : *
3783 : : * Note: we do not do initialize_mergeclause_eclasses() here. It is
3784 : : * caller's responsibility that left_ec/right_ec be set as necessary.
3785 : : */
3786 : : RestrictInfo *
1791 3787 : 44193 : build_implied_join_equality(PlannerInfo *root,
3788 : : Oid opno,
3789 : : Oid collation,
3790 : : Expr *item1,
3791 : : Expr *item2,
3792 : : Relids qualscope,
3793 : : Index security_level)
3794 : : {
3795 : : RestrictInfo *restrictinfo;
3796 : : Expr *clause;
3797 : :
3798 : : /*
3799 : : * Build the new clause. Copy to ensure it shares no substructure with
3800 : : * original (this is necessary in case there are subselects in there...)
3801 : : */
6906 3802 : 44193 : clause = make_opclause(opno,
3803 : : BOOLOID, /* opresulttype */
3804 : : false, /* opretset */
3205 peter_e@gmx.net 3805 : 44193 : copyObject(item1),
3806 : 44193 : copyObject(item2),
3807 : : InvalidOid,
3808 : : collation);
3809 : :
3810 : : /*
3811 : : * Build the RestrictInfo node itself.
3812 : : */
1791 tgl@sss.pgh.pa.us 3813 : 44193 : restrictinfo = make_restrictinfo(root,
3814 : : clause,
3815 : : true, /* is_pushed_down */
3816 : : false, /* !has_clone */
3817 : : false, /* !is_clone */
3818 : : false, /* pseudoconstant */
3819 : : security_level, /* security_level */
3820 : : qualscope, /* required_relids */
3821 : : NULL, /* incompatible_relids */
3822 : : NULL); /* outer_relids */
3823 : :
3824 : : /* Set mergejoinability/hashjoinability flags */
6906 3825 : 44193 : check_mergejoinable(restrictinfo);
5466 3826 : 44193 : check_hashjoinable(restrictinfo);
1617 drowley@postgresql.o 3827 : 44193 : check_memoizable(restrictinfo);
3828 : :
6906 tgl@sss.pgh.pa.us 3829 : 44193 : return restrictinfo;
3830 : : }
3831 : :
3832 : : /*
3833 : : * get_join_domain_min_rels
3834 : : * Identify the appropriate join level for derived quals belonging
3835 : : * to the join domain with the given relids.
3836 : : *
3837 : : * When we derive a pseudoconstant (Var-free) clause from an EquivalenceClass,
3838 : : * we'd ideally apply the clause at the top level of the EC's join domain.
3839 : : * However, if there are any outer joins inside that domain that get commuted
3840 : : * with joins outside it, that leads to not finding a correct place to apply
3841 : : * the clause. Instead, remove any lower outer joins from the relid set,
3842 : : * and apply the clause to just the remaining rels. This still results in a
3843 : : * correct answer, since if the clause produces FALSE then the LHS of these
3844 : : * joins will be empty leading to an empty join result.
3845 : : *
3846 : : * However, there's no need to remove outer joins if this is the top-level
3847 : : * join domain of the query, since then there's nothing else to commute with.
3848 : : *
3849 : : * Note: it's tempting to use this in distribute_qual_to_rels where it's
3850 : : * dealing with pseudoconstant quals; but we can't because the necessary
3851 : : * SpecialJoinInfos aren't all formed at that point.
3852 : : *
3853 : : * The result is always freshly palloc'd; we do not modify domain_relids.
3854 : : */
3855 : : static Relids
1029 3856 : 66 : get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids)
3857 : : {
3858 : 66 : Relids result = bms_copy(domain_relids);
3859 : : ListCell *lc;
3860 : :
3861 : : /* Top-level join domain? */
3862 [ + + ]: 66 : if (bms_equal(result, root->all_query_rels))
3863 : 33 : return result;
3864 : :
3865 : : /* Nope, look for lower outer joins that could potentially commute out */
3866 [ + - + + : 69 : foreach(lc, root->join_info_list)
+ + ]
3867 : : {
3868 : 36 : SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
3869 : :
3870 [ + - + + ]: 72 : if (sjinfo->jointype == JOIN_LEFT &&
3871 : 36 : bms_is_member(sjinfo->ojrelid, result))
3872 : : {
3873 : 3 : result = bms_del_member(result, sjinfo->ojrelid);
3874 : 3 : result = bms_del_members(result, sjinfo->syn_righthand);
3875 : : }
3876 : : }
3877 : 33 : return result;
3878 : : }
3879 : :
3880 : :
3881 : : /*
3882 : : * rebuild_joinclause_attr_needed
3883 : : * Put back attr_needed bits for Vars/PHVs needed for join clauses.
3884 : : *
3885 : : * This is used to rebuild attr_needed/ph_needed sets after removal of a
3886 : : * useless outer join. It should match what distribute_qual_to_rels did,
3887 : : * except that we call add_vars_to_attr_needed not add_vars_to_targetlist.
3888 : : */
3889 : : void
446 3890 : 5695 : rebuild_joinclause_attr_needed(PlannerInfo *root)
3891 : : {
3892 : : /*
3893 : : * We must examine all join clauses, but there's no value in processing
3894 : : * any join clause more than once. So it's slightly annoying that we have
3895 : : * to find them via the per-base-relation joininfo lists. Avoid duplicate
3896 : : * processing by tracking the rinfo_serial numbers of join clauses we've
3897 : : * already seen. (This doesn't work for is_clone clauses, so we must
3898 : : * waste effort on them.)
3899 : : */
3900 : 5695 : Bitmapset *seen_serials = NULL;
3901 : : Index rti;
3902 : :
3903 : : /* Scan all baserels for join clauses */
3904 [ + + ]: 36298 : for (rti = 1; rti < root->simple_rel_array_size; rti++)
3905 : : {
3906 : 30603 : RelOptInfo *brel = root->simple_rel_array[rti];
3907 : : ListCell *lc;
3908 : :
3909 [ + + ]: 30603 : if (brel == NULL)
3910 : 20808 : continue;
3911 [ - + ]: 9795 : if (brel->reloptkind != RELOPT_BASEREL)
446 tgl@sss.pgh.pa.us 3912 :UBC 0 : continue;
3913 : :
446 tgl@sss.pgh.pa.us 3914 [ + + + + :CBC 14679 : foreach(lc, brel->joininfo)
+ + ]
3915 : : {
3916 : 4884 : RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3917 : 4884 : Relids relids = rinfo->required_relids;
3918 : :
3919 [ + + ]: 4884 : if (!rinfo->is_clone) /* else serial number is not unique */
3920 : : {
3921 [ + + ]: 4836 : if (bms_is_member(rinfo->rinfo_serial, seen_serials))
3922 : 2595 : continue; /* saw it already */
3923 : 2241 : seen_serials = bms_add_member(seen_serials,
3924 : : rinfo->rinfo_serial);
3925 : : }
3926 : :
3927 [ + - ]: 2289 : if (bms_membership(relids) == BMS_MULTIPLE)
3928 : : {
3929 : 2289 : List *vars = pull_var_clause((Node *) rinfo->clause,
3930 : : PVC_RECURSE_AGGREGATES |
3931 : : PVC_RECURSE_WINDOWFUNCS |
3932 : : PVC_INCLUDE_PLACEHOLDERS);
3933 : : Relids where_needed;
3934 : :
3935 [ + + ]: 2289 : if (rinfo->is_clone)
3936 : 48 : where_needed = bms_intersect(relids, root->all_baserels);
3937 : : else
3938 : 2241 : where_needed = relids;
3939 : 2289 : add_vars_to_attr_needed(root, vars, where_needed);
3940 : 2289 : list_free(vars);
3941 : : }
3942 : : }
3943 : : }
3944 : 5695 : }
3945 : :
3946 : :
3947 : : /*
3948 : : * match_foreign_keys_to_quals
3949 : : * Match foreign-key constraints to equivalence classes and join quals
3950 : : *
3951 : : * The idea here is to see which query join conditions match equality
3952 : : * constraints of a foreign-key relationship. For such join conditions,
3953 : : * we can use the FK semantics to make selectivity estimates that are more
3954 : : * reliable than estimating from statistics, especially for multiple-column
3955 : : * FKs, where the normal assumption of independent conditions tends to fail.
3956 : : *
3957 : : * In this function we annotate the ForeignKeyOptInfos in root->fkey_list
3958 : : * with info about which eclasses and join qual clauses they match, and
3959 : : * discard any ForeignKeyOptInfos that are irrelevant for the query.
3960 : : */
3961 : : void
3469 3962 : 171197 : match_foreign_keys_to_quals(PlannerInfo *root)
3963 : : {
3964 : 171197 : List *newlist = NIL;
3965 : : ListCell *lc;
3966 : :
3967 [ + + + + : 172087 : foreach(lc, root->fkey_list)
+ + ]
3968 : : {
3969 : 890 : ForeignKeyOptInfo *fkinfo = (ForeignKeyOptInfo *) lfirst(lc);
3970 : : RelOptInfo *con_rel;
3971 : : RelOptInfo *ref_rel;
3972 : : int colno;
3973 : :
3974 : : /*
3975 : : * Either relid might identify a rel that is in the query's rtable but
3976 : : * isn't referenced by the jointree, or has been removed by join
3977 : : * removal, so that it won't have a RelOptInfo. Hence don't use
3978 : : * find_base_rel() here. We can ignore such FKs.
3979 : : */
3458 3980 [ + - ]: 890 : if (fkinfo->con_relid >= root->simple_rel_array_size ||
3981 [ - + ]: 890 : fkinfo->ref_relid >= root->simple_rel_array_size)
3458 tgl@sss.pgh.pa.us 3982 :UBC 0 : continue; /* just paranoia */
3458 tgl@sss.pgh.pa.us 3983 :CBC 890 : con_rel = root->simple_rel_array[fkinfo->con_relid];
3984 [ + + ]: 890 : if (con_rel == NULL)
3985 : 6 : continue;
3986 : 884 : ref_rel = root->simple_rel_array[fkinfo->ref_relid];
3987 [ + + ]: 884 : if (ref_rel == NULL)
3988 : 12 : continue;
3989 : :
3990 : : /*
3991 : : * Ignore FK unless both rels are baserels. This gets rid of FKs that
3992 : : * link to inheritance child rels (otherrels).
3993 : : */
3469 3994 [ + - ]: 872 : if (con_rel->reloptkind != RELOPT_BASEREL ||
3995 [ - + ]: 872 : ref_rel->reloptkind != RELOPT_BASEREL)
3469 tgl@sss.pgh.pa.us 3996 :UBC 0 : continue;
3997 : :
3998 : : /*
3999 : : * Scan the columns and try to match them to eclasses and quals.
4000 : : *
4001 : : * Note: for simple inner joins, any match should be in an eclass.
4002 : : * "Loose" quals that syntactically match an FK equality must have
4003 : : * been rejected for EC status because they are outer-join quals or
4004 : : * similar. We can still consider them to match the FK.
4005 : : */
3469 tgl@sss.pgh.pa.us 4006 [ + + ]:CBC 2022 : for (colno = 0; colno < fkinfo->nkeys; colno++)
4007 : : {
4008 : : EquivalenceClass *ec;
4009 : : AttrNumber con_attno,
4010 : : ref_attno;
4011 : : Oid fpeqop;
4012 : : ListCell *lc2;
4013 : :
1876 4014 : 1150 : ec = match_eclasses_to_foreign_key_col(root, fkinfo, colno);
4015 : : /* Don't bother looking for loose quals if we got an EC match */
4016 [ + + ]: 1150 : if (ec != NULL)
4017 : : {
3469 4018 : 171 : fkinfo->nmatched_ec++;
1876 4019 [ + + ]: 171 : if (ec->ec_has_const)
4020 : 37 : fkinfo->nconst_ec++;
3469 4021 : 171 : continue;
4022 : : }
4023 : :
4024 : : /*
4025 : : * Scan joininfo list for relevant clauses. Either rel's joininfo
4026 : : * list would do equally well; we use con_rel's.
4027 : : */
4028 : 979 : con_attno = fkinfo->conkey[colno];
4029 : 979 : ref_attno = fkinfo->confkey[colno];
4030 : 979 : fpeqop = InvalidOid; /* we'll look this up only if needed */
4031 : :
4032 [ + + + + : 2556 : foreach(lc2, con_rel->joininfo)
+ + ]
4033 : : {
4034 : 1577 : RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2);
4035 : 1577 : OpExpr *clause = (OpExpr *) rinfo->clause;
4036 : : Var *leftvar;
4037 : : Var *rightvar;
4038 : :
4039 : : /* Only binary OpExprs are useful for consideration */
4040 [ + - - + ]: 3154 : if (!IsA(clause, OpExpr) ||
4041 : 1577 : list_length(clause->args) != 2)
3469 tgl@sss.pgh.pa.us 4042 :UBC 0 : continue;
3469 tgl@sss.pgh.pa.us 4043 :CBC 1577 : leftvar = (Var *) get_leftop((Expr *) clause);
4044 : 1577 : rightvar = (Var *) get_rightop((Expr *) clause);
4045 : :
4046 : : /* Operands must be Vars, possibly with RelabelType */
4047 [ + - + + ]: 1700 : while (leftvar && IsA(leftvar, RelabelType))
4048 : 123 : leftvar = (Var *) ((RelabelType *) leftvar)->arg;
4049 [ + - - + ]: 1577 : if (!(leftvar && IsA(leftvar, Var)))
3469 tgl@sss.pgh.pa.us 4050 :UBC 0 : continue;
3469 tgl@sss.pgh.pa.us 4051 [ + - + + ]:CBC 1691 : while (rightvar && IsA(rightvar, RelabelType))
4052 : 114 : rightvar = (Var *) ((RelabelType *) rightvar)->arg;
4053 [ + - + + ]: 1577 : if (!(rightvar && IsA(rightvar, Var)))
4054 : 15 : continue;
4055 : :
4056 : : /* Now try to match the vars to the current foreign key cols */
4057 [ + + ]: 1562 : if (fkinfo->ref_relid == leftvar->varno &&
4058 [ + + ]: 1499 : ref_attno == leftvar->varattno &&
4059 [ + - ]: 856 : fkinfo->con_relid == rightvar->varno &&
4060 [ + + ]: 856 : con_attno == rightvar->varattno)
4061 : : {
4062 : : /* Vars match, but is it the right operator? */
4063 [ + - ]: 817 : if (clause->opno == fkinfo->conpfeqop[colno])
4064 : : {
4065 : 817 : fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
4066 : : rinfo);
4067 : 817 : fkinfo->nmatched_ri++;
4068 : : }
4069 : : }
4070 [ + + ]: 745 : else if (fkinfo->ref_relid == rightvar->varno &&
4071 [ + + ]: 45 : ref_attno == rightvar->varattno &&
4072 [ + - ]: 18 : fkinfo->con_relid == leftvar->varno &&
4073 [ + - ]: 18 : con_attno == leftvar->varattno)
4074 : : {
4075 : : /*
4076 : : * Reverse match, must check commutator operator. Look it
4077 : : * up if we didn't already. (In the worst case we might
4078 : : * do multiple lookups here, but that would require an FK
4079 : : * equality operator without commutator, which is
4080 : : * unlikely.)
4081 : : */
4082 [ + - ]: 18 : if (!OidIsValid(fpeqop))
4083 : 18 : fpeqop = get_commutator(fkinfo->conpfeqop[colno]);
4084 [ + - ]: 18 : if (clause->opno == fpeqop)
4085 : : {
4086 : 18 : fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
4087 : : rinfo);
4088 : 18 : fkinfo->nmatched_ri++;
4089 : : }
4090 : : }
4091 : : }
4092 : : /* If we found any matching loose quals, count col as matched */
4093 [ + + ]: 979 : if (fkinfo->rinfos[colno])
4094 : 835 : fkinfo->nmatched_rcols++;
4095 : : }
4096 : :
4097 : : /*
4098 : : * Currently, we drop multicolumn FKs that aren't fully matched to the
4099 : : * query. Later we might figure out how to derive some sort of
4100 : : * estimate from them, in which case this test should be weakened to
4101 : : * "if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) > 0)".
4102 : : */
4103 [ + + ]: 872 : if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) == fkinfo->nkeys)
4104 : 740 : newlist = lappend(newlist, fkinfo);
4105 : : }
4106 : : /* Replace fkey_list, thereby discarding any useless entries */
4107 : 171197 : root->fkey_list = newlist;
4108 : 171197 : }
4109 : :
4110 : :
4111 : : /*****************************************************************************
4112 : : *
4113 : : * CHECKS FOR MERGEJOINABLE AND HASHJOINABLE CLAUSES
4114 : : *
4115 : : *****************************************************************************/
4116 : :
4117 : : /*
4118 : : * check_mergejoinable
4119 : : * If the restrictinfo's clause is mergejoinable, set the mergejoin
4120 : : * info fields in the restrictinfo.
4121 : : *
4122 : : * Currently, we support mergejoin for binary opclauses where
4123 : : * the operator is a mergejoinable operator. The arguments can be
4124 : : * anything --- as long as there are no volatile functions in them.
4125 : : */
4126 : : static void
9620 4127 : 343237 : check_mergejoinable(RestrictInfo *restrictinfo)
4128 : : {
4129 : 343237 : Expr *clause = restrictinfo->clause;
4130 : : Oid opno;
4131 : : Node *leftarg;
4132 : :
7109 4133 [ + + ]: 343237 : if (restrictinfo->pseudoconstant)
4134 : 5489 : return;
8406 4135 [ + + ]: 337748 : if (!is_opclause(clause))
9620 4136 : 41683 : return;
7871 neilc@samurai.com 4137 [ + + ]: 296065 : if (list_length(((OpExpr *) clause)->args) != 2)
9620 tgl@sss.pgh.pa.us 4138 : 12 : return;
4139 : :
8406 4140 : 296053 : opno = ((OpExpr *) clause)->opno;
5527 4141 : 296053 : leftarg = linitial(((OpExpr *) clause)->args);
4142 : :
4143 [ + + ]: 296053 : if (op_mergejoinable(opno, exprType(leftarg)) &&
1724 drowley@postgresql.o 4144 [ + + ]: 253785 : !contain_volatile_functions((Node *) restrictinfo))
6906 tgl@sss.pgh.pa.us 4145 : 253769 : restrictinfo->mergeopfamilies = get_mergejoin_opfamilies(opno);
4146 : :
4147 : : /*
4148 : : * Note: op_mergejoinable is just a hint; if we fail to find the operator
4149 : : * in any btree opfamilies, mergeopfamilies remains NIL and so the clause
4150 : : * is not treated as mergejoinable.
4151 : : */
4152 : : }
4153 : :
4154 : : /*
4155 : : * check_hashjoinable
4156 : : * If the restrictinfo's clause is hashjoinable, set the hashjoin
4157 : : * info fields in the restrictinfo.
4158 : : *
4159 : : * Currently, we support hashjoin for binary opclauses where
4160 : : * the operator is a hashjoinable operator. The arguments can be
4161 : : * anything --- as long as there are no volatile functions in them.
4162 : : */
4163 : : static void
9620 4164 : 79390 : check_hashjoinable(RestrictInfo *restrictinfo)
4165 : : {
4166 : 79390 : Expr *clause = restrictinfo->clause;
4167 : : Oid opno;
4168 : : Node *leftarg;
4169 : :
7109 4170 [ + + ]: 79390 : if (restrictinfo->pseudoconstant)
4171 : 1775 : return;
8406 4172 [ + + ]: 77615 : if (!is_opclause(clause))
9620 4173 : 3831 : return;
7871 neilc@samurai.com 4174 [ - + ]: 73784 : if (list_length(((OpExpr *) clause)->args) != 2)
9620 tgl@sss.pgh.pa.us 4175 :UBC 0 : return;
4176 : :
8406 tgl@sss.pgh.pa.us 4177 :CBC 73784 : opno = ((OpExpr *) clause)->opno;
5527 4178 : 73784 : leftarg = linitial(((OpExpr *) clause)->args);
4179 : :
4180 [ + + ]: 73784 : if (op_hashjoinable(opno, exprType(leftarg)) &&
1724 drowley@postgresql.o 4181 [ + + ]: 72086 : !contain_volatile_functions((Node *) restrictinfo))
9620 tgl@sss.pgh.pa.us 4182 : 72082 : restrictinfo->hashjoinoperator = opno;
4183 : : }
4184 : :
4185 : : /*
4186 : : * check_memoizable
4187 : : * If the restrictinfo's clause is suitable to be used for a Memoize node,
4188 : : * set the left_hasheqoperator and right_hasheqoperator to the hash equality
4189 : : * operator that will be needed during caching.
4190 : : */
4191 : : static void
1617 drowley@postgresql.o 4192 : 79390 : check_memoizable(RestrictInfo *restrictinfo)
4193 : : {
4194 : : TypeCacheEntry *typentry;
1720 4195 : 79390 : Expr *clause = restrictinfo->clause;
4196 : : Oid lefttype;
4197 : : Oid righttype;
4198 : :
4199 [ + + ]: 79390 : if (restrictinfo->pseudoconstant)
4200 : 1775 : return;
4201 [ + + ]: 77615 : if (!is_opclause(clause))
4202 : 3831 : return;
4203 [ - + ]: 73784 : if (list_length(((OpExpr *) clause)->args) != 2)
1720 drowley@postgresql.o 4204 :UBC 0 : return;
4205 : :
1500 drowley@postgresql.o 4206 :CBC 73784 : lefttype = exprType(linitial(((OpExpr *) clause)->args));
4207 : :
4208 : 73784 : typentry = lookup_type_cache(lefttype, TYPECACHE_HASH_PROC |
4209 : : TYPECACHE_EQ_OPR);
4210 : :
4211 [ + + + - ]: 73784 : if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
4212 : 73580 : restrictinfo->left_hasheqoperator = typentry->eq_opr;
4213 : :
4214 : 73784 : righttype = exprType(lsecond(((OpExpr *) clause)->args));
4215 : :
4216 : : /*
4217 : : * Lookup the right type, unless it's the same as the left type, in which
4218 : : * case typentry is already pointing to the required TypeCacheEntry.
4219 : : */
4220 [ + + ]: 73784 : if (lefttype != righttype)
4221 : 1168 : typentry = lookup_type_cache(righttype, TYPECACHE_HASH_PROC |
4222 : : TYPECACHE_EQ_OPR);
4223 : :
4224 [ + + + - ]: 73784 : if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
4225 : 73478 : restrictinfo->right_hasheqoperator = typentry->eq_opr;
4226 : : }
|