1 /*-------------------------------------------------------------------------
4 * RestrictInfo node manipulation routines.
6 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.40 2005/10/13 00:06:46 tgl Exp $
13 *-------------------------------------------------------------------------
17 #include "optimizer/clauses.h"
18 #include "optimizer/cost.h"
19 #include "optimizer/paths.h"
20 #include "optimizer/predtest.h"
21 #include "optimizer/restrictinfo.h"
22 #include "optimizer/var.h"
25 static RestrictInfo *make_restrictinfo_internal(Expr *clause,
28 Relids required_relids);
29 static Expr *make_sub_restrictinfos(Expr *clause,
31 static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
40 * Build a RestrictInfo node containing the given subexpression.
42 * The is_pushed_down flag must be supplied by the caller.
43 * required_relids can be NULL, in which case it defaults to the
44 * actual clause contents (i.e., clause_relids).
46 * We initialize fields that depend only on the given subexpression, leaving
47 * others that depend on context (or may never be needed at all) to be filled
51 make_restrictinfo(Expr *clause, bool is_pushed_down, Relids required_relids)
54 * If it's an OR clause, build a modified copy with RestrictInfos
55 * inserted above each subclause of the top-level AND/OR structure.
57 if (or_clause((Node *) clause))
58 return (RestrictInfo *) make_sub_restrictinfos(clause, is_pushed_down);
60 /* Shouldn't be an AND clause, else AND/OR flattening messed up */
61 Assert(!and_clause((Node *) clause));
63 return make_restrictinfo_internal(clause, NULL, is_pushed_down,
68 * make_restrictinfo_from_bitmapqual
70 * Given the bitmapqual Path structure for a bitmap indexscan, generate
71 * RestrictInfo node(s) equivalent to the condition represented by the
72 * indexclauses of the Path structure.
74 * The result is a List (effectively, implicit-AND representation) of
77 * If include_predicates is true, we add any partial index predicates to
78 * the explicit index quals. When this is not true, we return a condition
79 * that might be weaker than the actual scan represents.
81 * To do this through the normal make_restrictinfo() API, callers would have
82 * to strip off the RestrictInfo nodes present in the indexclauses lists, and
83 * then make_restrictinfo() would have to build new ones. It's better to have
84 * a specialized routine to allow sharing of RestrictInfos.
86 * The qual manipulations here are much the same as in create_bitmap_subplan;
87 * keep the two routines in sync!
90 make_restrictinfo_from_bitmapqual(Path *bitmapqual,
92 bool include_predicates)
97 if (IsA(bitmapqual, BitmapAndPath))
99 BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
102 * There may well be redundant quals among the subplans, since a
103 * top-level WHERE qual might have gotten used to form several
104 * different index quals. We don't try exceedingly hard to
105 * eliminate redundancies, but we do eliminate obvious duplicates
106 * by using list_concat_unique.
109 foreach(l, apath->bitmapquals)
113 sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
116 result = list_concat_unique(result, sublist);
119 else if (IsA(bitmapqual, BitmapOrPath))
121 BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
123 List *withoutris = NIL;
126 * Here, we only detect qual-free subplans. A qual-free subplan would
127 * cause us to generate "... OR true ..." which we may as well reduce
128 * to just "true". We do not try to eliminate redundant subclauses
129 * because (a) it's not as likely as in the AND case, and (b) we might
130 * well be working with hundreds or even thousands of OR conditions,
131 * perhaps from a long IN list. The performance of list_append_unique
132 * would be unacceptable.
134 foreach(l, opath->bitmapquals)
138 sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
144 * If we find a qual-less subscan, it represents a constant
145 * TRUE, and hence the OR result is also constant TRUE, so
150 /* Create AND subclause with RestrictInfos */
151 withris = lappend(withris,
152 make_ands_explicit(sublist));
153 /* And one without */
154 sublist = get_actual_clauses(sublist);
155 withoutris = lappend(withoutris,
156 make_ands_explicit(sublist));
160 * Avoid generating one-element ORs, which could happen
161 * due to redundancy elimination.
163 if (list_length(withris) <= 1)
167 /* Here's the magic part not available to outside callers */
169 list_make1(make_restrictinfo_internal(make_orclause(withoutris),
170 make_orclause(withris),
175 else if (IsA(bitmapqual, IndexPath))
177 IndexPath *ipath = (IndexPath *) bitmapqual;
179 result = list_copy(ipath->indexclauses);
180 if (include_predicates && ipath->indexinfo->indpred != NIL)
182 foreach(l, ipath->indexinfo->indpred)
184 Expr *pred = (Expr *) lfirst(l);
187 * We know that the index predicate must have been implied
188 * by the query condition as a whole, but it may or may not
189 * be implied by the conditions that got pushed into the
190 * bitmapqual. Avoid generating redundant conditions.
192 if (!predicate_implied_by(list_make1(pred), result))
193 result = lappend(result,
194 make_restrictinfo(pred,
202 elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
203 result = NIL; /* keep compiler quiet */
210 * make_restrictinfo_internal
212 * Common code for the main entry points and the recursive cases.
214 static RestrictInfo *
215 make_restrictinfo_internal(Expr *clause, Expr *orclause,
216 bool is_pushed_down, Relids required_relids)
218 RestrictInfo *restrictinfo = makeNode(RestrictInfo);
220 restrictinfo->clause = clause;
221 restrictinfo->orclause = orclause;
222 restrictinfo->is_pushed_down = is_pushed_down;
223 restrictinfo->can_join = false; /* may get set below */
226 * If it's a binary opclause, set up left/right relids info. In any
227 * case set up the total clause relids info.
229 if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
231 restrictinfo->left_relids = pull_varnos(get_leftop(clause));
232 restrictinfo->right_relids = pull_varnos(get_rightop(clause));
234 restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,
235 restrictinfo->right_relids);
238 * Does it look like a normal join clause, i.e., a binary operator
239 * relating expressions that come from distinct relations? If so
240 * we might be able to use it in a join algorithm. Note that this
241 * is a purely syntactic test that is made regardless of context.
243 if (!bms_is_empty(restrictinfo->left_relids) &&
244 !bms_is_empty(restrictinfo->right_relids) &&
245 !bms_overlap(restrictinfo->left_relids,
246 restrictinfo->right_relids))
247 restrictinfo->can_join = true;
251 /* Not a binary opclause, so mark left/right relid sets as empty */
252 restrictinfo->left_relids = NULL;
253 restrictinfo->right_relids = NULL;
254 /* and get the total relid set the hard way */
255 restrictinfo->clause_relids = pull_varnos((Node *) clause);
258 /* required_relids defaults to clause_relids */
259 if (required_relids != NULL)
260 restrictinfo->required_relids = required_relids;
262 restrictinfo->required_relids = restrictinfo->clause_relids;
265 * Fill in all the cacheable fields with "not yet set" markers. None
266 * of these will be computed until/unless needed. Note in particular
267 * that we don't mark a binary opclause as mergejoinable or
268 * hashjoinable here; that happens only if it appears in the right
269 * context (top level of a joinclause list).
271 restrictinfo->eval_cost.startup = -1;
272 restrictinfo->this_selec = -1;
274 restrictinfo->mergejoinoperator = InvalidOid;
275 restrictinfo->left_sortop = InvalidOid;
276 restrictinfo->right_sortop = InvalidOid;
278 restrictinfo->left_pathkey = NIL;
279 restrictinfo->right_pathkey = NIL;
281 restrictinfo->left_mergescansel = -1;
282 restrictinfo->right_mergescansel = -1;
284 restrictinfo->hashjoinoperator = InvalidOid;
286 restrictinfo->left_bucketsize = -1;
287 restrictinfo->right_bucketsize = -1;
293 * Recursively insert sub-RestrictInfo nodes into a boolean expression.
295 * We put RestrictInfos above simple (non-AND/OR) clauses and above
296 * sub-OR clauses, but not above sub-AND clauses, because there's no need.
297 * This may seem odd but it is closely related to the fact that we use
298 * implicit-AND lists at top level of RestrictInfo lists. Only ORs and
299 * simple clauses are valid RestrictInfos.
302 make_sub_restrictinfos(Expr *clause, bool is_pushed_down)
304 if (or_clause((Node *) clause))
309 foreach(temp, ((BoolExpr *) clause)->args)
310 orlist = lappend(orlist,
311 make_sub_restrictinfos(lfirst(temp),
313 return (Expr *) make_restrictinfo_internal(clause,
314 make_orclause(orlist),
318 else if (and_clause((Node *) clause))
323 foreach(temp, ((BoolExpr *) clause)->args)
324 andlist = lappend(andlist,
325 make_sub_restrictinfos(lfirst(temp),
327 return make_andclause(andlist);
330 return (Expr *) make_restrictinfo_internal(clause,
337 * restriction_is_or_clause
339 * Returns t iff the restrictinfo node contains an 'or' clause.
342 restriction_is_or_clause(RestrictInfo *restrictinfo)
344 if (restrictinfo->orclause != NULL)
353 * Returns a list containing the bare clauses from 'restrictinfo_list'.
356 get_actual_clauses(List *restrictinfo_list)
361 foreach(temp, restrictinfo_list)
363 RestrictInfo *rinfo = (RestrictInfo *) lfirst(temp);
365 Assert(IsA(rinfo, RestrictInfo));
367 result = lappend(result, rinfo->clause);
373 * get_actual_join_clauses
375 * Extract clauses from 'restrictinfo_list', separating those that
376 * syntactically match the join level from those that were pushed down.
379 get_actual_join_clauses(List *restrictinfo_list,
380 List **joinquals, List **otherquals)
387 foreach(temp, restrictinfo_list)
389 RestrictInfo *clause = (RestrictInfo *) lfirst(temp);
391 if (clause->is_pushed_down)
392 *otherquals = lappend(*otherquals, clause->clause);
394 *joinquals = lappend(*joinquals, clause->clause);
399 * remove_redundant_join_clauses
401 * Given a list of RestrictInfo clauses that are to be applied in a join,
402 * remove any duplicate or redundant clauses.
404 * We must eliminate duplicates when forming the restrictlist for a joinrel,
405 * since we will see many of the same clauses arriving from both input
406 * relations. Also, if a clause is a mergejoinable clause, it's possible that
407 * it is redundant with previous clauses (see optimizer/README for
408 * discussion). We detect that case and omit the redundant clause from the
411 * The result is a fresh List, but it points to the same member nodes
412 * as were in the input.
415 remove_redundant_join_clauses(PlannerInfo *root, List *restrictinfo_list,
423 * If there are any redundant clauses, we want to eliminate the ones
424 * that are more expensive in favor of the ones that are less so. Run
425 * cost_qual_eval() to ensure the eval_cost fields are set up.
427 cost_qual_eval(&cost, restrictinfo_list);
430 * We don't have enough knowledge yet to be able to estimate the
431 * number of times a clause might be evaluated, so it's hard to weight
432 * the startup and per-tuple costs appropriately. For now just weight
435 #define CLAUSECOST(r) ((r)->eval_cost.startup + (r)->eval_cost.per_tuple)
437 foreach(item, restrictinfo_list)
439 RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
440 RestrictInfo *prevrinfo;
442 /* is it redundant with any prior clause? */
443 prevrinfo = join_clause_is_redundant(root, rinfo, result, isouterjoin);
444 if (prevrinfo == NULL)
446 /* no, so add it to result list */
447 result = lappend(result, rinfo);
449 else if (CLAUSECOST(rinfo) < CLAUSECOST(prevrinfo))
451 /* keep this one, drop the previous one */
452 result = list_delete_ptr(result, prevrinfo);
453 result = lappend(result, rinfo);
455 /* else, drop this one */
462 * select_nonredundant_join_clauses
464 * Given a list of RestrictInfo clauses that are to be applied in a join,
465 * select the ones that are not redundant with any clause in the
468 * This is similar to remove_redundant_join_clauses, but we are looking for
469 * redundancies with a separate list of clauses (i.e., clauses that have
470 * already been applied below the join itself).
472 * Note that we assume the given restrictinfo_list has already been checked
473 * for local redundancies, so we don't check again.
476 select_nonredundant_join_clauses(PlannerInfo *root,
477 List *restrictinfo_list,
478 List *reference_list,
484 foreach(item, restrictinfo_list)
486 RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
488 /* drop it if redundant with any reference clause */
489 if (join_clause_is_redundant(root, rinfo, reference_list, isouterjoin) != NULL)
492 /* otherwise, add it to result list */
493 result = lappend(result, rinfo);
500 * join_clause_is_redundant
501 * If rinfo is redundant with any clause in reference_list,
502 * return one such clause; otherwise return NULL.
504 * This is the guts of both remove_redundant_join_clauses and
505 * select_nonredundant_join_clauses. See the docs above for motivation.
507 * We can detect redundant mergejoinable clauses very cheaply by using their
508 * left and right pathkeys, which uniquely identify the sets of equijoined
509 * variables in question. All the members of a pathkey set that are in the
510 * left relation have already been forced to be equal; likewise for those in
511 * the right relation. So, we need to have only one clause that checks
512 * equality between any set member on the left and any member on the right;
513 * by transitivity, all the rest are then equal.
515 * However, clauses that are of the form "var expr = const expr" cannot be
516 * eliminated as redundant. This is because when there are const expressions
517 * in a pathkey set, generate_implied_equalities() suppresses "var = var"
518 * clauses in favor of "var = const" clauses. We cannot afford to drop any
519 * of the latter, even though they might seem redundant by the pathkey
522 * Weird special case: if we have two clauses that seem redundant
523 * except one is pushed down into an outer join and the other isn't,
524 * then they're not really redundant, because one constrains the
525 * joined rows after addition of null fill rows, and the other doesn't.
527 static RestrictInfo *
528 join_clause_is_redundant(PlannerInfo *root,
530 List *reference_list,
535 /* always consider exact duplicates redundant */
536 foreach(refitem, reference_list)
538 RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);
540 if (equal(rinfo, refrinfo))
544 /* check for redundant merge clauses */
545 if (rinfo->mergejoinoperator != InvalidOid)
547 /* do the cheap test first: is it a "var = const" clause? */
548 if (bms_is_empty(rinfo->left_relids) ||
549 bms_is_empty(rinfo->right_relids))
550 return NULL; /* var = const, so not redundant */
552 cache_mergeclause_pathkeys(root, rinfo);
554 foreach(refitem, reference_list)
556 RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);
558 if (refrinfo->mergejoinoperator != InvalidOid)
560 cache_mergeclause_pathkeys(root, refrinfo);
562 if (rinfo->left_pathkey == refrinfo->left_pathkey &&
563 rinfo->right_pathkey == refrinfo->right_pathkey &&
564 (rinfo->is_pushed_down == refrinfo->is_pushed_down ||
567 /* Yup, it's redundant */
574 /* otherwise, not redundant */