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.38 2005/07/02 23:00:41 tgl Exp $
13 *-------------------------------------------------------------------------
17 #include "optimizer/clauses.h"
18 #include "optimizer/cost.h"
19 #include "optimizer/paths.h"
20 #include "optimizer/restrictinfo.h"
21 #include "optimizer/var.h"
24 static RestrictInfo *make_restrictinfo_internal(Expr *clause,
27 Relids required_relids);
28 static Expr *make_sub_restrictinfos(Expr *clause,
30 static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
39 * Build a RestrictInfo node containing the given subexpression.
41 * The is_pushed_down flag must be supplied by the caller.
42 * required_relids can be NULL, in which case it defaults to the
43 * actual clause contents (i.e., clause_relids).
45 * We initialize fields that depend only on the given subexpression, leaving
46 * others that depend on context (or may never be needed at all) to be filled
50 make_restrictinfo(Expr *clause, bool is_pushed_down, Relids required_relids)
53 * If it's an OR clause, build a modified copy with RestrictInfos
54 * inserted above each subclause of the top-level AND/OR structure.
56 if (or_clause((Node *) clause))
57 return (RestrictInfo *) make_sub_restrictinfos(clause, is_pushed_down);
59 /* Shouldn't be an AND clause, else AND/OR flattening messed up */
60 Assert(!and_clause((Node *) clause));
62 return make_restrictinfo_internal(clause, NULL, is_pushed_down,
67 * make_restrictinfo_from_bitmapqual
69 * Given the bitmapqual Path structure for a bitmap indexscan, generate
70 * RestrictInfo node(s) equivalent to the condition represented by the
71 * indexclauses of the Path structure.
73 * The result is a List since we might need to return multiple RestrictInfos.
75 * To do this through the normal make_restrictinfo() API, callers would have
76 * to strip off the RestrictInfo nodes present in the indexclauses lists, and
77 * then make_restrictinfo() would have to build new ones. It's better to have
78 * a specialized routine to allow sharing of RestrictInfos.
81 make_restrictinfo_from_bitmapqual(Path *bitmapqual, bool is_pushed_down)
85 if (IsA(bitmapqual, BitmapAndPath))
87 BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
91 foreach(l, apath->bitmapquals)
95 sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
97 result = list_concat(result, sublist);
100 else if (IsA(bitmapqual, BitmapOrPath))
102 BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
104 List *withoutris = NIL;
107 foreach(l, opath->bitmapquals)
111 sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
115 /* constant TRUE input yields constant TRUE OR result */
116 /* (though this probably cannot happen) */
119 /* Create AND subclause with RestrictInfos */
120 withris = lappend(withris, make_ands_explicit(sublist));
121 /* And one without */
122 sublist = get_actual_clauses(sublist);
123 withoutris = lappend(withoutris, make_ands_explicit(sublist));
125 /* Here's the magic part not available to outside callers */
127 list_make1(make_restrictinfo_internal(make_orclause(withoutris),
128 make_orclause(withris),
132 else if (IsA(bitmapqual, IndexPath))
134 IndexPath *ipath = (IndexPath *) bitmapqual;
136 result = list_copy(ipath->indexclauses);
140 elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
141 result = NIL; /* keep compiler quiet */
148 * make_restrictinfo_internal
150 * Common code for the main entry points and the recursive cases.
152 static RestrictInfo *
153 make_restrictinfo_internal(Expr *clause, Expr *orclause,
154 bool is_pushed_down, Relids required_relids)
156 RestrictInfo *restrictinfo = makeNode(RestrictInfo);
158 restrictinfo->clause = clause;
159 restrictinfo->orclause = orclause;
160 restrictinfo->is_pushed_down = is_pushed_down;
161 restrictinfo->can_join = false; /* may get set below */
164 * If it's a binary opclause, set up left/right relids info. In any
165 * case set up the total clause relids info.
167 if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
169 restrictinfo->left_relids = pull_varnos(get_leftop(clause));
170 restrictinfo->right_relids = pull_varnos(get_rightop(clause));
172 restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,
173 restrictinfo->right_relids);
176 * Does it look like a normal join clause, i.e., a binary operator
177 * relating expressions that come from distinct relations? If so
178 * we might be able to use it in a join algorithm. Note that this
179 * is a purely syntactic test that is made regardless of context.
181 if (!bms_is_empty(restrictinfo->left_relids) &&
182 !bms_is_empty(restrictinfo->right_relids) &&
183 !bms_overlap(restrictinfo->left_relids,
184 restrictinfo->right_relids))
185 restrictinfo->can_join = true;
189 /* Not a binary opclause, so mark left/right relid sets as empty */
190 restrictinfo->left_relids = NULL;
191 restrictinfo->right_relids = NULL;
192 /* and get the total relid set the hard way */
193 restrictinfo->clause_relids = pull_varnos((Node *) clause);
196 /* required_relids defaults to clause_relids */
197 if (required_relids != NULL)
198 restrictinfo->required_relids = required_relids;
200 restrictinfo->required_relids = restrictinfo->clause_relids;
203 * Fill in all the cacheable fields with "not yet set" markers. None
204 * of these will be computed until/unless needed. Note in particular
205 * that we don't mark a binary opclause as mergejoinable or
206 * hashjoinable here; that happens only if it appears in the right
207 * context (top level of a joinclause list).
209 restrictinfo->eval_cost.startup = -1;
210 restrictinfo->this_selec = -1;
212 restrictinfo->mergejoinoperator = InvalidOid;
213 restrictinfo->left_sortop = InvalidOid;
214 restrictinfo->right_sortop = InvalidOid;
216 restrictinfo->left_pathkey = NIL;
217 restrictinfo->right_pathkey = NIL;
219 restrictinfo->left_mergescansel = -1;
220 restrictinfo->right_mergescansel = -1;
222 restrictinfo->hashjoinoperator = InvalidOid;
224 restrictinfo->left_bucketsize = -1;
225 restrictinfo->right_bucketsize = -1;
231 * Recursively insert sub-RestrictInfo nodes into a boolean expression.
233 * We put RestrictInfos above simple (non-AND/OR) clauses and above
234 * sub-OR clauses, but not above sub-AND clauses, because there's no need.
235 * This may seem odd but it is closely related to the fact that we use
236 * implicit-AND lists at top level of RestrictInfo lists. Only ORs and
237 * simple clauses are valid RestrictInfos.
240 make_sub_restrictinfos(Expr *clause, bool is_pushed_down)
242 if (or_clause((Node *) clause))
247 foreach(temp, ((BoolExpr *) clause)->args)
248 orlist = lappend(orlist,
249 make_sub_restrictinfos(lfirst(temp),
251 return (Expr *) make_restrictinfo_internal(clause,
252 make_orclause(orlist),
256 else if (and_clause((Node *) clause))
261 foreach(temp, ((BoolExpr *) clause)->args)
262 andlist = lappend(andlist,
263 make_sub_restrictinfos(lfirst(temp),
265 return make_andclause(andlist);
268 return (Expr *) make_restrictinfo_internal(clause,
275 * restriction_is_or_clause
277 * Returns t iff the restrictinfo node contains an 'or' clause.
280 restriction_is_or_clause(RestrictInfo *restrictinfo)
282 if (restrictinfo->orclause != NULL)
291 * Returns a list containing the bare clauses from 'restrictinfo_list'.
294 get_actual_clauses(List *restrictinfo_list)
299 foreach(temp, restrictinfo_list)
301 RestrictInfo *rinfo = (RestrictInfo *) lfirst(temp);
303 Assert(IsA(rinfo, RestrictInfo));
305 result = lappend(result, rinfo->clause);
311 * get_actual_join_clauses
313 * Extract clauses from 'restrictinfo_list', separating those that
314 * syntactically match the join level from those that were pushed down.
317 get_actual_join_clauses(List *restrictinfo_list,
318 List **joinquals, List **otherquals)
325 foreach(temp, restrictinfo_list)
327 RestrictInfo *clause = (RestrictInfo *) lfirst(temp);
329 if (clause->is_pushed_down)
330 *otherquals = lappend(*otherquals, clause->clause);
332 *joinquals = lappend(*joinquals, clause->clause);
337 * remove_redundant_join_clauses
339 * Given a list of RestrictInfo clauses that are to be applied in a join,
340 * remove any duplicate or redundant clauses.
342 * We must eliminate duplicates when forming the restrictlist for a joinrel,
343 * since we will see many of the same clauses arriving from both input
344 * relations. Also, if a clause is a mergejoinable clause, it's possible that
345 * it is redundant with previous clauses (see optimizer/README for
346 * discussion). We detect that case and omit the redundant clause from the
349 * The result is a fresh List, but it points to the same member nodes
350 * as were in the input.
353 remove_redundant_join_clauses(PlannerInfo *root, List *restrictinfo_list,
361 * If there are any redundant clauses, we want to eliminate the ones
362 * that are more expensive in favor of the ones that are less so. Run
363 * cost_qual_eval() to ensure the eval_cost fields are set up.
365 cost_qual_eval(&cost, restrictinfo_list);
368 * We don't have enough knowledge yet to be able to estimate the
369 * number of times a clause might be evaluated, so it's hard to weight
370 * the startup and per-tuple costs appropriately. For now just weight
373 #define CLAUSECOST(r) ((r)->eval_cost.startup + (r)->eval_cost.per_tuple)
375 foreach(item, restrictinfo_list)
377 RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
378 RestrictInfo *prevrinfo;
380 /* is it redundant with any prior clause? */
381 prevrinfo = join_clause_is_redundant(root, rinfo, result, isouterjoin);
382 if (prevrinfo == NULL)
384 /* no, so add it to result list */
385 result = lappend(result, rinfo);
387 else if (CLAUSECOST(rinfo) < CLAUSECOST(prevrinfo))
389 /* keep this one, drop the previous one */
390 result = list_delete_ptr(result, prevrinfo);
391 result = lappend(result, rinfo);
393 /* else, drop this one */
400 * select_nonredundant_join_clauses
402 * Given a list of RestrictInfo clauses that are to be applied in a join,
403 * select the ones that are not redundant with any clause in the
406 * This is similar to remove_redundant_join_clauses, but we are looking for
407 * redundancies with a separate list of clauses (i.e., clauses that have
408 * already been applied below the join itself).
410 * Note that we assume the given restrictinfo_list has already been checked
411 * for local redundancies, so we don't check again.
414 select_nonredundant_join_clauses(PlannerInfo *root,
415 List *restrictinfo_list,
416 List *reference_list,
422 foreach(item, restrictinfo_list)
424 RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
426 /* drop it if redundant with any reference clause */
427 if (join_clause_is_redundant(root, rinfo, reference_list, isouterjoin) != NULL)
430 /* otherwise, add it to result list */
431 result = lappend(result, rinfo);
438 * join_clause_is_redundant
439 * If rinfo is redundant with any clause in reference_list,
440 * return one such clause; otherwise return NULL.
442 * This is the guts of both remove_redundant_join_clauses and
443 * select_nonredundant_join_clauses. See the docs above for motivation.
445 * We can detect redundant mergejoinable clauses very cheaply by using their
446 * left and right pathkeys, which uniquely identify the sets of equijoined
447 * variables in question. All the members of a pathkey set that are in the
448 * left relation have already been forced to be equal; likewise for those in
449 * the right relation. So, we need to have only one clause that checks
450 * equality between any set member on the left and any member on the right;
451 * by transitivity, all the rest are then equal.
453 * However, clauses that are of the form "var expr = const expr" cannot be
454 * eliminated as redundant. This is because when there are const expressions
455 * in a pathkey set, generate_implied_equalities() suppresses "var = var"
456 * clauses in favor of "var = const" clauses. We cannot afford to drop any
457 * of the latter, even though they might seem redundant by the pathkey
460 * Weird special case: if we have two clauses that seem redundant
461 * except one is pushed down into an outer join and the other isn't,
462 * then they're not really redundant, because one constrains the
463 * joined rows after addition of null fill rows, and the other doesn't.
465 static RestrictInfo *
466 join_clause_is_redundant(PlannerInfo *root,
468 List *reference_list,
473 /* always consider exact duplicates redundant */
474 foreach(refitem, reference_list)
476 RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);
478 if (equal(rinfo, refrinfo))
482 /* check for redundant merge clauses */
483 if (rinfo->mergejoinoperator != InvalidOid)
485 /* do the cheap test first: is it a "var = const" clause? */
486 if (bms_is_empty(rinfo->left_relids) ||
487 bms_is_empty(rinfo->right_relids))
488 return NULL; /* var = const, so not redundant */
490 cache_mergeclause_pathkeys(root, rinfo);
492 foreach(refitem, reference_list)
494 RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);
496 if (refrinfo->mergejoinoperator != InvalidOid)
498 cache_mergeclause_pathkeys(root, refrinfo);
500 if (rinfo->left_pathkey == refrinfo->left_pathkey &&
501 rinfo->right_pathkey == refrinfo->right_pathkey &&
502 (rinfo->is_pushed_down == refrinfo->is_pushed_down ||
505 /* Yup, it's redundant */
512 /* otherwise, not redundant */