/src/postgres/src/backend/optimizer/plan/analyzejoins.c
Line | Count | Source |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * analyzejoins.c |
4 | | * Routines for simplifying joins after initial query analysis |
5 | | * |
6 | | * While we do a great deal of join simplification in prep/prepjointree.c, |
7 | | * certain optimizations cannot be performed at that stage for lack of |
8 | | * detailed information about the query. The routines here are invoked |
9 | | * after initsplan.c has done its work, and can do additional join removal |
10 | | * and simplification steps based on the information extracted. |
11 | | * |
12 | | * Although the decisions about what can be removed are made using the |
13 | | * planner's derived data structures, the removals themselves are implemented |
14 | | * by editing the query's jointree, which is a far simpler and more stable |
15 | | * representation. We make no attempt to update the derived data structures |
16 | | * to match; instead, query_planner() throws them all away and recomputes them |
17 | | * whenever we report having removed something. |
18 | | * |
19 | | * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group |
20 | | * Portions Copyright (c) 1994, Regents of the University of California |
21 | | * |
22 | | * |
23 | | * IDENTIFICATION |
24 | | * src/backend/optimizer/plan/analyzejoins.c |
25 | | * |
26 | | *------------------------------------------------------------------------- |
27 | | */ |
28 | | #include "postgres.h" |
29 | | |
30 | | #include "catalog/pg_class.h" |
31 | | #include "nodes/makefuncs.h" |
32 | | #include "nodes/nodeFuncs.h" |
33 | | #include "optimizer/optimizer.h" |
34 | | #include "optimizer/pathnode.h" |
35 | | #include "optimizer/paths.h" |
36 | | #include "optimizer/planmain.h" |
37 | | #include "optimizer/prep.h" |
38 | | #include "optimizer/restrictinfo.h" |
39 | | #include "parser/parse_agg.h" |
40 | | #include "parser/parse_relation.h" |
41 | | #include "rewrite/rewriteManip.h" |
42 | | #include "utils/lsyscache.h" |
43 | | |
44 | | /* |
45 | | * Utility structure. A sorting procedure is needed to simplify the search |
46 | | * for SJE-candidate baserels, which must reference the same database relation |
47 | | * with the same reader permissions (checkAsUser value). We require the |
48 | | * checkAsUser fields to match to ensure that merged RTEs carry the same |
49 | | * securityQuals; in future this rule might keep us out of trouble with other |
50 | | * role-based features, too. Having collected all baserels from the jointree, |
51 | | * remove_self_joins_recurse sorts them according to their reloid and useroid |
52 | | * values, groups them in another pass and attempts to remove self-joins |
53 | | * within each group. This preliminary sorting prevents quadratic behavior |
54 | | * in the case of numerous joins. |
55 | | */ |
56 | | typedef struct |
57 | | { |
58 | | int relid; |
59 | | Oid reloid; |
60 | | Oid useroid; |
61 | | } SelfJoinCandidate; |
62 | | |
63 | | bool enable_self_join_elimination; |
64 | | |
65 | | /* local functions */ |
66 | | static bool join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo); |
67 | | static Node *remove_join_from_jointree(Node *jtnode, int ojrelid, |
68 | | int *nremoved); |
69 | | static void remove_rels_from_query_tree(PlannerInfo *root, |
70 | | Relids removed_relids); |
71 | | static bool reduce_semijoin_in_jointree(Node *jtnode, Relids syn_righthand); |
72 | | static bool rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel); |
73 | | static bool rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, |
74 | | List *clause_list, List **extra_clauses); |
75 | | static DistinctColInfo *distinct_col_search(int colno, List *distinct_cols); |
76 | | static bool innerrel_is_unique_ext(PlannerInfo *root, |
77 | | Relids joinrelids, |
78 | | Relids outerrelids, |
79 | | RelOptInfo *innerrel, |
80 | | JoinType jointype, |
81 | | List *restrictlist, |
82 | | bool force_cache, |
83 | | List **extra_clauses); |
84 | | static bool is_innerrel_unique_for(PlannerInfo *root, |
85 | | Relids joinrelids, |
86 | | Relids outerrelids, |
87 | | RelOptInfo *innerrel, |
88 | | JoinType jointype, |
89 | | List *restrictlist, |
90 | | List **extra_clauses); |
91 | | static Node *remove_rel_from_jointree(Node *jtnode, int relid, |
92 | | Node **orphan_quals, int *nremoved); |
93 | | static Node *merge_quals(Node *quals1, Node *quals2); |
94 | | static void fixup_selfjoin_jointree(PlannerInfo *root, Node *jtnode, int relid, |
95 | | Node **hoist_quals, bool *found_relid); |
96 | | static List *fixup_selfjoin_quals(PlannerInfo *root, List *quals, int relid); |
97 | | static Node *replace_selfjoin_qual(Node *qual); |
98 | | static int self_join_candidates_cmp(const void *a, const void *b); |
99 | | |
100 | | |
101 | | /* |
102 | | * remove_useless_outer_joins |
103 | | * Check for relations that don't actually need to be joined at all, |
104 | | * and remove them from the query's jointree. |
105 | | * |
106 | | * Returns true if we removed anything. In that case the caller must discard |
107 | | * everything it has derived from the jointree and compute it over again, |
108 | | * since we don't try to update any of that here. |
109 | | */ |
110 | | bool |
111 | | remove_useless_outer_joins(PlannerInfo *root) |
112 | 0 | { |
113 | 0 | Relids removed_relids = NULL; |
114 | 0 | ListCell *lc; |
115 | | |
116 | | /* |
117 | | * We are only interested in relations that are left-joined to, so we can |
118 | | * scan the join_info_list to find them easily. |
119 | | */ |
120 | 0 | foreach(lc, root->join_info_list) |
121 | 0 | { |
122 | 0 | SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc); |
123 | 0 | int innerrelid; |
124 | 0 | int nremoved; |
125 | 0 | RangeTblEntry *rte; |
126 | | |
127 | | /* Skip if not removable */ |
128 | 0 | if (!join_is_removable(root, sjinfo)) |
129 | 0 | continue; |
130 | | |
131 | | /* |
132 | | * join_is_removable insists that the join's syntactic righthand side |
133 | | * be a single baserel, so we can implement the removal by dropping |
134 | | * the JoinExpr and everything below its righthand side. |
135 | | */ |
136 | 0 | innerrelid = bms_singleton_member(sjinfo->syn_righthand); |
137 | | |
138 | | /* We verify that exactly one JoinExpr gets removed */ |
139 | 0 | nremoved = 0; |
140 | 0 | root->parse->jointree = (FromExpr *) |
141 | 0 | remove_join_from_jointree((Node *) root->parse->jointree, |
142 | 0 | sjinfo->ojrelid, &nremoved); |
143 | 0 | if (nremoved != 1) |
144 | 0 | elog(ERROR, "failed to find join %d in jointree", sjinfo->ojrelid); |
145 | | |
146 | | /* Track all the relids we've removed, for use below */ |
147 | 0 | removed_relids = bms_add_member(removed_relids, innerrelid); |
148 | 0 | removed_relids = bms_add_member(removed_relids, sjinfo->ojrelid); |
149 | | |
150 | | /* |
151 | | * As in pull_up_simple_subquery, discard no-longer-needed subqueries. |
152 | | * This is not just an optimization, but is necessary to prevent |
153 | | * subsequent processing from descending into stale subtrees and |
154 | | * seeing inconsistent data. For the same reason, discard any |
155 | | * tablesample and securityQuals subtrees of the removed rel. |
156 | | * (Although simple_rte_array[] will be rebuilt shortly, we can still |
157 | | * use it to find the RTE in the parse tree.) |
158 | | */ |
159 | 0 | rte = root->simple_rte_array[innerrelid]; |
160 | 0 | if (rte->rtekind == RTE_SUBQUERY) |
161 | 0 | rte->subquery = NULL; |
162 | 0 | rte->tablesample = NULL; |
163 | 0 | rte->securityQuals = NIL; |
164 | | |
165 | | /* |
166 | | * It's okay to keep scanning join_info_list for more removable joins, |
167 | | * even though the data that join_is_removable consults is now |
168 | | * slightly out of date. Removing a join can only delete attr_needed |
169 | | * bits and join clauses, and any attr_needed bit or join clause that |
170 | | * mentions the removed rel above its own join level would have |
171 | | * prevented that rel from being removable. So what remains to be |
172 | | * examined is unchanged by what we just did. |
173 | | * |
174 | | * The converse doesn't hold: dropping a join can make some other join |
175 | | * removable that didn't look so before. That's why our caller loops |
176 | | * until we report finding nothing more to remove. |
177 | | */ |
178 | 0 | } |
179 | | |
180 | 0 | if (bms_is_empty(removed_relids)) |
181 | 0 | return false; |
182 | | |
183 | | /* Clean up the traces that the removed rels have left elsewhere */ |
184 | 0 | remove_rels_from_query_tree(root, removed_relids); |
185 | |
|
186 | 0 | return true; |
187 | 0 | } |
188 | | |
189 | | /* |
190 | | * join_is_removable |
191 | | * Check whether we need not perform this special join at all, because |
192 | | * it will just duplicate its left input. |
193 | | * |
194 | | * This is true for a left join for which the join condition cannot match |
195 | | * more than one inner-side row. (There are other possibly interesting |
196 | | * cases, but we don't have the infrastructure to prove them.) We also |
197 | | * have to check that the inner side doesn't generate any variables needed |
198 | | * above the join. |
199 | | */ |
200 | | static bool |
201 | | join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo) |
202 | 0 | { |
203 | 0 | int innerrelid; |
204 | 0 | RelOptInfo *innerrel; |
205 | 0 | Relids inputrelids; |
206 | 0 | Relids joinrelids; |
207 | 0 | List *clause_list = NIL; |
208 | 0 | ListCell *l; |
209 | 0 | int attroff; |
210 | | |
211 | | /* |
212 | | * Must be a left join to a single baserel, else we aren't going to be |
213 | | * able to do anything with it. |
214 | | */ |
215 | 0 | if (sjinfo->jointype != JOIN_LEFT) |
216 | 0 | return false; |
217 | | |
218 | | /* |
219 | | * We test the syntactic righthand side, not min_righthand, because the |
220 | | * removal is done by deleting the whole righthand subtree of the join. |
221 | | * (min_righthand can be a singleton when syn_righthand is not, but in |
222 | | * such a case the attr_needed tests below would reject the join anyway.) |
223 | | */ |
224 | 0 | if (!bms_get_singleton_member(sjinfo->syn_righthand, &innerrelid)) |
225 | 0 | return false; |
226 | 0 | Assert(bms_equal(sjinfo->min_righthand, sjinfo->syn_righthand)); |
227 | | |
228 | | /* |
229 | | * Never try to eliminate a left join to the query result rel. Although |
230 | | * the case is syntactically impossible in standard SQL, MERGE will build |
231 | | * a join tree that looks exactly like that. |
232 | | */ |
233 | 0 | if (innerrelid == root->parse->resultRelation) |
234 | 0 | return false; |
235 | | |
236 | 0 | innerrel = find_base_rel(root, innerrelid); |
237 | | |
238 | | /* |
239 | | * Before we go to the effort of checking whether any innerrel variables |
240 | | * are needed above the join, make a quick check to eliminate cases in |
241 | | * which we will surely be unable to prove uniqueness of the innerrel. |
242 | | */ |
243 | 0 | if (!rel_supports_distinctness(root, innerrel)) |
244 | 0 | return false; |
245 | | |
246 | | /* Compute the relid set for the join we are considering */ |
247 | 0 | inputrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand); |
248 | 0 | Assert(sjinfo->ojrelid != 0); |
249 | 0 | joinrelids = bms_copy(inputrelids); |
250 | 0 | joinrelids = bms_add_member(joinrelids, sjinfo->ojrelid); |
251 | | |
252 | | /* |
253 | | * We can't remove the join if any inner-rel attributes are used above the |
254 | | * join. Here, "above" the join includes pushed-down conditions, so we |
255 | | * should reject if attr_needed includes the OJ's own relid; therefore, |
256 | | * compare to inputrelids not joinrelids. |
257 | | * |
258 | | * As a micro-optimization, it seems better to start with max_attr and |
259 | | * count down rather than starting with min_attr and counting up, on the |
260 | | * theory that the system attributes are somewhat less likely to be wanted |
261 | | * and should be tested last. |
262 | | */ |
263 | 0 | for (attroff = innerrel->max_attr - innerrel->min_attr; |
264 | 0 | attroff >= 0; |
265 | 0 | attroff--) |
266 | 0 | { |
267 | 0 | if (!bms_is_subset(innerrel->attr_needed[attroff], inputrelids)) |
268 | 0 | return false; |
269 | 0 | } |
270 | | |
271 | | /* |
272 | | * Similarly check that the inner rel isn't needed by any PlaceHolderVars |
273 | | * that will be used above the join. The PHV case is a little bit more |
274 | | * complicated, because PHVs may have been assigned a ph_eval_at location |
275 | | * that includes the innerrel, yet their contained expression might not |
276 | | * actually reference the innerrel (it could be just a constant, for |
277 | | * instance). If such a PHV is due to be evaluated above the join then it |
278 | | * needn't prevent join removal. |
279 | | */ |
280 | 0 | foreach(l, root->placeholder_list) |
281 | 0 | { |
282 | 0 | PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l); |
283 | |
|
284 | 0 | if (bms_overlap(phinfo->ph_lateral, innerrel->relids)) |
285 | 0 | return false; /* it references innerrel laterally */ |
286 | 0 | if (!bms_overlap(phinfo->ph_eval_at, innerrel->relids)) |
287 | 0 | continue; /* it definitely doesn't reference innerrel */ |
288 | 0 | if (bms_is_subset(phinfo->ph_needed, inputrelids)) |
289 | 0 | continue; /* PHV is not used above the join */ |
290 | 0 | if (!bms_is_member(sjinfo->ojrelid, phinfo->ph_eval_at)) |
291 | 0 | return false; /* it has to be evaluated below the join */ |
292 | | |
293 | | /* |
294 | | * We need to be sure there will still be a place to evaluate the PHV |
295 | | * if we remove the join, ie that ph_eval_at wouldn't become empty. |
296 | | */ |
297 | 0 | if (!bms_overlap(sjinfo->min_lefthand, phinfo->ph_eval_at)) |
298 | 0 | return false; /* there isn't any other place to eval PHV */ |
299 | | /* Check contained expression last, since this is a bit expensive */ |
300 | 0 | if (bms_overlap(pull_varnos(root, (Node *) phinfo->ph_var->phexpr), |
301 | 0 | innerrel->relids)) |
302 | 0 | return false; /* contained expression references innerrel */ |
303 | 0 | } |
304 | | |
305 | | /* |
306 | | * Search for mergejoinable clauses that constrain the inner rel against |
307 | | * either the outer rel or a pseudoconstant. If an operator is |
308 | | * mergejoinable then it behaves like equality for some btree opclass, so |
309 | | * it's what we want. The mergejoinability test also eliminates clauses |
310 | | * containing volatile functions, which we couldn't depend on. |
311 | | */ |
312 | 0 | foreach(l, innerrel->joininfo) |
313 | 0 | { |
314 | 0 | RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l); |
315 | | |
316 | | /* |
317 | | * If the current join commutes with some other outer join(s) via |
318 | | * outer join identity 3, there will be multiple clones of its join |
319 | | * clauses in the joininfo list. We want to consider only the |
320 | | * has_clone form of such clauses. Processing more than one form |
321 | | * would be wasteful, and also some of the others would confuse the |
322 | | * RINFO_IS_PUSHED_DOWN test below. |
323 | | */ |
324 | 0 | if (restrictinfo->is_clone) |
325 | 0 | continue; /* ignore it */ |
326 | | |
327 | | /* |
328 | | * If it's not a join clause for this outer join, we can't use it. |
329 | | * Note that if the clause is pushed-down, then it is logically from |
330 | | * above the outer join, even if it references no other rels (it might |
331 | | * be from WHERE, for example). |
332 | | */ |
333 | 0 | if (RINFO_IS_PUSHED_DOWN(restrictinfo, joinrelids)) |
334 | 0 | continue; /* ignore; not useful here */ |
335 | | |
336 | | /* Ignore if it's not a mergejoinable clause */ |
337 | 0 | if (!restrictinfo->can_join || |
338 | 0 | restrictinfo->mergeopfamilies == NIL) |
339 | 0 | continue; /* not mergejoinable */ |
340 | | |
341 | | /* |
342 | | * Check if the clause has the form "outer op inner" or "inner op |
343 | | * outer", and if so mark which side is inner. |
344 | | */ |
345 | 0 | if (!clause_sides_match_join(restrictinfo, sjinfo->min_lefthand, |
346 | 0 | innerrel->relids)) |
347 | 0 | continue; /* no good for these input relations */ |
348 | | |
349 | | /* OK, add to list */ |
350 | 0 | clause_list = lappend(clause_list, restrictinfo); |
351 | 0 | } |
352 | | |
353 | | /* |
354 | | * Now that we have the relevant equality join clauses, try to prove the |
355 | | * innerrel distinct. |
356 | | */ |
357 | 0 | if (rel_is_distinct_for(root, innerrel, clause_list, NULL)) |
358 | 0 | return true; |
359 | | |
360 | | /* |
361 | | * Some day it would be nice to check for other methods of establishing |
362 | | * distinctness. |
363 | | */ |
364 | 0 | return false; |
365 | 0 | } |
366 | | |
367 | | /* |
368 | | * remove_join_from_jointree |
369 | | * Delete the JoinExpr with the given RT index, along with everything |
370 | | * below its righthand side, from the query's jointree. |
371 | | * |
372 | | * The JoinExpr is replaced by its lefthand input. Its ON conditions can just |
373 | | * be dropped: since this is a left join, they could only have determined |
374 | | * which righthand rows join to a given lefthand row, and there are no |
375 | | * righthand rows anymore. |
376 | | * |
377 | | * *nremoved is incremented by the number of JoinExprs removed (there should |
378 | | * be exactly one, but the caller checks that). |
379 | | */ |
380 | | static Node * |
381 | | remove_join_from_jointree(Node *jtnode, int ojrelid, int *nremoved) |
382 | 0 | { |
383 | 0 | if (jtnode == NULL) |
384 | 0 | return NULL; |
385 | 0 | if (IsA(jtnode, RangeTblRef)) |
386 | 0 | { |
387 | | /* nothing to do here */ |
388 | 0 | } |
389 | 0 | else if (IsA(jtnode, FromExpr)) |
390 | 0 | { |
391 | 0 | FromExpr *f = (FromExpr *) jtnode; |
392 | 0 | ListCell *l; |
393 | |
|
394 | 0 | foreach(l, f->fromlist) |
395 | 0 | lfirst(l) = remove_join_from_jointree((Node *) lfirst(l), |
396 | 0 | ojrelid, nremoved); |
397 | 0 | } |
398 | 0 | else if (IsA(jtnode, JoinExpr)) |
399 | 0 | { |
400 | 0 | JoinExpr *j = (JoinExpr *) jtnode; |
401 | |
|
402 | 0 | if (j->rtindex == ojrelid) |
403 | 0 | { |
404 | 0 | (*nremoved)++; |
405 | 0 | return j->larg; |
406 | 0 | } |
407 | 0 | j->larg = remove_join_from_jointree(j->larg, ojrelid, nremoved); |
408 | 0 | j->rarg = remove_join_from_jointree(j->rarg, ojrelid, nremoved); |
409 | 0 | } |
410 | 0 | else |
411 | 0 | elog(ERROR, "unrecognized jointree node type: %d", |
412 | 0 | (int) nodeTag(jtnode)); |
413 | | |
414 | 0 | return jtnode; |
415 | 0 | } |
416 | | |
417 | | /* |
418 | | * remove_rels_from_query_tree |
419 | | * Delete all remaining references to the given relids from the query. |
420 | | * |
421 | | * Having removed some relations and outer joins from the jointree, we must |
422 | | * get rid of any references to them that are left behind elsewhere. There |
423 | | * should be no ordinary Vars of a removed relation left, but OJ relids can |
424 | | * still appear in the nullingrels sets of surviving Vars and PlaceHolderVars, |
425 | | * and both regular and OJ relids can appear in the phrels sets of |
426 | | * PlaceHolderVars. ChangeVarNodes knows how to strip a relid out of all of |
427 | | * those. |
428 | | */ |
429 | | static void |
430 | | remove_rels_from_query_tree(PlannerInfo *root, Relids removed_relids) |
431 | 0 | { |
432 | 0 | int relid = -1; |
433 | |
|
434 | 0 | while ((relid = bms_next_member(removed_relids, relid)) >= 0) |
435 | 0 | { |
436 | 0 | ChangeVarNodes((Node *) root->parse, relid, INVALID_VAR, 0); |
437 | | |
438 | | /* |
439 | | * processed_tlist shares some but not all of its nodes with |
440 | | * parse->targetList, so it has to be processed separately. (That's |
441 | | * harmless: ChangeVarNodes works in-place, and removing a relid that |
442 | | * isn't there is idempotent.) |
443 | | */ |
444 | 0 | ChangeVarNodes((Node *) root->processed_tlist, relid, INVALID_VAR, 0); |
445 | | |
446 | | /* There could be references in the append_rel_list, too */ |
447 | 0 | if (root->append_rel_list != NIL) |
448 | 0 | ChangeVarNodes((Node *) root->append_rel_list, relid, INVALID_VAR, 0); |
449 | 0 | } |
450 | 0 | } |
451 | | |
452 | | /* |
453 | | * reduce_unique_semijoins |
454 | | * Check for semijoins that can be simplified to plain inner joins |
455 | | * because the inner relation is provably unique for the join clauses. |
456 | | * |
457 | | * Ideally this would happen during reduce_outer_joins, but we don't have |
458 | | * enough information at that point. |
459 | | * |
460 | | * Like the join removal cases, we do this on the query's jointree, so |
461 | | * returning true means the caller must recompute the derived data. |
462 | | */ |
463 | | bool |
464 | | reduce_unique_semijoins(PlannerInfo *root) |
465 | 0 | { |
466 | 0 | bool changed = false; |
467 | 0 | ListCell *lc; |
468 | | |
469 | | /* |
470 | | * Scan the join_info_list to find semijoins. |
471 | | */ |
472 | 0 | foreach(lc, root->join_info_list) |
473 | 0 | { |
474 | 0 | SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc); |
475 | 0 | int innerrelid; |
476 | 0 | RelOptInfo *innerrel; |
477 | 0 | Relids joinrelids; |
478 | 0 | List *restrictlist; |
479 | | |
480 | | /* |
481 | | * Must be a semijoin to a single baserel, else we aren't going to be |
482 | | * able to do anything with it. |
483 | | */ |
484 | 0 | if (sjinfo->jointype != JOIN_SEMI) |
485 | 0 | continue; |
486 | | |
487 | | /* |
488 | | * We test the syntactic righthand side, since that's what identifies |
489 | | * the JoinExpr we'll modify. |
490 | | */ |
491 | 0 | if (!bms_get_singleton_member(sjinfo->syn_righthand, &innerrelid)) |
492 | 0 | continue; |
493 | 0 | Assert(bms_equal(sjinfo->min_righthand, sjinfo->syn_righthand)); |
494 | |
|
495 | 0 | innerrel = find_base_rel(root, innerrelid); |
496 | | |
497 | | /* |
498 | | * Before we trouble to run generate_join_implied_equalities, make a |
499 | | * quick check to eliminate cases in which we will surely be unable to |
500 | | * prove uniqueness of the innerrel. |
501 | | */ |
502 | 0 | if (!rel_supports_distinctness(root, innerrel)) |
503 | 0 | continue; |
504 | | |
505 | | /* Compute the relid set for the join we are considering */ |
506 | 0 | joinrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand); |
507 | 0 | Assert(sjinfo->ojrelid == 0); /* SEMI joins don't have RT indexes */ |
508 | | |
509 | | /* |
510 | | * Since we're only considering a single-rel RHS, any join clauses it |
511 | | * has must be clauses linking it to the semijoin's min_lefthand. We |
512 | | * can also consider EC-derived join clauses. |
513 | | */ |
514 | 0 | restrictlist = |
515 | 0 | list_concat(generate_join_implied_equalities(root, |
516 | 0 | joinrelids, |
517 | 0 | sjinfo->min_lefthand, |
518 | 0 | innerrel, |
519 | 0 | NULL), |
520 | 0 | innerrel->joininfo); |
521 | | |
522 | | /* Test whether the innerrel is unique for those clauses. */ |
523 | 0 | if (!innerrel_is_unique(root, |
524 | 0 | joinrelids, sjinfo->min_lefthand, innerrel, |
525 | 0 | JOIN_SEMI, restrictlist, true)) |
526 | 0 | continue; |
527 | | |
528 | | /* OK, reduce the join to a plain inner join in the jointree. */ |
529 | 0 | if (!reduce_semijoin_in_jointree((Node *) root->parse->jointree, |
530 | 0 | sjinfo->syn_righthand)) |
531 | 0 | elog(ERROR, "failed to find semijoin in jointree"); |
532 | 0 | changed = true; |
533 | 0 | } |
534 | | |
535 | 0 | return changed; |
536 | 0 | } |
537 | | |
538 | | /* |
539 | | * reduce_semijoin_in_jointree |
540 | | * Find the JoinExpr for the semijoin with the given syntactic righthand |
541 | | * side, and turn it into an inner join. |
542 | | * |
543 | | * Semijoins have no RT index of their own, so we have to identify the one |
544 | | * we want by the set of relids on its righthand side. |
545 | | */ |
546 | | static bool |
547 | | reduce_semijoin_in_jointree(Node *jtnode, Relids syn_righthand) |
548 | 0 | { |
549 | 0 | if (jtnode == NULL) |
550 | 0 | return false; |
551 | 0 | if (IsA(jtnode, RangeTblRef)) |
552 | 0 | { |
553 | | /* nothing to do here */ |
554 | 0 | } |
555 | 0 | else if (IsA(jtnode, FromExpr)) |
556 | 0 | { |
557 | 0 | FromExpr *f = (FromExpr *) jtnode; |
558 | 0 | ListCell *l; |
559 | |
|
560 | 0 | foreach(l, f->fromlist) |
561 | 0 | { |
562 | 0 | if (reduce_semijoin_in_jointree((Node *) lfirst(l), syn_righthand)) |
563 | 0 | return true; |
564 | 0 | } |
565 | 0 | } |
566 | 0 | else if (IsA(jtnode, JoinExpr)) |
567 | 0 | { |
568 | 0 | JoinExpr *j = (JoinExpr *) jtnode; |
569 | |
|
570 | 0 | if (j->jointype == JOIN_SEMI && |
571 | 0 | bms_equal(get_relids_in_jointree(j->rarg, true, false), |
572 | 0 | syn_righthand)) |
573 | 0 | { |
574 | 0 | j->jointype = JOIN_INNER; |
575 | 0 | return true; |
576 | 0 | } |
577 | 0 | if (reduce_semijoin_in_jointree(j->larg, syn_righthand)) |
578 | 0 | return true; |
579 | 0 | if (reduce_semijoin_in_jointree(j->rarg, syn_righthand)) |
580 | 0 | return true; |
581 | 0 | } |
582 | 0 | else |
583 | 0 | elog(ERROR, "unrecognized jointree node type: %d", |
584 | 0 | (int) nodeTag(jtnode)); |
585 | | |
586 | 0 | return false; |
587 | 0 | } |
588 | | |
589 | | |
590 | | /* |
591 | | * rel_supports_distinctness |
592 | | * Could the relation possibly be proven distinct on some set of columns? |
593 | | * |
594 | | * This is effectively a pre-checking function for rel_is_distinct_for(). |
595 | | * It must return true if rel_is_distinct_for() could possibly return true |
596 | | * with this rel, but it should not expend a lot of cycles. The idea is |
597 | | * that callers can avoid doing possibly-expensive processing to compute |
598 | | * rel_is_distinct_for()'s argument lists if the call could not possibly |
599 | | * succeed. |
600 | | */ |
601 | | static bool |
602 | | rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel) |
603 | 0 | { |
604 | | /* We only know about baserels ... */ |
605 | 0 | if (rel->reloptkind != RELOPT_BASEREL) |
606 | 0 | return false; |
607 | 0 | if (rel->rtekind == RTE_RELATION) |
608 | 0 | { |
609 | | /* |
610 | | * For a plain relation, we only know how to prove uniqueness by |
611 | | * reference to unique indexes. Make sure there's at least one |
612 | | * suitable unique index. It must be immediately enforced, and not a |
613 | | * partial index. (Keep these conditions in sync with |
614 | | * relation_has_unique_index_for!) |
615 | | */ |
616 | 0 | ListCell *lc; |
617 | |
|
618 | 0 | foreach(lc, rel->indexlist) |
619 | 0 | { |
620 | 0 | IndexOptInfo *ind = (IndexOptInfo *) lfirst(lc); |
621 | |
|
622 | 0 | if (ind->unique && ind->immediate && ind->indpred == NIL) |
623 | 0 | return true; |
624 | 0 | } |
625 | 0 | } |
626 | 0 | else if (rel->rtekind == RTE_SUBQUERY) |
627 | 0 | { |
628 | 0 | Query *subquery = root->simple_rte_array[rel->relid]->subquery; |
629 | | |
630 | | /* Check if the subquery has any qualities that support distinctness */ |
631 | 0 | if (query_supports_distinctness(subquery)) |
632 | 0 | return true; |
633 | 0 | } |
634 | | /* We have no proof rules for any other rtekinds. */ |
635 | 0 | return false; |
636 | 0 | } |
637 | | |
638 | | /* |
639 | | * rel_is_distinct_for |
640 | | * Does the relation return only distinct rows according to clause_list? |
641 | | * |
642 | | * clause_list is a list of join restriction clauses involving this rel and |
643 | | * some other one. Return true if no two rows emitted by this rel could |
644 | | * possibly join to the same row of the other rel. |
645 | | * |
646 | | * The caller must have already determined that each condition is a |
647 | | * mergejoinable equality with an expression in this relation on one side, and |
648 | | * an expression not involving this relation on the other. The transient |
649 | | * outer_is_left flag is used to identify which side references this relation: |
650 | | * left side if outer_is_left is false, right side if it is true. |
651 | | * |
652 | | * Note that the passed-in clause_list may be destructively modified! This |
653 | | * is OK for current uses, because the clause_list is built by the caller for |
654 | | * the sole purpose of passing to this function. |
655 | | * |
656 | | * (*extra_clauses) to be set to the right sides of baserestrictinfo clauses, |
657 | | * looking like "x = const" if distinctness is derived from such clauses, not |
658 | | * joininfo clauses. Pass NULL to the extra_clauses if this value is not |
659 | | * needed. |
660 | | */ |
661 | | static bool |
662 | | rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list, |
663 | | List **extra_clauses) |
664 | 0 | { |
665 | | /* |
666 | | * We could skip a couple of tests here if we assume all callers checked |
667 | | * rel_supports_distinctness first, but it doesn't seem worth taking any |
668 | | * risk for. |
669 | | */ |
670 | 0 | if (rel->reloptkind != RELOPT_BASEREL) |
671 | 0 | return false; |
672 | 0 | if (rel->rtekind == RTE_RELATION) |
673 | 0 | { |
674 | | /* |
675 | | * Examine the indexes to see if we have a matching unique index. |
676 | | * relation_has_unique_index_for automatically adds any usable |
677 | | * restriction clauses for the rel, so we needn't do that here. |
678 | | */ |
679 | 0 | if (relation_has_unique_index_for(root, rel, clause_list, extra_clauses)) |
680 | 0 | return true; |
681 | 0 | } |
682 | 0 | else if (rel->rtekind == RTE_SUBQUERY) |
683 | 0 | { |
684 | 0 | Index relid = rel->relid; |
685 | 0 | Query *subquery = root->simple_rte_array[relid]->subquery; |
686 | 0 | List *distinct_cols = NIL; |
687 | 0 | ListCell *l; |
688 | | |
689 | | /* |
690 | | * Build the argument list for query_is_distinct_for: a list of |
691 | | * DistinctColInfo entries, each holding an output column number that |
692 | | * the query needs to be distinct over, the equality operator that the |
693 | | * column needs to be distinct according to, and that operator's input |
694 | | * collation. The collation matters because the subquery's own |
695 | | * DISTINCT / GROUP BY / set-op proves uniqueness under its own |
696 | | * collation, which need not agree with the operator's. |
697 | | * |
698 | | * (XXX we are not considering restriction clauses attached to the |
699 | | * subquery; is that worth doing?) |
700 | | */ |
701 | 0 | foreach(l, clause_list) |
702 | 0 | { |
703 | 0 | RestrictInfo *rinfo = lfirst_node(RestrictInfo, l); |
704 | 0 | OpExpr *opexpr; |
705 | 0 | Var *var; |
706 | 0 | DistinctColInfo *dcinfo; |
707 | | |
708 | | /* |
709 | | * The caller's mergejoinability test should have selected only |
710 | | * OpExprs. The operator might be a cross-type operator and thus |
711 | | * not exactly the same operator the subquery would consider; |
712 | | * that's all right since query_is_distinct_for can resolve such |
713 | | * cases. |
714 | | */ |
715 | 0 | opexpr = castNode(OpExpr, rinfo->clause); |
716 | | |
717 | | /* caller identified the inner side for us */ |
718 | 0 | if (rinfo->outer_is_left) |
719 | 0 | var = (Var *) get_rightop(rinfo->clause); |
720 | 0 | else |
721 | 0 | var = (Var *) get_leftop(rinfo->clause); |
722 | | |
723 | | /* |
724 | | * We may ignore any RelabelType node above the operand. (There |
725 | | * won't be more than one, since eval_const_expressions() has been |
726 | | * applied already.) |
727 | | */ |
728 | 0 | if (var && IsA(var, RelabelType)) |
729 | 0 | var = (Var *) ((RelabelType *) var)->arg; |
730 | | |
731 | | /* |
732 | | * If inner side isn't a Var referencing a subquery output column, |
733 | | * this clause doesn't help us. |
734 | | */ |
735 | 0 | if (!var || !IsA(var, Var) || |
736 | 0 | var->varno != relid || var->varlevelsup != 0) |
737 | 0 | continue; |
738 | | |
739 | 0 | dcinfo = palloc_object(DistinctColInfo); |
740 | 0 | dcinfo->colno = var->varattno; |
741 | 0 | dcinfo->opid = opexpr->opno; |
742 | 0 | dcinfo->collid = opexpr->inputcollid; |
743 | 0 | distinct_cols = lappend(distinct_cols, dcinfo); |
744 | 0 | } |
745 | |
|
746 | 0 | if (query_is_distinct_for(subquery, distinct_cols)) |
747 | 0 | return true; |
748 | 0 | } |
749 | 0 | return false; |
750 | 0 | } |
751 | | |
752 | | |
753 | | /* |
754 | | * query_supports_distinctness - could the query possibly be proven distinct |
755 | | * on some set of output columns? |
756 | | * |
757 | | * This is effectively a pre-checking function for query_is_distinct_for(). |
758 | | * It must return true if query_is_distinct_for() could possibly return true |
759 | | * with this query, but it should not expend a lot of cycles. The idea is |
760 | | * that callers can avoid doing possibly-expensive processing to compute |
761 | | * query_is_distinct_for()'s argument lists if the call could not possibly |
762 | | * succeed. |
763 | | */ |
764 | | bool |
765 | | query_supports_distinctness(Query *query) |
766 | 0 | { |
767 | | /* SRFs break distinctness except with plain DISTINCT, see below */ |
768 | 0 | if (query->hasTargetSRFs && |
769 | 0 | (query->distinctClause == NIL || query->hasDistinctOn)) |
770 | 0 | return false; |
771 | | |
772 | | /* check for features we can prove distinctness with */ |
773 | 0 | if (query->distinctClause != NIL || |
774 | 0 | query->groupClause != NIL || |
775 | 0 | query->groupingSets != NIL || |
776 | 0 | query->hasAggs || |
777 | 0 | query->havingQual || |
778 | 0 | query->setOperations) |
779 | 0 | return true; |
780 | | |
781 | 0 | return false; |
782 | 0 | } |
783 | | |
784 | | /* |
785 | | * query_is_distinct_for - does query never return duplicates of the |
786 | | * specified columns? |
787 | | * |
788 | | * query is a not-yet-planned subquery (in current usage, it's always from |
789 | | * a subquery RTE, which the planner avoids scribbling on). |
790 | | * |
791 | | * distinct_cols is a list of DistinctColInfo, one per requested output column. |
792 | | * Each entry names the subquery output column number we want distinct, the |
793 | | * upper-level equality operator we'll compare values with, and that operator's |
794 | | * input collation. We are interested in whether rows consisting of just these |
795 | | * columns are certain to be distinct. |
796 | | * |
797 | | * "Distinctness" is defined according to whether the corresponding upper-level |
798 | | * equality operators would think the values are distinct. (Note: each opid |
799 | | * could be a cross-type operator, and thus not exactly the equality operator |
800 | | * that the subquery would use itself. We use equality_ops_are_compatible() to |
801 | | * check compatibility. That looks at opfamily membership for index AMs that |
802 | | * have declared that they support consistent equality semantics within an |
803 | | * opfamily, and so should give trustworthy answers for all operators that we |
804 | | * might need to deal with here.) |
805 | | * |
806 | | * The collid must also agree on equality with the collation the subquery's own |
807 | | * DISTINCT/GROUP BY/set-op uses to deduplicate the column, else the subquery's |
808 | | * distinctness does not carry over to the caller's equality semantics. Two |
809 | | * collations agree on equality if they match or if both are deterministic (in |
810 | | * which case both reduce equality to byte-equality; see CREATE COLLATION). |
811 | | */ |
812 | | bool |
813 | | query_is_distinct_for(Query *query, List *distinct_cols) |
814 | 0 | { |
815 | 0 | ListCell *l; |
816 | 0 | DistinctColInfo *dcinfo; |
817 | | |
818 | | /* |
819 | | * DISTINCT (including DISTINCT ON) guarantees uniqueness if all the |
820 | | * columns in the DISTINCT clause appear in colnos and operator semantics |
821 | | * match. With plain DISTINCT this is true even if there are SRFs in the |
822 | | * tlist, since they are all DISTINCT columns and hence get expanded |
823 | | * before the Unique step. But with DISTINCT ON, the planner may postpone |
824 | | * SRFs that are not DISTINCT ON or ORDER BY columns until after the |
825 | | * Unique step, which can produce duplicates of the DISTINCT ON columns; |
826 | | * so we can't rely on DISTINCT ON if there are any tlist SRFs. |
827 | | */ |
828 | 0 | if (query->distinctClause && |
829 | 0 | !(query->hasTargetSRFs && query->hasDistinctOn)) |
830 | 0 | { |
831 | 0 | foreach(l, query->distinctClause) |
832 | 0 | { |
833 | 0 | SortGroupClause *sgc = (SortGroupClause *) lfirst(l); |
834 | 0 | TargetEntry *tle = get_sortgroupclause_tle(sgc, |
835 | 0 | query->targetList); |
836 | |
|
837 | 0 | dcinfo = distinct_col_search(tle->resno, distinct_cols); |
838 | 0 | if (dcinfo == NULL || |
839 | 0 | !equality_ops_are_compatible(dcinfo->opid, sgc->eqop) || |
840 | 0 | !collations_agree_on_equality(dcinfo->collid, |
841 | 0 | exprCollation((Node *) tle->expr))) |
842 | 0 | break; /* exit early if no match */ |
843 | 0 | } |
844 | 0 | if (l == NULL) /* had matches for all? */ |
845 | 0 | return true; |
846 | 0 | } |
847 | | |
848 | | /* |
849 | | * Otherwise, a set-returning function in the query's targetlist can |
850 | | * result in returning duplicate rows, despite any grouping that might |
851 | | * occur before tlist evaluation. (If all tlist SRFs are within GROUP BY |
852 | | * columns, it would be safe because they'd be expanded before grouping. |
853 | | * But it doesn't currently seem worth the effort to check for that.) |
854 | | */ |
855 | 0 | if (query->hasTargetSRFs) |
856 | 0 | return false; |
857 | | |
858 | | /* |
859 | | * Similarly, GROUP BY without GROUPING SETS guarantees uniqueness if all |
860 | | * the grouped columns appear in colnos and operator semantics match. |
861 | | */ |
862 | 0 | if (query->groupClause && !query->groupingSets) |
863 | 0 | { |
864 | 0 | foreach(l, query->groupClause) |
865 | 0 | { |
866 | 0 | SortGroupClause *sgc = (SortGroupClause *) lfirst(l); |
867 | 0 | TargetEntry *tle = get_sortgroupclause_tle(sgc, |
868 | 0 | query->targetList); |
869 | |
|
870 | 0 | dcinfo = distinct_col_search(tle->resno, distinct_cols); |
871 | 0 | if (dcinfo == NULL || |
872 | 0 | !equality_ops_are_compatible(dcinfo->opid, sgc->eqop) || |
873 | 0 | !collations_agree_on_equality(dcinfo->collid, |
874 | 0 | exprCollation((Node *) tle->expr))) |
875 | 0 | break; /* exit early if no match */ |
876 | 0 | } |
877 | 0 | if (l == NULL) /* had matches for all? */ |
878 | 0 | return true; |
879 | 0 | } |
880 | 0 | else if (query->groupingSets) |
881 | 0 | { |
882 | 0 | List *gsets; |
883 | | |
884 | | /* |
885 | | * If we have grouping sets with expressions, we probably don't have |
886 | | * uniqueness and analysis would be hard. Punt. |
887 | | */ |
888 | 0 | if (query->groupClause) |
889 | 0 | return false; |
890 | | |
891 | | /* |
892 | | * If we have no groupClause (therefore no grouping expressions), we |
893 | | * might have one or many empty grouping sets. If there's just one, |
894 | | * or if the DISTINCT clause is used on the GROUP BY, then we're |
895 | | * returning only one row and are certainly unique. But otherwise, we |
896 | | * know we're certainly not unique. |
897 | | */ |
898 | 0 | if (query->groupDistinct) |
899 | 0 | return true; |
900 | | |
901 | 0 | gsets = expand_grouping_sets(query->groupingSets, false, -1); |
902 | |
|
903 | 0 | return (list_length(gsets) == 1); |
904 | 0 | } |
905 | 0 | else |
906 | 0 | { |
907 | | /* |
908 | | * If we have no GROUP BY, but do have aggregates or HAVING, then the |
909 | | * result is at most one row so it's surely unique, for any operators. |
910 | | */ |
911 | 0 | if (query->hasAggs || query->havingQual) |
912 | 0 | return true; |
913 | 0 | } |
914 | | |
915 | | /* |
916 | | * UNION, INTERSECT, EXCEPT guarantee uniqueness of the whole output row, |
917 | | * except with ALL. |
918 | | */ |
919 | 0 | if (query->setOperations) |
920 | 0 | { |
921 | 0 | SetOperationStmt *topop = castNode(SetOperationStmt, query->setOperations); |
922 | |
|
923 | 0 | Assert(topop->op != SETOP_NONE); |
924 | |
|
925 | 0 | if (!topop->all) |
926 | 0 | { |
927 | 0 | ListCell *lg; |
928 | | |
929 | | /* We're good if all the nonjunk output columns are in colnos */ |
930 | 0 | lg = list_head(topop->groupClauses); |
931 | 0 | foreach(l, query->targetList) |
932 | 0 | { |
933 | 0 | TargetEntry *tle = (TargetEntry *) lfirst(l); |
934 | 0 | SortGroupClause *sgc; |
935 | |
|
936 | 0 | if (tle->resjunk) |
937 | 0 | continue; /* ignore resjunk columns */ |
938 | | |
939 | | /* non-resjunk columns should have grouping clauses */ |
940 | 0 | Assert(lg != NULL); |
941 | 0 | sgc = (SortGroupClause *) lfirst(lg); |
942 | 0 | lg = lnext(topop->groupClauses, lg); |
943 | |
|
944 | 0 | dcinfo = distinct_col_search(tle->resno, distinct_cols); |
945 | 0 | if (dcinfo == NULL || |
946 | 0 | !equality_ops_are_compatible(dcinfo->opid, sgc->eqop) || |
947 | 0 | !collations_agree_on_equality(dcinfo->collid, |
948 | 0 | exprCollation((Node *) tle->expr))) |
949 | 0 | break; /* exit early if no match */ |
950 | 0 | } |
951 | 0 | if (l == NULL) /* had matches for all? */ |
952 | 0 | return true; |
953 | 0 | } |
954 | 0 | } |
955 | | |
956 | | /* |
957 | | * XXX Are there any other cases in which we can easily see the result |
958 | | * must be distinct? |
959 | | * |
960 | | * If you do add more smarts to this function, be sure to update |
961 | | * query_supports_distinctness() to match. |
962 | | */ |
963 | | |
964 | 0 | return false; |
965 | 0 | } |
966 | | |
967 | | /* |
968 | | * distinct_col_search - subroutine for query_is_distinct_for |
969 | | * |
970 | | * If colno matches the colno field of an entry in distinct_cols, return a |
971 | | * pointer to that entry; else return NULL. (Ordinarily distinct_cols would |
972 | | * not contain duplicate colnos, but if it does, we arbitrarily select the |
973 | | * first match.) |
974 | | */ |
975 | | static DistinctColInfo * |
976 | | distinct_col_search(int colno, List *distinct_cols) |
977 | 0 | { |
978 | 0 | foreach_ptr(DistinctColInfo, dcinfo, distinct_cols) |
979 | 0 | { |
980 | 0 | if (dcinfo->colno == colno) |
981 | 0 | return dcinfo; |
982 | 0 | } |
983 | | |
984 | 0 | return NULL; |
985 | 0 | } |
986 | | |
987 | | |
988 | | /* |
989 | | * innerrel_is_unique |
990 | | * Check if the innerrel provably contains at most one tuple matching any |
991 | | * tuple from the outerrel, based on join clauses in the 'restrictlist'. |
992 | | * |
993 | | * We need an actual RelOptInfo for the innerrel, but it's sufficient to |
994 | | * identify the outerrel by its Relids. This asymmetry supports use of this |
995 | | * function before joinrels have been built. (The caller is expected to |
996 | | * also supply the joinrelids, just to save recalculating that.) |
997 | | * |
998 | | * The proof must be made based only on clauses that will be "joinquals" |
999 | | * rather than "otherquals" at execution. For an inner join there's no |
1000 | | * difference; but if the join is outer, we must ignore pushed-down quals, |
1001 | | * as those will become "otherquals". Note that this means the answer might |
1002 | | * vary depending on whether IS_OUTER_JOIN(jointype); since we cache the |
1003 | | * answer without regard to that, callers must take care not to call this |
1004 | | * with jointypes that would be classified differently by IS_OUTER_JOIN(). |
1005 | | * |
1006 | | * The actual proof is undertaken by is_innerrel_unique_for(); this function |
1007 | | * is a frontend that is mainly concerned with caching the answers. |
1008 | | * In particular, the force_cache argument allows overriding the internal |
1009 | | * heuristic about whether to cache negative answers; it should be "true" |
1010 | | * if making an inquiry that is not part of the normal bottom-up join search |
1011 | | * sequence. |
1012 | | */ |
1013 | | bool |
1014 | | innerrel_is_unique(PlannerInfo *root, |
1015 | | Relids joinrelids, |
1016 | | Relids outerrelids, |
1017 | | RelOptInfo *innerrel, |
1018 | | JoinType jointype, |
1019 | | List *restrictlist, |
1020 | | bool force_cache) |
1021 | 0 | { |
1022 | 0 | return innerrel_is_unique_ext(root, joinrelids, outerrelids, innerrel, |
1023 | 0 | jointype, restrictlist, force_cache, NULL); |
1024 | 0 | } |
1025 | | |
1026 | | /* |
1027 | | * innerrel_is_unique_ext |
1028 | | * Do the same as innerrel_is_unique(), but also set to (*extra_clauses) |
1029 | | * additional clauses from a baserestrictinfo list used to prove the |
1030 | | * uniqueness. |
1031 | | * |
1032 | | * A non-NULL extra_clauses indicates that we're checking for self-join and |
1033 | | * correspondingly dealing with filtered clauses. |
1034 | | */ |
1035 | | static bool |
1036 | | innerrel_is_unique_ext(PlannerInfo *root, |
1037 | | Relids joinrelids, |
1038 | | Relids outerrelids, |
1039 | | RelOptInfo *innerrel, |
1040 | | JoinType jointype, |
1041 | | List *restrictlist, |
1042 | | bool force_cache, |
1043 | | List **extra_clauses) |
1044 | 0 | { |
1045 | 0 | MemoryContext old_context; |
1046 | 0 | ListCell *lc; |
1047 | 0 | UniqueRelInfo *uniqueRelInfo; |
1048 | 0 | List *outer_exprs = NIL; |
1049 | 0 | bool self_join = (extra_clauses != NULL); |
1050 | | |
1051 | | /* Certainly can't prove uniqueness when there are no joinclauses */ |
1052 | 0 | if (restrictlist == NIL) |
1053 | 0 | return false; |
1054 | | |
1055 | | /* |
1056 | | * Make a quick check to eliminate cases in which we will surely be unable |
1057 | | * to prove uniqueness of the innerrel. |
1058 | | */ |
1059 | 0 | if (!rel_supports_distinctness(root, innerrel)) |
1060 | 0 | return false; |
1061 | | |
1062 | | /* |
1063 | | * Query the cache to see if we've managed to prove that innerrel is |
1064 | | * unique for any subset of this outerrel. For non-self-join search, we |
1065 | | * don't need an exact match, as extra outerrels can't make the innerrel |
1066 | | * any less unique (or more formally, the restrictlist for a join to a |
1067 | | * superset outerrel must be a superset of the conditions we successfully |
1068 | | * used before). For self-join search, we require an exact match of |
1069 | | * outerrels because we need extra clauses to be valid for our case. Also, |
1070 | | * for self-join checking we've filtered the clauses list. Thus, we can |
1071 | | * match only the result cached for a self-join search for another |
1072 | | * self-join check. |
1073 | | */ |
1074 | 0 | foreach(lc, innerrel->unique_for_rels) |
1075 | 0 | { |
1076 | 0 | uniqueRelInfo = (UniqueRelInfo *) lfirst(lc); |
1077 | |
|
1078 | 0 | if ((!self_join && bms_is_subset(uniqueRelInfo->outerrelids, outerrelids)) || |
1079 | 0 | (self_join && bms_equal(uniqueRelInfo->outerrelids, outerrelids) && |
1080 | 0 | uniqueRelInfo->self_join)) |
1081 | 0 | { |
1082 | 0 | if (extra_clauses) |
1083 | 0 | *extra_clauses = uniqueRelInfo->extra_clauses; |
1084 | 0 | return true; /* Success! */ |
1085 | 0 | } |
1086 | 0 | } |
1087 | | |
1088 | | /* |
1089 | | * Conversely, we may have already determined that this outerrel, or some |
1090 | | * superset thereof, cannot prove this innerrel to be unique. |
1091 | | */ |
1092 | 0 | foreach(lc, innerrel->non_unique_for_rels) |
1093 | 0 | { |
1094 | 0 | Relids unique_for_rels = (Relids) lfirst(lc); |
1095 | |
|
1096 | 0 | if (bms_is_subset(outerrelids, unique_for_rels)) |
1097 | 0 | return false; |
1098 | 0 | } |
1099 | | |
1100 | | /* No cached information, so try to make the proof. */ |
1101 | 0 | if (is_innerrel_unique_for(root, joinrelids, outerrelids, innerrel, |
1102 | 0 | jointype, restrictlist, |
1103 | 0 | self_join ? &outer_exprs : NULL)) |
1104 | 0 | { |
1105 | | /* |
1106 | | * Cache the positive result for future probes, being sure to keep it |
1107 | | * in the planner_cxt even if we are working in GEQO. |
1108 | | * |
1109 | | * Note: one might consider trying to isolate the minimal subset of |
1110 | | * the outerrels that proved the innerrel unique. But it's not worth |
1111 | | * the trouble, because the planner builds up joinrels incrementally |
1112 | | * and so we'll see the minimally sufficient outerrels before any |
1113 | | * supersets of them anyway. |
1114 | | */ |
1115 | 0 | old_context = MemoryContextSwitchTo(root->planner_cxt); |
1116 | 0 | uniqueRelInfo = makeNode(UniqueRelInfo); |
1117 | 0 | uniqueRelInfo->outerrelids = bms_copy(outerrelids); |
1118 | 0 | uniqueRelInfo->self_join = self_join; |
1119 | 0 | uniqueRelInfo->extra_clauses = outer_exprs; |
1120 | 0 | innerrel->unique_for_rels = lappend(innerrel->unique_for_rels, |
1121 | 0 | uniqueRelInfo); |
1122 | 0 | MemoryContextSwitchTo(old_context); |
1123 | |
|
1124 | 0 | if (extra_clauses) |
1125 | 0 | *extra_clauses = outer_exprs; |
1126 | 0 | return true; /* Success! */ |
1127 | 0 | } |
1128 | 0 | else |
1129 | 0 | { |
1130 | | /* |
1131 | | * None of the join conditions for outerrel proved innerrel unique, so |
1132 | | * we can safely reject this outerrel or any subset of it in future |
1133 | | * checks. |
1134 | | * |
1135 | | * However, in normal planning mode, caching this knowledge is totally |
1136 | | * pointless; it won't be queried again, because we build up joinrels |
1137 | | * from smaller to larger. It's only useful when using GEQO or |
1138 | | * another planner extension that attempts planning multiple times. |
1139 | | * |
1140 | | * Also, allow callers to override that heuristic and force caching; |
1141 | | * that's useful for reduce_unique_semijoins, which calls here before |
1142 | | * the normal join search starts. |
1143 | | */ |
1144 | 0 | if (force_cache || root->assumeReplanning) |
1145 | 0 | { |
1146 | 0 | old_context = MemoryContextSwitchTo(root->planner_cxt); |
1147 | 0 | innerrel->non_unique_for_rels = |
1148 | 0 | lappend(innerrel->non_unique_for_rels, |
1149 | 0 | bms_copy(outerrelids)); |
1150 | 0 | MemoryContextSwitchTo(old_context); |
1151 | 0 | } |
1152 | |
|
1153 | 0 | return false; |
1154 | 0 | } |
1155 | 0 | } |
1156 | | |
1157 | | /* |
1158 | | * is_innerrel_unique_for |
1159 | | * Check if the innerrel provably contains at most one tuple matching any |
1160 | | * tuple from the outerrel, based on join clauses in the 'restrictlist'. |
1161 | | */ |
1162 | | static bool |
1163 | | is_innerrel_unique_for(PlannerInfo *root, |
1164 | | Relids joinrelids, |
1165 | | Relids outerrelids, |
1166 | | RelOptInfo *innerrel, |
1167 | | JoinType jointype, |
1168 | | List *restrictlist, |
1169 | | List **extra_clauses) |
1170 | 0 | { |
1171 | 0 | List *clause_list = NIL; |
1172 | 0 | ListCell *lc; |
1173 | | |
1174 | | /* |
1175 | | * Search for mergejoinable clauses that constrain the inner rel against |
1176 | | * the outer rel. If an operator is mergejoinable then it behaves like |
1177 | | * equality for some btree opclass, so it's what we want. The |
1178 | | * mergejoinability test also eliminates clauses containing volatile |
1179 | | * functions, which we couldn't depend on. |
1180 | | */ |
1181 | 0 | foreach(lc, restrictlist) |
1182 | 0 | { |
1183 | 0 | RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(lc); |
1184 | | |
1185 | | /* |
1186 | | * As noted above, if it's a pushed-down clause and we're at an outer |
1187 | | * join, we can't use it. |
1188 | | */ |
1189 | 0 | if (IS_OUTER_JOIN(jointype) && |
1190 | 0 | RINFO_IS_PUSHED_DOWN(restrictinfo, joinrelids)) |
1191 | 0 | continue; |
1192 | | |
1193 | | /* Ignore if it's not a mergejoinable clause */ |
1194 | 0 | if (!restrictinfo->can_join || |
1195 | 0 | restrictinfo->mergeopfamilies == NIL) |
1196 | 0 | continue; /* not mergejoinable */ |
1197 | | |
1198 | | /* |
1199 | | * Check if the clause has the form "outer op inner" or "inner op |
1200 | | * outer", and if so mark which side is inner. |
1201 | | */ |
1202 | 0 | if (!clause_sides_match_join(restrictinfo, outerrelids, |
1203 | 0 | innerrel->relids)) |
1204 | 0 | continue; /* no good for these input relations */ |
1205 | | |
1206 | | /* OK, add to the list */ |
1207 | 0 | clause_list = lappend(clause_list, restrictinfo); |
1208 | 0 | } |
1209 | | |
1210 | | /* Let rel_is_distinct_for() do the hard work */ |
1211 | 0 | return rel_is_distinct_for(root, innerrel, clause_list, extra_clauses); |
1212 | 0 | } |
1213 | | |
1214 | | /* |
1215 | | * Remove the toRemove relation after we have proven that it participates only |
1216 | | * in an unneeded unique self-join with toKeep. |
1217 | | * |
1218 | | * The removal is done by deleting the relation's RangeTblRef from the |
1219 | | * jointree and then pointing everything that referenced it at the relation we |
1220 | | * are keeping. All the conditions that were attached to the removed relation |
1221 | | * thereby become conditions on the remaining one, which is what we want: |
1222 | | * we've proven that the two relations select the same rows. Note that |
1223 | | * this change requires us to hoist those conditions up to someplace |
1224 | | * syntactically enclosing toKeep. |
1225 | | * |
1226 | | * kmark and rmark are the PlanRowMarks (if any) for the kept and removed |
1227 | | * relations. We could re-locate those, but the caller already found them. |
1228 | | */ |
1229 | | static void |
1230 | | remove_self_join_rel(PlannerInfo *root, |
1231 | | RelOptInfo *toKeep, RelOptInfo *toRemove, |
1232 | | PlanRowMark *kmark, PlanRowMark *rmark) |
1233 | 0 | { |
1234 | 0 | Node *orphan_quals = NULL; |
1235 | 0 | int nremoved = 0; |
1236 | 0 | Node *hoist_quals = NULL; |
1237 | 0 | bool found_relid = false; |
1238 | |
|
1239 | 0 | Assert(toKeep->relid > 0); |
1240 | 0 | Assert(toRemove->relid > 0); |
1241 | | |
1242 | | /* We verify that exactly one reference gets removed from the jointree */ |
1243 | 0 | root->parse->jointree = (FromExpr *) |
1244 | 0 | remove_rel_from_jointree((Node *) root->parse->jointree, |
1245 | 0 | toRemove->relid, |
1246 | 0 | &orphan_quals, &nremoved); |
1247 | 0 | if (nremoved != 1) |
1248 | 0 | elog(ERROR, "failed to find relation %d in jointree", toRemove->relid); |
1249 | | /* The topmost FromExpr can't have gone away, so nothing can be orphaned */ |
1250 | 0 | Assert(root->parse->jointree != NULL); |
1251 | 0 | Assert(orphan_quals == NULL); |
1252 | | |
1253 | | /* |
1254 | | * Replace all references to the removed relation. Note that this must |
1255 | | * happen after the jointree surgery, else we'd not be able to tell the |
1256 | | * two relations' RangeTblRefs apart. |
1257 | | */ |
1258 | 0 | ChangeVarNodes((Node *) root->parse, toRemove->relid, toKeep->relid, 0); |
1259 | | |
1260 | | /* |
1261 | | * processed_tlist shares some but not all of its nodes with |
1262 | | * parse->targetList, so it has to be processed separately. (That's |
1263 | | * harmless: ChangeVarNodes works in-place, and the second visit to a |
1264 | | * shared node finds nothing to change.) |
1265 | | */ |
1266 | 0 | ChangeVarNodes((Node *) root->processed_tlist, toRemove->relid, |
1267 | 0 | toKeep->relid, 0); |
1268 | | |
1269 | | /* There could be references in the append_rel_list, too */ |
1270 | 0 | if (root->append_rel_list != NIL) |
1271 | 0 | ChangeVarNodes((Node *) root->append_rel_list, toRemove->relid, |
1272 | 0 | toKeep->relid, 0); |
1273 | | |
1274 | | /* |
1275 | | * As in remove_useless_outer_joins, discard the securityQuals of the |
1276 | | * removed rel, so that later passes don't visit them. We know the kept |
1277 | | * rel has the same quals. (tablesample is already known NULL.) |
1278 | | */ |
1279 | 0 | root->simple_rte_array[toRemove->relid]->securityQuals = NIL; |
1280 | | |
1281 | | /* Clean up the quals that the substitution has messed with */ |
1282 | 0 | fixup_selfjoin_jointree(root, (Node *) root->parse->jointree, |
1283 | 0 | toKeep->relid, |
1284 | 0 | &hoist_quals, &found_relid); |
1285 | | /* We shouldn't have any leftover quals, and we must have found toKeep */ |
1286 | 0 | Assert(hoist_quals == NULL); |
1287 | 0 | Assert(found_relid); |
1288 | | |
1289 | | /* |
1290 | | * If the removed relation has a row mark, transfer it to the remaining |
1291 | | * one. |
1292 | | * |
1293 | | * If both rels have row marks, just keep the one corresponding to the |
1294 | | * remaining relation because we verified earlier that they have the same |
1295 | | * strength. |
1296 | | */ |
1297 | 0 | if (rmark) |
1298 | 0 | { |
1299 | 0 | if (kmark) |
1300 | 0 | { |
1301 | 0 | Assert(kmark->markType == rmark->markType); |
1302 | |
|
1303 | 0 | root->rowMarks = list_delete_ptr(root->rowMarks, rmark); |
1304 | 0 | } |
1305 | 0 | else |
1306 | 0 | { |
1307 | | /* Shouldn't have inheritance children yet. */ |
1308 | 0 | Assert(rmark->rti == rmark->prti); |
1309 | |
|
1310 | 0 | rmark->rti = rmark->prti = toKeep->relid; |
1311 | 0 | } |
1312 | 0 | } |
1313 | 0 | } |
1314 | | |
1315 | | /* |
1316 | | * remove_rel_from_jointree |
1317 | | * Delete the RangeTblRef for the given relation from the query's |
1318 | | * jointree. |
1319 | | * |
1320 | | * This is used for self-join elimination, where the removed relation's |
1321 | | * qual conditions must all be preserved (they will be transposed onto the |
1322 | | * remaining relation afterwards). Hence, if dropping the RangeTblRef leaves |
1323 | | * a JoinExpr or FromExpr with nothing under it, we can't simply drop that |
1324 | | * node; we hand its quals back to the caller in *orphan_quals, to be merged |
1325 | | * into the nearest enclosing node that still has some content. That's a |
1326 | | * valid transformation only for inner joins, but a jointree node can't become |
1327 | | * empty at an outer join here: remove_self_joins_one_group() insists that the |
1328 | | * two relations be on the same side of every outer join, so the relation we |
1329 | | * are keeping would have to be in the emptied subtree too. |
1330 | | * |
1331 | | * *nremoved is incremented by the number of RangeTblRefs removed (there |
1332 | | * should be exactly one, but the caller checks that). |
1333 | | */ |
1334 | | static Node * |
1335 | | remove_rel_from_jointree(Node *jtnode, int relid, |
1336 | | Node **orphan_quals, int *nremoved) |
1337 | 0 | { |
1338 | 0 | if (jtnode == NULL) |
1339 | 0 | return NULL; |
1340 | 0 | if (IsA(jtnode, RangeTblRef)) |
1341 | 0 | { |
1342 | 0 | RangeTblRef *rtr = (RangeTblRef *) jtnode; |
1343 | |
|
1344 | 0 | if (rtr->rtindex == relid) |
1345 | 0 | { |
1346 | 0 | (*nremoved)++; |
1347 | 0 | return NULL; |
1348 | 0 | } |
1349 | 0 | } |
1350 | 0 | else if (IsA(jtnode, FromExpr)) |
1351 | 0 | { |
1352 | 0 | FromExpr *f = (FromExpr *) jtnode; |
1353 | 0 | List *newfromlist = NIL; |
1354 | 0 | Node *sub_orphans = NULL; |
1355 | 0 | ListCell *l; |
1356 | |
|
1357 | 0 | foreach(l, f->fromlist) |
1358 | 0 | { |
1359 | 0 | Node *newchild; |
1360 | |
|
1361 | 0 | newchild = remove_rel_from_jointree((Node *) lfirst(l), relid, |
1362 | 0 | &sub_orphans, nremoved); |
1363 | 0 | if (newchild != NULL) |
1364 | 0 | newfromlist = lappend(newfromlist, newchild); |
1365 | 0 | } |
1366 | 0 | f->fromlist = newfromlist; |
1367 | 0 | f->quals = merge_quals(sub_orphans, f->quals); |
1368 | 0 | if (newfromlist == NIL) |
1369 | 0 | { |
1370 | | /* Nothing left here, so pass our quals up to the parent */ |
1371 | 0 | *orphan_quals = merge_quals(f->quals, *orphan_quals); |
1372 | 0 | return NULL; |
1373 | 0 | } |
1374 | 0 | } |
1375 | 0 | else if (IsA(jtnode, JoinExpr)) |
1376 | 0 | { |
1377 | 0 | JoinExpr *j = (JoinExpr *) jtnode; |
1378 | 0 | Node *sub_orphans = NULL; |
1379 | |
|
1380 | 0 | j->larg = remove_rel_from_jointree(j->larg, relid, |
1381 | 0 | &sub_orphans, nremoved); |
1382 | 0 | j->rarg = remove_rel_from_jointree(j->rarg, relid, |
1383 | 0 | &sub_orphans, nremoved); |
1384 | 0 | if (j->larg == NULL || j->rarg == NULL) |
1385 | 0 | { |
1386 | 0 | Node *surviving = (j->larg != NULL) ? j->larg : j->rarg; |
1387 | 0 | Node *quals = merge_quals(sub_orphans, j->quals); |
1388 | | |
1389 | | /* As explained above, this can only happen for an inner join */ |
1390 | 0 | Assert(j->jointype == JOIN_INNER); |
1391 | | /* We can't have removed both children */ |
1392 | 0 | Assert(surviving != NULL); |
1393 | | |
1394 | | /* |
1395 | | * Replace the join by a FromExpr, so that the surviving side's |
1396 | | * rows are still filtered by the join's conditions. |
1397 | | */ |
1398 | 0 | return (Node *) makeFromExpr(list_make1(surviving), quals); |
1399 | 0 | } |
1400 | | /* A subtree that survives never hands any quals back to us */ |
1401 | 0 | Assert(sub_orphans == NULL); |
1402 | 0 | } |
1403 | 0 | else |
1404 | 0 | elog(ERROR, "unrecognized jointree node type: %d", |
1405 | 0 | (int) nodeTag(jtnode)); |
1406 | | |
1407 | 0 | return jtnode; |
1408 | 0 | } |
1409 | | |
1410 | | /* |
1411 | | * merge_quals |
1412 | | * Combine two jointree qual conditions. |
1413 | | * |
1414 | | * quals1 should be the quals from the lower of the two jointree levels, |
1415 | | * so that those quals get applied first. |
1416 | | * |
1417 | | * Jointree quals have been through preprocess_expression() by now, so each |
1418 | | * one is either NULL or an implicitly-ANDed List. |
1419 | | */ |
1420 | | static Node * |
1421 | | merge_quals(Node *quals1, Node *quals2) |
1422 | 0 | { |
1423 | 0 | if (quals1 == NULL) |
1424 | 0 | return quals2; |
1425 | 0 | if (quals2 == NULL) |
1426 | 0 | return quals1; |
1427 | 0 | return (Node *) list_concat(castNode(List, quals1), |
1428 | 0 | castNode(List, quals2)); |
1429 | 0 | } |
1430 | | |
1431 | | /* |
1432 | | * fixup_selfjoin_jointree |
1433 | | * Clean up the query's jointree quals after self-join elimination has |
1434 | | * merged one relation into another. (relid is the kept relation.) |
1435 | | * |
1436 | | * See fixup_selfjoin_quals() for what needs fixing locally to each qual list. |
1437 | | * In addition, we need to check quals to see if they refer to relid, and if |
1438 | | * so make sure they get hoisted to someplace syntactically above relid. |
1439 | | * Do that using a "hoist_quals" in/out parameter similar to "orphan_quals" |
1440 | | * in remove_rel_from_jointree. (We can't readily merge these concerns into |
1441 | | * a single pass, since remove_rel_from_jointree must run before we relabel |
1442 | | * the removed rel's Vars.) In addition, *found_relid is set true if |
1443 | | * the subtree rooted at jtnode is found to contain relid's RangeTblRef, |
1444 | | * so that we can tell when to stop hoisting quals. |
1445 | | * If a qual gets hoisted up, we apply fixup_selfjoin_quals() to it only |
1446 | | * after it reaches its final level. This rule improves the odds of |
1447 | | * detecting duplicate quals. |
1448 | | */ |
1449 | | static void |
1450 | | fixup_selfjoin_jointree(PlannerInfo *root, Node *jtnode, int relid, |
1451 | | Node **hoist_quals, bool *found_relid) |
1452 | 0 | { |
1453 | 0 | if (jtnode == NULL) |
1454 | 0 | return; |
1455 | 0 | if (IsA(jtnode, RangeTblRef)) |
1456 | 0 | { |
1457 | 0 | RangeTblRef *rtr = (RangeTblRef *) jtnode; |
1458 | |
|
1459 | 0 | if (rtr->rtindex == relid) |
1460 | 0 | { |
1461 | 0 | Assert(!*found_relid); |
1462 | 0 | *found_relid = true; |
1463 | 0 | } |
1464 | 0 | } |
1465 | 0 | else if (IsA(jtnode, FromExpr)) |
1466 | 0 | { |
1467 | 0 | FromExpr *f = (FromExpr *) jtnode; |
1468 | 0 | Node *sub_hoist_quals = NULL; |
1469 | 0 | bool sub_found_relid = false; |
1470 | 0 | ListCell *l; |
1471 | |
|
1472 | 0 | foreach(l, f->fromlist) |
1473 | 0 | fixup_selfjoin_jointree(root, (Node *) lfirst(l), relid, |
1474 | 0 | &sub_hoist_quals, &sub_found_relid); |
1475 | 0 | if (sub_found_relid) |
1476 | 0 | { |
1477 | | /* This FromExpr covers relid, so OK to stop hoisting quals here */ |
1478 | 0 | f->quals = merge_quals(sub_hoist_quals, f->quals); |
1479 | 0 | Assert(!*found_relid); |
1480 | 0 | *found_relid = true; |
1481 | 0 | } |
1482 | 0 | else |
1483 | 0 | { |
1484 | | /* We might need to hoist some of our own quals too */ |
1485 | 0 | List *hoistable = NIL; |
1486 | 0 | List *keepable = NIL; |
1487 | |
|
1488 | 0 | foreach_ptr(Node, qual, castNode(List, f->quals)) |
1489 | 0 | { |
1490 | 0 | if (bms_is_member(relid, pull_varnos(root, qual))) |
1491 | 0 | hoistable = lappend(hoistable, qual); |
1492 | 0 | else |
1493 | 0 | keepable = lappend(keepable, qual); |
1494 | 0 | } |
1495 | 0 | f->quals = (Node *) keepable; |
1496 | 0 | sub_hoist_quals = merge_quals(sub_hoist_quals, (Node *) hoistable); |
1497 | 0 | *hoist_quals = merge_quals(sub_hoist_quals, *hoist_quals); |
1498 | 0 | } |
1499 | 0 | f->quals = (Node *) fixup_selfjoin_quals(root, |
1500 | 0 | castNode(List, f->quals), |
1501 | 0 | relid); |
1502 | 0 | } |
1503 | 0 | else if (IsA(jtnode, JoinExpr)) |
1504 | 0 | { |
1505 | 0 | JoinExpr *j = (JoinExpr *) jtnode; |
1506 | 0 | Node *sub_hoist_quals = NULL; |
1507 | 0 | bool sub_found_relid = false; |
1508 | |
|
1509 | 0 | fixup_selfjoin_jointree(root, j->larg, relid, |
1510 | 0 | &sub_hoist_quals, &sub_found_relid); |
1511 | 0 | fixup_selfjoin_jointree(root, j->rarg, relid, |
1512 | 0 | &sub_hoist_quals, &sub_found_relid); |
1513 | 0 | if (sub_found_relid) |
1514 | 0 | { |
1515 | | /* This JoinExpr covers relid, so OK to stop hoisting quals here */ |
1516 | 0 | j->quals = merge_quals(sub_hoist_quals, j->quals); |
1517 | 0 | Assert(!*found_relid); |
1518 | 0 | *found_relid = true; |
1519 | 0 | } |
1520 | 0 | else |
1521 | 0 | { |
1522 | | /* We might need to hoist some of our own quals too */ |
1523 | 0 | List *hoistable = NIL; |
1524 | 0 | List *keepable = NIL; |
1525 | |
|
1526 | 0 | foreach_ptr(Node, qual, castNode(List, j->quals)) |
1527 | 0 | { |
1528 | 0 | if (bms_is_member(relid, pull_varnos(root, qual))) |
1529 | 0 | hoistable = lappend(hoistable, qual); |
1530 | 0 | else |
1531 | 0 | keepable = lappend(keepable, qual); |
1532 | 0 | } |
1533 | 0 | j->quals = (Node *) keepable; |
1534 | 0 | sub_hoist_quals = merge_quals(sub_hoist_quals, (Node *) hoistable); |
1535 | | /* We should never need to hoist quals above an outer join */ |
1536 | 0 | Assert(sub_hoist_quals == NULL || j->jointype == JOIN_INNER); |
1537 | 0 | *hoist_quals = merge_quals(sub_hoist_quals, *hoist_quals); |
1538 | 0 | } |
1539 | 0 | j->quals = (Node *) fixup_selfjoin_quals(root, |
1540 | 0 | castNode(List, j->quals), |
1541 | 0 | relid); |
1542 | 0 | } |
1543 | 0 | else |
1544 | 0 | elog(ERROR, "unrecognized jointree node type: %d", |
1545 | 0 | (int) nodeTag(jtnode)); |
1546 | 0 | } |
1547 | | |
1548 | | /* |
1549 | | * fixup_selfjoin_quals |
1550 | | * Clean up one qual list after self-join elimination. |
1551 | | * |
1552 | | * Two things need fixing here. First, a join clause such as "t1.a = t2.a" |
1553 | | * has turned into "t1.a = t1.a". For a strict mergejoinable operator that |
1554 | | * means "t1.a IS NOT NULL", and we should make the substitution, for two |
1555 | | * reasons: |
1556 | | * 1. It will typically result in better selectivity estimates. |
1557 | | * 2. EquivalenceClass processing is likely to make the substitution |
1558 | | * if we don't. While not directly harmful, we'd then fail to |
1559 | | * recognize it as a duplicate of a user-written "t1.a IS NOT NULL" |
1560 | | * clause, again leading to bad selectivity estimates. |
1561 | | * Second, conditions that were written against the two relations separately |
1562 | | * may now be identical, and we don't want to apply the same condition twice |
1563 | | * (much less double-count its selectivity). |
1564 | | * |
1565 | | * We only touch the top-level conjuncts of the list. There, turning a NULL |
1566 | | * result into FALSE makes no difference, whereas below a NOT it would, |
1567 | | * invalidating the IS NOT NULL substitution. EquivalenceClass processing |
1568 | | * will not be applied to sub-clauses, and cleaning up duplicates in them |
1569 | | * seems like more trouble than it's worth. Also, we only consider clauses |
1570 | | * that mention the relation we merged into, so that we don't change the |
1571 | | * treatment of anything we didn't touch. |
1572 | | * |
1573 | | * Since this is not a correctness issue but just an optimization opportunity, |
1574 | | * we likewise don't worry about recognizing duplicates that appear in |
1575 | | * different qual lists. |
1576 | | */ |
1577 | | static List * |
1578 | | fixup_selfjoin_quals(PlannerInfo *root, List *quals, int relid) |
1579 | 0 | { |
1580 | 0 | List *result = NIL; |
1581 | 0 | ListCell *l; |
1582 | |
|
1583 | 0 | foreach(l, quals) |
1584 | 0 | { |
1585 | 0 | Node *qual = (Node *) lfirst(l); |
1586 | |
|
1587 | 0 | if (bms_is_member(relid, pull_varnos(root, qual))) |
1588 | 0 | { |
1589 | 0 | qual = replace_selfjoin_qual(qual); |
1590 | | /* Drop it if the substitution has made it a duplicate */ |
1591 | 0 | if (list_member(result, qual)) |
1592 | 0 | continue; |
1593 | 0 | } |
1594 | 0 | result = lappend(result, qual); |
1595 | 0 | } |
1596 | |
|
1597 | 0 | return result; |
1598 | 0 | } |
1599 | | |
1600 | | /* |
1601 | | * replace_selfjoin_qual |
1602 | | * Replace one "X = X" qual by "X IS NOT NULL", if it is one. |
1603 | | */ |
1604 | | static Node * |
1605 | | replace_selfjoin_qual(Node *qual) |
1606 | 0 | { |
1607 | 0 | OpExpr *opexpr; |
1608 | 0 | Node *leftop; |
1609 | 0 | Node *rightop; |
1610 | 0 | NullTest *ntest; |
1611 | | |
1612 | | /* See if it looks like "X op X" */ |
1613 | 0 | if (!is_opclause(qual)) |
1614 | 0 | return qual; |
1615 | 0 | opexpr = (OpExpr *) qual; |
1616 | 0 | if (list_length(opexpr->args) != 2) |
1617 | 0 | return qual; |
1618 | 0 | leftop = get_leftop((Expr *) opexpr); |
1619 | 0 | rightop = get_rightop((Expr *) opexpr); |
1620 | 0 | if (!equal(leftop, rightop)) |
1621 | 0 | return qual; |
1622 | | |
1623 | | /* |
1624 | | * The operator must be strict and behave like btree equality, else we |
1625 | | * can't conclude that it yields true for any non-null input. And the |
1626 | | * input had better not be volatile, else the two evaluations might not |
1627 | | * agree. If either condition doesn't hold, the clause is not a candidate |
1628 | | * to be an equivalence, so we needn't worry about it getting replaced by |
1629 | | * equivclass.c. |
1630 | | */ |
1631 | 0 | set_opfuncid(opexpr); |
1632 | 0 | if (!func_strict(opexpr->opfuncid)) |
1633 | 0 | return qual; |
1634 | 0 | if (!op_mergejoinable(opexpr->opno, exprType(leftop))) |
1635 | 0 | return qual; |
1636 | 0 | if (contain_volatile_functions(leftop)) |
1637 | 0 | return qual; |
1638 | | |
1639 | | /* OK, replace it */ |
1640 | 0 | ntest = makeNode(NullTest); |
1641 | 0 | ntest->arg = (Expr *) leftop; |
1642 | 0 | ntest->nulltesttype = IS_NOT_NULL; |
1643 | 0 | ntest->argisrow = false; /* correct even if composite arg */ |
1644 | 0 | ntest->location = -1; |
1645 | 0 | return (Node *) ntest; |
1646 | 0 | } |
1647 | | |
1648 | | /* |
1649 | | * split_selfjoin_quals |
1650 | | * Processes 'joinquals' by building two lists: one containing the quals |
1651 | | * where the columns/exprs are on either side of the join match and |
1652 | | * another one containing the remaining quals. |
1653 | | * |
1654 | | * 'joinquals' must only contain quals for a RTE_RELATION being joined to |
1655 | | * itself. |
1656 | | */ |
1657 | | static void |
1658 | | split_selfjoin_quals(PlannerInfo *root, List *joinquals, List **selfjoinquals, |
1659 | | List **otherjoinquals, int from, int to) |
1660 | 0 | { |
1661 | 0 | List *sjoinquals = NIL; |
1662 | 0 | List *ojoinquals = NIL; |
1663 | |
|
1664 | 0 | foreach_node(RestrictInfo, rinfo, joinquals) |
1665 | 0 | { |
1666 | 0 | OpExpr *expr; |
1667 | 0 | Node *leftexpr; |
1668 | 0 | Node *rightexpr; |
1669 | | |
1670 | | /* |
1671 | | * Since the given joinquals all came from |
1672 | | * generate_join_implied_equalities, they ought to look like equality |
1673 | | * operators on single-relation expressions. But let's check that. |
1674 | | * Anything that doesn't look like that can be dumped into ojoinquals. |
1675 | | */ |
1676 | 0 | if (!rinfo->mergeopfamilies || |
1677 | 0 | bms_num_members(rinfo->clause_relids) != 2 || |
1678 | 0 | bms_membership(rinfo->left_relids) != BMS_SINGLETON || |
1679 | 0 | bms_membership(rinfo->right_relids) != BMS_SINGLETON) |
1680 | 0 | { |
1681 | 0 | ojoinquals = lappend(ojoinquals, rinfo); |
1682 | 0 | continue; |
1683 | 0 | } |
1684 | | |
1685 | 0 | expr = (OpExpr *) rinfo->clause; |
1686 | |
|
1687 | 0 | if (!IsA(expr, OpExpr) || list_length(expr->args) != 2) |
1688 | 0 | { |
1689 | 0 | ojoinquals = lappend(ojoinquals, rinfo); |
1690 | 0 | continue; |
1691 | 0 | } |
1692 | | |
1693 | 0 | leftexpr = get_leftop(rinfo->clause); |
1694 | 0 | rightexpr = copyObject(get_rightop(rinfo->clause)); |
1695 | |
|
1696 | 0 | if (leftexpr && IsA(leftexpr, RelabelType)) |
1697 | 0 | leftexpr = (Node *) ((RelabelType *) leftexpr)->arg; |
1698 | 0 | if (rightexpr && IsA(rightexpr, RelabelType)) |
1699 | 0 | rightexpr = (Node *) ((RelabelType *) rightexpr)->arg; |
1700 | | |
1701 | | /* |
1702 | | * Quite an expensive operation, narrowing the use case. For example, |
1703 | | * when we have cast of the same var to different (but compatible) |
1704 | | * types. |
1705 | | */ |
1706 | 0 | ChangeVarNodes(rightexpr, |
1707 | 0 | bms_singleton_member(rinfo->right_relids), |
1708 | 0 | bms_singleton_member(rinfo->left_relids), 0); |
1709 | |
|
1710 | 0 | if (equal(leftexpr, rightexpr)) |
1711 | 0 | sjoinquals = lappend(sjoinquals, rinfo); |
1712 | 0 | else |
1713 | 0 | ojoinquals = lappend(ojoinquals, rinfo); |
1714 | 0 | } |
1715 | |
|
1716 | 0 | *selfjoinquals = sjoinquals; |
1717 | 0 | *otherjoinquals = ojoinquals; |
1718 | 0 | } |
1719 | | |
1720 | | /* |
1721 | | * Check that each base restriction used to prove uniqueness of relid has |
1722 | | * a matching restriction in outer->baserestrictinfo, after replacing |
1723 | | * relid with outer->relid. |
1724 | | * |
1725 | | * Require equal() clauses, including the operator and input collation. |
1726 | | * Formerly this tried to match commuted forms of clauses, but that added |
1727 | | * a great deal of extra complication without much extra value. |
1728 | | */ |
1729 | | static bool |
1730 | | match_unique_clauses(PlannerInfo *root, RelOptInfo *outer, List *uclauses, |
1731 | | Index relid) |
1732 | 0 | { |
1733 | 0 | Assert(outer->relid > 0 && relid > 0); |
1734 | |
|
1735 | 0 | foreach_node(RestrictInfo, rinfo, uclauses) |
1736 | 0 | { |
1737 | 0 | Expr *clause; |
1738 | 0 | bool matched = false; |
1739 | | |
1740 | | /* Convert the clause from uclauses to use outer's Vars */ |
1741 | 0 | clause = (Expr *) copyObject(rinfo->clause); |
1742 | 0 | ChangeVarNodes((Node *) clause, relid, outer->relid, 0); |
1743 | | |
1744 | | /* Look for a matching restriction on the outer relation */ |
1745 | 0 | foreach_node(RestrictInfo, orinfo, outer->baserestrictinfo) |
1746 | 0 | { |
1747 | 0 | if (equal(clause, orinfo->clause)) |
1748 | 0 | { |
1749 | 0 | matched = true; |
1750 | 0 | break; |
1751 | 0 | } |
1752 | 0 | } |
1753 | |
|
1754 | 0 | if (!matched) |
1755 | 0 | return false; |
1756 | 0 | } |
1757 | | |
1758 | 0 | return true; |
1759 | 0 | } |
1760 | | |
1761 | | /* |
1762 | | * Find and remove unique self-joins in a group of base relations that have |
1763 | | * the same Oid. |
1764 | | * |
1765 | | * Return true if we removed any joins. |
1766 | | * |
1767 | | * After a removal, we continue searching for more removals, even though the |
1768 | | * tests will be using derived data that is now partially stale. That is safe |
1769 | | * because we are trying to prove that a candidate pair of relations must |
1770 | | * match the same row, and the stale data can only omit quals, never invent |
1771 | | * them. The removed relation's quals are moved onto the kept relation in |
1772 | | * the jointree but not into its baserestrictinfo, and no other derived data |
1773 | | * changes. A proof made from a subset of the applicable quals remains valid |
1774 | | * when the rest are added, since extra quals can only remove rows from the |
1775 | | * join. So a pass may miss a removal that a later pass will find, but it |
1776 | | * cannot make one that isn't justified. |
1777 | | */ |
1778 | | static bool |
1779 | | remove_self_joins_one_group(PlannerInfo *root, Relids relids) |
1780 | 0 | { |
1781 | 0 | bool removed = false; |
1782 | 0 | int k; /* Index of kept relation */ |
1783 | 0 | int r = -1; /* Index of removed relation */ |
1784 | |
|
1785 | 0 | while ((r = bms_next_member(relids, r)) > 0) |
1786 | 0 | { |
1787 | 0 | RelOptInfo *rrel = root->simple_rel_array[r]; |
1788 | | |
1789 | | /* k iterates over the relids after r */ |
1790 | 0 | k = r; |
1791 | 0 | while ((k = bms_next_member(relids, k)) > 0) |
1792 | 0 | { |
1793 | 0 | Relids joinrelids = NULL; |
1794 | 0 | RelOptInfo *krel = root->simple_rel_array[k]; |
1795 | 0 | List *restrictlist; |
1796 | 0 | List *selfjoinquals; |
1797 | 0 | List *otherjoinquals; |
1798 | 0 | ListCell *lc; |
1799 | 0 | bool jinfo_check = true; |
1800 | 0 | PlanRowMark *kmark = NULL; |
1801 | 0 | PlanRowMark *rmark = NULL; |
1802 | 0 | List *uclauses = NIL; |
1803 | | |
1804 | | /* A sanity check: the relations have the same Oid. */ |
1805 | 0 | Assert(root->simple_rte_array[k]->relid == |
1806 | 0 | root->simple_rte_array[r]->relid); |
1807 | | |
1808 | | /* |
1809 | | * It is impossible to eliminate the join of two relations if they |
1810 | | * are not on the same side of every outer join. Otherwise, the |
1811 | | * planner can't find any variants of the correct query plan. |
1812 | | */ |
1813 | 0 | foreach(lc, root->join_info_list) |
1814 | 0 | { |
1815 | 0 | SpecialJoinInfo *info = (SpecialJoinInfo *) lfirst(lc); |
1816 | |
|
1817 | 0 | if ((bms_is_member(k, info->syn_lefthand) ^ |
1818 | 0 | bms_is_member(r, info->syn_lefthand)) || |
1819 | 0 | (bms_is_member(k, info->syn_righthand) ^ |
1820 | 0 | bms_is_member(r, info->syn_righthand))) |
1821 | 0 | { |
1822 | 0 | jinfo_check = false; |
1823 | 0 | break; |
1824 | 0 | } |
1825 | 0 | } |
1826 | 0 | if (!jinfo_check) |
1827 | 0 | continue; |
1828 | | |
1829 | | /* |
1830 | | * Check Row Marks equivalence. We can't remove the join if the |
1831 | | * relations have row marks of different strength (e.g., one is |
1832 | | * locked FOR UPDATE, and another just has ROW_MARK_REFERENCE for |
1833 | | * EvalPlanQual rechecking). |
1834 | | */ |
1835 | 0 | foreach(lc, root->rowMarks) |
1836 | 0 | { |
1837 | 0 | PlanRowMark *rowMark = (PlanRowMark *) lfirst(lc); |
1838 | |
|
1839 | 0 | if (rowMark->rti == r) |
1840 | 0 | { |
1841 | 0 | Assert(rmark == NULL); |
1842 | 0 | rmark = rowMark; |
1843 | 0 | } |
1844 | 0 | else if (rowMark->rti == k) |
1845 | 0 | { |
1846 | 0 | Assert(kmark == NULL); |
1847 | 0 | kmark = rowMark; |
1848 | 0 | } |
1849 | |
|
1850 | 0 | if (kmark && rmark) |
1851 | 0 | break; |
1852 | 0 | } |
1853 | 0 | if (kmark && rmark && kmark->markType != rmark->markType) |
1854 | 0 | continue; |
1855 | | |
1856 | | /* |
1857 | | * We only deal with base rels here, so their relids bitset |
1858 | | * contains only one member -- their relid. |
1859 | | */ |
1860 | 0 | joinrelids = bms_add_member(joinrelids, r); |
1861 | 0 | joinrelids = bms_add_member(joinrelids, k); |
1862 | | |
1863 | | /* |
1864 | | * PHVs should not impose any constraints on removing self-joins. |
1865 | | */ |
1866 | | |
1867 | | /* |
1868 | | * At this stage, joininfo lists of inner and outer can contain |
1869 | | * only clauses required for a superior outer join that can't |
1870 | | * influence this optimization. So, we can avoid to call the |
1871 | | * build_joinrel_restrictlist() routine. |
1872 | | */ |
1873 | 0 | restrictlist = generate_join_implied_equalities(root, joinrelids, |
1874 | 0 | rrel->relids, |
1875 | 0 | krel, NULL); |
1876 | 0 | if (restrictlist == NIL) |
1877 | 0 | continue; |
1878 | | |
1879 | | /* |
1880 | | * Process restrictlist to separate the self-join quals from the |
1881 | | * other quals. e.g., "x = x" goes to selfjoinquals and "a = b" to |
1882 | | * otherjoinquals. |
1883 | | */ |
1884 | 0 | split_selfjoin_quals(root, restrictlist, &selfjoinquals, |
1885 | 0 | &otherjoinquals, rrel->relid, krel->relid); |
1886 | |
|
1887 | 0 | Assert(list_length(restrictlist) == |
1888 | 0 | (list_length(selfjoinquals) + list_length(otherjoinquals))); |
1889 | | |
1890 | | /* |
1891 | | * To enable SJE for the only degenerate case without any self |
1892 | | * join clauses at all, add baserestrictinfo to this list. The |
1893 | | * degenerate case works only if both sides have the same clause. |
1894 | | * So doesn't matter which side to add. |
1895 | | */ |
1896 | 0 | selfjoinquals = list_concat(selfjoinquals, krel->baserestrictinfo); |
1897 | | |
1898 | | /* |
1899 | | * Determine if the rrel can duplicate outer rows. We must bypass |
1900 | | * the unique rel cache here since we're possibly using a subset |
1901 | | * of join quals. We can use 'force_cache' == true when all join |
1902 | | * quals are self-join quals. Otherwise, we could end up putting |
1903 | | * false negatives in the cache. |
1904 | | */ |
1905 | 0 | if (!innerrel_is_unique_ext(root, joinrelids, rrel->relids, |
1906 | 0 | krel, JOIN_INNER, selfjoinquals, |
1907 | 0 | list_length(otherjoinquals) == 0, |
1908 | 0 | &uclauses)) |
1909 | 0 | continue; |
1910 | | |
1911 | | /* |
1912 | | * 'uclauses' is the copy of outer->baserestrictinfo that are |
1913 | | * associated with an index. We proved by matching selfjoinquals |
1914 | | * to a unique index that the outer relation has at most one |
1915 | | * matching row for each inner row. Sometimes that is not enough. |
1916 | | * e.g. "WHERE s1.b = s2.b AND s1.a = 1 AND s2.a = 2" when the |
1917 | | * unique index is (a,b). Having non-empty uclauses, we must |
1918 | | * validate that the inner baserestrictinfo contains the same |
1919 | | * expressions, or we won't match the same row on each side of the |
1920 | | * join. |
1921 | | */ |
1922 | 0 | if (!match_unique_clauses(root, rrel, uclauses, krel->relid)) |
1923 | 0 | continue; |
1924 | | |
1925 | | /* OK, remove rrel from the query */ |
1926 | 0 | remove_self_join_rel(root, krel, rrel, kmark, rmark); |
1927 | 0 | removed = true; |
1928 | | |
1929 | | /* |
1930 | | * Since relation r is now gone, we mustn't keep looking for |
1931 | | * matches to it. But we can keep scanning later relids members |
1932 | | * for additional join pairs. |
1933 | | */ |
1934 | 0 | break; |
1935 | 0 | } |
1936 | 0 | } |
1937 | |
|
1938 | 0 | return removed; |
1939 | 0 | } |
1940 | | |
1941 | | /* |
1942 | | * Gather indexes of base relations from the joinlist and try to eliminate |
1943 | | * self-joins. |
1944 | | * |
1945 | | * Return true if we removed any joins. |
1946 | | */ |
1947 | | static bool |
1948 | | remove_self_joins_recurse(PlannerInfo *root, List *joinlist) |
1949 | 0 | { |
1950 | 0 | bool removed = false; |
1951 | 0 | ListCell *jl; |
1952 | 0 | Relids relids = NULL; |
1953 | 0 | SelfJoinCandidate *candidates; |
1954 | 0 | int i; |
1955 | 0 | int j; |
1956 | 0 | int numRels; |
1957 | | |
1958 | | /* Collect indexes of possibly-mergeable relations from the joinlist */ |
1959 | 0 | foreach(jl, joinlist) |
1960 | 0 | { |
1961 | 0 | Node *jlnode = (Node *) lfirst(jl); |
1962 | |
|
1963 | 0 | if (IsA(jlnode, RangeTblRef)) |
1964 | 0 | { |
1965 | 0 | int varno = ((RangeTblRef *) jlnode)->rtindex; |
1966 | 0 | RangeTblEntry *rte = root->simple_rte_array[varno]; |
1967 | | |
1968 | | /* |
1969 | | * To be considered for self-join removal, the RTE must: |
1970 | | * |
1971 | | * 1. Be an ordinary relation. (Someday we might support SJE on |
1972 | | * partitioned tables, but not yet.) |
1973 | | * |
1974 | | * 2. Not have inh set, ie it has no inheritance children (or the |
1975 | | * user wrote ONLY to ignore them). Under traditional inheritance |
1976 | | * a unique index on a parent table does not establish uniqueness |
1977 | | * across its children. This rule also keeps us from trying to |
1978 | | * merge an inheritance scan with an ONLY scan, which would be |
1979 | | * wrong. (preprocess_relation_rtes already cleared the inh flag |
1980 | | * for tables known not to have inheritance children.) |
1981 | | * |
1982 | | * 3. Not have a TABLESAMPLE clause. Removing a relation with a |
1983 | | * TABLESAMPLE clause would change the semantics of the query, |
1984 | | * even if we merged it with another RTE with an identical |
1985 | | * TABLESAMPLE clause. (Two such RTEs should represent |
1986 | | * independent samplings of the base table.) |
1987 | | * |
1988 | | * 4. Not be the query's result relation or MERGE target. Merging |
1989 | | * would cause misbehavior during EPQ. |
1990 | | */ |
1991 | 0 | if (rte->rtekind == RTE_RELATION && |
1992 | 0 | rte->relkind == RELKIND_RELATION && |
1993 | 0 | !rte->inh && |
1994 | 0 | rte->tablesample == NULL && |
1995 | 0 | varno != root->parse->resultRelation && |
1996 | 0 | varno != root->parse->mergeTargetRelation) |
1997 | 0 | { |
1998 | 0 | Assert(!bms_is_member(varno, relids)); |
1999 | 0 | relids = bms_add_member(relids, varno); |
2000 | 0 | } |
2001 | 0 | } |
2002 | 0 | else if (IsA(jlnode, List)) |
2003 | 0 | { |
2004 | | /* Recursively perform SJE within the sub-joinlist */ |
2005 | 0 | removed |= remove_self_joins_recurse(root, (List *) jlnode); |
2006 | 0 | } |
2007 | 0 | else |
2008 | 0 | elog(ERROR, "unrecognized joinlist node type: %d", |
2009 | 0 | (int) nodeTag(jlnode)); |
2010 | 0 | } |
2011 | | |
2012 | 0 | numRels = bms_num_members(relids); |
2013 | | |
2014 | | /* No work if not at least two relations at this level */ |
2015 | 0 | if (numRels < 2) |
2016 | 0 | return removed; /* ... but don't fail to report sub-removals */ |
2017 | | |
2018 | | /* |
2019 | | * In order to find relations with the same reloid/useroid we first build |
2020 | | * an array of candidates and then sort it by those oids. |
2021 | | */ |
2022 | 0 | candidates = palloc_array(SelfJoinCandidate, numRels); |
2023 | 0 | i = -1; |
2024 | 0 | j = 0; |
2025 | 0 | while ((i = bms_next_member(relids, i)) >= 0) |
2026 | 0 | { |
2027 | 0 | RangeTblEntry *rte = root->simple_rte_array[i]; |
2028 | |
|
2029 | 0 | candidates[j].relid = i; |
2030 | 0 | candidates[j].reloid = rte->relid; |
2031 | 0 | if (rte->perminfoindex != 0) |
2032 | 0 | { |
2033 | 0 | RTEPermissionInfo *perminfo; |
2034 | |
|
2035 | 0 | perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte); |
2036 | 0 | candidates[j].useroid = perminfo->checkAsUser; |
2037 | 0 | } |
2038 | 0 | else |
2039 | 0 | candidates[j].useroid = InvalidOid; |
2040 | 0 | j++; |
2041 | 0 | } |
2042 | |
|
2043 | 0 | qsort(candidates, numRels, sizeof(SelfJoinCandidate), |
2044 | 0 | self_join_candidates_cmp); |
2045 | | |
2046 | | /* |
2047 | | * Iteratively form a group of relation indexes with the same oids and |
2048 | | * launch the routine that detects self-joins in this group. |
2049 | | * |
2050 | | * We remove considered relations from relids as we scan, so that that set |
2051 | | * should be empty at the end. |
2052 | | */ |
2053 | 0 | i = 0; |
2054 | 0 | for (j = 1; j <= numRels; j++) |
2055 | 0 | { |
2056 | 0 | if (j == numRels || |
2057 | 0 | candidates[j].reloid != candidates[i].reloid || |
2058 | 0 | candidates[j].useroid != candidates[i].useroid) |
2059 | 0 | { |
2060 | 0 | if (j - i >= 2) |
2061 | 0 | { |
2062 | | /* Create a group of relation indexes with the same oids */ |
2063 | 0 | Relids group = NULL; |
2064 | |
|
2065 | 0 | while (i < j) |
2066 | 0 | { |
2067 | 0 | group = bms_add_member(group, candidates[i].relid); |
2068 | 0 | i++; |
2069 | 0 | } |
2070 | 0 | relids = bms_del_members(relids, group); |
2071 | | |
2072 | | /* Try to remove self-joins from the group */ |
2073 | 0 | removed |= remove_self_joins_one_group(root, group); |
2074 | 0 | bms_free(group); |
2075 | 0 | } |
2076 | 0 | else |
2077 | 0 | { |
2078 | | /* Nothing to do with this group, just drop it from the set */ |
2079 | 0 | while (i < j) |
2080 | 0 | { |
2081 | 0 | relids = bms_del_member(relids, candidates[i].relid); |
2082 | 0 | i++; |
2083 | 0 | } |
2084 | 0 | } |
2085 | 0 | } |
2086 | 0 | } |
2087 | |
|
2088 | 0 | Assert(bms_is_empty(relids)); |
2089 | |
|
2090 | 0 | return removed; |
2091 | 0 | } |
2092 | | |
2093 | | /* |
2094 | | * Compare self-join candidates by their reloid and then useroid. |
2095 | | */ |
2096 | | static int |
2097 | | self_join_candidates_cmp(const void *a, const void *b) |
2098 | 0 | { |
2099 | 0 | const SelfJoinCandidate *ca = (const SelfJoinCandidate *) a; |
2100 | 0 | const SelfJoinCandidate *cb = (const SelfJoinCandidate *) b; |
2101 | |
|
2102 | 0 | if (ca->reloid != cb->reloid) |
2103 | 0 | return (ca->reloid < cb->reloid ? -1 : 1); |
2104 | 0 | else if (ca->useroid != cb->useroid) |
2105 | 0 | return (ca->useroid < cb->useroid ? -1 : 1); |
2106 | 0 | else |
2107 | 0 | return 0; |
2108 | 0 | } |
2109 | | |
2110 | | /* |
2111 | | * Find and remove useless self joins. |
2112 | | * |
2113 | | * Search for joins where a relation is joined to itself. If the join clause |
2114 | | * for each tuple from one side of the join is proven to match the same |
2115 | | * physical row (or nothing) on the other side, that self-join can be |
2116 | | * eliminated from the query. Suitable join clauses are assumed to be in the |
2117 | | * form of X = X, and can be replaced with NOT NULL clauses. |
2118 | | * |
2119 | | * For the sake of simplicity, we don't apply this optimization to special |
2120 | | * joins. Here is a list of what we could do in some particular cases: |
2121 | | * 'a a1 semi join a a2': is reduced to inner by reduce_unique_semijoins, |
2122 | | * and then removed normally. |
2123 | | * 'a a1 anti join a a2': could simplify to a scan with 'outer quals AND |
2124 | | * (IS NULL on join columns OR NOT inner quals)'. |
2125 | | * 'a a1 left join a a2': could simplify to a scan like inner but without |
2126 | | * NOT NULL conditions on join columns. |
2127 | | * 'a a1 left join (a a2 join b)': can't simplify this, because join to b |
2128 | | * can both remove rows and introduce duplicates. |
2129 | | * |
2130 | | * To search for removable joins, we order all the relations on their Oid, |
2131 | | * go over each set with the same Oid, and consider each pair of relations |
2132 | | * in this set. |
2133 | | * |
2134 | | * To remove the join, we delete one of the participating relations from the |
2135 | | * query's jointree and rewrite all references to it to point to the remaining |
2136 | | * relation. We also have to modify their row marks. |
2137 | | * |
2138 | | * 'joinlist' is the top-level joinlist of the query; we use it to identify |
2139 | | * groups of relations that could be joined to each other. |
2140 | | * |
2141 | | * We return true if we removed any self-joins. If so, the caller must |
2142 | | * recompute everything that was derived from the jointree, and should then |
2143 | | * try join simplifications again since we might have exposed opportunities |
2144 | | * for additional simplifications. |
2145 | | */ |
2146 | | bool |
2147 | | remove_useless_self_joins(PlannerInfo *root, List *joinlist) |
2148 | 0 | { |
2149 | | /* Skip if SJE is disabled, or if the joinlist has less than 2 members. */ |
2150 | 0 | if (!enable_self_join_elimination || joinlist == NIL || |
2151 | 0 | (list_length(joinlist) == 1 && !IsA(linitial(joinlist), List))) |
2152 | 0 | return false; |
2153 | | |
2154 | | /* Try to merge pairs of self-joined relations. */ |
2155 | 0 | return remove_self_joins_recurse(root, joinlist); |
2156 | 0 | } |