PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
clausesel.c File Reference
#include "postgres.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/plancat.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/selfuncs.h"
#include "statistics/statistics.h"
Include dependency graph for clausesel.c:

Go to the source code of this file.

Data Structures

struct  RangeQueryClause
 

Typedefs

typedef struct RangeQueryClause RangeQueryClause
 

Functions

static void addRangeClause (RangeQueryClause **rqlist, Node *clause, bool varonleft, bool isLTsel, Selectivity s2)
 
static RelOptInfofind_single_rel_for_clauses (PlannerInfo *root, List *clauses)
 
Selectivity clauselist_selectivity (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
static bool bms_is_subset_singleton (const Bitmapset *s, int x)
 
static bool treat_as_join_clause (Node *clause, RestrictInfo *rinfo, int varRelid, SpecialJoinInfo *sjinfo)
 
Selectivity clause_selectivity (PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 

Typedef Documentation

Function Documentation

static void addRangeClause ( RangeQueryClause **  rqlist,
Node clause,
bool  varonleft,
bool  isLTsel,
Selectivity  s2 
)
static

Definition at line 332 of file clausesel.c.

References equal(), get_leftop(), get_rightop(), RangeQueryClause::have_hibound, RangeQueryClause::have_lobound, RangeQueryClause::hibound, RangeQueryClause::lobound, RangeQueryClause::next, palloc(), s2, and RangeQueryClause::var.

Referenced by clauselist_selectivity().

334 {
335  RangeQueryClause *rqelem;
336  Node *var;
337  bool is_lobound;
338 
339  if (varonleft)
340  {
341  var = get_leftop((Expr *) clause);
342  is_lobound = !isLTsel; /* x < something is high bound */
343  }
344  else
345  {
346  var = get_rightop((Expr *) clause);
347  is_lobound = isLTsel; /* something < x is low bound */
348  }
349 
350  for (rqelem = *rqlist; rqelem; rqelem = rqelem->next)
351  {
352  /*
353  * We use full equal() here because the "var" might be a function of
354  * one or more attributes of the same relation...
355  */
356  if (!equal(var, rqelem->var))
357  continue;
358  /* Found the right group to put this clause in */
359  if (is_lobound)
360  {
361  if (!rqelem->have_lobound)
362  {
363  rqelem->have_lobound = true;
364  rqelem->lobound = s2;
365  }
366  else
367  {
368 
369  /*------
370  * We have found two similar clauses, such as
371  * x < y AND x < z.
372  * Keep only the more restrictive one.
373  *------
374  */
375  if (rqelem->lobound > s2)
376  rqelem->lobound = s2;
377  }
378  }
379  else
380  {
381  if (!rqelem->have_hibound)
382  {
383  rqelem->have_hibound = true;
384  rqelem->hibound = s2;
385  }
386  else
387  {
388 
389  /*------
390  * We have found two similar clauses, such as
391  * x > y AND x > z.
392  * Keep only the more restrictive one.
393  *------
394  */
395  if (rqelem->hibound > s2)
396  rqelem->hibound = s2;
397  }
398  }
399  return;
400  }
401 
402  /* No matching var found, so make a new clause-pair data structure */
403  rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause));
404  rqelem->var = var;
405  if (is_lobound)
406  {
407  rqelem->have_lobound = true;
408  rqelem->have_hibound = false;
409  rqelem->lobound = s2;
410  }
411  else
412  {
413  rqelem->have_lobound = false;
414  rqelem->have_hibound = true;
415  rqelem->hibound = s2;
416  }
417  rqelem->next = *rqlist;
418  *rqlist = rqelem;
419 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2962
Definition: nodes.h:509
Node * get_leftop(const Expr *clause)
Definition: clauses.c:199
struct RangeQueryClause * next
Definition: clausesel.c:34
Selectivity hibound
Definition: clausesel.c:39
Selectivity lobound
Definition: clausesel.c:38
char * s2
Node * get_rightop(const Expr *clause)
Definition: clauses.c:216
void * palloc(Size size)
Definition: mcxt.c:849
static bool bms_is_subset_singleton ( const Bitmapset s,
int  x 
)
static

Definition at line 473 of file clausesel.c.

References BMS_EMPTY_SET, bms_is_member(), bms_membership(), BMS_MULTIPLE, and BMS_SINGLETON.

Referenced by clause_selectivity().

474 {
475  switch (bms_membership(s))
476  {
477  case BMS_EMPTY_SET:
478  return true;
479  case BMS_SINGLETON:
480  return bms_is_member(x, s);
481  case BMS_MULTIPLE:
482  return false;
483  }
484  /* can't get here... */
485  return false;
486 }
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:634
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
Selectivity clause_selectivity ( PlannerInfo root,
Node clause,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo 
)

Definition at line 572 of file clausesel.c.

References and_clause(), arg, generate_unaccent_rules::args, OpExpr::args, bms_is_subset_singleton(), booltestsel(), boolvarsel(), RestrictInfo::clause, RestrictInfo::clause_relids, clause_selectivity(), clauselist_selectivity(), Const::constisnull, Const::constvalue, CurrentOfExpr::cvarno, DatumGetBool, DEBUG4, elog, estimate_expression_value(), find_base_rel(), get_notclausearg(), OpExpr::inputcollid, is_opclause, IsA, JOIN_INNER, join_selectivity(), lfirst, RestrictInfo::norm_selec, not_clause(), NULL, nulltestsel(), OpExpr::opno, or_clause(), RestrictInfo::orclause, RestrictInfo::outer_selec, RestrictInfo::pseudoconstant, restriction_selectivity(), rowcomparesel(), s1, s2, scalararraysel(), treat_as_join_clause(), RelOptInfo::tuples, RangeQueryClause::var, Var::varlevelsup, and Var::varno.

Referenced by approx_tuple_count(), booltestsel(), clause_selectivity(), clauselist_selectivity(), consider_new_or_clause(), and dependencies_clauselist_selectivity().

577 {
578  Selectivity s1 = 0.5; /* default for any unhandled clause type */
579  RestrictInfo *rinfo = NULL;
580  bool cacheable = false;
581 
582  if (clause == NULL) /* can this still happen? */
583  return s1;
584 
585  if (IsA(clause, RestrictInfo))
586  {
587  rinfo = (RestrictInfo *) clause;
588 
589  /*
590  * If the clause is marked pseudoconstant, then it will be used as a
591  * gating qual and should not affect selectivity estimates; hence
592  * return 1.0. The only exception is that a constant FALSE may be
593  * taken as having selectivity 0.0, since it will surely mean no rows
594  * out of the plan. This case is simple enough that we need not
595  * bother caching the result.
596  */
597  if (rinfo->pseudoconstant)
598  {
599  if (!IsA(rinfo->clause, Const))
600  return (Selectivity) 1.0;
601  }
602 
603  /*
604  * If the clause is marked redundant, always return 1.0.
605  */
606  if (rinfo->norm_selec > 1)
607  return (Selectivity) 1.0;
608 
609  /*
610  * If possible, cache the result of the selectivity calculation for
611  * the clause. We can cache if varRelid is zero or the clause
612  * contains only vars of that relid --- otherwise varRelid will affect
613  * the result, so mustn't cache. Outer join quals might be examined
614  * with either their join's actual jointype or JOIN_INNER, so we need
615  * two cache variables to remember both cases. Note: we assume the
616  * result won't change if we are switching the input relations or
617  * considering a unique-ified case, so we only need one cache variable
618  * for all non-JOIN_INNER cases.
619  */
620  if (varRelid == 0 ||
621  bms_is_subset_singleton(rinfo->clause_relids, varRelid))
622  {
623  /* Cacheable --- do we already have the result? */
624  if (jointype == JOIN_INNER)
625  {
626  if (rinfo->norm_selec >= 0)
627  return rinfo->norm_selec;
628  }
629  else
630  {
631  if (rinfo->outer_selec >= 0)
632  return rinfo->outer_selec;
633  }
634  cacheable = true;
635  }
636 
637  /*
638  * Proceed with examination of contained clause. If the clause is an
639  * OR-clause, we want to look at the variant with sub-RestrictInfos,
640  * so that per-subclause selectivities can be cached.
641  */
642  if (rinfo->orclause)
643  clause = (Node *) rinfo->orclause;
644  else
645  clause = (Node *) rinfo->clause;
646  }
647 
648  if (IsA(clause, Var))
649  {
650  Var *var = (Var *) clause;
651 
652  /*
653  * We probably shouldn't ever see an uplevel Var here, but if we do,
654  * return the default selectivity...
655  */
656  if (var->varlevelsup == 0 &&
657  (varRelid == 0 || varRelid == (int) var->varno))
658  {
659  /* Use the restriction selectivity function for a bool Var */
660  s1 = boolvarsel(root, (Node *) var, varRelid);
661  }
662  }
663  else if (IsA(clause, Const))
664  {
665  /* bool constant is pretty easy... */
666  Const *con = (Const *) clause;
667 
668  s1 = con->constisnull ? 0.0 :
669  DatumGetBool(con->constvalue) ? 1.0 : 0.0;
670  }
671  else if (IsA(clause, Param))
672  {
673  /* see if we can replace the Param */
674  Node *subst = estimate_expression_value(root, clause);
675 
676  if (IsA(subst, Const))
677  {
678  /* bool constant is pretty easy... */
679  Const *con = (Const *) subst;
680 
681  s1 = con->constisnull ? 0.0 :
682  DatumGetBool(con->constvalue) ? 1.0 : 0.0;
683  }
684  else
685  {
686  /* XXX any way to do better than default? */
687  }
688  }
689  else if (not_clause(clause))
690  {
691  /* inverse of the selectivity of the underlying clause */
692  s1 = 1.0 - clause_selectivity(root,
693  (Node *) get_notclausearg((Expr *) clause),
694  varRelid,
695  jointype,
696  sjinfo);
697  }
698  else if (and_clause(clause))
699  {
700  /* share code with clauselist_selectivity() */
701  s1 = clauselist_selectivity(root,
702  ((BoolExpr *) clause)->args,
703  varRelid,
704  jointype,
705  sjinfo);
706  }
707  else if (or_clause(clause))
708  {
709  /*
710  * Selectivities for an OR clause are computed as s1+s2 - s1*s2 to
711  * account for the probable overlap of selected tuple sets.
712  *
713  * XXX is this too conservative?
714  */
715  ListCell *arg;
716 
717  s1 = 0.0;
718  foreach(arg, ((BoolExpr *) clause)->args)
719  {
721  (Node *) lfirst(arg),
722  varRelid,
723  jointype,
724  sjinfo);
725 
726  s1 = s1 + s2 - s1 * s2;
727  }
728  }
729  else if (is_opclause(clause) || IsA(clause, DistinctExpr))
730  {
731  OpExpr *opclause = (OpExpr *) clause;
732  Oid opno = opclause->opno;
733 
734  if (treat_as_join_clause(clause, rinfo, varRelid, sjinfo))
735  {
736  /* Estimate selectivity for a join clause. */
737  s1 = join_selectivity(root, opno,
738  opclause->args,
739  opclause->inputcollid,
740  jointype,
741  sjinfo);
742  }
743  else
744  {
745  /* Estimate selectivity for a restriction clause. */
746  s1 = restriction_selectivity(root, opno,
747  opclause->args,
748  opclause->inputcollid,
749  varRelid);
750  }
751 
752  /*
753  * DistinctExpr has the same representation as OpExpr, but the
754  * contained operator is "=" not "<>", so we must negate the result.
755  * This estimation method doesn't give the right behavior for nulls,
756  * but it's better than doing nothing.
757  */
758  if (IsA(clause, DistinctExpr))
759  s1 = 1.0 - s1;
760  }
761  else if (IsA(clause, ScalarArrayOpExpr))
762  {
763  /* Use node specific selectivity calculation function */
764  s1 = scalararraysel(root,
765  (ScalarArrayOpExpr *) clause,
766  treat_as_join_clause(clause, rinfo,
767  varRelid, sjinfo),
768  varRelid,
769  jointype,
770  sjinfo);
771  }
772  else if (IsA(clause, RowCompareExpr))
773  {
774  /* Use node specific selectivity calculation function */
775  s1 = rowcomparesel(root,
776  (RowCompareExpr *) clause,
777  varRelid,
778  jointype,
779  sjinfo);
780  }
781  else if (IsA(clause, NullTest))
782  {
783  /* Use node specific selectivity calculation function */
784  s1 = nulltestsel(root,
785  ((NullTest *) clause)->nulltesttype,
786  (Node *) ((NullTest *) clause)->arg,
787  varRelid,
788  jointype,
789  sjinfo);
790  }
791  else if (IsA(clause, BooleanTest))
792  {
793  /* Use node specific selectivity calculation function */
794  s1 = booltestsel(root,
795  ((BooleanTest *) clause)->booltesttype,
796  (Node *) ((BooleanTest *) clause)->arg,
797  varRelid,
798  jointype,
799  sjinfo);
800  }
801  else if (IsA(clause, CurrentOfExpr))
802  {
803  /* CURRENT OF selects at most one row of its table */
804  CurrentOfExpr *cexpr = (CurrentOfExpr *) clause;
805  RelOptInfo *crel = find_base_rel(root, cexpr->cvarno);
806 
807  if (crel->tuples > 0)
808  s1 = 1.0 / crel->tuples;
809  }
810  else if (IsA(clause, RelabelType))
811  {
812  /* Not sure this case is needed, but it can't hurt */
813  s1 = clause_selectivity(root,
814  (Node *) ((RelabelType *) clause)->arg,
815  varRelid,
816  jointype,
817  sjinfo);
818  }
819  else if (IsA(clause, CoerceToDomain))
820  {
821  /* Not sure this case is needed, but it can't hurt */
822  s1 = clause_selectivity(root,
823  (Node *) ((CoerceToDomain *) clause)->arg,
824  varRelid,
825  jointype,
826  sjinfo);
827  }
828  else
829  {
830  /*
831  * For anything else, see if we can consider it as a boolean variable.
832  * This only works if it's an immutable expression in Vars of a single
833  * relation; but there's no point in us checking that here because
834  * boolvarsel() will do it internally, and return a suitable default
835  * selectivity if not.
836  */
837  s1 = boolvarsel(root, clause, varRelid);
838  }
839 
840  /* Cache the result if possible */
841  if (cacheable)
842  {
843  if (jointype == JOIN_INNER)
844  rinfo->norm_selec = s1;
845  else
846  rinfo->outer_selec = s1;
847  }
848 
849 #ifdef SELECTIVITY_DEBUG
850  elog(DEBUG4, "clause_selectivity: s1 %f", s1);
851 #endif /* SELECTIVITY_DEBUG */
852 
853  return s1;
854 }
Datum constvalue
Definition: primnodes.h:196
Expr * get_notclausearg(Expr *notclause)
Definition: clauses.c:265
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Index varlevelsup
Definition: primnodes.h:173
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2433
Expr * orclause
Definition: relation.h:1778
Selectivity restriction_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, int varRelid)
Definition: plancat.c:1652
double tuples
Definition: relation.h:565
Selectivity rowcomparesel(PlannerInfo *root, RowCompareExpr *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:2132
Relids clause_relids
Definition: relation.h:1762
bool pseudoconstant
Definition: relation.h:1755
Definition: nodes.h:509
double Selectivity
Definition: nodes.h:639
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:163
#define DEBUG4
Definition: elog.h:22
Selectivity scalararraysel(PlannerInfo *root, ScalarArrayOpExpr *clause, bool is_join_clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1775
Selectivity norm_selec
Definition: relation.h:1785
static bool treat_as_join_clause(Node *clause, RestrictInfo *rinfo, int varRelid, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:494
static bool bms_is_subset_singleton(const Bitmapset *s, int x)
Definition: clausesel.c:473
char * s1
#define is_opclause(clause)
Definition: clauses.h:20
Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1675
bool and_clause(Node *clause)
Definition: clauses.c:314
Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:572
#define DatumGetBool(X)
Definition: postgres.h:399
Selectivity outer_selec
Definition: relation.h:1788
bool not_clause(Node *clause)
Definition: clauses.c:236
Expr * clause
Definition: relation.h:1747
Index varno
Definition: primnodes.h:166
char * s2
bool or_clause(Node *clause)
Definition: clauses.c:280
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Oid inputcollid
Definition: primnodes.h:501
void * arg
Selectivity join_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: plancat.c:1689
Oid opno
Definition: primnodes.h:496
#define elog
Definition: elog.h:219
Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:99
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:243
List * args
Definition: primnodes.h:502
Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1517
Selectivity boolvarsel(PlannerInfo *root, Node *arg, int varRelid)
Definition: selfuncs.c:1478
bool constisnull
Definition: primnodes.h:197
Selectivity clauselist_selectivity ( PlannerInfo root,
List clauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo 
)

Definition at line 99 of file clausesel.c.

References addRangeClause(), generate_unaccent_rules::args, OpExpr::args, bms_is_member(), bms_membership(), BMS_SINGLETON, RestrictInfo::clause, RestrictInfo::clause_relids, clause_selectivity(), DEFAULT_INEQ_SEL, DEFAULT_RANGE_INEQ_SEL, dependencies_clauselist_selectivity(), find_single_rel_for_clauses(), get_oprrest(), RangeQueryClause::have_hibound, RangeQueryClause::have_lobound, RangeQueryClause::hibound, IS_NULL, is_opclause, is_pseudo_constant_clause(), is_pseudo_constant_clause_relids(), IsA, RestrictInfo::left_relids, lfirst, linitial, list_length(), RangeQueryClause::lobound, lsecond, RangeQueryClause::next, NIL, NULL, nulltestsel(), NumRelids(), OpExpr::opno, pfree(), RestrictInfo::pseudoconstant, RestrictInfo::right_relids, RTE_RELATION, RelOptInfo::rtekind, s1, s2, RelOptInfo::statlist, and RangeQueryClause::var.

Referenced by brincostestimate(), btcostestimate(), calc_joinrel_size_estimate(), clause_selectivity(), compute_semi_anti_join_factors(), estimate_path_cost_size(), estimate_size(), genericcostestimate(), get_parameterized_baserel_size(), gincostestimate(), postgresGetForeignJoinPaths(), postgresGetForeignRelSize(), and set_baserel_size_estimates().

104 {
105  Selectivity s1 = 1.0;
106  RelOptInfo *rel;
107  Bitmapset *estimatedclauses = NULL;
108  RangeQueryClause *rqlist = NULL;
109  ListCell *l;
110  int listidx;
111 
112  /*
113  * If there's exactly one clause, just go directly to
114  * clause_selectivity(). None of what we might do below is relevant.
115  */
116  if (list_length(clauses) == 1)
117  return clause_selectivity(root, (Node *) linitial(clauses),
118  varRelid, jointype, sjinfo);
119 
120  /*
121  * Determine if these clauses reference a single relation. If so, and if
122  * it has extended statistics, try to apply those.
123  */
124  rel = find_single_rel_for_clauses(root, clauses);
125  if (rel && rel->rtekind == RTE_RELATION && rel->statlist != NIL)
126  {
127  /*
128  * Perform selectivity estimations on any clauses found applicable by
129  * dependencies_clauselist_selectivity. 'estimatedclauses' will be
130  * filled with the 0-based list positions of clauses used that way, so
131  * that we can ignore them below.
132  */
133  s1 *= dependencies_clauselist_selectivity(root, clauses, varRelid,
134  jointype, sjinfo, rel,
135  &estimatedclauses);
136 
137  /*
138  * This would be the place to apply any other types of extended
139  * statistics selectivity estimations for remaining clauses.
140  */
141  }
142 
143  /*
144  * Apply normal selectivity estimates for remaining clauses. We'll be
145  * careful to skip any clauses which were already estimated above.
146  *
147  * Anything that doesn't look like a potential rangequery clause gets
148  * multiplied into s1 and forgotten. Anything that does gets inserted into
149  * an rqlist entry.
150  */
151  listidx = -1;
152  foreach(l, clauses)
153  {
154  Node *clause = (Node *) lfirst(l);
155  RestrictInfo *rinfo;
156  Selectivity s2;
157 
158  listidx++;
159 
160  /*
161  * Skip this clause if it's already been estimated by some other
162  * statistics above.
163  */
164  if (bms_is_member(listidx, estimatedclauses))
165  continue;
166 
167  /* Always compute the selectivity using clause_selectivity */
168  s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo);
169 
170  /*
171  * Check for being passed a RestrictInfo.
172  *
173  * If it's a pseudoconstant RestrictInfo, then s2 is either 1.0 or
174  * 0.0; just use that rather than looking for range pairs.
175  */
176  if (IsA(clause, RestrictInfo))
177  {
178  rinfo = (RestrictInfo *) clause;
179  if (rinfo->pseudoconstant)
180  {
181  s1 = s1 * s2;
182  continue;
183  }
184  clause = (Node *) rinfo->clause;
185  }
186  else
187  rinfo = NULL;
188 
189  /*
190  * See if it looks like a restriction clause with a pseudoconstant on
191  * one side. (Anything more complicated than that might not behave in
192  * the simple way we are expecting.) Most of the tests here can be
193  * done more efficiently with rinfo than without.
194  */
195  if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
196  {
197  OpExpr *expr = (OpExpr *) clause;
198  bool varonleft = true;
199  bool ok;
200 
201  if (rinfo)
202  {
203  ok = (bms_membership(rinfo->clause_relids) == BMS_SINGLETON) &&
205  rinfo->right_relids) ||
206  (varonleft = false,
208  rinfo->left_relids)));
209  }
210  else
211  {
212  ok = (NumRelids(clause) == 1) &&
214  (varonleft = false,
216  }
217 
218  if (ok)
219  {
220  /*
221  * If it's not a "<" or ">" operator, just merge the
222  * selectivity in generically. But if it's the right oprrest,
223  * add the clause to rqlist for later processing.
224  */
225  switch (get_oprrest(expr->opno))
226  {
227  case F_SCALARLTSEL:
228  addRangeClause(&rqlist, clause,
229  varonleft, true, s2);
230  break;
231  case F_SCALARGTSEL:
232  addRangeClause(&rqlist, clause,
233  varonleft, false, s2);
234  break;
235  default:
236  /* Just merge the selectivity in generically */
237  s1 = s1 * s2;
238  break;
239  }
240  continue; /* drop to loop bottom */
241  }
242  }
243 
244  /* Not the right form, so treat it generically. */
245  s1 = s1 * s2;
246  }
247 
248  /*
249  * Now scan the rangequery pair list.
250  */
251  while (rqlist != NULL)
252  {
253  RangeQueryClause *rqnext;
254 
255  if (rqlist->have_lobound && rqlist->have_hibound)
256  {
257  /* Successfully matched a pair of range clauses */
258  Selectivity s2;
259 
260  /*
261  * Exact equality to the default value probably means the
262  * selectivity function punted. This is not airtight but should
263  * be good enough.
264  */
265  if (rqlist->hibound == DEFAULT_INEQ_SEL ||
266  rqlist->lobound == DEFAULT_INEQ_SEL)
267  {
269  }
270  else
271  {
272  s2 = rqlist->hibound + rqlist->lobound - 1.0;
273 
274  /* Adjust for double-exclusion of NULLs */
275  s2 += nulltestsel(root, IS_NULL, rqlist->var,
276  varRelid, jointype, sjinfo);
277 
278  /*
279  * A zero or slightly negative s2 should be converted into a
280  * small positive value; we probably are dealing with a very
281  * tight range and got a bogus result due to roundoff errors.
282  * However, if s2 is very negative, then we probably have
283  * default selectivity estimates on one or both sides of the
284  * range that we failed to recognize above for some reason.
285  */
286  if (s2 <= 0.0)
287  {
288  if (s2 < -0.01)
289  {
290  /*
291  * No data available --- use a default estimate that
292  * is small, but not real small.
293  */
295  }
296  else
297  {
298  /*
299  * It's just roundoff error; use a small positive
300  * value
301  */
302  s2 = 1.0e-10;
303  }
304  }
305  }
306  /* Merge in the selectivity of the pair of clauses */
307  s1 *= s2;
308  }
309  else
310  {
311  /* Only found one of a pair, merge it in generically */
312  if (rqlist->have_lobound)
313  s1 *= rqlist->lobound;
314  else
315  s1 *= rqlist->hibound;
316  }
317  /* release storage and advance */
318  rqnext = rqlist->next;
319  pfree(rqlist);
320  rqlist = rqnext;
321  }
322 
323  return s1;
324 }
#define NIL
Definition: pg_list.h:69
Selectivity dependencies_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
Definition: dependencies.c:919
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
List * statlist
Definition: relation.h:563
bool is_pseudo_constant_clause_relids(Node *clause, Relids relids)
Definition: clauses.c:2195
#define DEFAULT_INEQ_SEL
Definition: selfuncs.h:37
Relids clause_relids
Definition: relation.h:1762
bool pseudoconstant
Definition: relation.h:1755
Definition: nodes.h:509
Relids left_relids
Definition: relation.h:1774
double Selectivity
Definition: nodes.h:639
#define lsecond(l)
Definition: pg_list.h:116
void pfree(void *pointer)
Definition: mcxt.c:950
#define linitial(l)
Definition: pg_list.h:111
char * s1
#define is_opclause(clause)
Definition: clauses.h:20
Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1675
Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:572
bool is_pseudo_constant_clause(Node *clause)
Definition: clauses.c:2175
struct RangeQueryClause * next
Definition: clausesel.c:34
static void addRangeClause(RangeQueryClause **rqlist, Node *clause, bool varonleft, bool isLTsel, Selectivity s2)
Definition: clausesel.c:332
Selectivity hibound
Definition: clausesel.c:39
Expr * clause
Definition: relation.h:1747
Selectivity lobound
Definition: clausesel.c:38
RegProcedure get_oprrest(Oid opno)
Definition: lsyscache.c:1361
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:634
char * s2
RTEKind rtekind
Definition: relation.h:555
static RelOptInfo * find_single_rel_for_clauses(PlannerInfo *root, List *clauses)
Definition: clausesel.c:428
Relids right_relids
Definition: relation.h:1775
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
#define DEFAULT_RANGE_INEQ_SEL
Definition: selfuncs.h:40
Oid opno
Definition: primnodes.h:496
List * args
Definition: primnodes.h:502
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
int NumRelids(Node *clause)
Definition: clauses.c:2217
static RelOptInfo * find_single_rel_for_clauses ( PlannerInfo root,
List clauses 
)
static

