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