#include "postgres.h"
#include "optimizer/cost.h"
#include "optimizer/paths.h"
#include "optimizer/restrictinfo.h"
Go to the source code of this file.
Functions | |
bool | create_or_index_quals (PlannerInfo *root, RelOptInfo *rel) |
bool create_or_index_quals | ( | PlannerInfo * | root, | |
RelOptInfo * | rel | |||
) |
Definition at line 81 of file orindxpath.c.
References Assert, RelOptInfo::baserestrictinfo, clause_selectivity(), generate_bitmap_or_paths(), i, RelOptInfo::indexlist, IsA, join_clause_is_movable_to(), JOIN_INNER, RelOptInfo::joininfo, lfirst, linitial, list_concat(), list_length(), list_make1, make_restrictinfo_from_bitmapqual(), NIL, NULL, BitmapOrPath::path, RelOptInfo::relid, restriction_is_or_clause(), and Path::total_cost.
Referenced by set_plain_rel_size().
{ BitmapOrPath *bestpath = NULL; RestrictInfo *bestrinfo = NULL; List *newrinfos; RestrictInfo *or_rinfo; Selectivity or_selec, orig_selec; ListCell *i; /* Skip the whole mess if no indexes */ if (rel->indexlist == NIL) return false; /* * Find potentially interesting OR joinclauses. We can use any joinclause * that is considered safe to move to this rel by the parameterized-path * machinery, even though what we are going to do with it is not exactly a * parameterized path. */ foreach(i, rel->joininfo) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(i); if (restriction_is_or_clause(rinfo) && join_clause_is_movable_to(rinfo, rel->relid)) { /* * Use the generate_bitmap_or_paths() machinery to estimate the * value of each OR clause. We can use regular restriction * clauses along with the OR clause contents to generate * indexquals. We pass restriction_only = true so that any * sub-clauses that are actually joins will be ignored. */ List *orpaths; ListCell *k; orpaths = generate_bitmap_or_paths(root, rel, list_make1(rinfo), rel->baserestrictinfo, true); /* Locate the cheapest OR path */ foreach(k, orpaths) { BitmapOrPath *path = (BitmapOrPath *) lfirst(k); Assert(IsA(path, BitmapOrPath)); if (bestpath == NULL || path->path.total_cost < bestpath->path.total_cost) { bestpath = path; bestrinfo = rinfo; } } } } /* Fail if no suitable clauses found */ if (bestpath == NULL) return false; /* * Convert the path's indexclauses structure to a RestrictInfo tree. We * include any partial-index predicates so as to get a reasonable * representation of what the path is actually scanning. */ newrinfos = make_restrictinfo_from_bitmapqual((Path *) bestpath, true, true); /* It's possible we get back something other than a single OR clause */ if (list_length(newrinfos) != 1) return false; or_rinfo = (RestrictInfo *) linitial(newrinfos); Assert(IsA(or_rinfo, RestrictInfo)); if (!restriction_is_or_clause(or_rinfo)) return false; /* * OK, add it to the rel's restriction list. */ rel->baserestrictinfo = list_concat(rel->baserestrictinfo, newrinfos); /* * Adjust the original OR clause's cached selectivity to compensate for * the selectivity of the added (but redundant) lower-level qual. This * should result in the join rel getting approximately the same rows * estimate as it would have gotten without all these shenanigans. (XXX * major hack alert ... this depends on the assumption that the * selectivity will stay cached ...) */ or_selec = clause_selectivity(root, (Node *) or_rinfo, 0, JOIN_INNER, NULL); if (or_selec > 0 && or_selec < 1) { orig_selec = clause_selectivity(root, (Node *) bestrinfo, 0, JOIN_INNER, NULL); bestrinfo->norm_selec = orig_selec / or_selec; /* clamp result to sane range */ if (bestrinfo->norm_selec > 1) bestrinfo->norm_selec = 1; /* It isn't an outer join clause, so no need to adjust outer_selec */ } /* Tell caller to recompute partial index status and rowcount estimate */ return true; }