Definition at line 428 of file clausesel.c.

References bms_get_singleton_member(), bms_is_empty(), RestrictInfo::clause_relids, find_base_rel(), IsA, lfirst, and NULL.

Referenced by clauselist_selectivity().

429 {
430  int lastrelid = 0;
431  ListCell *l;
432 
433  foreach(l, clauses)
434  {
435  RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
436  int relid;
437 
438  /*
439  * If we have a list of bare clauses rather than RestrictInfos, we
440  * could pull out their relids the hard way with pull_varnos().
441  * However, currently the extended-stats machinery won't do anything
442  * with non-RestrictInfo clauses anyway, so there's no point in
443  * spending extra cycles; just fail if that's what we have.
444  */
445  if (!IsA(rinfo, RestrictInfo))
446  return NULL;
447 
448  if (bms_is_empty(rinfo->clause_relids))
449  continue; /* we can ignore variable-free clauses */
450  if (!bms_get_singleton_member(rinfo->clause_relids, &relid))
451  return NULL; /* multiple relations in this clause */
452  if (lastrelid == 0)
453  lastrelid = relid; /* first clause referencing a relation */
454  else if (relid != lastrelid)
455  return NULL; /* relation not same as last one */
456  }
457 
458  if (lastrelid != 0)
459  return find_base_rel(root, lastrelid);
460 
461  return NULL; /* no clauses */
462 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Relids clause_relids
Definition: relation.h:1762
bool bms_get_singleton_member(const Bitmapset *a, int *member)
Definition: bitmapset.c:569
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:243
static bool treat_as_join_clause ( Node clause,
RestrictInfo rinfo,
int  varRelid,
SpecialJoinInfo sjinfo 
)
inlinestatic

Definition at line 494 of file clausesel.c.

References bms_membership(), BMS_MULTIPLE, RestrictInfo::clause_relids, NULL, and NumRelids().

Referenced by clause_selectivity().

496 {
497  if (varRelid != 0)
498  {
499  /*
500  * Caller is forcing restriction mode (eg, because we are examining an
501  * inner indexscan qual).
502  */
503  return false;
504  }
505  else if (sjinfo == NULL)
506  {
507  /*
508  * It must be a restriction clause, since it's being evaluated at a
509  * scan node.
510  */
511  return false;
512  }
513  else
514  {
515  /*
516  * Otherwise, it's a join if there's more than one relation used. We
517  * can optimize this calculation if an rinfo was passed.
518  *
519  * XXX Since we know the clause is being evaluated at a join, the
520  * only way it could be single-relation is if it was delayed by outer
521  * joins. Although we can make use of the restriction qual estimators
522  * anyway, it seems likely that we ought to account for the
523  * probability of injected nulls somehow.
524  */
525  if (rinfo)
526  return (bms_membership(rinfo->clause_relids) == BMS_MULTIPLE);
527  else
528  return (NumRelids(clause) > 1);
529  }
530 }
Relids clause_relids
Definition: relation.h:1762
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:634
#define NULL
Definition: c.h:229
int NumRelids(Node *clause)
Definition: clauses.c:2217