Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * restrictinfo.c
4 : * RestrictInfo node manipulation routines.
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/optimizer/util/restrictinfo.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "nodes/makefuncs.h"
18 : #include "nodes/nodeFuncs.h"
19 : #include "optimizer/clauses.h"
20 : #include "optimizer/optimizer.h"
21 : #include "optimizer/restrictinfo.h"
22 :
23 :
24 : static RestrictInfo *make_restrictinfo_internal(PlannerInfo *root,
25 : Expr *clause,
26 : Expr *orclause,
27 : bool is_pushed_down,
28 : bool pseudoconstant,
29 : Index security_level,
30 : Relids required_relids,
31 : Relids outer_relids);
32 : static Expr *make_sub_restrictinfos(PlannerInfo *root,
33 : Expr *clause,
34 : bool is_pushed_down,
35 : bool pseudoconstant,
36 : Index security_level,
37 : Relids required_relids,
38 : Relids outer_relids);
39 :
40 :
41 : /*
42 : * make_restrictinfo
43 : *
44 : * Build a RestrictInfo node containing the given subexpression.
45 : *
46 : * The is_pushed_down and pseudoconstant flags for the
47 : * RestrictInfo must be supplied by the caller, as well as the correct values
48 : * for security_level and outer_relids.
49 : * required_relids can be NULL, in which case it defaults to the actual clause
50 : * contents (i.e., clause_relids).
51 : *
52 : * Note that there aren't options to set the has_clone and is_clone flags:
53 : * we always initialize those to false. There's just one place that wants
54 : * something different, so making all callers pass them seems inconvenient.
55 : *
56 : * We initialize fields that depend only on the given subexpression, leaving
57 : * others that depend on context (or may never be needed at all) to be filled
58 : * later.
59 : */
60 : RestrictInfo *
808 tgl 61 CBC 250946 : make_restrictinfo(PlannerInfo *root,
62 : Expr *clause,
63 : bool is_pushed_down,
64 : bool pseudoconstant,
65 : Index security_level,
66 : Relids required_relids,
67 : Relids outer_relids)
68 : {
69 : /*
70 : * If it's an OR clause, build a modified copy with RestrictInfos inserted
6385 bruce 71 ECB : * above each subclause of the top-level AND/OR structure.
7034 tgl 72 : */
1531 tgl 73 GIC 250946 : if (is_orclause(clause))
808 74 3475 : return (RestrictInfo *) make_sub_restrictinfos(root,
75 : clause,
76 : is_pushed_down,
77 : pseudoconstant,
78 : security_level,
79 : required_relids,
80 : outer_relids);
7034 tgl 81 ECB :
82 : /* Shouldn't be an AND clause, else AND/OR flattening messed up */
1531 tgl 83 GIC 247471 : Assert(!is_andclause(clause));
84 :
808 85 247471 : return make_restrictinfo_internal(root,
86 : clause,
87 : NULL,
88 : is_pushed_down,
89 : pseudoconstant,
90 : security_level,
91 : required_relids,
92 : outer_relids);
93 : }
94 :
7034 tgl 95 ECB : /*
96 : * make_restrictinfo_internal
97 : *
98 : * Common code for the main entry points and the recursive cases.
99 : */
100 : static RestrictInfo *
808 tgl 101 GIC 260725 : make_restrictinfo_internal(PlannerInfo *root,
102 : Expr *clause,
103 : Expr *orclause,
6126 tgl 104 ECB : bool is_pushed_down,
105 : bool pseudoconstant,
2272 106 : Index security_level,
5106 107 : Relids required_relids,
108 : Relids outer_relids)
7035 109 : {
7035 tgl 110 CBC 260725 : RestrictInfo *restrictinfo = makeNode(RestrictInfo);
111 : Relids baserels;
7035 tgl 112 ECB :
7035 tgl 113 CBC 260725 : restrictinfo->clause = clause;
7034 114 260725 : restrictinfo->orclause = orclause;
7034 tgl 115 GIC 260725 : restrictinfo->is_pushed_down = is_pushed_down;
6126 116 260725 : restrictinfo->pseudoconstant = pseudoconstant;
69 tgl 117 GNC 260725 : restrictinfo->has_clone = false; /* may get set by caller */
118 260725 : restrictinfo->is_clone = false; /* may get set by caller */
2118 tgl 119 GIC 260725 : restrictinfo->can_join = false; /* may get set below */
2272 120 260725 : restrictinfo->security_level = security_level;
4007 121 260725 : restrictinfo->outer_relids = outer_relids;
7035 tgl 122 ECB :
123 : /*
2272 124 : * If it's potentially delayable by lower-level security quals, figure out
125 : * whether it's leakproof. We can skip testing this for level-zero quals,
126 : * since they would never get delayed on security grounds anyway.
127 : */
2272 tgl 128 GIC 260725 : if (security_level > 0)
129 2026 : restrictinfo->leakproof = !contain_leaked_vars((Node *) clause);
130 : else
2118 tgl 131 CBC 258699 : restrictinfo->leakproof = false; /* really, "don't know" */
132 :
133 : /*
134 : * Mark volatility as unknown. The contain_volatile_functions function
135 : * will determine if there are any volatile functions when called for the
136 : * first time with this RestrictInfo.
741 drowley 137 ECB : */
741 drowley 138 GIC 260725 : restrictinfo->has_volatile = VOLATILITY_UNKNOWN;
741 drowley 139 ECB :
7035 tgl 140 : /*
141 : * If it's a binary opclause, set up left/right relids info. In any case
6385 bruce 142 : * set up the total clause relids info.
7035 tgl 143 : */
6888 neilc 144 GIC 260725 : if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
145 : {
808 tgl 146 216494 : restrictinfo->left_relids = pull_varnos(root, get_leftop(clause));
147 216494 : restrictinfo->right_relids = pull_varnos(root, get_rightop(clause));
148 :
7035 149 432988 : restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,
6385 bruce 150 216494 : restrictinfo->right_relids);
7035 tgl 151 ECB :
152 : /*
153 : * Does it look like a normal join clause, i.e., a binary operator
6385 bruce 154 : * relating expressions that come from distinct relations? If so we
155 : * might be able to use it in a join algorithm. Note that this is a
156 : * purely syntactic test that is made regardless of context.
157 : */
7035 tgl 158 CBC 216494 : if (!bms_is_empty(restrictinfo->left_relids) &&
7035 tgl 159 GIC 212677 : !bms_is_empty(restrictinfo->right_relids) &&
160 75853 : !bms_overlap(restrictinfo->left_relids,
161 75853 : restrictinfo->right_relids))
162 : {
7034 163 75064 : restrictinfo->can_join = true;
6126 tgl 164 ECB : /* pseudoconstant should certainly not be true */
6126 tgl 165 CBC 75064 : Assert(!restrictinfo->pseudoconstant);
166 : }
7035 tgl 167 ECB : }
168 : else
169 : {
170 : /* Not a binary opclause, so mark left/right relid sets as empty */
7035 tgl 171 CBC 44231 : restrictinfo->left_relids = NULL;
172 44231 : restrictinfo->right_relids = NULL;
173 : /* and get the total relid set the hard way */
808 174 44231 : restrictinfo->clause_relids = pull_varnos(root, (Node *) clause);
175 : }
176 :
177 : /* required_relids defaults to clause_relids */
6513 tgl 178 GIC 260725 : if (required_relids != NULL)
179 234403 : restrictinfo->required_relids = required_relids;
180 : else
181 26322 : restrictinfo->required_relids = restrictinfo->clause_relids;
182 :
183 : /*
184 : * Count the number of base rels appearing in clause_relids. To do this,
185 : * we just delete rels mentioned in root->outer_join_rels and count the
186 : * survivors. Because we are called during deconstruct_jointree which is
187 : * the same tree walk that populates outer_join_rels, this is a little bit
188 : * unsafe-looking; but it should be fine because the recursion in
189 : * deconstruct_jointree should already have visited any outer join that
190 : * could be mentioned in this clause.
191 : */
69 tgl 192 GNC 260725 : baserels = bms_difference(restrictinfo->clause_relids,
193 260725 : root->outer_join_rels);
194 260725 : restrictinfo->num_base_rels = bms_num_members(baserels);
195 260725 : bms_free(baserels);
196 :
197 : /*
198 : * Label this RestrictInfo with a fresh serial number.
199 : */
200 260725 : restrictinfo->rinfo_serial = ++(root->last_rinfo_serial);
201 :
202 : /*
203 : * Fill in all the cacheable fields with "not yet set" markers. None of
3260 bruce 204 ECB : * these will be computed until/unless needed. Note in particular that we
6385 205 : * don't mark a binary opclause as mergejoinable or hashjoinable here;
206 : * that happens only if it appears in the right context (top level of a
207 : * joinclause list).
208 : */
5923 tgl 209 GIC 260725 : restrictinfo->parent_ec = NULL;
210 :
7035 211 260725 : restrictinfo->eval_cost.startup = -1;
5175 tgl 212 CBC 260725 : restrictinfo->norm_selec = -1;
5175 tgl 213 GIC 260725 : restrictinfo->outer_selec = -1;
214 :
5923 215 260725 : restrictinfo->mergeopfamilies = NIL;
216 :
217 260725 : restrictinfo->left_ec = NULL;
218 260725 : restrictinfo->right_ec = NULL;
5921 219 260725 : restrictinfo->left_em = NULL;
220 260725 : restrictinfo->right_em = NULL;
5921 tgl 221 CBC 260725 : restrictinfo->scansel_cache = NIL;
222 :
5923 223 260725 : restrictinfo->outer_is_left = false;
7035 tgl 224 ECB :
7035 tgl 225 CBC 260725 : restrictinfo->hashjoinoperator = InvalidOid;
226 :
227 260725 : restrictinfo->left_bucketsize = -1;
7035 tgl 228 GIC 260725 : restrictinfo->right_bucketsize = -1;
2063 tgl 229 CBC 260725 : restrictinfo->left_mcvfreq = -1;
230 260725 : restrictinfo->right_mcvfreq = -1;
7035 tgl 231 ECB :
517 drowley 232 CBC 260725 : restrictinfo->left_hasheqoperator = InvalidOid;
233 260725 : restrictinfo->right_hasheqoperator = InvalidOid;
234 :
7035 tgl 235 260725 : return restrictinfo;
236 : }
7035 tgl 237 ECB :
238 : /*
239 : * Recursively insert sub-RestrictInfo nodes into a boolean expression.
6561 240 : *
241 : * We put RestrictInfos above simple (non-AND/OR) clauses and above
242 : * sub-OR clauses, but not above sub-AND clauses, because there's no need.
243 : * This may seem odd but it is closely related to the fact that we use
244 : * implicit-AND lists at top level of RestrictInfo lists. Only ORs and
245 : * simple clauses are valid RestrictInfos.
246 : *
247 : * The same is_pushed_down and pseudoconstant flag
248 : * values can be applied to all RestrictInfo nodes in the result. Likewise
249 : * for security_level and outer_relids.
250 : *
251 : * The given required_relids are attached to our top-level output,
252 : * but any OR-clause constituents are allowed to default to just the
253 : * contained rels.
254 : */
255 : static Expr *
808 tgl 256 GIC 14536 : make_sub_restrictinfos(PlannerInfo *root,
257 : Expr *clause,
258 : bool is_pushed_down,
259 : bool pseudoconstant,
260 : Index security_level,
261 : Relids required_relids,
262 : Relids outer_relids)
263 : {
1531 264 14536 : if (is_orclause(clause))
265 : {
7035 tgl 266 CBC 3514 : List *orlist = NIL;
267 : ListCell *temp;
268 :
7035 tgl 269 GIC 11821 : foreach(temp, ((BoolExpr *) clause)->args)
270 8307 : orlist = lappend(orlist,
808 271 8307 : make_sub_restrictinfos(root,
272 8307 : lfirst(temp),
273 : is_pushed_down,
274 : pseudoconstant,
2272 tgl 275 ECB : security_level,
276 : NULL,
277 : outer_relids));
808 tgl 278 CBC 3514 : return (Expr *) make_restrictinfo_internal(root,
808 tgl 279 ECB : clause,
6561 280 : make_orclause(orlist),
281 : is_pushed_down,
282 : pseudoconstant,
283 : security_level,
284 : required_relids,
285 : outer_relids);
286 : }
1531 tgl 287 GIC 11022 : else if (is_andclause(clause))
288 : {
7035 289 1282 : List *andlist = NIL;
290 : ListCell *temp;
291 :
292 4036 : foreach(temp, ((BoolExpr *) clause)->args)
7035 tgl 293 CBC 2754 : andlist = lappend(andlist,
808 tgl 294 GIC 2754 : make_sub_restrictinfos(root,
808 tgl 295 CBC 2754 : lfirst(temp),
296 : is_pushed_down,
6126 tgl 297 ECB : pseudoconstant,
2272 298 : security_level,
5106 299 : required_relids,
300 : outer_relids));
7035 tgl 301 GIC 1282 : return make_andclause(andlist);
302 : }
303 : else
808 304 9740 : return (Expr *) make_restrictinfo_internal(root,
808 tgl 305 ECB : clause,
306 : NULL,
307 : is_pushed_down,
308 : pseudoconstant,
309 : security_level,
310 : required_relids,
311 : outer_relids);
312 : }
313 :
314 : /*
315 : * commute_restrictinfo
316 : *
317 : * Given a RestrictInfo containing a binary opclause, produce a RestrictInfo
318 : * representing the commutation of that clause. The caller must pass the
319 : * OID of the commutator operator (which it's presumably looked up, else
320 : * it would not know this is valid).
321 : *
322 : * Beware that the result shares sub-structure with the given RestrictInfo.
323 : * That's okay for the intended usage with derived index quals, but might
324 : * be hazardous if the source is subject to change. Also notice that we
325 : * assume without checking that the commutator op is a member of the same
326 : * btree and hash opclasses as the original op.
327 : */
328 : RestrictInfo *
1520 tgl 329 GIC 23039 : commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op)
330 : {
1520 tgl 331 ECB : RestrictInfo *result;
332 : OpExpr *newclause;
1520 tgl 333 GIC 23039 : OpExpr *clause = castNode(OpExpr, rinfo->clause);
334 :
1520 tgl 335 CBC 23039 : Assert(list_length(clause->args) == 2);
336 :
1520 tgl 337 ECB : /* flat-copy all the fields of clause ... */
1520 tgl 338 GIC 23039 : newclause = makeNode(OpExpr);
339 23039 : memcpy(newclause, clause, sizeof(OpExpr));
1520 tgl 340 ECB :
341 : /* ... and adjust those we need to change to commute it */
1520 tgl 342 GIC 23039 : newclause->opno = comm_op;
343 23039 : newclause->opfuncid = InvalidOid;
1520 tgl 344 CBC 23039 : newclause->args = list_make2(lsecond(clause->args),
1520 tgl 345 ECB : linitial(clause->args));
346 :
347 : /* likewise, flat-copy all the fields of rinfo ... */
1520 tgl 348 GIC 23039 : result = makeNode(RestrictInfo);
349 23039 : memcpy(result, rinfo, sizeof(RestrictInfo));
1520 tgl 350 ECB :
351 : /*
352 : * ... and adjust those we need to change. Note in particular that we can
353 : * preserve any cached selectivity or cost estimates, since those ought to
354 : * be the same for the new clause. Likewise we can keep the source's
355 : * parent_ec. It's also important that we keep the same rinfo_serial.
356 : */
1520 tgl 357 GIC 23039 : result->clause = (Expr *) newclause;
358 23039 : result->left_relids = rinfo->right_relids;
1520 tgl 359 CBC 23039 : result->right_relids = rinfo->left_relids;
360 23039 : Assert(result->orclause == NULL);
361 23039 : result->left_ec = rinfo->right_ec;
362 23039 : result->right_ec = rinfo->left_ec;
363 23039 : result->left_em = rinfo->right_em;
364 23039 : result->right_em = rinfo->left_em;
365 23039 : result->scansel_cache = NIL; /* not worth updating this */
366 23039 : if (rinfo->hashjoinoperator == clause->opno)
367 22537 : result->hashjoinoperator = comm_op;
1520 tgl 368 ECB : else
1520 tgl 369 CBC 502 : result->hashjoinoperator = InvalidOid;
1520 tgl 370 GIC 23039 : result->left_bucketsize = rinfo->right_bucketsize;
1520 tgl 371 CBC 23039 : result->right_bucketsize = rinfo->left_bucketsize;
372 23039 : result->left_mcvfreq = rinfo->right_mcvfreq;
373 23039 : result->right_mcvfreq = rinfo->left_mcvfreq;
517 drowley 374 23039 : result->left_hasheqoperator = InvalidOid;
375 23039 : result->right_hasheqoperator = InvalidOid;
1520 tgl 376 ECB :
1520 tgl 377 CBC 23039 : return result;
378 : }
1520 tgl 379 ECB :
380 : /*
381 : * restriction_is_or_clause
382 : *
383 : * Returns t iff the restrictinfo node contains an 'or' clause.
384 : */
385 : bool
8660 tgl 386 GIC 386446 : restriction_is_or_clause(RestrictInfo *restrictinfo)
387 : {
7035 tgl 388 CBC 386446 : if (restrictinfo->orclause != NULL)
8986 bruce 389 GIC 14268 : return true;
9345 bruce 390 ECB : else
8986 bruce 391 CBC 372178 : return false;
392 : }
9770 scrappy 393 ECB :
394 : /*
395 : * restriction_is_securely_promotable
396 : *
397 : * Returns true if it's okay to evaluate this clause "early", that is before
398 : * other restriction clauses attached to the specified relation.
399 : */
400 : bool
2272 tgl 401 GIC 569087 : restriction_is_securely_promotable(RestrictInfo *restrictinfo,
402 : RelOptInfo *rel)
9770 scrappy 403 ECB : {
404 : /*
405 : * It's okay if there are no baserestrictinfo clauses for the rel that
406 : * would need to go before this one, *or* if this one is leakproof.
407 : */
2272 tgl 408 GIC 569087 : if (restrictinfo->security_level <= rel->baserestrict_min_security ||
409 2095 : restrictinfo->leakproof)
2272 tgl 410 CBC 568036 : return true;
2272 tgl 411 ECB : else
2272 tgl 412 CBC 1051 : return false;
413 : }
8244 tgl 414 ECB :
415 : /*
416 : * Detect whether a RestrictInfo's clause is constant TRUE (note that it's
417 : * surely of type boolean). No such WHERE clause could survive qual
418 : * canonicalization, but equivclass.c may generate such RestrictInfos for
419 : * reasons discussed therein. We should drop them again when creating
420 : * the finished plan, which is handled by the next few functions.
421 : */
422 : static inline bool
69 tgl 423 GNC 157289 : rinfo_is_constant_true(RestrictInfo *rinfo)
424 : {
425 158035 : return IsA(rinfo->clause, Const) &&
426 158008 : !((Const *) rinfo->clause)->constisnull &&
427 719 : DatumGetBool(((Const *) rinfo->clause)->constvalue);
428 : }
429 :
430 : /*
431 : * get_actual_clauses
432 : *
433 : * Returns a list containing the bare clauses from 'restrictinfo_list'.
434 : *
435 : * This is only to be used in cases where none of the RestrictInfos can
436 : * be pseudoconstant clauses (for instance, it's OK on indexqual lists).
437 : */
438 : List *
2272 tgl 439 GIC 27541 : get_actual_clauses(List *restrictinfo_list)
5025 tgl 440 ECB : {
5025 tgl 441 GIC 27541 : List *result = NIL;
5025 tgl 442 ECB : ListCell *l;
443 :
5025 tgl 444 CBC 56547 : foreach(l, restrictinfo_list)
445 : {
2190 tgl 446 GIC 29006 : RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
447 :
2272 448 29006 : Assert(!rinfo->pseudoconstant);
69 tgl 449 GNC 29006 : Assert(!rinfo_is_constant_true(rinfo));
450 :
5025 tgl 451 GIC 29006 : result = lappend(result, rinfo->clause);
452 : }
453 27541 : return result;
454 : }
455 :
456 : /*
6126 tgl 457 ECB : * extract_actual_clauses
458 : *
459 : * Extract bare clauses from 'restrictinfo_list', returning either the
460 : * regular ones or the pseudoconstant ones per 'pseudoconstant'.
461 : * Constant-TRUE clauses are dropped in any case.
462 : */
463 : List *
6126 tgl 464 GIC 252629 : extract_actual_clauses(List *restrictinfo_list,
6126 tgl 465 ECB : bool pseudoconstant)
466 : {
6126 tgl 467 CBC 252629 : List *result = NIL;
6126 tgl 468 ECB : ListCell *l;
469 :
6126 tgl 470 CBC 377522 : foreach(l, restrictinfo_list)
471 : {
2190 472 124893 : RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
473 :
69 tgl 474 GNC 124893 : if (rinfo->pseudoconstant == pseudoconstant &&
475 114408 : !rinfo_is_constant_true(rinfo))
6126 tgl 476 GIC 114408 : result = lappend(result, rinfo->clause);
477 : }
478 252629 : return result;
479 : }
480 :
481 : /*
482 : * extract_actual_join_clauses
483 : *
6126 tgl 484 ECB : * Extract bare clauses from 'restrictinfo_list', separating those that
485 : * semantically match the join level from those that were pushed down.
486 : * Pseudoconstant and constant-TRUE clauses are excluded from the results.
487 : *
488 : * This is only used at outer joins, since for plain joins we don't care
489 : * about pushed-down-ness.
8244 490 : */
491 : void
6126 tgl 492 CBC 16047 : extract_actual_join_clauses(List *restrictinfo_list,
493 : Relids joinrelids,
6126 tgl 494 ECB : List **joinquals,
495 : List **otherquals)
8244 496 : {
497 : ListCell *l;
498 :
8244 tgl 499 GIC 16047 : *joinquals = NIL;
500 16047 : *otherquals = NIL;
501 :
6126 502 29925 : foreach(l, restrictinfo_list)
503 : {
2190 504 13878 : RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
505 :
1815 506 13878 : if (RINFO_IS_PUSHED_DOWN(rinfo, joinrelids))
507 : {
69 tgl 508 GNC 1874 : if (!rinfo->pseudoconstant &&
509 1871 : !rinfo_is_constant_true(rinfo))
6126 tgl 510 GIC 1221 : *otherquals = lappend(*otherquals, rinfo->clause);
511 : }
512 : else
6126 tgl 513 ECB : {
514 : /* joinquals shouldn't have been marked pseudoconstant */
6126 tgl 515 GIC 12004 : Assert(!rinfo->pseudoconstant);
69 tgl 516 GNC 12004 : Assert(!rinfo_is_constant_true(rinfo));
6126 tgl 517 GIC 12004 : *joinquals = lappend(*joinquals, rinfo->clause);
518 : }
519 : }
8244 520 16047 : }
7441 tgl 521 ECB :
522 : /*
523 : * clause_is_computable_at
524 : * Test whether a clause is computable at a given evaluation level.
525 : *
526 : * There are two conditions for whether an expression can actually be
527 : * evaluated at a given join level: the evaluation context must include
528 : * all the relids (both base and OJ) used by the expression, and we must
529 : * not have already evaluated any outer joins that null Vars/PHVs of the
530 : * expression and are not listed in their nullingrels.
531 : *
532 : * This function checks the second condition; we assume the caller already
533 : * saw to the first one.
534 : *
535 : * For speed reasons, we don't individually examine each Var/PHV of the
536 : * expression, but just look at the overall clause_relids (the union of the
537 : * varnos and varnullingrels). This could give a misleading answer if the
538 : * Vars of a given varno don't all have the same varnullingrels; but that
539 : * really shouldn't happen within a single scalar expression or RestrictInfo
540 : * clause. Despite that, this is still annoyingly expensive :-(
541 : */
542 : bool
69 tgl 543 GNC 125738 : clause_is_computable_at(PlannerInfo *root,
544 : Relids clause_relids,
545 : Relids eval_relids)
546 : {
547 : ListCell *lc;
548 :
549 : /* Nothing to do if no outer joins have been performed yet. */
550 125738 : if (!bms_overlap(eval_relids, root->outer_join_rels))
551 66602 : return true;
552 :
553 202403 : foreach(lc, root->join_info_list)
554 : {
555 149437 : SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
556 :
557 : /* Ignore outer joins that are not yet performed. */
558 149437 : if (!bms_is_member(sjinfo->ojrelid, eval_relids))
559 71872 : continue;
560 :
561 : /* OK if clause lists it (we assume all Vars in it agree). */
562 77565 : if (bms_is_member(sjinfo->ojrelid, clause_relids))
563 9853 : continue;
564 :
565 : /* Else, trouble if clause mentions any nullable Vars. */
566 67712 : if (bms_overlap(clause_relids, sjinfo->min_righthand) ||
567 61548 : (sjinfo->jointype == JOIN_FULL &&
568 6 : bms_overlap(clause_relids, sjinfo->min_lefthand)))
569 6170 : return false; /* doesn't work */
570 : }
571 :
572 52966 : return true; /* OK */
573 : }
5083 tgl 574 ECB :
575 : /*
4007 576 : * join_clause_is_movable_to
577 : * Test whether a join clause is a safe candidate for parameterization
578 : * of a scan on the specified base relation.
579 : *
580 : * A movable join clause is one that can safely be evaluated at a rel below
581 : * its normal semantic level (ie, its required_relids), if the values of
582 : * variables that it would need from other rels are provided.
583 : *
584 : * We insist that the clause actually reference the target relation; this
585 : * prevents undesirable movement of degenerate join clauses, and ensures
586 : * that there is a unique place that a clause can be moved down to.
587 : *
588 : * We cannot move an outer-join clause into the non-nullable side of its
589 : * outer join, as that would change the results (rows would be suppressed
590 : * rather than being null-extended).
591 : *
592 : * Also there must not be an outer join below the clause that would null the
593 : * Vars coming from the target relation. Otherwise the clause might give
2812 594 : * results different from what it would give at its normal semantic level.
595 : *
596 : * Also, the join clause must not use any relations that have LATERAL
597 : * references to the target relation, since we could not put such rels on
598 : * the outer side of a nestloop with the target relation.
599 : *
600 : * Also, we reject is_clone versions of outer-join clauses. This has the
601 : * effect of preventing us from generating variant parameterized paths
602 : * that differ only in which outer joins null the parameterization rel(s).
603 : * Generating one path from the minimally-parameterized has_clone version
604 : * is sufficient.
605 : */
606 : bool
3522 tgl 607 GIC 103556 : join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel)
608 : {
609 : /* Clause must physically reference target rel */
610 103556 : if (!bms_is_member(baserel->relid, rinfo->clause_relids))
4007 611 15375 : return false;
612 :
613 : /* Cannot move an outer-join clause into the join's outer side */
3522 614 88181 : if (bms_is_member(baserel->relid, rinfo->outer_relids))
4007 615 39989 : return false;
616 :
617 : /*
618 : * Target rel's Vars must not be nulled by any outer join. We can check
619 : * this without groveling through the individual Vars by seeing whether
620 : * clause_relids (which includes all such Vars' varnullingrels) includes
621 : * any outer join that can null the target rel. You might object that
622 : * this could reject the clause on the basis of an OJ relid that came from
623 : * some other rel's Var. However, that would still mean that the clause
624 : * came from above that outer join and shouldn't be pushed down; so there
625 : * should be no false positives.
626 : */
69 tgl 627 GNC 48192 : if (bms_overlap(rinfo->clause_relids, baserel->nulling_relids))
3522 tgl 628 GIC 2140 : return false;
629 :
630 : /* Clause must not use any rels with LATERAL references to this rel */
631 46052 : if (bms_overlap(baserel->lateral_referencers, rinfo->clause_relids))
4007 tgl 632 CBC 9 : return false;
633 :
634 : /* Ignore clones, too */
69 tgl 635 GNC 46043 : if (rinfo->is_clone)
636 4021 : return false;
637 :
4007 tgl 638 GIC 42022 : return true;
639 : }
640 :
641 : /*
642 : * join_clause_is_movable_into
4007 tgl 643 ECB : * Test whether a join clause is movable and can be evaluated within
644 : * the current join context.
645 : *
646 : * currentrelids: the relids of the proposed evaluation location
647 : * current_and_outer: the union of currentrelids and the required_outer
648 : * relids (parameterization's outer relations)
649 : *
650 : * The API would be a bit clearer if we passed the current relids and the
651 : * outer relids separately and did bms_union internally; but since most
652 : * callers need to apply this function to multiple clauses, we make the
653 : * caller perform the union.
654 : *
655 : * Obviously, the clause must only refer to Vars available from the current
656 : * relation plus the outer rels. We also check that it does reference at
657 : * least one current Var, ensuring that the clause will be pushed down to
658 : * a unique place in a parameterized join tree. And we check that we're
659 : * not pushing the clause into its outer-join outer side.
69 660 : *
661 : * We used to need to check that we're not pushing the clause into a lower
662 : * outer join's inner side. However, now that clause_relids includes
663 : * references to potentially-nulling outer joins, the other tests handle that
664 : * concern. If the clause references any Var coming from the inside of a
665 : * lower outer join, its clause_relids will mention that outer join, causing
666 : * the evaluability check to fail; while if it references no such Vars, the
667 : * references-a-target-rel check will fail.
668 : *
669 : * There's no check here equivalent to join_clause_is_movable_to's test on
670 : * lateral_referencers. We assume the caller wouldn't be inquiring unless
671 : * it'd verified that the proposed outer rels don't have lateral references
672 : * to the current rel(s). (If we are considering join paths with the outer
673 : * rels on the outside and the current rels on the inside, then this should
674 : * have been checked at the outset of such consideration; see join_is_legal
675 : * and the path parameterization checks in joinpath.c.) On the other hand,
676 : * in join_clause_is_movable_to we are asking whether the clause could be
677 : * moved for some valid set of outer rels, so we don't have the benefit of
678 : * relying on prior checks for lateral-reference validity.
679 : *
680 : * Likewise, we don't check is_clone here: rejecting the inappropriate
681 : * variants of a cloned clause must be handled upstream.
682 : *
683 : * Note: if this returns true, it means that the clause could be moved to
684 : * this join relation, but that doesn't mean that this is the lowest join
685 : * it could be moved to. Caller may need to make additional calls to verify
686 : * that this doesn't succeed on either of the inputs of a proposed join.
687 : *
688 : * Note: get_joinrel_parampathinfo depends on the fact that if
689 : * current_and_outer is NULL, this function will always return false
690 : * (since one or the other of the first two tests must fail).
691 : */
692 : bool
4007 tgl 693 GIC 121022 : join_clause_is_movable_into(RestrictInfo *rinfo,
694 : Relids currentrelids,
695 : Relids current_and_outer)
696 : {
697 : /* Clause must be evaluable given available context */
698 121022 : if (!bms_is_subset(rinfo->clause_relids, current_and_outer))
699 22085 : return false;
6981 tgl 700 ECB :
701 : /* Clause must physically reference at least one target rel */
4007 tgl 702 GIC 98937 : if (!bms_overlap(currentrelids, rinfo->clause_relids))
4007 tgl 703 CBC 7069 : return false;
6981 tgl 704 ECB :
705 : /* Cannot move an outer-join clause into the join's outer side */
4007 tgl 706 GIC 91868 : if (bms_overlap(currentrelids, rinfo->outer_relids))
4007 tgl 707 CBC 314 : return false;
7441 tgl 708 ECB :
4007 tgl 709 GIC 91554 : return true;
710 : }
|