/src/postgres/src/backend/optimizer/plan/initsplan.c
Line | Count | Source |
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 |
176 | | add_base_rels_to_query(PlannerInfo *root, Node *jtnode) |
177 | 0 | { |
178 | 0 | if (jtnode == NULL) |
179 | 0 | return; |
180 | 0 | if (IsA(jtnode, RangeTblRef)) |
181 | 0 | { |
182 | 0 | int varno = ((RangeTblRef *) jtnode)->rtindex; |
183 | |
|
184 | 0 | (void) build_simple_rel(root, varno, NULL); |
185 | 0 | } |
186 | 0 | else if (IsA(jtnode, FromExpr)) |
187 | 0 | { |
188 | 0 | FromExpr *f = (FromExpr *) jtnode; |
189 | 0 | ListCell *l; |
190 | |
|
191 | 0 | foreach(l, f->fromlist) |
192 | 0 | add_base_rels_to_query(root, lfirst(l)); |
193 | 0 | } |
194 | 0 | else if (IsA(jtnode, JoinExpr)) |
195 | 0 | { |
196 | 0 | JoinExpr *j = (JoinExpr *) jtnode; |
197 | |
|
198 | 0 | add_base_rels_to_query(root, j->larg); |
199 | 0 | add_base_rels_to_query(root, j->rarg); |
200 | 0 | } |
201 | 0 | else |
202 | 0 | elog(ERROR, "unrecognized node type: %d", |
203 | 0 | (int) nodeTag(jtnode)); |
204 | 0 | } |
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 |
214 | | add_other_rels_to_query(PlannerInfo *root) |
215 | 0 | { |
216 | 0 | int rti; |
217 | |
|
218 | 0 | for (rti = 1; rti < root->simple_rel_array_size; rti++) |
219 | 0 | { |
220 | 0 | RelOptInfo *rel = root->simple_rel_array[rti]; |
221 | 0 | RangeTblEntry *rte = root->simple_rte_array[rti]; |
222 | | |
223 | | /* there may be empty slots corresponding to non-baserel RTEs */ |
224 | 0 | if (rel == NULL) |
225 | 0 | continue; |
226 | | |
227 | | /* Ignore any "otherrels" that were already added. */ |
228 | 0 | if (rel->reloptkind != RELOPT_BASEREL) |
229 | 0 | continue; |
230 | | |
231 | | /* If it's marked as inheritable, look for children. */ |
232 | 0 | if (rte->inh) |
233 | 0 | expand_inherited_rtentry(root, rel, rte, rti); |
234 | 0 | } |
235 | 0 | } |
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 |
253 | | build_base_rel_tlists(PlannerInfo *root, List *final_tlist) |
254 | 0 | { |
255 | 0 | List *tlist_vars = pull_var_clause((Node *) final_tlist, |
256 | 0 | PVC_RECURSE_AGGREGATES | |
257 | 0 | PVC_RECURSE_WINDOWFUNCS | |
258 | 0 | PVC_INCLUDE_PLACEHOLDERS); |
259 | |
|
260 | 0 | if (tlist_vars != NIL) |
261 | 0 | { |
262 | 0 | add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0)); |
263 | 0 | list_free(tlist_vars); |
264 | 0 | } |
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 | | */ |
270 | 0 | if (root->parse->havingQual) |
271 | 0 | { |
272 | 0 | List *having_vars = pull_var_clause(root->parse->havingQual, |
273 | 0 | PVC_RECURSE_AGGREGATES | |
274 | 0 | PVC_INCLUDE_PLACEHOLDERS); |
275 | |
|
276 | 0 | if (having_vars != NIL) |
277 | 0 | { |
278 | 0 | add_vars_to_targetlist(root, having_vars, |
279 | 0 | bms_make_singleton(0)); |
280 | 0 | list_free(having_vars); |
281 | 0 | } |
282 | 0 | } |
283 | 0 | } |
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 |
298 | | add_vars_to_targetlist(PlannerInfo *root, List *vars, |
299 | | Relids where_needed) |
300 | 0 | { |
301 | 0 | ListCell *temp; |
302 | |
|
303 | 0 | Assert(!bms_is_empty(where_needed)); |
304 | |
|
305 | 0 | foreach(temp, vars) |
306 | 0 | { |
307 | 0 | Node *node = (Node *) lfirst(temp); |
308 | |
|
309 | 0 | if (IsA(node, Var)) |
310 | 0 | { |
311 | 0 | Var *var = (Var *) node; |
312 | 0 | RelOptInfo *rel = find_base_rel(root, var->varno); |
313 | 0 | int attno = var->varattno; |
314 | |
|
315 | 0 | if (bms_is_subset(where_needed, rel->relids)) |
316 | 0 | continue; |
317 | 0 | Assert(attno >= rel->min_attr && attno <= rel->max_attr); |
318 | 0 | attno -= rel->min_attr; |
319 | 0 | if (rel->attr_needed[attno] == NULL) |
320 | 0 | { |
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 | | */ |
328 | 0 | var = copyObject(var); |
329 | 0 | var->varnullingrels = NULL; |
330 | 0 | rel->reltarget->exprs = lappend(rel->reltarget->exprs, var); |
331 | | /* reltarget cost and width will be computed later */ |
332 | 0 | } |
333 | 0 | rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno], |
334 | 0 | where_needed); |
335 | 0 | } |
336 | 0 | else if (IsA(node, PlaceHolderVar)) |
337 | 0 | { |
338 | 0 | PlaceHolderVar *phv = (PlaceHolderVar *) node; |
339 | 0 | PlaceHolderInfo *phinfo = find_placeholder_info(root, phv); |
340 | |
|
341 | 0 | phinfo->ph_needed = bms_add_members(phinfo->ph_needed, |
342 | 0 | where_needed); |
343 | 0 | } |
344 | 0 | else |
345 | 0 | elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); |
346 | 0 | } |
347 | 0 | } |
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 |
371 | | remove_useless_groupby_columns(PlannerInfo *root) |
372 | 0 | { |
373 | 0 | Query *parse = root->parse; |
374 | 0 | Bitmapset **groupbyattnos; |
375 | 0 | List **groupbycols; |
376 | 0 | Bitmapset **surplusvars; |
377 | 0 | bool tryremove = false; |
378 | 0 | ListCell *lc; |
379 | 0 | int relid; |
380 | | |
381 | | /* No chance to do anything if there are less than two GROUP BY items */ |
382 | 0 | if (list_length(root->processed_groupClause) < 2) |
383 | 0 | return; |
384 | | |
385 | | /* Don't fiddle with the GROUP BY clause if the query has grouping sets */ |
386 | 0 | if (parse->groupingSets) |
387 | 0 | 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 | | */ |
398 | 0 | groupbyattnos = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1); |
399 | 0 | groupbycols = palloc0_array(List *, list_length(parse->rtable) + 1); |
400 | 0 | foreach(lc, root->processed_groupClause) |
401 | 0 | { |
402 | 0 | SortGroupClause *sgc = lfirst_node(SortGroupClause, lc); |
403 | 0 | TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList); |
404 | 0 | Var *var = (Var *) tle->expr; |
405 | 0 | 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 | 0 | if (!IsA(var, Var) || |
416 | 0 | var->varlevelsup > 0) |
417 | 0 | continue; |
418 | | |
419 | | /* OK, remember we have this Var */ |
420 | 0 | relid = var->varno; |
421 | 0 | 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 | 0 | tryremove |= !bms_is_empty(groupbyattnos[relid]); |
429 | 0 | groupbyattnos[relid] = bms_add_member(groupbyattnos[relid], |
430 | 0 | var->varattno - FirstLowInvalidHeapAttributeNumber); |
431 | |
|
432 | 0 | info = palloc_object(GroupByColInfo); |
433 | 0 | info->attno = var->varattno; |
434 | 0 | info->eq_opfamilies = get_mergejoin_opfamilies(sgc->eqop); |
435 | 0 | info->coll = var->varcollid; |
436 | 0 | groupbycols[relid] = lappend(groupbycols[relid], info); |
437 | 0 | } |
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 | | */ |
443 | 0 | if (!tryremove) |
444 | 0 | 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 | 0 | surplusvars = NULL; /* don't allocate array unless required */ |
453 | 0 | relid = 0; |
454 | 0 | foreach(lc, parse->rtable) |
455 | 0 | { |
456 | 0 | RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc); |
457 | 0 | RelOptInfo *rel; |
458 | 0 | Bitmapset *relattnos; |
459 | 0 | Bitmapset *best_keycolumns = NULL; |
460 | 0 | int32 best_nkeycolumns = PG_INT32_MAX; |
461 | |
|
462 | 0 | relid++; |
463 | | |
464 | | /* Only plain relations could have primary-key constraints */ |
465 | 0 | if (rte->rtekind != RTE_RELATION) |
466 | 0 | 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 | 0 | if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE) |
474 | 0 | continue; |
475 | | |
476 | | /* Nothing to do unless this rel has multiple Vars in GROUP BY */ |
477 | 0 | relattnos = groupbyattnos[relid]; |
478 | 0 | if (bms_membership(relattnos) != BMS_MULTIPLE) |
479 | 0 | continue; |
480 | | |
481 | 0 | 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 | 0 | foreach_node(IndexOptInfo, index, rel->indexlist) |
489 | 0 | { |
490 | 0 | Bitmapset *ind_attnos; |
491 | 0 | 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 | 0 | if (!index->unique || !index->immediate || index->indpred != NIL) |
499 | 0 | continue; |
500 | | |
501 | | /* For simplicity, we currently don't support expression indexes */ |
502 | 0 | if (index->indexprs != NIL) |
503 | 0 | continue; |
504 | | |
505 | 0 | ind_attnos = NULL; |
506 | 0 | index_check_ok = true; |
507 | 0 | for (int i = 0; i < index->nkeycolumns; i++) |
508 | 0 | { |
509 | 0 | AttrNumber indkey_attno = index->indexkeys[i]; |
510 | 0 | Oid indkey_opfamily = index->opfamily[i]; |
511 | 0 | Oid indkey_coll = index->indexcollations[i]; |
512 | 0 | 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 | | */ |
522 | 0 | if (!index->nullsnotdistinct && |
523 | 0 | !bms_is_member(indkey_attno, rel->notnullattnums)) |
524 | 0 | { |
525 | 0 | index_check_ok = false; |
526 | 0 | break; |
527 | 0 | } |
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 | 0 | foreach(lc2, groupbycols[relid]) |
536 | 0 | { |
537 | 0 | GroupByColInfo *info = (GroupByColInfo *) lfirst(lc2); |
538 | |
|
539 | 0 | if (info->attno != indkey_attno) |
540 | 0 | continue; |
541 | 0 | if (list_member_oid(info->eq_opfamilies, indkey_opfamily) && |
542 | 0 | collations_agree_on_equality(indkey_coll, info->coll)) |
543 | 0 | break; |
544 | 0 | } |
545 | 0 | if (lc2 == NULL) |
546 | 0 | { |
547 | 0 | index_check_ok = false; |
548 | 0 | break; |
549 | 0 | } |
550 | | |
551 | 0 | ind_attnos = |
552 | 0 | bms_add_member(ind_attnos, |
553 | 0 | indkey_attno - |
554 | 0 | FirstLowInvalidHeapAttributeNumber); |
555 | 0 | } |
556 | |
|
557 | 0 | if (!index_check_ok) |
558 | 0 | continue; |
559 | | |
560 | | /* |
561 | | * Skip any indexes where the indexed columns aren't a proper |
562 | | * subset of the GROUP BY. |
563 | | */ |
564 | 0 | if (bms_subset_compare(ind_attnos, relattnos) != BMS_SUBSET1) |
565 | 0 | 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 | 0 | if (index->nkeycolumns < best_nkeycolumns) |
576 | 0 | { |
577 | 0 | best_keycolumns = ind_attnos; |
578 | 0 | best_nkeycolumns = index->nkeycolumns; |
579 | 0 | } |
580 | 0 | } |
581 | | |
582 | | /* Did we find a suitable index? */ |
583 | 0 | if (!bms_is_empty(best_keycolumns)) |
584 | 0 | { |
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 | 0 | if (surplusvars == NULL) |
590 | 0 | surplusvars = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1); |
591 | | |
592 | | /* Remember the attnos of the removable columns */ |
593 | 0 | surplusvars[relid] = bms_difference(relattnos, best_keycolumns); |
594 | 0 | } |
595 | 0 | } |
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 | 0 | if (surplusvars != NULL) |
603 | 0 | { |
604 | 0 | List *new_groupby = NIL; |
605 | |
|
606 | 0 | foreach(lc, root->processed_groupClause) |
607 | 0 | { |
608 | 0 | SortGroupClause *sgc = lfirst_node(SortGroupClause, lc); |
609 | 0 | TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList); |
610 | 0 | 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 | 0 | if (!IsA(var, Var) || |
617 | 0 | var->varlevelsup > 0 || |
618 | 0 | !bms_is_member(var->varattno - FirstLowInvalidHeapAttributeNumber, |
619 | 0 | surplusvars[var->varno])) |
620 | 0 | new_groupby = lappend(new_groupby, sgc); |
621 | 0 | } |
622 | |
|
623 | 0 | root->processed_groupClause = new_groupby; |
624 | 0 | } |
625 | 0 | } |
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 |
633 | | setup_eager_aggregation(PlannerInfo *root) |
634 | 0 | { |
635 | | /* |
636 | | * Don't apply eager aggregation if disabled by user. |
637 | | */ |
638 | 0 | if (!enable_eager_aggregate) |
639 | 0 | return; |
640 | | |
641 | | /* |
642 | | * Don't apply eager aggregation if there are no available GROUP BY |
643 | | * clauses. |
644 | | */ |
645 | 0 | if (!root->processed_groupClause) |
646 | 0 | return; |
647 | | |
648 | | /* |
649 | | * For now we don't try to support grouping sets. |
650 | | */ |
651 | 0 | if (root->parse->groupingSets) |
652 | 0 | return; |
653 | | |
654 | | /* |
655 | | * For now we don't try to support DISTINCT or ORDER BY aggregates. |
656 | | */ |
657 | 0 | if (root->numOrderedAggs > 0) |
658 | 0 | 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 | 0 | if (root->hasNonPartialAggs || root->hasNonSerialAggs) |
666 | 0 | return; |
667 | | |
668 | | /* |
669 | | * We don't try to apply eager aggregation if there are set-returning |
670 | | * functions in targetlist. |
671 | | */ |
672 | 0 | if (root->parse->hasTargetSRFs) |
673 | 0 | return; |
674 | | |
675 | | /* |
676 | | * Eager aggregation only makes sense if there are multiple base rels in |
677 | | * the query. |
678 | | */ |
679 | 0 | if (bms_membership(root->all_baserels) != BMS_MULTIPLE) |
680 | 0 | 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 | 0 | if (is_partial_agg_memory_risky(root)) |
687 | 0 | return; |
688 | | |
689 | | /* |
690 | | * Collect aggregate expressions and plain Vars that appear in the |
691 | | * targetlist and havingQual. |
692 | | */ |
693 | 0 | create_agg_clause_infos(root); |
694 | | |
695 | | /* |
696 | | * If there are no suitable aggregate expressions, we cannot apply eager |
697 | | * aggregation. |
698 | | */ |
699 | 0 | if (root->agg_clause_list == NIL) |
700 | 0 | return; |
701 | | |
702 | | /* |
703 | | * Collect grouping expressions that appear in grouping clauses. |
704 | | */ |
705 | 0 | create_grouping_expr_infos(root); |
706 | 0 | } |
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 | | is_partial_agg_memory_risky(PlannerInfo *root) |
721 | 0 | { |
722 | 0 | ListCell *lc; |
723 | |
|
724 | 0 | foreach(lc, root->aggtransinfos) |
725 | 0 | { |
726 | 0 | AggTransInfo *transinfo = lfirst_node(AggTransInfo, lc); |
727 | |
|
728 | 0 | if (transinfo->aggtransspace < 0) |
729 | 0 | return true; |
730 | 0 | } |
731 | | |
732 | 0 | return false; |
733 | 0 | } |
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 | | create_agg_clause_infos(PlannerInfo *root) |
742 | 0 | { |
743 | 0 | List *tlist_exprs; |
744 | 0 | List *agg_clause_list = NIL; |
745 | 0 | List *tlist_vars = NIL; |
746 | 0 | Relids aggregate_relids = NULL; |
747 | 0 | bool eager_agg_applicable = true; |
748 | 0 | ListCell *lc; |
749 | |
|
750 | 0 | Assert(root->agg_clause_list == NIL); |
751 | 0 | Assert(root->tlist_vars == NIL); |
752 | |
|
753 | 0 | tlist_exprs = pull_var_clause((Node *) root->processed_tlist, |
754 | 0 | PVC_INCLUDE_AGGREGATES | |
755 | 0 | PVC_RECURSE_WINDOWFUNCS | |
756 | 0 | 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 | 0 | if (root->parse->havingQual != NULL) |
764 | 0 | { |
765 | 0 | List *having_exprs; |
766 | |
|
767 | 0 | having_exprs = pull_var_clause((Node *) root->parse->havingQual, |
768 | 0 | PVC_INCLUDE_AGGREGATES | |
769 | 0 | PVC_RECURSE_PLACEHOLDERS); |
770 | 0 | if (having_exprs != NIL) |
771 | 0 | { |
772 | 0 | tlist_exprs = list_concat(tlist_exprs, having_exprs); |
773 | 0 | list_free(having_exprs); |
774 | 0 | } |
775 | 0 | } |
776 | |
|
777 | 0 | foreach(lc, tlist_exprs) |
778 | 0 | { |
779 | 0 | Expr *expr = (Expr *) lfirst(lc); |
780 | 0 | Aggref *aggref; |
781 | 0 | Relids agg_eval_at; |
782 | 0 | AggClauseInfo *ac_info; |
783 | | |
784 | | /* For now we don't try to support GROUPING() expressions */ |
785 | 0 | if (IsA(expr, GroupingFunc)) |
786 | 0 | { |
787 | 0 | eager_agg_applicable = false; |
788 | 0 | break; |
789 | 0 | } |
790 | | |
791 | | /* Collect plain Vars for future reference */ |
792 | 0 | if (IsA(expr, Var)) |
793 | 0 | { |
794 | 0 | tlist_vars = list_append_unique(tlist_vars, expr); |
795 | 0 | continue; |
796 | 0 | } |
797 | | |
798 | 0 | aggref = castNode(Aggref, expr); |
799 | |
|
800 | 0 | Assert(aggref->aggorder == NIL); |
801 | 0 | 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 | | */ |
808 | 0 | if (contain_volatile_functions((Node *) aggref)) |
809 | 0 | { |
810 | 0 | eager_agg_applicable = false; |
811 | 0 | break; |
812 | 0 | } |
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 | | */ |
819 | 0 | if (root->qual_security_level > 0 && |
820 | 0 | !get_func_leakproof(aggref->aggfnoid)) |
821 | 0 | { |
822 | 0 | eager_agg_applicable = false; |
823 | 0 | break; |
824 | 0 | } |
825 | | |
826 | 0 | 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 | 0 | aggregate_relids = bms_add_members(aggregate_relids, agg_eval_at); |
833 | 0 | if (bms_is_subset(root->all_baserels, aggregate_relids)) |
834 | 0 | { |
835 | 0 | eager_agg_applicable = false; |
836 | 0 | break; |
837 | 0 | } |
838 | | |
839 | | /* OK, create the AggClauseInfo node */ |
840 | 0 | ac_info = makeNode(AggClauseInfo); |
841 | 0 | ac_info->aggref = aggref; |
842 | 0 | ac_info->agg_eval_at = agg_eval_at; |
843 | | |
844 | | /* ... and add it to the list */ |
845 | 0 | agg_clause_list = list_append_unique(agg_clause_list, ac_info); |
846 | 0 | } |
847 | |
|
848 | 0 | list_free(tlist_exprs); |
849 | |
|
850 | 0 | if (eager_agg_applicable) |
851 | 0 | { |
852 | 0 | root->agg_clause_list = agg_clause_list; |
853 | 0 | root->tlist_vars = tlist_vars; |
854 | 0 | } |
855 | 0 | else |
856 | 0 | { |
857 | 0 | list_free_deep(agg_clause_list); |
858 | 0 | list_free(tlist_vars); |
859 | 0 | } |
860 | 0 | } |
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 | | create_grouping_expr_infos(PlannerInfo *root) |
871 | 0 | { |
872 | 0 | List *exprs = NIL; |
873 | 0 | List *sortgrouprefs = NIL; |
874 | 0 | List *ecs = NIL; |
875 | 0 | ListCell *lc, |
876 | 0 | *lc1, |
877 | 0 | *lc2, |
878 | 0 | *lc3; |
879 | |
|
880 | 0 | Assert(root->group_expr_list == NIL); |
881 | |
|
882 | 0 | foreach(lc, root->processed_groupClause) |
883 | 0 | { |
884 | 0 | SortGroupClause *sgc = lfirst_node(SortGroupClause, lc); |
885 | 0 | TargetEntry *tle = get_sortgroupclause_tle(sgc, root->processed_tlist); |
886 | 0 | TypeCacheEntry *tce; |
887 | 0 | Oid equalimageproc; |
888 | |
|
889 | 0 | Assert(tle->ressortgroupref > 0); |
890 | | |
891 | | /* |
892 | | * For now we only support plain Vars as grouping expressions. |
893 | | */ |
894 | 0 | if (!IsA(tle->expr, Var)) |
895 | 0 | 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 | 0 | tce = lookup_type_cache(exprType((Node *) tle->expr), |
908 | 0 | TYPECACHE_BTREE_OPFAMILY); |
909 | 0 | if (!OidIsValid(tce->btree_opf) || |
910 | 0 | !OidIsValid(tce->btree_opintype)) |
911 | 0 | return; |
912 | | |
913 | 0 | equalimageproc = get_opfamily_proc(tce->btree_opf, |
914 | 0 | tce->btree_opintype, |
915 | 0 | tce->btree_opintype, |
916 | 0 | 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 | 0 | if (!OidIsValid(equalimageproc) || |
926 | 0 | !DatumGetBool(OidFunctionCall1Coll(equalimageproc, |
927 | 0 | exprCollation((Node *) tle->expr), |
928 | 0 | ObjectIdGetDatum(tce->btree_opintype)))) |
929 | 0 | return; |
930 | | |
931 | 0 | exprs = lappend(exprs, tle->expr); |
932 | 0 | sortgrouprefs = lappend_int(sortgrouprefs, tle->ressortgroupref); |
933 | 0 | ecs = lappend(ecs, get_eclass_for_sortgroupclause(root, sgc, tle->expr)); |
934 | 0 | } |
935 | | |
936 | | /* |
937 | | * Construct a GroupingExprInfo for each expression. |
938 | | */ |
939 | 0 | forthree(lc1, exprs, lc2, sortgrouprefs, lc3, ecs) |
940 | 0 | { |
941 | 0 | Expr *expr = (Expr *) lfirst(lc1); |
942 | 0 | int sortgroupref = lfirst_int(lc2); |
943 | 0 | EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc3); |
944 | 0 | GroupingExprInfo *ge_info; |
945 | |
|
946 | 0 | ge_info = makeNode(GroupingExprInfo); |
947 | 0 | ge_info->expr = (Expr *) copyObject(expr); |
948 | 0 | ge_info->sortgroupref = sortgroupref; |
949 | 0 | ge_info->ec = ec; |
950 | |
|
951 | 0 | root->group_expr_list = lappend(root->group_expr_list, ge_info); |
952 | 0 | } |
953 | 0 | } |
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 | | get_eclass_for_sortgroupclause(PlannerInfo *root, SortGroupClause *sgc, |
962 | | Expr *expr) |
963 | 0 | { |
964 | 0 | Oid opfamily, |
965 | 0 | opcintype, |
966 | 0 | collation; |
967 | 0 | CompareType cmptype; |
968 | 0 | Oid equality_op; |
969 | 0 | List *opfamilies; |
970 | | |
971 | | /* Punt if the group clause is not sortable */ |
972 | 0 | if (!OidIsValid(sgc->sortop)) |
973 | 0 | return NULL; |
974 | | |
975 | | /* Find the operator in pg_amop --- failure shouldn't happen */ |
976 | 0 | if (!get_ordering_op_properties(sgc->sortop, |
977 | 0 | &opfamily, &opcintype, &cmptype)) |
978 | 0 | elog(ERROR, "operator %u is not a valid ordering operator", |
979 | 0 | sgc->sortop); |
980 | | |
981 | | /* Because SortGroupClause doesn't carry collation, consult the expr */ |
982 | 0 | 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 | 0 | equality_op = get_opfamily_member_for_cmptype(opfamily, |
991 | 0 | opcintype, |
992 | 0 | opcintype, |
993 | 0 | COMPARE_EQ); |
994 | 0 | if (!OidIsValid(equality_op)) /* shouldn't happen */ |
995 | 0 | elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", |
996 | 0 | COMPARE_EQ, opcintype, opcintype, opfamily); |
997 | 0 | opfamilies = get_mergejoin_opfamilies(equality_op); |
998 | 0 | if (!opfamilies) /* certainly should find some */ |
999 | 0 | elog(ERROR, "could not find opfamilies for equality operator %u", |
1000 | 0 | equality_op); |
1001 | | |
1002 | | /* Now find a matching EquivalenceClass */ |
1003 | 0 | return get_eclass_for_sort_expr(root, expr, opfamilies, opcintype, |
1004 | 0 | collation, sgc->tleSortGroupRef, |
1005 | 0 | NULL, false); |
1006 | 0 | } |
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 |
1035 | | find_lateral_references(PlannerInfo *root) |
1036 | 0 | { |
1037 | 0 | Index rti; |
1038 | | |
1039 | | /* We need do nothing if the query contains no LATERAL RTEs */ |
1040 | 0 | if (!root->hasLateralRTEs) |
1041 | 0 | return; |
1042 | | |
1043 | | /* |
1044 | | * Examine all baserels (the rel array has been set up by now). |
1045 | | */ |
1046 | 0 | for (rti = 1; rti < root->simple_rel_array_size; rti++) |
1047 | 0 | { |
1048 | 0 | RelOptInfo *brel = root->simple_rel_array[rti]; |
1049 | | |
1050 | | /* there may be empty slots corresponding to non-baserel RTEs */ |
1051 | 0 | if (brel == NULL) |
1052 | 0 | continue; |
1053 | | |
1054 | 0 | 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" */ |
1075 | 0 | if (brel->reloptkind != RELOPT_BASEREL) |
1076 | 0 | continue; |
1077 | | |
1078 | 0 | extract_lateral_references(root, brel, rti); |
1079 | 0 | } |
1080 | 0 | } |
1081 | | |
1082 | | static void |
1083 | | extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex) |
1084 | 0 | { |
1085 | 0 | RangeTblEntry *rte = root->simple_rte_array[rtindex]; |
1086 | 0 | List *vars; |
1087 | 0 | List *newvars; |
1088 | 0 | Relids where_needed; |
1089 | 0 | ListCell *lc; |
1090 | | |
1091 | | /* No cross-references are possible if it's not LATERAL */ |
1092 | 0 | if (!rte->lateral) |
1093 | 0 | return; |
1094 | | |
1095 | | /* Fetch the appropriate variables */ |
1096 | 0 | if (rte->rtekind == RTE_RELATION) |
1097 | 0 | vars = pull_vars_of_level((Node *) rte->tablesample, 0); |
1098 | 0 | else if (rte->rtekind == RTE_SUBQUERY) |
1099 | 0 | vars = pull_vars_of_level((Node *) rte->subquery, 1); |
1100 | 0 | else if (rte->rtekind == RTE_FUNCTION) |
1101 | 0 | vars = pull_vars_of_level((Node *) rte->functions, 0); |
1102 | 0 | else if (rte->rtekind == RTE_TABLEFUNC) |
1103 | 0 | vars = pull_vars_of_level((Node *) rte->tablefunc, 0); |
1104 | 0 | else if (rte->rtekind == RTE_VALUES) |
1105 | 0 | vars = pull_vars_of_level((Node *) rte->values_lists, 0); |
1106 | 0 | else |
1107 | 0 | { |
1108 | 0 | Assert(false); |
1109 | 0 | return; /* keep compiler quiet */ |
1110 | 0 | } |
1111 | | |
1112 | 0 | if (vars == NIL) |
1113 | 0 | return; /* nothing to do */ |
1114 | | |
1115 | | /* Copy each Var (or PlaceHolderVar) and adjust it to match our level */ |
1116 | 0 | newvars = NIL; |
1117 | 0 | foreach(lc, vars) |
1118 | 0 | { |
1119 | 0 | Node *node = (Node *) lfirst(lc); |
1120 | |
|
1121 | 0 | node = copyObject(node); |
1122 | 0 | if (IsA(node, Var)) |
1123 | 0 | { |
1124 | 0 | Var *var = (Var *) node; |
1125 | | |
1126 | | /* Adjustment is easy since it's just one node */ |
1127 | 0 | var->varlevelsup = 0; |
1128 | 0 | } |
1129 | 0 | else if (IsA(node, PlaceHolderVar)) |
1130 | 0 | { |
1131 | 0 | PlaceHolderVar *phv = (PlaceHolderVar *) node; |
1132 | 0 | 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 | | */ |
1139 | 0 | if (levelsup != 0) |
1140 | 0 | IncrementVarSublevelsUp(node, -levelsup, 0); |
1141 | 0 | } |
1142 | 0 | else |
1143 | 0 | Assert(false); |
1144 | 0 | newvars = lappend(newvars, node); |
1145 | 0 | } |
1146 | |
|
1147 | 0 | 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 | | */ |
1156 | 0 | where_needed = bms_make_singleton(rtindex); |
1157 | | |
1158 | | /* |
1159 | | * Push Vars into their source relations' targetlists, and PHVs into |
1160 | | * root->placeholder_list. |
1161 | | */ |
1162 | 0 | add_vars_to_targetlist(root, newvars, where_needed); |
1163 | | |
1164 | | /* Remember the lateral references for create_lateral_join_info */ |
1165 | 0 | brel->lateral_vars = newvars; |
1166 | 0 | } |
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 | | create_lateral_join_info(PlannerInfo *root) |
1175 | 0 | { |
1176 | 0 | bool found_laterals = false; |
1177 | 0 | Index rti; |
1178 | 0 | ListCell *lc; |
1179 | | |
1180 | | /* We need do nothing if the query contains no LATERAL RTEs */ |
1181 | 0 | if (!root->hasLateralRTEs) |
1182 | 0 | return; |
1183 | | |
1184 | | /* We'll need to have the ph_eval_at values for PlaceHolderVars */ |
1185 | 0 | Assert(root->placeholdersFrozen); |
1186 | | |
1187 | | /* |
1188 | | * Examine all baserels (the rel array has been set up by now). |
1189 | | */ |
1190 | 0 | for (rti = 1; rti < root->simple_rel_array_size; rti++) |
1191 | 0 | { |
1192 | 0 | RelOptInfo *brel = root->simple_rel_array[rti]; |
1193 | 0 | Relids lateral_relids; |
1194 | | |
1195 | | /* there may be empty slots corresponding to non-baserel RTEs */ |
1196 | 0 | if (brel == NULL) |
1197 | 0 | continue; |
1198 | | |
1199 | 0 | Assert(brel->relid == rti); /* sanity check on array */ |
1200 | | |
1201 | | /* ignore RTEs that are "other rels" */ |
1202 | 0 | if (brel->reloptkind != RELOPT_BASEREL) |
1203 | 0 | continue; |
1204 | | |
1205 | 0 | lateral_relids = NULL; |
1206 | | |
1207 | | /* consider each laterally-referenced Var or PHV */ |
1208 | 0 | foreach(lc, brel->lateral_vars) |
1209 | 0 | { |
1210 | 0 | Node *node = (Node *) lfirst(lc); |
1211 | |
|
1212 | 0 | if (IsA(node, Var)) |
1213 | 0 | { |
1214 | 0 | Var *var = (Var *) node; |
1215 | |
|
1216 | 0 | found_laterals = true; |
1217 | 0 | lateral_relids = bms_add_member(lateral_relids, |
1218 | 0 | var->varno); |
1219 | 0 | } |
1220 | 0 | else if (IsA(node, PlaceHolderVar)) |
1221 | 0 | { |
1222 | 0 | PlaceHolderVar *phv = (PlaceHolderVar *) node; |
1223 | 0 | PlaceHolderInfo *phinfo = find_placeholder_info(root, phv); |
1224 | |
|
1225 | 0 | found_laterals = true; |
1226 | 0 | lateral_relids = bms_add_members(lateral_relids, |
1227 | 0 | phinfo->ph_eval_at); |
1228 | 0 | } |
1229 | 0 | else |
1230 | 0 | Assert(false); |
1231 | 0 | } |
1232 | | |
1233 | | /* We now have all the simple lateral refs from this rel */ |
1234 | 0 | brel->direct_lateral_relids = lateral_relids; |
1235 | 0 | brel->lateral_relids = bms_copy(lateral_relids); |
1236 | 0 | } |
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 | | */ |
1251 | 0 | foreach(lc, root->placeholder_list) |
1252 | 0 | { |
1253 | 0 | PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc); |
1254 | 0 | Relids eval_at = phinfo->ph_eval_at; |
1255 | 0 | Relids lateral_refs; |
1256 | 0 | int varno; |
1257 | |
|
1258 | 0 | if (phinfo->ph_lateral == NULL) |
1259 | 0 | continue; /* PHV is uninteresting if no lateral refs */ |
1260 | | |
1261 | 0 | 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 | | */ |
1269 | 0 | lateral_refs = bms_intersect(phinfo->ph_lateral, root->all_baserels); |
1270 | 0 | Assert(!bms_is_empty(lateral_refs)); |
1271 | |
|
1272 | 0 | if (bms_get_singleton_member(eval_at, &varno)) |
1273 | 0 | { |
1274 | | /* Evaluation site is a baserel */ |
1275 | 0 | RelOptInfo *brel = find_base_rel(root, varno); |
1276 | |
|
1277 | 0 | brel->direct_lateral_relids = |
1278 | 0 | bms_add_members(brel->direct_lateral_relids, |
1279 | 0 | lateral_refs); |
1280 | 0 | brel->lateral_relids = |
1281 | 0 | bms_add_members(brel->lateral_relids, |
1282 | 0 | lateral_refs); |
1283 | 0 | } |
1284 | 0 | else |
1285 | 0 | { |
1286 | | /* Evaluation site is a join */ |
1287 | 0 | varno = -1; |
1288 | 0 | while ((varno = bms_next_member(eval_at, varno)) >= 0) |
1289 | 0 | { |
1290 | 0 | RelOptInfo *brel = find_base_rel_ignore_join(root, varno); |
1291 | |
|
1292 | 0 | if (brel == NULL) |
1293 | 0 | continue; /* ignore outer joins in eval_at */ |
1294 | 0 | brel->lateral_relids = bms_add_members(brel->lateral_relids, |
1295 | 0 | lateral_refs); |
1296 | 0 | } |
1297 | 0 | } |
1298 | 0 | } |
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 | 0 | if (!found_laterals) |
1305 | 0 | { |
1306 | 0 | root->hasLateralRTEs = false; |
1307 | 0 | return; |
1308 | 0 | } |
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 | 0 | for (rti = 1; rti < root->simple_rel_array_size; rti++) |
1322 | 0 | { |
1323 | 0 | RelOptInfo *brel = root->simple_rel_array[rti]; |
1324 | 0 | Relids outer_lateral_relids; |
1325 | 0 | Index rti2; |
1326 | |
|
1327 | 0 | if (brel == NULL || brel->reloptkind != RELOPT_BASEREL) |
1328 | 0 | continue; |
1329 | | |
1330 | | /* need not consider baserel further if it has no lateral refs */ |
1331 | 0 | outer_lateral_relids = brel->lateral_relids; |
1332 | 0 | if (outer_lateral_relids == NULL) |
1333 | 0 | continue; |
1334 | | |
1335 | | /* else scan all baserels */ |
1336 | 0 | for (rti2 = 1; rti2 < root->simple_rel_array_size; rti2++) |
1337 | 0 | { |
1338 | 0 | RelOptInfo *brel2 = root->simple_rel_array[rti2]; |
1339 | |
|
1340 | 0 | if (brel2 == NULL || brel2->reloptkind != RELOPT_BASEREL) |
1341 | 0 | continue; |
1342 | | |
1343 | | /* if brel2 has lateral ref to brel, propagate brel's refs */ |
1344 | 0 | if (bms_is_member(rti, brel2->lateral_relids)) |
1345 | 0 | brel2->lateral_relids = bms_add_members(brel2->lateral_relids, |
1346 | 0 | outer_lateral_relids); |
1347 | 0 | } |
1348 | 0 | } |
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 | 0 | for (rti = 1; rti < root->simple_rel_array_size; rti++) |
1356 | 0 | { |
1357 | 0 | RelOptInfo *brel = root->simple_rel_array[rti]; |
1358 | 0 | Relids lateral_relids; |
1359 | 0 | int rti2; |
1360 | |
|
1361 | 0 | if (brel == NULL || brel->reloptkind != RELOPT_BASEREL) |
1362 | 0 | continue; |
1363 | | |
1364 | | /* Nothing to do at rels with no lateral refs */ |
1365 | 0 | lateral_relids = brel->lateral_relids; |
1366 | 0 | if (bms_is_empty(lateral_relids)) |
1367 | 0 | continue; |
1368 | | |
1369 | | /* No rel should have a lateral dependency on itself */ |
1370 | 0 | Assert(!bms_is_member(rti, lateral_relids)); |
1371 | | |
1372 | | /* Mark this rel's referencees */ |
1373 | 0 | rti2 = -1; |
1374 | 0 | while ((rti2 = bms_next_member(lateral_relids, rti2)) >= 0) |
1375 | 0 | { |
1376 | 0 | RelOptInfo *brel2 = root->simple_rel_array[rti2]; |
1377 | |
|
1378 | 0 | if (brel2 == NULL) |
1379 | 0 | continue; /* must be an OJ */ |
1380 | | |
1381 | 0 | Assert(brel2->reloptkind == RELOPT_BASEREL); |
1382 | 0 | brel2->lateral_referencers = |
1383 | 0 | bms_add_member(brel2->lateral_referencers, rti); |
1384 | 0 | } |
1385 | 0 | } |
1386 | 0 | } |
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 * |
1413 | | deconstruct_jointree(PlannerInfo *root) |
1414 | 0 | { |
1415 | 0 | List *result; |
1416 | 0 | JoinDomain *top_jdomain; |
1417 | 0 | List *item_list = NIL; |
1418 | 0 | 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 | | */ |
1425 | 0 | root->placeholdersFrozen = true; |
1426 | | |
1427 | | /* Fetch the already-created top-level join domain for the query */ |
1428 | 0 | top_jdomain = linitial_node(JoinDomain, root->join_domains); |
1429 | 0 | top_jdomain->jd_relids = NULL; /* filled during deconstruct_recurse */ |
1430 | | |
1431 | | /* Start recursion at top of jointree */ |
1432 | 0 | Assert(root->parse->jointree != NULL && |
1433 | 0 | IsA(root->parse->jointree, FromExpr)); |
1434 | | |
1435 | | /* These are filled as we scan the jointree */ |
1436 | 0 | root->all_baserels = NULL; |
1437 | 0 | root->outer_join_rels = NULL; |
1438 | | |
1439 | | /* Perform the initial scan of the jointree */ |
1440 | 0 | result = deconstruct_recurse(root, (Node *) root->parse->jointree, |
1441 | 0 | top_jdomain, NULL, |
1442 | 0 | &item_list); |
1443 | | |
1444 | | /* Now we can form the value of all_query_rels, too */ |
1445 | 0 | 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 | 0 | Assert(bms_equal(root->all_query_rels, top_jdomain->jd_relids)); |
1449 | | |
1450 | | /* Now scan all the jointree nodes again, and distribute quals */ |
1451 | 0 | foreach(lc, item_list) |
1452 | 0 | { |
1453 | 0 | JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc); |
1454 | |
|
1455 | 0 | deconstruct_distribute(root, jtitem); |
1456 | 0 | } |
1457 | | |
1458 | | /* |
1459 | | * If there were any special joins then we may have some postponed LEFT |
1460 | | * JOIN clauses to deal with. |
1461 | | */ |
1462 | 0 | if (root->join_info_list) |
1463 | 0 | { |
1464 | 0 | foreach(lc, item_list) |
1465 | 0 | { |
1466 | 0 | JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc); |
1467 | |
|
1468 | 0 | if (jtitem->oj_joinclauses != NIL) |
1469 | 0 | deconstruct_distribute_oj_quals(root, item_list, jtitem); |
1470 | 0 | } |
1471 | 0 | } |
1472 | | |
1473 | | /* Don't need the JoinTreeItems any more */ |
1474 | 0 | list_free_deep(item_list); |
1475 | |
|
1476 | 0 | return result; |
1477 | 0 | } |
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 * |
1495 | | deconstruct_recurse(PlannerInfo *root, Node *jtnode, |
1496 | | JoinDomain *parent_domain, |
1497 | | JoinTreeItem *parent_jtitem, |
1498 | | List **item_list) |
1499 | 0 | { |
1500 | 0 | List *joinlist; |
1501 | 0 | JoinTreeItem *jtitem; |
1502 | |
|
1503 | 0 | Assert(jtnode != NULL); |
1504 | | |
1505 | | /* Make the new JoinTreeItem, but don't add it to item_list yet */ |
1506 | 0 | jtitem = palloc0_object(JoinTreeItem); |
1507 | 0 | jtitem->jtnode = jtnode; |
1508 | 0 | jtitem->jti_parent = parent_jtitem; |
1509 | |
|
1510 | 0 | if (IsA(jtnode, RangeTblRef)) |
1511 | 0 | { |
1512 | 0 | int varno = ((RangeTblRef *) jtnode)->rtindex; |
1513 | | |
1514 | | /* Fill all_baserels as we encounter baserel jointree nodes */ |
1515 | 0 | root->all_baserels = bms_add_member(root->all_baserels, varno); |
1516 | | /* This node belongs to parent_domain */ |
1517 | 0 | jtitem->jdomain = parent_domain; |
1518 | 0 | parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids, |
1519 | 0 | varno); |
1520 | | /* qualscope is just the one RTE */ |
1521 | 0 | jtitem->qualscope = bms_make_singleton(varno); |
1522 | | /* A single baserel does not create an inner join */ |
1523 | 0 | jtitem->inner_join_rels = NULL; |
1524 | 0 | joinlist = list_make1(jtnode); |
1525 | 0 | } |
1526 | 0 | else if (IsA(jtnode, FromExpr)) |
1527 | 0 | { |
1528 | 0 | FromExpr *f = (FromExpr *) jtnode; |
1529 | 0 | int remaining; |
1530 | 0 | ListCell *l; |
1531 | | |
1532 | | /* This node belongs to parent_domain, as do its children */ |
1533 | 0 | 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 | 0 | jtitem->qualscope = NULL; |
1543 | 0 | jtitem->inner_join_rels = NULL; |
1544 | 0 | joinlist = NIL; |
1545 | 0 | remaining = list_length(f->fromlist); |
1546 | 0 | foreach(l, f->fromlist) |
1547 | 0 | { |
1548 | 0 | JoinTreeItem *sub_item; |
1549 | 0 | List *sub_joinlist; |
1550 | 0 | int sub_members; |
1551 | |
|
1552 | 0 | sub_joinlist = deconstruct_recurse(root, lfirst(l), |
1553 | 0 | parent_domain, |
1554 | 0 | jtitem, |
1555 | 0 | item_list); |
1556 | 0 | sub_item = (JoinTreeItem *) llast(*item_list); |
1557 | 0 | jtitem->qualscope = bms_add_members(jtitem->qualscope, |
1558 | 0 | sub_item->qualscope); |
1559 | 0 | jtitem->inner_join_rels = sub_item->inner_join_rels; |
1560 | 0 | sub_members = list_length(sub_joinlist); |
1561 | 0 | remaining--; |
1562 | 0 | if (sub_members <= 1 || |
1563 | 0 | list_length(joinlist) + sub_members + remaining <= from_collapse_limit) |
1564 | 0 | joinlist = list_concat(joinlist, sub_joinlist); |
1565 | 0 | else |
1566 | 0 | joinlist = lappend(joinlist, sub_joinlist); |
1567 | 0 | } |
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 | | */ |
1576 | 0 | if (list_length(f->fromlist) > 1) |
1577 | 0 | jtitem->inner_join_rels = jtitem->qualscope; |
1578 | 0 | } |
1579 | 0 | else if (IsA(jtnode, JoinExpr)) |
1580 | 0 | { |
1581 | 0 | JoinExpr *j = (JoinExpr *) jtnode; |
1582 | 0 | JoinDomain *child_domain, |
1583 | 0 | *fj_domain; |
1584 | 0 | JoinTreeItem *left_item, |
1585 | 0 | *right_item; |
1586 | 0 | List *leftjoinlist, |
1587 | 0 | *rightjoinlist; |
1588 | |
|
1589 | 0 | switch (j->jointype) |
1590 | 0 | { |
1591 | 0 | case JOIN_INNER: |
1592 | | /* This node belongs to parent_domain, as do its children */ |
1593 | 0 | jtitem->jdomain = parent_domain; |
1594 | | /* Recurse */ |
1595 | 0 | leftjoinlist = deconstruct_recurse(root, j->larg, |
1596 | 0 | parent_domain, |
1597 | 0 | jtitem, |
1598 | 0 | item_list); |
1599 | 0 | left_item = (JoinTreeItem *) llast(*item_list); |
1600 | 0 | rightjoinlist = deconstruct_recurse(root, j->rarg, |
1601 | 0 | parent_domain, |
1602 | 0 | jtitem, |
1603 | 0 | item_list); |
1604 | 0 | right_item = (JoinTreeItem *) llast(*item_list); |
1605 | | /* Compute qualscope etc */ |
1606 | 0 | jtitem->qualscope = bms_union(left_item->qualscope, |
1607 | 0 | right_item->qualscope); |
1608 | 0 | jtitem->inner_join_rels = jtitem->qualscope; |
1609 | 0 | jtitem->left_rels = left_item->qualscope; |
1610 | 0 | jtitem->right_rels = right_item->qualscope; |
1611 | | /* Inner join adds no restrictions for quals */ |
1612 | 0 | jtitem->nonnullable_rels = NULL; |
1613 | 0 | break; |
1614 | 0 | case JOIN_LEFT: |
1615 | 0 | case JOIN_ANTI: |
1616 | | /* Make new join domain for my quals and the RHS */ |
1617 | 0 | child_domain = makeNode(JoinDomain); |
1618 | 0 | child_domain->jd_relids = NULL; /* filled by recursion */ |
1619 | 0 | root->join_domains = lappend(root->join_domains, child_domain); |
1620 | 0 | jtitem->jdomain = child_domain; |
1621 | | /* Recurse */ |
1622 | 0 | leftjoinlist = deconstruct_recurse(root, j->larg, |
1623 | 0 | parent_domain, |
1624 | 0 | jtitem, |
1625 | 0 | item_list); |
1626 | 0 | left_item = (JoinTreeItem *) llast(*item_list); |
1627 | 0 | rightjoinlist = deconstruct_recurse(root, j->rarg, |
1628 | 0 | child_domain, |
1629 | 0 | jtitem, |
1630 | 0 | item_list); |
1631 | 0 | right_item = (JoinTreeItem *) llast(*item_list); |
1632 | | /* Compute join domain contents, qualscope etc */ |
1633 | 0 | parent_domain->jd_relids = |
1634 | 0 | bms_add_members(parent_domain->jd_relids, |
1635 | 0 | child_domain->jd_relids); |
1636 | 0 | jtitem->qualscope = bms_union(left_item->qualscope, |
1637 | 0 | right_item->qualscope); |
1638 | | /* caution: ANTI join derived from SEMI will lack rtindex */ |
1639 | 0 | if (j->rtindex != 0) |
1640 | 0 | { |
1641 | 0 | parent_domain->jd_relids = |
1642 | 0 | bms_add_member(parent_domain->jd_relids, |
1643 | 0 | j->rtindex); |
1644 | 0 | jtitem->qualscope = bms_add_member(jtitem->qualscope, |
1645 | 0 | j->rtindex); |
1646 | 0 | root->outer_join_rels = bms_add_member(root->outer_join_rels, |
1647 | 0 | j->rtindex); |
1648 | 0 | mark_rels_nulled_by_join(root, j->rtindex, |
1649 | 0 | right_item->qualscope); |
1650 | 0 | } |
1651 | 0 | jtitem->inner_join_rels = bms_union(left_item->inner_join_rels, |
1652 | 0 | right_item->inner_join_rels); |
1653 | 0 | jtitem->left_rels = left_item->qualscope; |
1654 | 0 | jtitem->right_rels = right_item->qualscope; |
1655 | 0 | jtitem->nonnullable_rels = left_item->qualscope; |
1656 | 0 | break; |
1657 | 0 | case JOIN_SEMI: |
1658 | | /* This node belongs to parent_domain, as do its children */ |
1659 | 0 | jtitem->jdomain = parent_domain; |
1660 | | /* Recurse */ |
1661 | 0 | leftjoinlist = deconstruct_recurse(root, j->larg, |
1662 | 0 | parent_domain, |
1663 | 0 | jtitem, |
1664 | 0 | item_list); |
1665 | 0 | left_item = (JoinTreeItem *) llast(*item_list); |
1666 | 0 | rightjoinlist = deconstruct_recurse(root, j->rarg, |
1667 | 0 | parent_domain, |
1668 | 0 | jtitem, |
1669 | 0 | item_list); |
1670 | 0 | right_item = (JoinTreeItem *) llast(*item_list); |
1671 | | /* Compute qualscope etc */ |
1672 | 0 | jtitem->qualscope = bms_union(left_item->qualscope, |
1673 | 0 | right_item->qualscope); |
1674 | | /* SEMI join never has rtindex, so don't add to anything */ |
1675 | 0 | Assert(j->rtindex == 0); |
1676 | 0 | jtitem->inner_join_rels = bms_union(left_item->inner_join_rels, |
1677 | 0 | right_item->inner_join_rels); |
1678 | 0 | jtitem->left_rels = left_item->qualscope; |
1679 | 0 | jtitem->right_rels = right_item->qualscope; |
1680 | | /* Semi join adds no restrictions for quals */ |
1681 | 0 | jtitem->nonnullable_rels = NULL; |
1682 | 0 | break; |
1683 | 0 | case JOIN_FULL: |
1684 | | /* The FULL JOIN's quals need their very own domain */ |
1685 | 0 | fj_domain = makeNode(JoinDomain); |
1686 | 0 | root->join_domains = lappend(root->join_domains, fj_domain); |
1687 | 0 | jtitem->jdomain = fj_domain; |
1688 | | /* Recurse, giving each side its own join domain */ |
1689 | 0 | child_domain = makeNode(JoinDomain); |
1690 | 0 | child_domain->jd_relids = NULL; /* filled by recursion */ |
1691 | 0 | root->join_domains = lappend(root->join_domains, child_domain); |
1692 | 0 | leftjoinlist = deconstruct_recurse(root, j->larg, |
1693 | 0 | child_domain, |
1694 | 0 | jtitem, |
1695 | 0 | item_list); |
1696 | 0 | left_item = (JoinTreeItem *) llast(*item_list); |
1697 | 0 | fj_domain->jd_relids = bms_copy(child_domain->jd_relids); |
1698 | 0 | child_domain = makeNode(JoinDomain); |
1699 | 0 | child_domain->jd_relids = NULL; /* filled by recursion */ |
1700 | 0 | root->join_domains = lappend(root->join_domains, child_domain); |
1701 | 0 | rightjoinlist = deconstruct_recurse(root, j->rarg, |
1702 | 0 | child_domain, |
1703 | 0 | jtitem, |
1704 | 0 | item_list); |
1705 | 0 | right_item = (JoinTreeItem *) llast(*item_list); |
1706 | | /* Compute qualscope etc */ |
1707 | 0 | fj_domain->jd_relids = bms_add_members(fj_domain->jd_relids, |
1708 | 0 | child_domain->jd_relids); |
1709 | 0 | parent_domain->jd_relids = bms_add_members(parent_domain->jd_relids, |
1710 | 0 | fj_domain->jd_relids); |
1711 | 0 | jtitem->qualscope = bms_union(left_item->qualscope, |
1712 | 0 | right_item->qualscope); |
1713 | 0 | Assert(j->rtindex != 0); |
1714 | 0 | parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids, |
1715 | 0 | j->rtindex); |
1716 | 0 | jtitem->qualscope = bms_add_member(jtitem->qualscope, |
1717 | 0 | j->rtindex); |
1718 | 0 | root->outer_join_rels = bms_add_member(root->outer_join_rels, |
1719 | 0 | j->rtindex); |
1720 | 0 | mark_rels_nulled_by_join(root, j->rtindex, |
1721 | 0 | left_item->qualscope); |
1722 | 0 | mark_rels_nulled_by_join(root, j->rtindex, |
1723 | 0 | right_item->qualscope); |
1724 | 0 | jtitem->inner_join_rels = bms_union(left_item->inner_join_rels, |
1725 | 0 | right_item->inner_join_rels); |
1726 | 0 | jtitem->left_rels = left_item->qualscope; |
1727 | 0 | jtitem->right_rels = right_item->qualscope; |
1728 | | /* each side is both outer and inner */ |
1729 | 0 | jtitem->nonnullable_rels = jtitem->qualscope; |
1730 | 0 | break; |
1731 | 0 | default: |
1732 | | /* JOIN_RIGHT was eliminated during reduce_outer_joins() */ |
1733 | 0 | elog(ERROR, "unrecognized join type: %d", |
1734 | 0 | (int) j->jointype); |
1735 | 0 | leftjoinlist = rightjoinlist = NIL; /* keep compiler quiet */ |
1736 | 0 | break; |
1737 | 0 | } |
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 | | */ |
1743 | 0 | if (j->jointype == JOIN_FULL) |
1744 | 0 | { |
1745 | | /* force the join order exactly at this node */ |
1746 | 0 | joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist)); |
1747 | 0 | } |
1748 | 0 | else if (list_length(leftjoinlist) + list_length(rightjoinlist) <= |
1749 | 0 | join_collapse_limit) |
1750 | 0 | { |
1751 | | /* OK to combine subproblems */ |
1752 | 0 | joinlist = list_concat(leftjoinlist, rightjoinlist); |
1753 | 0 | } |
1754 | 0 | else |
1755 | 0 | { |
1756 | | /* can't combine, but needn't force join order above here */ |
1757 | 0 | Node *leftpart, |
1758 | 0 | *rightpart; |
1759 | | |
1760 | | /* avoid creating useless 1-element sublists */ |
1761 | 0 | if (list_length(leftjoinlist) == 1) |
1762 | 0 | leftpart = (Node *) linitial(leftjoinlist); |
1763 | 0 | else |
1764 | 0 | leftpart = (Node *) leftjoinlist; |
1765 | 0 | if (list_length(rightjoinlist) == 1) |
1766 | 0 | rightpart = (Node *) linitial(rightjoinlist); |
1767 | 0 | else |
1768 | 0 | rightpart = (Node *) rightjoinlist; |
1769 | 0 | joinlist = list_make2(leftpart, rightpart); |
1770 | 0 | } |
1771 | 0 | } |
1772 | 0 | else |
1773 | 0 | { |
1774 | 0 | elog(ERROR, "unrecognized node type: %d", |
1775 | 0 | (int) nodeTag(jtnode)); |
1776 | 0 | joinlist = NIL; /* keep compiler quiet */ |
1777 | 0 | } |
1778 | | |
1779 | | /* Finally, we can add the new JoinTreeItem to item_list */ |
1780 | 0 | *item_list = lappend(*item_list, jtitem); |
1781 | |
|
1782 | 0 | return joinlist; |
1783 | 0 | } |
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 |
1793 | | deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem) |
1794 | 0 | { |
1795 | 0 | Node *jtnode = jtitem->jtnode; |
1796 | |
|
1797 | 0 | if (IsA(jtnode, RangeTblRef)) |
1798 | 0 | { |
1799 | 0 | int varno = ((RangeTblRef *) jtnode)->rtindex; |
1800 | | |
1801 | | /* Deal with any securityQuals attached to the RTE */ |
1802 | 0 | if (root->qual_security_level > 0) |
1803 | 0 | process_security_barrier_quals(root, |
1804 | 0 | varno, |
1805 | 0 | jtitem); |
1806 | 0 | } |
1807 | 0 | else if (IsA(jtnode, FromExpr)) |
1808 | 0 | { |
1809 | 0 | FromExpr *f = (FromExpr *) jtnode; |
1810 | | |
1811 | | /* |
1812 | | * Process any lateral-referencing quals that were postponed to this |
1813 | | * level by children. |
1814 | | */ |
1815 | 0 | distribute_quals_to_rels(root, jtitem->lateral_clauses, |
1816 | 0 | jtitem, |
1817 | 0 | NULL, |
1818 | 0 | root->qual_security_level, |
1819 | 0 | jtitem->qualscope, |
1820 | 0 | NULL, NULL, NULL, |
1821 | 0 | true, false, false, |
1822 | 0 | NULL); |
1823 | | |
1824 | | /* |
1825 | | * Now process the top-level quals. |
1826 | | */ |
1827 | 0 | distribute_quals_to_rels(root, (List *) f->quals, |
1828 | 0 | jtitem, |
1829 | 0 | NULL, |
1830 | 0 | root->qual_security_level, |
1831 | 0 | jtitem->qualscope, |
1832 | 0 | NULL, NULL, NULL, |
1833 | 0 | true, false, false, |
1834 | 0 | NULL); |
1835 | 0 | } |
1836 | 0 | else if (IsA(jtnode, JoinExpr)) |
1837 | 0 | { |
1838 | 0 | JoinExpr *j = (JoinExpr *) jtnode; |
1839 | 0 | Relids ojscope; |
1840 | 0 | List *my_quals; |
1841 | 0 | SpecialJoinInfo *sjinfo; |
1842 | 0 | 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 | | */ |
1850 | 0 | my_quals = list_concat(jtitem->lateral_clauses, |
1851 | 0 | (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 | | */ |
1860 | 0 | if (j->jointype != JOIN_INNER) |
1861 | 0 | { |
1862 | 0 | sjinfo = make_outerjoininfo(root, |
1863 | 0 | jtitem->left_rels, |
1864 | 0 | jtitem->right_rels, |
1865 | 0 | jtitem->inner_join_rels, |
1866 | 0 | j->jointype, |
1867 | 0 | j->rtindex, |
1868 | 0 | my_quals); |
1869 | 0 | jtitem->sjinfo = sjinfo; |
1870 | 0 | if (j->jointype == JOIN_SEMI) |
1871 | 0 | ojscope = NULL; |
1872 | 0 | else |
1873 | 0 | ojscope = bms_union(sjinfo->min_lefthand, |
1874 | 0 | sjinfo->min_righthand); |
1875 | 0 | } |
1876 | 0 | else |
1877 | 0 | { |
1878 | 0 | sjinfo = NULL; |
1879 | 0 | ojscope = NULL; |
1880 | 0 | } |
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 | | */ |
1889 | 0 | if (j->jointype == JOIN_LEFT && sjinfo->lhs_strict) |
1890 | 0 | { |
1891 | 0 | 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 | | */ |
1902 | 0 | ojscope = bms_add_members(ojscope, sjinfo->commute_below_l); |
1903 | 0 | ojscope = bms_add_members(ojscope, sjinfo->commute_below_r); |
1904 | 0 | } |
1905 | 0 | else |
1906 | 0 | postponed_oj_qual_list = NULL; |
1907 | | |
1908 | | /* Process the JOIN's qual clauses */ |
1909 | 0 | distribute_quals_to_rels(root, my_quals, |
1910 | 0 | jtitem, |
1911 | 0 | sjinfo, |
1912 | 0 | root->qual_security_level, |
1913 | 0 | jtitem->qualscope, |
1914 | 0 | ojscope, jtitem->nonnullable_rels, |
1915 | 0 | NULL, /* incompatible_relids */ |
1916 | 0 | true, /* allow_equivalence */ |
1917 | 0 | false, false, /* not clones */ |
1918 | 0 | postponed_oj_qual_list); |
1919 | | |
1920 | | /* And add the SpecialJoinInfo to join_info_list */ |
1921 | 0 | if (sjinfo) |
1922 | 0 | root->join_info_list = lappend(root->join_info_list, sjinfo); |
1923 | 0 | } |
1924 | 0 | else |
1925 | 0 | { |
1926 | 0 | elog(ERROR, "unrecognized node type: %d", |
1927 | 0 | (int) nodeTag(jtnode)); |
1928 | 0 | } |
1929 | 0 | } |
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 |
1945 | | process_security_barrier_quals(PlannerInfo *root, |
1946 | | int rti, JoinTreeItem *jtitem) |
1947 | 0 | { |
1948 | 0 | RangeTblEntry *rte = root->simple_rte_array[rti]; |
1949 | 0 | Index security_level = 0; |
1950 | 0 | 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 | 0 | foreach(lc, rte->securityQuals) |
1959 | 0 | { |
1960 | 0 | 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 | | */ |
1968 | 0 | distribute_quals_to_rels(root, qualset, |
1969 | 0 | jtitem, |
1970 | 0 | NULL, |
1971 | 0 | security_level, |
1972 | 0 | jtitem->qualscope, |
1973 | 0 | jtitem->qualscope, |
1974 | 0 | NULL, |
1975 | 0 | NULL, |
1976 | 0 | true, |
1977 | 0 | false, false, /* not clones */ |
1978 | 0 | NULL); |
1979 | 0 | security_level++; |
1980 | 0 | } |
1981 | | |
1982 | | /* Assert that qual_security_level is higher than anything we just used */ |
1983 | 0 | Assert(security_level <= root->qual_security_level); |
1984 | 0 | } |
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 |
1995 | | mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid, |
1996 | | Relids lower_rels) |
1997 | 0 | { |
1998 | 0 | int relid = -1; |
1999 | |
|
2000 | 0 | while ((relid = bms_next_member(lower_rels, relid)) > 0) |
2001 | 0 | { |
2002 | 0 | RelOptInfo *rel = root->simple_rel_array[relid]; |
2003 | | |
2004 | | /* ignore the RTE_GROUP RTE */ |
2005 | 0 | if (relid == root->group_rtindex) |
2006 | 0 | continue; |
2007 | | |
2008 | 0 | if (rel == NULL) /* must be an outer join */ |
2009 | 0 | { |
2010 | 0 | Assert(bms_is_member(relid, root->outer_join_rels)); |
2011 | 0 | continue; |
2012 | 0 | } |
2013 | 0 | rel->nulling_relids = bms_add_member(rel->nulling_relids, ojrelid); |
2014 | 0 | } |
2015 | 0 | } |
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 * |
2037 | | 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 | 0 | { |
2043 | 0 | SpecialJoinInfo *sjinfo = makeNode(SpecialJoinInfo); |
2044 | 0 | Relids clause_relids; |
2045 | 0 | Relids strict_relids; |
2046 | 0 | Relids min_lefthand; |
2047 | 0 | Relids min_righthand; |
2048 | 0 | Relids commute_below_l; |
2049 | 0 | Relids commute_below_r; |
2050 | 0 | ListCell *l; |
2051 | | |
2052 | | /* |
2053 | | * We should not see RIGHT JOIN here because left/right were switched |
2054 | | * earlier |
2055 | | */ |
2056 | 0 | Assert(jointype != JOIN_INNER); |
2057 | 0 | 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 | | */ |
2074 | 0 | foreach(l, root->parse->rowMarks) |
2075 | 0 | { |
2076 | 0 | RowMarkClause *rc = (RowMarkClause *) lfirst(l); |
2077 | |
|
2078 | 0 | if (bms_is_member(rc->rti, right_rels) || |
2079 | 0 | (jointype == JOIN_FULL && bms_is_member(rc->rti, left_rels))) |
2080 | 0 | ereport(ERROR, |
2081 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
2082 | | /*------ |
2083 | | translator: %s is a SQL row locking clause such as FOR UPDATE */ |
2084 | 0 | errmsg("%s cannot be applied to the nullable side of an outer join", |
2085 | 0 | LCS_asString(rc->strength)))); |
2086 | 0 | } |
2087 | | |
2088 | 0 | sjinfo->syn_lefthand = left_rels; |
2089 | 0 | sjinfo->syn_righthand = right_rels; |
2090 | 0 | sjinfo->jointype = jointype; |
2091 | 0 | sjinfo->ojrelid = ojrelid; |
2092 | | /* these fields may get added to later: */ |
2093 | 0 | sjinfo->commute_above_l = NULL; |
2094 | 0 | sjinfo->commute_above_r = NULL; |
2095 | 0 | sjinfo->commute_below_l = NULL; |
2096 | 0 | sjinfo->commute_below_r = NULL; |
2097 | |
|
2098 | 0 | compute_semijoin_info(root, sjinfo, clause); |
2099 | | |
2100 | | /* If it's a full join, no need to be very smart */ |
2101 | 0 | if (jointype == JOIN_FULL) |
2102 | 0 | { |
2103 | 0 | sjinfo->min_lefthand = bms_copy(left_rels); |
2104 | 0 | sjinfo->min_righthand = bms_copy(right_rels); |
2105 | 0 | sjinfo->lhs_strict = false; /* don't care about this */ |
2106 | 0 | return sjinfo; |
2107 | 0 | } |
2108 | | |
2109 | | /* |
2110 | | * Retrieve all relids mentioned within the join clause. |
2111 | | */ |
2112 | 0 | 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 | | */ |
2118 | 0 | strict_relids = find_nonnullable_rels((Node *) clause); |
2119 | | |
2120 | | /* Remember whether the clause is strict for any LHS relations */ |
2121 | 0 | 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 | | */ |
2127 | 0 | 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 | 0 | min_righthand = bms_int_members(bms_union(clause_relids, inner_join_rels), |
2134 | 0 | 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 | | */ |
2145 | 0 | commute_below_l = commute_below_r = NULL; |
2146 | 0 | foreach(l, root->join_info_list) |
2147 | 0 | { |
2148 | 0 | SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l); |
2149 | 0 | 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 | 0 | if (otherinfo->jointype == JOIN_FULL) |
2157 | 0 | { |
2158 | 0 | Assert(otherinfo->ojrelid != 0); |
2159 | 0 | if (bms_overlap(left_rels, otherinfo->syn_lefthand) || |
2160 | 0 | bms_overlap(left_rels, otherinfo->syn_righthand)) |
2161 | 0 | { |
2162 | 0 | min_lefthand = bms_add_members(min_lefthand, |
2163 | 0 | otherinfo->syn_lefthand); |
2164 | 0 | min_lefthand = bms_add_members(min_lefthand, |
2165 | 0 | otherinfo->syn_righthand); |
2166 | 0 | min_lefthand = bms_add_member(min_lefthand, |
2167 | 0 | otherinfo->ojrelid); |
2168 | 0 | } |
2169 | 0 | if (bms_overlap(right_rels, otherinfo->syn_lefthand) || |
2170 | 0 | bms_overlap(right_rels, otherinfo->syn_righthand)) |
2171 | 0 | { |
2172 | 0 | min_righthand = bms_add_members(min_righthand, |
2173 | 0 | otherinfo->syn_lefthand); |
2174 | 0 | min_righthand = bms_add_members(min_righthand, |
2175 | 0 | otherinfo->syn_righthand); |
2176 | 0 | min_righthand = bms_add_member(min_righthand, |
2177 | 0 | otherinfo->ojrelid); |
2178 | 0 | } |
2179 | | /* Needn't do anything else with the full join */ |
2180 | 0 | continue; |
2181 | 0 | } |
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 | | */ |
2187 | 0 | if (otherinfo->ojrelid != 0) |
2188 | 0 | have_unsafe_phvs = |
2189 | 0 | contain_placeholder_references_to(root, |
2190 | 0 | (Node *) clause, |
2191 | 0 | otherinfo->ojrelid); |
2192 | 0 | else |
2193 | 0 | 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 | | */ |
2213 | 0 | if (bms_overlap(left_rels, otherinfo->syn_righthand)) |
2214 | 0 | { |
2215 | 0 | if (bms_overlap(clause_relids, otherinfo->syn_righthand) && |
2216 | 0 | (have_unsafe_phvs || |
2217 | 0 | jointype == JOIN_SEMI || jointype == JOIN_ANTI || |
2218 | 0 | !bms_overlap(strict_relids, otherinfo->min_righthand))) |
2219 | 0 | { |
2220 | | /* Preserve ordering */ |
2221 | 0 | min_lefthand = bms_add_members(min_lefthand, |
2222 | 0 | otherinfo->syn_lefthand); |
2223 | 0 | min_lefthand = bms_add_members(min_lefthand, |
2224 | 0 | otherinfo->syn_righthand); |
2225 | 0 | if (otherinfo->ojrelid != 0) |
2226 | 0 | min_lefthand = bms_add_member(min_lefthand, |
2227 | 0 | otherinfo->ojrelid); |
2228 | 0 | } |
2229 | 0 | else if (jointype == JOIN_LEFT && |
2230 | 0 | otherinfo->jointype == JOIN_LEFT && |
2231 | 0 | bms_overlap(strict_relids, otherinfo->min_righthand) && |
2232 | 0 | !bms_overlap(clause_relids, otherinfo->syn_lefthand)) |
2233 | 0 | { |
2234 | | /* Identity 3 applies, so remove the ordering restriction */ |
2235 | 0 | min_lefthand = bms_del_member(min_lefthand, otherinfo->ojrelid); |
2236 | | /* Record the (still tentative) commutability relationship */ |
2237 | 0 | commute_below_l = |
2238 | 0 | bms_add_member(commute_below_l, otherinfo->ojrelid); |
2239 | 0 | } |
2240 | 0 | } |
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 | | */ |
2260 | 0 | if (bms_overlap(right_rels, otherinfo->syn_righthand)) |
2261 | 0 | { |
2262 | 0 | if (bms_overlap(clause_relids, otherinfo->syn_righthand) || |
2263 | 0 | !bms_overlap(clause_relids, otherinfo->min_lefthand) || |
2264 | 0 | have_unsafe_phvs || |
2265 | 0 | jointype == JOIN_SEMI || |
2266 | 0 | jointype == JOIN_ANTI || |
2267 | 0 | otherinfo->jointype == JOIN_SEMI || |
2268 | 0 | otherinfo->jointype == JOIN_ANTI || |
2269 | 0 | !otherinfo->lhs_strict) |
2270 | 0 | { |
2271 | | /* Preserve ordering */ |
2272 | 0 | min_righthand = bms_add_members(min_righthand, |
2273 | 0 | otherinfo->syn_lefthand); |
2274 | 0 | min_righthand = bms_add_members(min_righthand, |
2275 | 0 | otherinfo->syn_righthand); |
2276 | 0 | if (otherinfo->ojrelid != 0) |
2277 | 0 | min_righthand = bms_add_member(min_righthand, |
2278 | 0 | otherinfo->ojrelid); |
2279 | 0 | } |
2280 | 0 | else if (jointype == JOIN_LEFT && |
2281 | 0 | otherinfo->jointype == JOIN_LEFT && |
2282 | 0 | otherinfo->lhs_strict) |
2283 | 0 | { |
2284 | | /* Identity 3 applies, so remove the ordering restriction */ |
2285 | 0 | min_righthand = bms_del_member(min_righthand, |
2286 | 0 | otherinfo->ojrelid); |
2287 | | /* Record the (still tentative) commutability relationship */ |
2288 | 0 | commute_below_r = |
2289 | 0 | bms_add_member(commute_below_r, otherinfo->ojrelid); |
2290 | 0 | } |
2291 | 0 | } |
2292 | 0 | } |
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 | | */ |
2302 | 0 | foreach(l, root->placeholder_list) |
2303 | 0 | { |
2304 | 0 | PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l); |
2305 | 0 | Relids ph_syn_level = phinfo->ph_var->phrels; |
2306 | | |
2307 | | /* Ignore placeholder if it didn't syntactically come from RHS */ |
2308 | 0 | if (!bms_is_subset(ph_syn_level, right_rels)) |
2309 | 0 | continue; |
2310 | | |
2311 | | /* Else, prevent join from being formed before we eval the PHV */ |
2312 | 0 | min_righthand = bms_add_members(min_righthand, phinfo->ph_eval_at); |
2313 | 0 | } |
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 | | */ |
2321 | 0 | if (bms_is_empty(min_lefthand)) |
2322 | 0 | min_lefthand = bms_copy(left_rels); |
2323 | 0 | if (bms_is_empty(min_righthand)) |
2324 | 0 | min_righthand = bms_copy(right_rels); |
2325 | | |
2326 | | /* Now they'd better be nonempty */ |
2327 | 0 | Assert(!bms_is_empty(min_lefthand)); |
2328 | 0 | Assert(!bms_is_empty(min_righthand)); |
2329 | | /* Shouldn't overlap either */ |
2330 | 0 | Assert(!bms_overlap(min_lefthand, min_righthand)); |
2331 | |
|
2332 | 0 | sjinfo->min_lefthand = min_lefthand; |
2333 | 0 | 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 | | */ |
2344 | 0 | commute_below_l = bms_del_members(commute_below_l, min_lefthand); |
2345 | 0 | commute_below_r = bms_del_members(commute_below_r, min_righthand); |
2346 | | |
2347 | | /* Anything left? */ |
2348 | 0 | if (commute_below_l || commute_below_r) |
2349 | 0 | { |
2350 | | /* Yup, so we must update the derived data in the SpecialJoinInfos */ |
2351 | 0 | sjinfo->commute_below_l = commute_below_l; |
2352 | 0 | sjinfo->commute_below_r = commute_below_r; |
2353 | 0 | foreach(l, root->join_info_list) |
2354 | 0 | { |
2355 | 0 | SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l); |
2356 | |
|
2357 | 0 | if (bms_is_member(otherinfo->ojrelid, commute_below_l)) |
2358 | 0 | otherinfo->commute_above_l = |
2359 | 0 | bms_add_member(otherinfo->commute_above_l, ojrelid); |
2360 | 0 | else if (bms_is_member(otherinfo->ojrelid, commute_below_r)) |
2361 | 0 | otherinfo->commute_above_r = |
2362 | 0 | bms_add_member(otherinfo->commute_above_r, ojrelid); |
2363 | 0 | } |
2364 | 0 | } |
2365 | |
|
2366 | 0 | return sjinfo; |
2367 | 0 | } |
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 |
2377 | | compute_semijoin_info(PlannerInfo *root, SpecialJoinInfo *sjinfo, List *clause) |
2378 | 0 | { |
2379 | 0 | List *semi_operators; |
2380 | 0 | List *semi_rhs_exprs; |
2381 | 0 | bool all_btree; |
2382 | 0 | bool all_hash; |
2383 | 0 | ListCell *lc; |
2384 | | |
2385 | | /* Initialize semijoin-related fields in case we can't unique-ify */ |
2386 | 0 | sjinfo->semi_can_btree = false; |
2387 | 0 | sjinfo->semi_can_hash = false; |
2388 | 0 | sjinfo->semi_operators = NIL; |
2389 | 0 | sjinfo->semi_rhs_exprs = NIL; |
2390 | | |
2391 | | /* Nothing more to do if it's not a semijoin */ |
2392 | 0 | if (sjinfo->jointype != JOIN_SEMI) |
2393 | 0 | 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 | 0 | semi_operators = NIL; |
2422 | 0 | semi_rhs_exprs = NIL; |
2423 | 0 | all_btree = true; |
2424 | 0 | all_hash = enable_hashagg; /* don't consider hash if not enabled */ |
2425 | 0 | foreach(lc, clause) |
2426 | 0 | { |
2427 | 0 | OpExpr *op = (OpExpr *) lfirst(lc); |
2428 | 0 | Oid opno; |
2429 | 0 | Node *left_expr; |
2430 | 0 | Node *right_expr; |
2431 | 0 | Relids left_varnos; |
2432 | 0 | Relids right_varnos; |
2433 | 0 | Relids all_varnos; |
2434 | 0 | Oid opinputtype; |
2435 | | |
2436 | | /* Is it a binary opclause? */ |
2437 | 0 | if (!IsA(op, OpExpr) || |
2438 | 0 | list_length(op->args) != 2) |
2439 | 0 | { |
2440 | | /* No, but does it reference both sides? */ |
2441 | 0 | all_varnos = pull_varnos(root, (Node *) op); |
2442 | 0 | if (!bms_overlap(all_varnos, sjinfo->syn_righthand) || |
2443 | 0 | bms_is_subset(all_varnos, sjinfo->syn_righthand)) |
2444 | 0 | { |
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 | 0 | if (contain_volatile_functions((Node *) op)) |
2451 | 0 | return; |
2452 | 0 | continue; |
2453 | 0 | } |
2454 | | /* Non-operator clause referencing both sides, must punt */ |
2455 | 0 | return; |
2456 | 0 | } |
2457 | | |
2458 | | /* Extract data from binary opclause */ |
2459 | 0 | opno = op->opno; |
2460 | 0 | left_expr = linitial(op->args); |
2461 | 0 | right_expr = lsecond(op->args); |
2462 | 0 | left_varnos = pull_varnos(root, left_expr); |
2463 | 0 | right_varnos = pull_varnos(root, right_expr); |
2464 | 0 | all_varnos = bms_union(left_varnos, right_varnos); |
2465 | 0 | opinputtype = exprType(left_expr); |
2466 | | |
2467 | | /* Does it reference both sides? */ |
2468 | 0 | if (!bms_overlap(all_varnos, sjinfo->syn_righthand) || |
2469 | 0 | bms_is_subset(all_varnos, sjinfo->syn_righthand)) |
2470 | 0 | { |
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 | 0 | if (contain_volatile_functions((Node *) op)) |
2476 | 0 | return; |
2477 | 0 | continue; |
2478 | 0 | } |
2479 | | |
2480 | | /* check rel membership of arguments */ |
2481 | 0 | if (!bms_is_empty(right_varnos) && |
2482 | 0 | bms_is_subset(right_varnos, sjinfo->syn_righthand) && |
2483 | 0 | !bms_overlap(left_varnos, sjinfo->syn_righthand)) |
2484 | 0 | { |
2485 | | /* typical case, right_expr is RHS variable */ |
2486 | 0 | } |
2487 | 0 | else if (!bms_is_empty(left_varnos) && |
2488 | 0 | bms_is_subset(left_varnos, sjinfo->syn_righthand) && |
2489 | 0 | !bms_overlap(right_varnos, sjinfo->syn_righthand)) |
2490 | 0 | { |
2491 | | /* flipped case, left_expr is RHS variable */ |
2492 | 0 | opno = get_commutator(opno); |
2493 | 0 | if (!OidIsValid(opno)) |
2494 | 0 | return; |
2495 | 0 | right_expr = left_expr; |
2496 | 0 | } |
2497 | 0 | else |
2498 | 0 | { |
2499 | | /* mixed membership of args, punt */ |
2500 | 0 | return; |
2501 | 0 | } |
2502 | | |
2503 | | /* all operators must be btree equality or hash equality */ |
2504 | 0 | if (all_btree) |
2505 | 0 | { |
2506 | | /* oprcanmerge is considered a hint... */ |
2507 | 0 | if (!op_mergejoinable(opno, opinputtype) || |
2508 | 0 | get_mergejoin_opfamilies(opno) == NIL) |
2509 | 0 | all_btree = false; |
2510 | 0 | } |
2511 | 0 | if (all_hash) |
2512 | 0 | { |
2513 | | /* ... but oprcanhash had better be correct */ |
2514 | 0 | if (!op_hashjoinable(opno, opinputtype)) |
2515 | 0 | all_hash = false; |
2516 | 0 | } |
2517 | 0 | if (!(all_btree || all_hash)) |
2518 | 0 | 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 | | */ |
2525 | 0 | right_expr = (Node *) canonicalize_ec_expression((Expr *) copyObject(right_expr), |
2526 | 0 | exprType(right_expr), |
2527 | 0 | op->inputcollid); |
2528 | | |
2529 | | /* so far so good, keep building lists */ |
2530 | 0 | semi_operators = lappend_oid(semi_operators, opno); |
2531 | 0 | semi_rhs_exprs = lappend(semi_rhs_exprs, right_expr); |
2532 | 0 | } |
2533 | | |
2534 | | /* Punt if we didn't find at least one column to unique-ify */ |
2535 | 0 | if (semi_rhs_exprs == NIL) |
2536 | 0 | return; |
2537 | | |
2538 | | /* |
2539 | | * The expressions we'd need to unique-ify mustn't be volatile. |
2540 | | */ |
2541 | 0 | if (contain_volatile_functions((Node *) semi_rhs_exprs)) |
2542 | 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 | | */ |
2548 | 0 | sjinfo->semi_can_btree = all_btree; |
2549 | 0 | sjinfo->semi_can_hash = all_hash; |
2550 | 0 | sjinfo->semi_operators = semi_operators; |
2551 | 0 | sjinfo->semi_rhs_exprs = semi_rhs_exprs; |
2552 | 0 | } |
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 |
2564 | | deconstruct_distribute_oj_quals(PlannerInfo *root, |
2565 | | List *jtitems, |
2566 | | JoinTreeItem *jtitem) |
2567 | 0 | { |
2568 | 0 | SpecialJoinInfo *sjinfo = jtitem->sjinfo; |
2569 | 0 | Relids qualscope, |
2570 | 0 | ojscope, |
2571 | 0 | nonnullable_rels; |
2572 | | |
2573 | | /* Recompute syntactic and semantic scopes of this left join */ |
2574 | 0 | qualscope = bms_union(sjinfo->syn_lefthand, sjinfo->syn_righthand); |
2575 | 0 | qualscope = bms_add_member(qualscope, sjinfo->ojrelid); |
2576 | 0 | ojscope = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand); |
2577 | 0 | 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 | 0 | Assert(sjinfo->lhs_strict); /* else we shouldn't be here */ |
2587 | 0 | if (sjinfo->commute_above_r || sjinfo->commute_below_l) |
2588 | 0 | { |
2589 | 0 | Relids joins_above; |
2590 | 0 | Relids joins_below; |
2591 | 0 | Relids incompatible_joins; |
2592 | 0 | Relids joins_so_far; |
2593 | 0 | List *quals; |
2594 | 0 | int save_last_rinfo_serial; |
2595 | 0 | ListCell *lc; |
2596 | | |
2597 | | /* Identify the outer joins this one commutes with */ |
2598 | 0 | joins_above = sjinfo->commute_above_r; |
2599 | 0 | 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 | | */ |
2619 | 0 | quals = jtitem->oj_joinclauses; |
2620 | 0 | if (!bms_is_empty(joins_below)) |
2621 | 0 | quals = (List *) remove_nulling_relids((Node *) quals, |
2622 | 0 | joins_below, |
2623 | 0 | 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 | | */ |
2630 | 0 | incompatible_joins = bms_union(joins_below, joins_above); |
2631 | 0 | incompatible_joins = bms_add_member(incompatible_joins, |
2632 | 0 | 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 | | */ |
2642 | 0 | save_last_rinfo_serial = root->last_rinfo_serial; |
2643 | |
|
2644 | 0 | joins_so_far = NULL; |
2645 | 0 | foreach(lc, jtitems) |
2646 | 0 | { |
2647 | 0 | JoinTreeItem *otherjtitem = (JoinTreeItem *) lfirst(lc); |
2648 | 0 | SpecialJoinInfo *othersj = otherjtitem->sjinfo; |
2649 | 0 | bool below_sjinfo = false; |
2650 | 0 | bool above_sjinfo = false; |
2651 | 0 | Relids this_qualscope; |
2652 | 0 | Relids this_ojscope; |
2653 | 0 | bool allow_equivalence, |
2654 | 0 | has_clone, |
2655 | 0 | is_clone; |
2656 | |
|
2657 | 0 | if (othersj == NULL) |
2658 | 0 | continue; /* not an outer-join item, ignore */ |
2659 | | |
2660 | 0 | if (bms_is_member(othersj->ojrelid, joins_below)) |
2661 | 0 | { |
2662 | | /* othersj commutes with sjinfo from below left */ |
2663 | 0 | below_sjinfo = true; |
2664 | 0 | } |
2665 | 0 | else if (othersj == sjinfo) |
2666 | 0 | { |
2667 | | /* found our join in syntactic order */ |
2668 | 0 | Assert(bms_equal(joins_so_far, joins_below)); |
2669 | 0 | } |
2670 | 0 | else if (bms_is_member(othersj->ojrelid, joins_above)) |
2671 | 0 | { |
2672 | | /* othersj commutes with sjinfo from above */ |
2673 | 0 | above_sjinfo = true; |
2674 | 0 | } |
2675 | 0 | else |
2676 | 0 | { |
2677 | | /* othersj is not relevant, ignore */ |
2678 | 0 | continue; |
2679 | 0 | } |
2680 | | |
2681 | | /* Reset serial counter for this version of the quals */ |
2682 | 0 | 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 | 0 | if (above_sjinfo) |
2698 | 0 | { |
2699 | 0 | quals = (List *) |
2700 | 0 | add_nulling_relids((Node *) quals, |
2701 | 0 | sjinfo->syn_lefthand, |
2702 | 0 | bms_make_singleton(othersj->ojrelid)); |
2703 | 0 | incompatible_joins = bms_del_member(incompatible_joins, |
2704 | 0 | othersj->ojrelid); |
2705 | 0 | } |
2706 | | |
2707 | | /* Compute qualscope and ojscope for this join level */ |
2708 | 0 | this_qualscope = bms_union(qualscope, joins_so_far); |
2709 | 0 | this_ojscope = bms_union(ojscope, joins_so_far); |
2710 | 0 | if (above_sjinfo) |
2711 | 0 | { |
2712 | | /* othersj is not yet in joins_so_far, but we need it */ |
2713 | 0 | this_qualscope = bms_add_member(this_qualscope, |
2714 | 0 | othersj->ojrelid); |
2715 | 0 | this_ojscope = bms_add_member(this_ojscope, |
2716 | 0 | othersj->ojrelid); |
2717 | | /* sjinfo is in joins_so_far, and we don't want it */ |
2718 | 0 | this_ojscope = bms_del_member(this_ojscope, |
2719 | 0 | sjinfo->ojrelid); |
2720 | 0 | } |
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 | 0 | allow_equivalence = (joins_so_far == NULL); |
2738 | 0 | has_clone = allow_equivalence; |
2739 | 0 | is_clone = !has_clone; |
2740 | |
|
2741 | 0 | distribute_quals_to_rels(root, quals, |
2742 | 0 | otherjtitem, |
2743 | 0 | sjinfo, |
2744 | 0 | root->qual_security_level, |
2745 | 0 | this_qualscope, |
2746 | 0 | this_ojscope, nonnullable_rels, |
2747 | 0 | bms_copy(incompatible_joins), |
2748 | 0 | allow_equivalence, |
2749 | 0 | has_clone, |
2750 | 0 | is_clone, |
2751 | 0 | 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 | 0 | if (below_sjinfo) |
2763 | 0 | { |
2764 | 0 | quals = (List *) |
2765 | 0 | add_nulling_relids((Node *) quals, |
2766 | 0 | othersj->syn_righthand, |
2767 | 0 | bms_make_singleton(othersj->ojrelid)); |
2768 | 0 | incompatible_joins = bms_del_member(incompatible_joins, |
2769 | 0 | othersj->ojrelid); |
2770 | 0 | } |
2771 | | |
2772 | | /* ... and track joins processed so far */ |
2773 | 0 | joins_so_far = bms_add_member(joins_so_far, othersj->ojrelid); |
2774 | 0 | } |
2775 | 0 | } |
2776 | 0 | else |
2777 | 0 | { |
2778 | | /* No commutation possible, just process the postponed clauses */ |
2779 | 0 | distribute_quals_to_rels(root, jtitem->oj_joinclauses, |
2780 | 0 | jtitem, |
2781 | 0 | sjinfo, |
2782 | 0 | root->qual_security_level, |
2783 | 0 | qualscope, |
2784 | 0 | ojscope, nonnullable_rels, |
2785 | 0 | NULL, /* incompatible_relids */ |
2786 | 0 | true, /* allow_equivalence */ |
2787 | 0 | false, false, /* not clones */ |
2788 | 0 | NULL); /* no more postponement */ |
2789 | 0 | } |
2790 | 0 | } |
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 | | 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 | 0 | { |
2818 | 0 | ListCell *lc; |
2819 | |
|
2820 | 0 | foreach(lc, clauses) |
2821 | 0 | { |
2822 | 0 | Node *clause = (Node *) lfirst(lc); |
2823 | |
|
2824 | 0 | distribute_qual_to_rels(root, clause, |
2825 | 0 | jtitem, |
2826 | 0 | sjinfo, |
2827 | 0 | security_level, |
2828 | 0 | qualscope, |
2829 | 0 | ojscope, |
2830 | 0 | outerjoin_nonnullable, |
2831 | 0 | incompatible_relids, |
2832 | 0 | allow_equivalence, |
2833 | 0 | has_clone, |
2834 | 0 | is_clone, |
2835 | 0 | postponed_oj_qual_list); |
2836 | 0 | } |
2837 | 0 | } |
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 |
2879 | | 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 | 0 | { |
2892 | 0 | Relids relids; |
2893 | 0 | bool is_pushed_down; |
2894 | 0 | bool pseudoconstant = false; |
2895 | 0 | bool maybe_equivalence; |
2896 | 0 | bool maybe_outer_join; |
2897 | 0 | RestrictInfo *restrictinfo; |
2898 | | |
2899 | | /* |
2900 | | * Retrieve all relids mentioned within the clause. |
2901 | | */ |
2902 | 0 | 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 | | */ |
2916 | 0 | if (!bms_is_subset(relids, qualscope)) |
2917 | 0 | { |
2918 | 0 | JoinTreeItem *pitem; |
2919 | |
|
2920 | 0 | Assert(root->hasLateralRTEs); /* shouldn't happen otherwise */ |
2921 | 0 | Assert(sjinfo == NULL); /* mustn't postpone past outer join */ |
2922 | 0 | for (pitem = jtitem->jti_parent; pitem; pitem = pitem->jti_parent) |
2923 | 0 | { |
2924 | 0 | if (bms_is_subset(relids, pitem->qualscope)) |
2925 | 0 | { |
2926 | 0 | pitem->lateral_clauses = lappend(pitem->lateral_clauses, |
2927 | 0 | clause); |
2928 | 0 | return; |
2929 | 0 | } |
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 | 0 | Assert(pitem->sjinfo == NULL); |
2936 | 0 | } |
2937 | 0 | elog(ERROR, "failed to postpone qual containing lateral reference"); |
2938 | 0 | } |
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 | | */ |
2944 | 0 | if (ojscope && !bms_is_subset(relids, ojscope)) |
2945 | 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 | | */ |
2967 | 0 | if (bms_is_empty(relids)) |
2968 | 0 | { |
2969 | 0 | if (ojscope) |
2970 | 0 | { |
2971 | | /* clause is attached to outer join, eval it there */ |
2972 | 0 | relids = bms_copy(ojscope); |
2973 | | /* mustn't use as gating qual, so don't mark pseudoconstant */ |
2974 | 0 | } |
2975 | 0 | else if (contain_volatile_functions(clause)) |
2976 | 0 | { |
2977 | | /* eval at original syntactic level */ |
2978 | 0 | relids = bms_copy(qualscope); |
2979 | | /* again, can't mark pseudoconstant */ |
2980 | 0 | } |
2981 | 0 | else |
2982 | 0 | { |
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 | | */ |
2992 | 0 | if (jtitem->jdomain == (JoinDomain *) linitial(root->join_domains)) |
2993 | 0 | relids = bms_copy(jtitem->jdomain->jd_relids); |
2994 | 0 | else |
2995 | 0 | relids = bms_copy(qualscope); |
2996 | | /* mark as gating qual */ |
2997 | 0 | pseudoconstant = true; |
2998 | | /* tell createplan.c to check for gating quals */ |
2999 | 0 | root->hasPseudoConstantQuals = true; |
3000 | 0 | } |
3001 | 0 | } |
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 | | */ |
3035 | 0 | if (bms_overlap(relids, outerjoin_nonnullable)) |
3036 | 0 | { |
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 | | */ |
3044 | 0 | if (postponed_oj_qual_list != NULL) |
3045 | 0 | { |
3046 | 0 | *postponed_oj_qual_list = lappend(*postponed_oj_qual_list, clause); |
3047 | 0 | return; |
3048 | 0 | } |
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 | | */ |
3057 | 0 | is_pushed_down = false; |
3058 | 0 | maybe_equivalence = false; |
3059 | 0 | 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 | | */ |
3068 | 0 | Assert(ojscope); |
3069 | 0 | relids = ojscope; |
3070 | 0 | Assert(!pseudoconstant); |
3071 | 0 | } |
3072 | 0 | else |
3073 | 0 | { |
3074 | | /* |
3075 | | * Normal qual clause or degenerate outer-join clause. Either way, we |
3076 | | * can mark it as pushed-down. |
3077 | | */ |
3078 | 0 | is_pushed_down = true; |
3079 | | |
3080 | | /* Feed qual to the equivalence machinery, if allowed by caller */ |
3081 | 0 | 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 | | */ |
3087 | 0 | maybe_outer_join = false; |
3088 | 0 | } |
3089 | | |
3090 | | /* |
3091 | | * Build the RestrictInfo node itself. |
3092 | | */ |
3093 | 0 | restrictinfo = make_restrictinfo(root, |
3094 | 0 | (Expr *) clause, |
3095 | 0 | is_pushed_down, |
3096 | 0 | has_clone, |
3097 | 0 | is_clone, |
3098 | 0 | pseudoconstant, |
3099 | 0 | security_level, |
3100 | 0 | relids, |
3101 | 0 | incompatible_relids, |
3102 | 0 | 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 | | */ |
3122 | 0 | if (bms_membership(relids) == BMS_MULTIPLE) |
3123 | 0 | { |
3124 | 0 | List *vars = pull_var_clause(clause, |
3125 | 0 | PVC_RECURSE_AGGREGATES | |
3126 | 0 | PVC_RECURSE_WINDOWFUNCS | |
3127 | 0 | PVC_INCLUDE_PLACEHOLDERS); |
3128 | 0 | Relids where_needed; |
3129 | |
|
3130 | 0 | if (is_clone) |
3131 | 0 | where_needed = bms_intersect(relids, root->all_baserels); |
3132 | 0 | else |
3133 | 0 | where_needed = relids; |
3134 | 0 | add_vars_to_targetlist(root, vars, where_needed); |
3135 | 0 | list_free(vars); |
3136 | 0 | } |
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 | 0 | 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 | 0 | if (restrictinfo->mergeopfamilies) |
3178 | 0 | { |
3179 | 0 | if (maybe_equivalence) |
3180 | 0 | { |
3181 | 0 | if (process_equivalence(root, &restrictinfo, jtitem->jdomain)) |
3182 | 0 | return; |
3183 | | /* EC rejected it, so set left_ec/right_ec the hard way ... */ |
3184 | 0 | if (restrictinfo->mergeopfamilies) /* EC might have changed this */ |
3185 | 0 | initialize_mergeclause_eclasses(root, restrictinfo); |
3186 | | /* ... and fall through to distribute_restrictinfo_to_rels */ |
3187 | 0 | } |
3188 | 0 | else if (maybe_outer_join && restrictinfo->can_join) |
3189 | 0 | { |
3190 | | /* we need to set up left_ec/right_ec the hard way */ |
3191 | 0 | initialize_mergeclause_eclasses(root, restrictinfo); |
3192 | | /* now see if it should go to any outer-join lists */ |
3193 | 0 | Assert(sjinfo != NULL); |
3194 | 0 | if (bms_is_subset(restrictinfo->left_relids, |
3195 | 0 | outerjoin_nonnullable) && |
3196 | 0 | !bms_overlap(restrictinfo->right_relids, |
3197 | 0 | outerjoin_nonnullable)) |
3198 | 0 | { |
3199 | | /* we have outervar = innervar */ |
3200 | 0 | OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo); |
3201 | |
|
3202 | 0 | ojcinfo->rinfo = restrictinfo; |
3203 | 0 | ojcinfo->sjinfo = sjinfo; |
3204 | 0 | root->left_join_clauses = lappend(root->left_join_clauses, |
3205 | 0 | ojcinfo); |
3206 | 0 | return; |
3207 | 0 | } |
3208 | 0 | if (bms_is_subset(restrictinfo->right_relids, |
3209 | 0 | outerjoin_nonnullable) && |
3210 | 0 | !bms_overlap(restrictinfo->left_relids, |
3211 | 0 | outerjoin_nonnullable)) |
3212 | 0 | { |
3213 | | /* we have innervar = outervar */ |
3214 | 0 | OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo); |
3215 | |
|
3216 | 0 | ojcinfo->rinfo = restrictinfo; |
3217 | 0 | ojcinfo->sjinfo = sjinfo; |
3218 | 0 | root->right_join_clauses = lappend(root->right_join_clauses, |
3219 | 0 | ojcinfo); |
3220 | 0 | return; |
3221 | 0 | } |
3222 | 0 | if (sjinfo->jointype == JOIN_FULL) |
3223 | 0 | { |
3224 | | /* FULL JOIN (above tests cannot match in this case) */ |
3225 | 0 | OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo); |
3226 | |
|
3227 | 0 | ojcinfo->rinfo = restrictinfo; |
3228 | 0 | ojcinfo->sjinfo = sjinfo; |
3229 | 0 | root->full_join_clauses = lappend(root->full_join_clauses, |
3230 | 0 | ojcinfo); |
3231 | 0 | return; |
3232 | 0 | } |
3233 | | /* nope, so fall through to distribute_restrictinfo_to_rels */ |
3234 | 0 | } |
3235 | 0 | else |
3236 | 0 | { |
3237 | | /* we still need to set up left_ec/right_ec */ |
3238 | 0 | initialize_mergeclause_eclasses(root, restrictinfo); |
3239 | 0 | } |
3240 | 0 | } |
3241 | | |
3242 | | /* No EC special case applies, so push it into the clause lists */ |
3243 | 0 | distribute_restrictinfo_to_rels(root, restrictinfo); |
3244 | 0 | } |
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 |
3255 | | add_base_clause_to_rel(PlannerInfo *root, Index relid, |
3256 | | RestrictInfo *restrictinfo) |
3257 | 0 | { |
3258 | 0 | RelOptInfo *rel = find_base_rel(root, relid); |
3259 | 0 | RangeTblEntry *rte = root->simple_rte_array[relid]; |
3260 | |
|
3261 | 0 | 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 | | */ |
3278 | 0 | if (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE) |
3279 | 0 | { |
3280 | | /* Don't add the clause if it is always true */ |
3281 | 0 | if (restriction_is_always_true(root, restrictinfo)) |
3282 | 0 | 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 | 0 | if (restriction_is_always_false(root, restrictinfo)) |
3295 | 0 | { |
3296 | 0 | int save_rinfo_serial = restrictinfo->rinfo_serial; |
3297 | 0 | int save_last_rinfo_serial = root->last_rinfo_serial; |
3298 | |
|
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 | 0, /* security_level */ |
3306 | 0 | restrictinfo->required_relids, |
3307 | 0 | restrictinfo->incompatible_relids, |
3308 | 0 | restrictinfo->outer_relids); |
3309 | 0 | restrictinfo->rinfo_serial = save_rinfo_serial; |
3310 | 0 | root->last_rinfo_serial = save_last_rinfo_serial; |
3311 | 0 | } |
3312 | 0 | } |
3313 | | |
3314 | | /* Add clause to rel's restriction list */ |
3315 | 0 | rel->baserestrictinfo = lappend(rel->baserestrictinfo, restrictinfo); |
3316 | | |
3317 | | /* Update security level info */ |
3318 | 0 | rel->baserestrict_min_security = Min(rel->baserestrict_min_security, |
3319 | 0 | restrictinfo->security_level); |
3320 | 0 | } |
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 | | restriction_is_always_true(PlannerInfo *root, |
3331 | | RestrictInfo *restrictinfo) |
3332 | 0 | { |
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 | | */ |
3339 | 0 | if (restrictinfo->has_clone || restrictinfo->is_clone) |
3340 | 0 | return false; |
3341 | | |
3342 | | /* Check for NullTest qual */ |
3343 | 0 | if (IsA(restrictinfo->clause, NullTest)) |
3344 | 0 | { |
3345 | 0 | NullTest *nulltest = (NullTest *) restrictinfo->clause; |
3346 | | |
3347 | | /* is this NullTest an IS_NOT_NULL qual? */ |
3348 | 0 | if (nulltest->nulltesttype != IS_NOT_NULL) |
3349 | 0 | 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 | | */ |
3355 | 0 | if (nulltest->argisrow) |
3356 | 0 | return false; |
3357 | | |
3358 | 0 | return expr_is_nonnullable(root, nulltest->arg, NOTNULL_SOURCE_RELOPT); |
3359 | 0 | } |
3360 | | |
3361 | | /* If it's an OR, check its sub-clauses */ |
3362 | 0 | if (restriction_is_or_clause(restrictinfo)) |
3363 | 0 | { |
3364 | 0 | ListCell *lc; |
3365 | |
|
3366 | 0 | 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 | 0 | foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args) |
3373 | 0 | { |
3374 | 0 | Node *orarg = (Node *) lfirst(lc); |
3375 | |
|
3376 | 0 | if (!IsA(orarg, RestrictInfo)) |
3377 | 0 | continue; |
3378 | | |
3379 | 0 | if (restriction_is_always_true(root, (RestrictInfo *) orarg)) |
3380 | 0 | return true; |
3381 | 0 | } |
3382 | 0 | } |
3383 | | |
3384 | 0 | return false; |
3385 | 0 | } |
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 | | restriction_is_always_false(PlannerInfo *root, |
3396 | | RestrictInfo *restrictinfo) |
3397 | 0 | { |
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 | | */ |
3404 | 0 | if (restrictinfo->has_clone || restrictinfo->is_clone) |
3405 | 0 | return false; |
3406 | | |
3407 | | /* Check for NullTest qual */ |
3408 | 0 | if (IsA(restrictinfo->clause, NullTest)) |
3409 | 0 | { |
3410 | 0 | NullTest *nulltest = (NullTest *) restrictinfo->clause; |
3411 | | |
3412 | | /* is this NullTest an IS_NULL qual? */ |
3413 | 0 | if (nulltest->nulltesttype != IS_NULL) |
3414 | 0 | 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 | | */ |
3420 | 0 | if (nulltest->argisrow) |
3421 | 0 | return false; |
3422 | | |
3423 | 0 | return expr_is_nonnullable(root, nulltest->arg, NOTNULL_SOURCE_RELOPT); |
3424 | 0 | } |
3425 | | |
3426 | | /* If it's an OR, check its sub-clauses */ |
3427 | 0 | if (restriction_is_or_clause(restrictinfo)) |
3428 | 0 | { |
3429 | 0 | ListCell *lc; |
3430 | |
|
3431 | 0 | 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 | 0 | foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args) |
3443 | 0 | { |
3444 | 0 | Node *orarg = (Node *) lfirst(lc); |
3445 | |
|
3446 | 0 | if (!IsA(orarg, RestrictInfo) || |
3447 | 0 | !restriction_is_always_false(root, (RestrictInfo *) orarg)) |
3448 | 0 | return false; |
3449 | 0 | } |
3450 | 0 | return true; |
3451 | 0 | } |
3452 | | |
3453 | 0 | return false; |
3454 | 0 | } |
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 |
3466 | | distribute_restrictinfo_to_rels(PlannerInfo *root, |
3467 | | RestrictInfo *restrictinfo) |
3468 | 0 | { |
3469 | 0 | Relids relids = restrictinfo->required_relids; |
3470 | |
|
3471 | 0 | if (!bms_is_empty(relids)) |
3472 | 0 | { |
3473 | 0 | int relid; |
3474 | |
|
3475 | 0 | if (bms_get_singleton_member(relids, &relid)) |
3476 | 0 | { |
3477 | | /* |
3478 | | * There is only one relation participating in the clause, so it |
3479 | | * is a restriction clause for that relation. |
3480 | | */ |
3481 | 0 | add_base_clause_to_rel(root, relid, restrictinfo); |
3482 | 0 | } |
3483 | 0 | else |
3484 | 0 | { |
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 | | */ |
3494 | 0 | 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 | | */ |
3501 | 0 | check_memoizable(restrictinfo); |
3502 | | |
3503 | | /* |
3504 | | * Add clause to the join lists of all the relevant relations. |
3505 | | */ |
3506 | 0 | add_join_clause_to_rels(root, restrictinfo, relids); |
3507 | 0 | } |
3508 | 0 | } |
3509 | 0 | else |
3510 | 0 | { |
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 | | */ |
3515 | 0 | elog(ERROR, "cannot cope with variable-free clause"); |
3516 | 0 | } |
3517 | 0 | } |
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 | | 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 | 0 | { |
3560 | 0 | RestrictInfo *restrictinfo; |
3561 | 0 | Node *clause; |
3562 | 0 | Relids relids; |
3563 | 0 | 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 | 0 | clause = (Node *) make_opclause(opno, |
3570 | 0 | BOOLOID, /* opresulttype */ |
3571 | 0 | false, /* opretset */ |
3572 | 0 | copyObject(item1), |
3573 | 0 | copyObject(item2), |
3574 | 0 | InvalidOid, |
3575 | 0 | collation); |
3576 | | |
3577 | | /* If both constant, try to reduce to a boolean constant. */ |
3578 | 0 | if (both_const) |
3579 | 0 | { |
3580 | 0 | clause = eval_const_expressions(root, clause); |
3581 | | |
3582 | | /* If we produced const TRUE, just drop the clause */ |
3583 | 0 | if (clause && IsA(clause, Const)) |
3584 | 0 | { |
3585 | 0 | Const *cclause = (Const *) clause; |
3586 | |
|
3587 | 0 | Assert(cclause->consttype == BOOLOID); |
3588 | 0 | if (!cclause->constisnull && DatumGetBool(cclause->constvalue)) |
3589 | 0 | return NULL; |
3590 | 0 | } |
3591 | 0 | } |
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 | | */ |
3600 | 0 | relids = pull_varnos(root, clause); |
3601 | 0 | 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 | 0 | if (bms_is_empty(relids)) |
3610 | 0 | { |
3611 | | /* eval at join domain's safe level */ |
3612 | 0 | relids = get_join_domain_min_rels(root, qualscope); |
3613 | | /* mark as gating qual */ |
3614 | 0 | pseudoconstant = true; |
3615 | | /* tell createplan.c to check for gating quals */ |
3616 | 0 | root->hasPseudoConstantQuals = true; |
3617 | 0 | } |
3618 | | |
3619 | | /* |
3620 | | * Build the RestrictInfo node itself. |
3621 | | */ |
3622 | 0 | restrictinfo = make_restrictinfo(root, |
3623 | 0 | (Expr *) clause, |
3624 | 0 | true, /* is_pushed_down */ |
3625 | 0 | false, /* !has_clone */ |
3626 | 0 | false, /* !is_clone */ |
3627 | 0 | pseudoconstant, |
3628 | 0 | security_level, |
3629 | 0 | relids, |
3630 | 0 | NULL, /* incompatible_relids */ |
3631 | 0 | 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 | | */ |
3644 | 0 | if (bms_membership(relids) == BMS_MULTIPLE) |
3645 | 0 | { |
3646 | 0 | List *vars = pull_var_clause(clause, |
3647 | 0 | PVC_RECURSE_AGGREGATES | |
3648 | 0 | PVC_RECURSE_WINDOWFUNCS | |
3649 | 0 | PVC_INCLUDE_PLACEHOLDERS); |
3650 | |
|
3651 | 0 | add_vars_to_targetlist(root, vars, relids); |
3652 | 0 | list_free(vars); |
3653 | 0 | } |
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 | 0 | 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 | 0 | distribute_restrictinfo_to_rels(root, restrictinfo); |
3672 | |
|
3673 | 0 | return restrictinfo; |
3674 | 0 | } |
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 * |
3690 | | 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 | 0 | { |
3698 | 0 | RestrictInfo *restrictinfo; |
3699 | 0 | 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 | | */ |
3705 | 0 | clause = make_opclause(opno, |
3706 | 0 | BOOLOID, /* opresulttype */ |
3707 | 0 | false, /* opretset */ |
3708 | 0 | copyObject(item1), |
3709 | 0 | copyObject(item2), |
3710 | 0 | InvalidOid, |
3711 | 0 | collation); |
3712 | | |
3713 | | /* |
3714 | | * Build the RestrictInfo node itself. |
3715 | | */ |
3716 | 0 | restrictinfo = make_restrictinfo(root, |
3717 | 0 | clause, |
3718 | 0 | true, /* is_pushed_down */ |
3719 | 0 | false, /* !has_clone */ |
3720 | 0 | false, /* !is_clone */ |
3721 | 0 | false, /* pseudoconstant */ |
3722 | 0 | security_level, /* security_level */ |
3723 | 0 | qualscope, /* required_relids */ |
3724 | 0 | NULL, /* incompatible_relids */ |
3725 | 0 | NULL); /* outer_relids */ |
3726 | | |
3727 | | /* Set mergejoinability/hashjoinability flags */ |
3728 | 0 | check_mergejoinable(restrictinfo); |
3729 | 0 | check_hashjoinable(restrictinfo); |
3730 | 0 | check_memoizable(restrictinfo); |
3731 | |
|
3732 | 0 | return restrictinfo; |
3733 | 0 | } |
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 |
3759 | | get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids) |
3760 | 0 | { |
3761 | 0 | Relids result = bms_copy(domain_relids); |
3762 | 0 | ListCell *lc; |
3763 | | |
3764 | | /* Top-level join domain? */ |
3765 | 0 | if (bms_equal(result, root->all_query_rels)) |
3766 | 0 | return result; |
3767 | | |
3768 | | /* Nope, look for lower outer joins that could potentially commute out */ |
3769 | 0 | foreach(lc, root->join_info_list) |
3770 | 0 | { |
3771 | 0 | SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc); |
3772 | |
|
3773 | 0 | if (sjinfo->jointype == JOIN_LEFT && |
3774 | 0 | bms_is_member(sjinfo->ojrelid, result)) |
3775 | 0 | { |
3776 | 0 | result = bms_del_member(result, sjinfo->ojrelid); |
3777 | 0 | result = bms_del_members(result, sjinfo->syn_righthand); |
3778 | 0 | } |
3779 | 0 | } |
3780 | 0 | return result; |
3781 | 0 | } |
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 |
3799 | | match_foreign_keys_to_quals(PlannerInfo *root) |
3800 | 0 | { |
3801 | 0 | List *newlist = NIL; |
3802 | 0 | ListCell *lc; |
3803 | |
|
3804 | 0 | foreach(lc, root->fkey_list) |
3805 | 0 | { |
3806 | 0 | ForeignKeyOptInfo *fkinfo = (ForeignKeyOptInfo *) lfirst(lc); |
3807 | 0 | RelOptInfo *con_rel; |
3808 | 0 | RelOptInfo *ref_rel; |
3809 | 0 | 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 | | */ |
3817 | 0 | if (fkinfo->con_relid >= root->simple_rel_array_size || |
3818 | 0 | fkinfo->ref_relid >= root->simple_rel_array_size) |
3819 | 0 | continue; /* just paranoia */ |
3820 | 0 | con_rel = root->simple_rel_array[fkinfo->con_relid]; |
3821 | 0 | if (con_rel == NULL) |
3822 | 0 | continue; |
3823 | 0 | ref_rel = root->simple_rel_array[fkinfo->ref_relid]; |
3824 | 0 | if (ref_rel == NULL) |
3825 | 0 | 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 | | */ |
3831 | 0 | if (con_rel->reloptkind != RELOPT_BASEREL || |
3832 | 0 | ref_rel->reloptkind != RELOPT_BASEREL) |
3833 | 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 | | */ |
3843 | 0 | for (colno = 0; colno < fkinfo->nkeys; colno++) |
3844 | 0 | { |
3845 | 0 | EquivalenceClass *ec; |
3846 | 0 | AttrNumber con_attno, |
3847 | 0 | ref_attno; |
3848 | 0 | Oid fpeqop; |
3849 | 0 | ListCell *lc2; |
3850 | |
|
3851 | 0 | 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 | 0 | if (ec != NULL) |
3854 | 0 | { |
3855 | 0 | fkinfo->nmatched_ec++; |
3856 | 0 | if (ec->ec_has_const) |
3857 | 0 | fkinfo->nconst_ec++; |
3858 | 0 | continue; |
3859 | 0 | } |
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 | 0 | con_attno = fkinfo->conkey[colno]; |
3866 | 0 | ref_attno = fkinfo->confkey[colno]; |
3867 | 0 | fpeqop = InvalidOid; /* we'll look this up only if needed */ |
3868 | |
|
3869 | 0 | foreach(lc2, con_rel->joininfo) |
3870 | 0 | { |
3871 | 0 | RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2); |
3872 | 0 | OpExpr *clause = (OpExpr *) rinfo->clause; |
3873 | 0 | Var *leftvar; |
3874 | 0 | Var *rightvar; |
3875 | | |
3876 | | /* Only binary OpExprs are useful for consideration */ |
3877 | 0 | if (!IsA(clause, OpExpr) || |
3878 | 0 | list_length(clause->args) != 2) |
3879 | 0 | continue; |
3880 | 0 | leftvar = (Var *) get_leftop((Expr *) clause); |
3881 | 0 | rightvar = (Var *) get_rightop((Expr *) clause); |
3882 | | |
3883 | | /* Operands must be Vars, possibly with RelabelType */ |
3884 | 0 | while (leftvar && IsA(leftvar, RelabelType)) |
3885 | 0 | leftvar = (Var *) ((RelabelType *) leftvar)->arg; |
3886 | 0 | if (!(leftvar && IsA(leftvar, Var))) |
3887 | 0 | continue; |
3888 | 0 | while (rightvar && IsA(rightvar, RelabelType)) |
3889 | 0 | rightvar = (Var *) ((RelabelType *) rightvar)->arg; |
3890 | 0 | if (!(rightvar && IsA(rightvar, Var))) |
3891 | 0 | continue; |
3892 | | |
3893 | | /* Now try to match the vars to the current foreign key cols */ |
3894 | 0 | if (fkinfo->ref_relid == leftvar->varno && |
3895 | 0 | ref_attno == leftvar->varattno && |
3896 | 0 | fkinfo->con_relid == rightvar->varno && |
3897 | 0 | con_attno == rightvar->varattno) |
3898 | 0 | { |
3899 | | /* Vars match, but is it the right operator? */ |
3900 | 0 | if (clause->opno == fkinfo->conpfeqop[colno]) |
3901 | 0 | { |
3902 | 0 | fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno], |
3903 | 0 | rinfo); |
3904 | 0 | fkinfo->nmatched_ri++; |
3905 | 0 | } |
3906 | 0 | } |
3907 | 0 | else if (fkinfo->ref_relid == rightvar->varno && |
3908 | 0 | ref_attno == rightvar->varattno && |
3909 | 0 | fkinfo->con_relid == leftvar->varno && |
3910 | 0 | con_attno == leftvar->varattno) |
3911 | 0 | { |
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 | 0 | if (!OidIsValid(fpeqop)) |
3920 | 0 | fpeqop = get_commutator(fkinfo->conpfeqop[colno]); |
3921 | 0 | if (clause->opno == fpeqop) |
3922 | 0 | { |
3923 | 0 | fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno], |
3924 | 0 | rinfo); |
3925 | 0 | fkinfo->nmatched_ri++; |
3926 | 0 | } |
3927 | 0 | } |
3928 | 0 | } |
3929 | | /* If we found any matching loose quals, count col as matched */ |
3930 | 0 | if (fkinfo->rinfos[colno]) |
3931 | 0 | fkinfo->nmatched_rcols++; |
3932 | 0 | } |
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 | 0 | if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) == fkinfo->nkeys) |
3941 | 0 | newlist = lappend(newlist, fkinfo); |
3942 | 0 | } |
3943 | | /* Replace fkey_list, thereby discarding any useless entries */ |
3944 | 0 | root->fkey_list = newlist; |
3945 | 0 | } |
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 |
3964 | | check_mergejoinable(RestrictInfo *restrictinfo) |
3965 | 0 | { |
3966 | 0 | Expr *clause = restrictinfo->clause; |
3967 | 0 | Oid opno; |
3968 | 0 | Node *leftarg; |
3969 | |
|
3970 | 0 | if (restrictinfo->pseudoconstant) |
3971 | 0 | return; |
3972 | 0 | if (!is_opclause(clause)) |
3973 | 0 | return; |
3974 | 0 | if (list_length(((OpExpr *) clause)->args) != 2) |
3975 | 0 | return; |
3976 | | |
3977 | 0 | opno = ((OpExpr *) clause)->opno; |
3978 | 0 | leftarg = linitial(((OpExpr *) clause)->args); |
3979 | |
|
3980 | 0 | if (op_mergejoinable(opno, exprType(leftarg)) && |
3981 | 0 | !contain_volatile_functions((Node *) restrictinfo)) |
3982 | 0 | 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 | 0 | } |
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 |
4001 | | check_hashjoinable(RestrictInfo *restrictinfo) |
4002 | 0 | { |
4003 | 0 | Expr *clause = restrictinfo->clause; |
4004 | 0 | Oid opno; |
4005 | 0 | Node *leftarg; |
4006 | |
|
4007 | 0 | if (restrictinfo->pseudoconstant) |
4008 | 0 | return; |
4009 | 0 | if (!is_opclause(clause)) |
4010 | 0 | return; |
4011 | 0 | if (list_length(((OpExpr *) clause)->args) != 2) |
4012 | 0 | return; |
4013 | | |
4014 | 0 | opno = ((OpExpr *) clause)->opno; |
4015 | 0 | leftarg = linitial(((OpExpr *) clause)->args); |
4016 | |
|
4017 | 0 | if (op_hashjoinable(opno, exprType(leftarg)) && |
4018 | 0 | !contain_volatile_functions((Node *) restrictinfo)) |
4019 | 0 | restrictinfo->hashjoinoperator = opno; |
4020 | 0 | } |
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 |
4029 | | check_memoizable(RestrictInfo *restrictinfo) |
4030 | 0 | { |
4031 | 0 | TypeCacheEntry *typentry; |
4032 | 0 | Expr *clause = restrictinfo->clause; |
4033 | 0 | Oid lefttype; |
4034 | 0 | Oid righttype; |
4035 | |
|
4036 | 0 | if (restrictinfo->pseudoconstant) |
4037 | 0 | return; |
4038 | 0 | if (!is_opclause(clause)) |
4039 | 0 | return; |
4040 | 0 | if (list_length(((OpExpr *) clause)->args) != 2) |
4041 | 0 | return; |
4042 | | |
4043 | 0 | lefttype = exprType(linitial(((OpExpr *) clause)->args)); |
4044 | |
|
4045 | 0 | typentry = lookup_type_cache(lefttype, TYPECACHE_HASH_PROC | |
4046 | 0 | TYPECACHE_EQ_OPR); |
4047 | |
|
4048 | 0 | if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr)) |
4049 | 0 | restrictinfo->left_hasheqoperator = typentry->eq_opr; |
4050 | |
|
4051 | 0 | 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 | 0 | if (lefttype != righttype) |
4058 | 0 | typentry = lookup_type_cache(righttype, TYPECACHE_HASH_PROC | |
4059 | 0 | TYPECACHE_EQ_OPR); |
4060 | |
|
4061 | 0 | if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr)) |
4062 | 0 | restrictinfo->right_hasheqoperator = typentry->eq_opr; |
4063 | 0 | } |