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 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)
 
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 286 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().

288 {
289  RangeQueryClause *rqelem;
290  Node *var;
291  bool is_lobound;
292 
293  if (varonleft)
294  {
295  var = get_leftop((Expr *) clause);
296  is_lobound = !isLTsel; /* x < something is high bound */
297  }
298  else
299  {
300  var = get_rightop((Expr *) clause);
301  is_lobound = isLTsel; /* something < x is low bound */
302  }
303 
304  for (rqelem = *rqlist; rqelem; rqelem = rqelem->next)
305  {
306  /*
307  * We use full equal() here because the "var" might be a function of
308  * one or more attributes of the same relation...
309  */
310  if (!equal(var, rqelem->var))
311  continue;
312  /* Found the right group to put this clause in */
313  if (is_lobound)
314  {
315  if (!rqelem->have_lobound)
316  {
317  rqelem->have_lobound = true;
318  rqelem->lobound = s2;
319  }
320  else
321  {
322 
323  /*------
324  * We have found two similar clauses, such as
325  * x < y AND x < z.
326  * Keep only the more restrictive one.
327  *------
328  */
329  if (rqelem->lobound > s2)
330  rqelem->lobound = s2;
331  }
332  }
333  else
334  {
335  if (!rqelem->have_hibound)
336  {
337  rqelem->have_hibound = true;
338  rqelem->hibound = s2;
339  }
340  else
341  {
342 
343  /*------
344  * We have found two similar clauses, such as
345  * x > y AND x > z.
346  * Keep only the more restrictive one.
347  *------
348  */
349  if (rqelem->hibound > s2)
350  rqelem->hibound = s2;
351  }
352  }
353  return;
354  }
355 
356  /* No matching var found, so make a new clause-pair data structure */
357  rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause));
358  rqelem->var = var;
359  if (is_lobound)
360  {
361  rqelem->have_lobound = true;
362  rqelem->have_hibound = false;
363  rqelem->lobound = s2;
364  }
365  else
366  {
367  rqelem->have_lobound = false;
368  rqelem->have_hibound = true;
369  rqelem->hibound = s2;
370  }
371  rqelem->next = *rqlist;
372  *rqlist = rqelem;
373 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2946
Definition: nodes.h:522
Node * get_leftop(const Expr *clause)
Definition: clauses.c:198
struct RangeQueryClause * next
Definition: clausesel.c:33
Selectivity hibound
Definition: clausesel.c:38
Selectivity lobound
Definition: clausesel.c:37
char * s2
Node * get_rightop(const Expr *clause)
Definition: clauses.c:215
void * palloc(Size size)
Definition: mcxt.c:849
static bool bms_is_subset_singleton ( const Bitmapset s,
int  x 
)
static

Definition at line 384 of file clausesel.c.

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

Referenced by clause_selectivity().

385 {
386  switch (bms_membership(s))
387  {
388  case BMS_EMPTY_SET:
389  return true;
390  case BMS_SINGLETON:
391  return bms_is_member(x, s);
392  case BMS_MULTIPLE:
393  return false;
394  }
395  /* can't get here... */
396  return false;
397 }
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:604
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
Selectivity clause_selectivity ( PlannerInfo root,
Node clause,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo 
)

Definition at line 483 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 get_foreign_key_join_selectivity().

488 {
489  Selectivity s1 = 0.5; /* default for any unhandled clause type */
490  RestrictInfo *rinfo = NULL;
491  bool cacheable = false;
492 
493  if (clause == NULL) /* can this still happen? */
494  return s1;
495 
496  if (IsA(clause, RestrictInfo))
497  {
498  rinfo = (RestrictInfo *) clause;
499 
500  /*
501  * If the clause is marked pseudoconstant, then it will be used as a
502  * gating qual and should not affect selectivity estimates; hence
503  * return 1.0. The only exception is that a constant FALSE may be
504  * taken as having selectivity 0.0, since it will surely mean no rows
505  * out of the plan. This case is simple enough that we need not
506  * bother caching the result.
507  */
508  if (rinfo->pseudoconstant)
509  {
510  if (!IsA(rinfo->clause, Const))
511  return (Selectivity) 1.0;
512  }
513 
514  /*
515  * If the clause is marked redundant, always return 1.0.
516  */
517  if (rinfo->norm_selec > 1)
518  return (Selectivity) 1.0;
519 
520  /*
521  * If possible, cache the result of the selectivity calculation for
522  * the clause. We can cache if varRelid is zero or the clause
523  * contains only vars of that relid --- otherwise varRelid will affect
524  * the result, so mustn't cache. Outer join quals might be examined
525  * with either their join's actual jointype or JOIN_INNER, so we need
526  * two cache variables to remember both cases. Note: we assume the
527  * result won't change if we are switching the input relations or
528  * considering a unique-ified case, so we only need one cache variable
529  * for all non-JOIN_INNER cases.
530  */
531  if (varRelid == 0 ||
532  bms_is_subset_singleton(rinfo->clause_relids, varRelid))
533  {
534  /* Cacheable --- do we already have the result? */
535  if (jointype == JOIN_INNER)
536  {
537  if (rinfo->norm_selec >= 0)
538  return rinfo->norm_selec;
539  }
540  else
541  {
542  if (rinfo->outer_selec >= 0)
543  return rinfo->outer_selec;
544  }
545  cacheable = true;
546  }
547 
548  /*
549  * Proceed with examination of contained clause. If the clause is an
550  * OR-clause, we want to look at the variant with sub-RestrictInfos,
551  * so that per-subclause selectivities can be cached.
552  */
553  if (rinfo->orclause)
554  clause = (Node *) rinfo->orclause;
555  else
556  clause = (Node *) rinfo->clause;
557  }
558 
559  if (IsA(clause, Var))
560  {
561  Var *var = (Var *) clause;
562 
563  /*
564  * We probably shouldn't ever see an uplevel Var here, but if we do,
565  * return the default selectivity...
566  */
567  if (var->varlevelsup == 0 &&
568  (varRelid == 0 || varRelid == (int) var->varno))
569  {
570  /* Use the restriction selectivity function for a bool Var */
571  s1 = boolvarsel(root, (Node *) var, varRelid);
572  }
573  }
574  else if (IsA(clause, Const))
575  {
576  /* bool constant is pretty easy... */
577  Const *con = (Const *) clause;
578 
579  s1 = con->constisnull ? 0.0 :
580  DatumGetBool(con->constvalue) ? 1.0 : 0.0;
581  }
582  else if (IsA(clause, Param))
583  {
584  /* see if we can replace the Param */
585  Node *subst = estimate_expression_value(root, clause);
586 
587  if (IsA(subst, Const))
588  {
589  /* bool constant is pretty easy... */
590  Const *con = (Const *) subst;
591 
592  s1 = con->constisnull ? 0.0 :
593  DatumGetBool(con->constvalue) ? 1.0 : 0.0;
594  }
595  else
596  {
597  /* XXX any way to do better than default? */
598  }
599  }
600  else if (not_clause(clause))
601  {
602  /* inverse of the selectivity of the underlying clause */
603  s1 = 1.0 - clause_selectivity(root,
604  (Node *) get_notclausearg((Expr *) clause),
605  varRelid,
606  jointype,
607  sjinfo);
608  }
609  else if (and_clause(clause))
610  {
611  /* share code with clauselist_selectivity() */
612  s1 = clauselist_selectivity(root,
613  ((BoolExpr *) clause)->args,
614  varRelid,
615  jointype,
616  sjinfo);
617  }
618  else if (or_clause(clause))
619  {
620  /*
621  * Selectivities for an OR clause are computed as s1+s2 - s1*s2 to
622  * account for the probable overlap of selected tuple sets.
623  *
624  * XXX is this too conservative?
625  */
626  ListCell *arg;
627 
628  s1 = 0.0;
629  foreach(arg, ((BoolExpr *) clause)->args)
630  {
632  (Node *) lfirst(arg),
633  varRelid,
634  jointype,
635  sjinfo);
636 
637  s1 = s1 + s2 - s1 * s2;
638  }
639  }
640  else if (is_opclause(clause) || IsA(clause, DistinctExpr))
641  {
642  OpExpr *opclause = (OpExpr *) clause;
643  Oid opno = opclause->opno;
644 
645  if (treat_as_join_clause(clause, rinfo, varRelid, sjinfo))
646  {
647  /* Estimate selectivity for a join clause. */
648  s1 = join_selectivity(root, opno,
649  opclause->args,
650  opclause->inputcollid,
651  jointype,
652  sjinfo);
653  }
654  else
655  {
656  /* Estimate selectivity for a restriction clause. */
657  s1 = restriction_selectivity(root, opno,
658  opclause->args,
659  opclause->inputcollid,
660  varRelid);
661  }
662 
663  /*
664  * DistinctExpr has the same representation as OpExpr, but the
665  * contained operator is "=" not "<>", so we must negate the result.
666  * This estimation method doesn't give the right behavior for nulls,
667  * but it's better than doing nothing.
668  */
669  if (IsA(clause, DistinctExpr))
670  s1 = 1.0 - s1;
671  }
672  else if (IsA(clause, ScalarArrayOpExpr))
673  {
674  /* Use node specific selectivity calculation function */
675  s1 = scalararraysel(root,
676  (ScalarArrayOpExpr *) clause,
677  treat_as_join_clause(clause, rinfo,
678  varRelid, sjinfo),
679  varRelid,
680  jointype,
681  sjinfo);
682  }
683  else if (IsA(clause, RowCompareExpr))
684  {
685  /* Use node specific selectivity calculation function */
686  s1 = rowcomparesel(root,
687  (RowCompareExpr *) clause,
688  varRelid,
689  jointype,
690  sjinfo);
691  }
692  else if (IsA(clause, NullTest))
693  {
694  /* Use node specific selectivity calculation function */
695  s1 = nulltestsel(root,
696  ((NullTest *) clause)->nulltesttype,
697  (Node *) ((NullTest *) clause)->arg,
698  varRelid,
699  jointype,
700  sjinfo);
701  }
702  else if (IsA(clause, BooleanTest))
703  {
704  /* Use node specific selectivity calculation function */
705  s1 = booltestsel(root,
706  ((BooleanTest *) clause)->booltesttype,
707  (Node *) ((BooleanTest *) clause)->arg,
708  varRelid,
709  jointype,
710  sjinfo);
711  }
712  else if (IsA(clause, CurrentOfExpr))
713  {
714  /* CURRENT OF selects at most one row of its table */
715  CurrentOfExpr *cexpr = (CurrentOfExpr *) clause;
716  RelOptInfo *crel = find_base_rel(root, cexpr->cvarno);
717 
718  if (crel->tuples > 0)
719  s1 = 1.0 / crel->tuples;
720  }
721  else if (IsA(clause, RelabelType))
722  {
723  /* Not sure this case is needed, but it can't hurt */
724  s1 = clause_selectivity(root,
725  (Node *) ((RelabelType *) clause)->arg,
726  varRelid,
727  jointype,
728  sjinfo);
729  }
730  else if (IsA(clause, CoerceToDomain))
731  {
732  /* Not sure this case is needed, but it can't hurt */
733  s1 = clause_selectivity(root,
734  (Node *) ((CoerceToDomain *) clause)->arg,
735  varRelid,
736  jointype,
737  sjinfo);
738  }
739  else
740  {
741  /*
742  * For anything else, see if we can consider it as a boolean variable.
743  * This only works if it's an immutable expression in Vars of a single
744  * relation; but there's no point in us checking that here because
745  * boolvarsel() will do it internally, and return a suitable default
746  * selectivity if not.
747  */
748  s1 = boolvarsel(root, clause, varRelid);
749  }
750 
751  /* Cache the result if possible */
752  if (cacheable)
753  {
754  if (jointype == JOIN_INNER)
755  rinfo->norm_selec = s1;
756  else
757  rinfo->outer_selec = s1;
758  }
759 
760 #ifdef SELECTIVITY_DEBUG
761  elog(DEBUG4, "clause_selectivity: s1 %f", s1);
762 #endif /* SELECTIVITY_DEBUG */
763 
764  return s1;
765 }
Datum constvalue
Definition: primnodes.h:196
Expr * get_notclausearg(Expr *notclause)
Definition: clauses.c:264
#define IsA(nodeptr, _type_)
Definition: nodes.h:573
Index varlevelsup
Definition: primnodes.h:173
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2399
Expr * orclause
Definition: relation.h:1710
Selectivity restriction_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, int varRelid)
Definition: plancat.c:1635
double tuples
Definition: relation.h:534
Selectivity rowcomparesel(PlannerInfo *root, RowCompareExpr *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:2121
Relids clause_relids
Definition: relation.h:1694
bool pseudoconstant
Definition: relation.h:1687
Definition: nodes.h:522
double Selectivity
Definition: nodes.h:645
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:1764
Selectivity norm_selec
Definition: relation.h:1717
static bool treat_as_join_clause(Node *clause, RestrictInfo *rinfo, int varRelid, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:405
static bool bms_is_subset_singleton(const Bitmapset *s, int x)
Definition: clausesel.c:384
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:1664
bool and_clause(Node *clause)
Definition: clauses.c:313
Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:483
#define DatumGetBool(X)
Definition: postgres.h:399
Selectivity outer_selec
Definition: relation.h:1720
bool not_clause(Node *clause)
Definition: clauses.c:235
Expr * clause
Definition: relation.h:1679
Index varno
Definition: primnodes.h:166
char * s2
bool or_clause(Node *clause)
Definition: clauses.c:279
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Oid inputcollid
Definition: primnodes.h:500
void * arg
Selectivity join_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: plancat.c:1672
Oid opno
Definition: primnodes.h:495
#define elog
Definition: elog.h:219
Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:92
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:223
List * args
Definition: primnodes.h:501
Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1499
Selectivity boolvarsel(PlannerInfo *root, Node *arg, int varRelid)
Definition: selfuncs.c:1460
bool constisnull
Definition: primnodes.h:197
Selectivity clauselist_selectivity ( PlannerInfo root,
List clauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo 
)

Definition at line 92 of file clausesel.c.

References addRangeClause(), generate_unaccent_rules::args, OpExpr::args, bms_membership(), BMS_SINGLETON, RestrictInfo::clause, RestrictInfo::clause_relids, clause_selectivity(), DEFAULT_INEQ_SEL, DEFAULT_RANGE_INEQ_SEL, 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, NULL, nulltestsel(), NumRelids(), OpExpr::opno, pfree(), RestrictInfo::pseudoconstant, RestrictInfo::right_relids, s1, s2, 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().

97 {
98  Selectivity s1 = 1.0;
99  RangeQueryClause *rqlist = NULL;
100  ListCell *l;
101 
102  /*
103  * If there's exactly one clause, then no use in trying to match up pairs,
104  * so just go directly to clause_selectivity().
105  */
106  if (list_length(clauses) == 1)
107  return clause_selectivity(root, (Node *) linitial(clauses),
108  varRelid, jointype, sjinfo);
109 
110  /*
111  * Initial scan over clauses. Anything that doesn't look like a potential
112  * rangequery clause gets multiplied into s1 and forgotten. Anything that
113  * does gets inserted into an rqlist entry.
114  */
115  foreach(l, clauses)
116  {
117  Node *clause = (Node *) lfirst(l);
118  RestrictInfo *rinfo;
119  Selectivity s2;
120 
121  /* Always compute the selectivity using clause_selectivity */
122  s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo);
123 
124  /*
125  * Check for being passed a RestrictInfo.
126  *
127  * If it's a pseudoconstant RestrictInfo, then s2 is either 1.0 or
128  * 0.0; just use that rather than looking for range pairs.
129  */
130  if (IsA(clause, RestrictInfo))
131  {
132  rinfo = (RestrictInfo *) clause;
133  if (rinfo->pseudoconstant)
134  {
135  s1 = s1 * s2;
136  continue;
137  }
138  clause = (Node *) rinfo->clause;
139  }
140  else
141  rinfo = NULL;
142 
143  /*
144  * See if it looks like a restriction clause with a pseudoconstant on
145  * one side. (Anything more complicated than that might not behave in
146  * the simple way we are expecting.) Most of the tests here can be
147  * done more efficiently with rinfo than without.
148  */
149  if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
150  {
151  OpExpr *expr = (OpExpr *) clause;
152  bool varonleft = true;
153  bool ok;
154 
155  if (rinfo)
156  {
157  ok = (bms_membership(rinfo->clause_relids) == BMS_SINGLETON) &&
159  rinfo->right_relids) ||
160  (varonleft = false,
162  rinfo->left_relids)));
163  }
164  else
165  {
166  ok = (NumRelids(clause) == 1) &&
168  (varonleft = false,
170  }
171 
172  if (ok)
173  {
174  /*
175  * If it's not a "<" or ">" operator, just merge the
176  * selectivity in generically. But if it's the right oprrest,
177  * add the clause to rqlist for later processing.
178  */
179  switch (get_oprrest(expr->opno))
180  {
181  case F_SCALARLTSEL:
182  addRangeClause(&rqlist, clause,
183  varonleft, true, s2);
184  break;
185  case F_SCALARGTSEL:
186  addRangeClause(&rqlist, clause,
187  varonleft, false, s2);
188  break;
189  default:
190  /* Just merge the selectivity in generically */
191  s1 = s1 * s2;
192  break;
193  }
194  continue; /* drop to loop bottom */
195  }
196  }
197 
198  /* Not the right form, so treat it generically. */
199  s1 = s1 * s2;
200  }
201 
202  /*
203  * Now scan the rangequery pair list.
204  */
205  while (rqlist != NULL)
206  {
207  RangeQueryClause *rqnext;
208 
209  if (rqlist->have_lobound && rqlist->have_hibound)
210  {
211  /* Successfully matched a pair of range clauses */
212  Selectivity s2;
213 
214  /*
215  * Exact equality to the default value probably means the
216  * selectivity function punted. This is not airtight but should
217  * be good enough.
218  */
219  if (rqlist->hibound == DEFAULT_INEQ_SEL ||
220  rqlist->lobound == DEFAULT_INEQ_SEL)
221  {
223  }
224  else
225  {
226  s2 = rqlist->hibound + rqlist->lobound - 1.0;
227 
228  /* Adjust for double-exclusion of NULLs */
229  s2 += nulltestsel(root, IS_NULL, rqlist->var,
230  varRelid, jointype, sjinfo);
231 
232  /*
233  * A zero or slightly negative s2 should be converted into a
234  * small positive value; we probably are dealing with a very
235  * tight range and got a bogus result due to roundoff errors.
236  * However, if s2 is very negative, then we probably have
237  * default selectivity estimates on one or both sides of the
238  * range that we failed to recognize above for some reason.
239  */
240  if (s2 <= 0.0)
241  {
242  if (s2 < -0.01)
243  {
244  /*
245  * No data available --- use a default estimate that
246  * is small, but not real small.
247  */
249  }
250  else
251  {
252  /*
253  * It's just roundoff error; use a small positive
254  * value
255  */
256  s2 = 1.0e-10;
257  }
258  }
259  }
260  /* Merge in the selectivity of the pair of clauses */
261  s1 *= s2;
262  }
263  else
264  {
265  /* Only found one of a pair, merge it in generically */
266  if (rqlist->have_lobound)
267  s1 *= rqlist->lobound;
268  else
269  s1 *= rqlist->hibound;
270  }
271  /* release storage and advance */
272  rqnext = rqlist->next;
273  pfree(rqlist);
274  rqlist = rqnext;
275  }
276 
277  return s1;
278 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:573
bool is_pseudo_constant_clause_relids(Node *clause, Relids relids)
Definition: clauses.c:2161
#define DEFAULT_INEQ_SEL
Definition: selfuncs.h:37
Relids clause_relids
Definition: relation.h:1694
bool pseudoconstant
Definition: relation.h:1687
Definition: nodes.h:522
Relids left_relids
Definition: relation.h:1706
double Selectivity
Definition: nodes.h:645
#define lsecond(l)
Definition: pg_list.h:114
void pfree(void *pointer)
Definition: mcxt.c:950
#define linitial(l)
Definition: pg_list.h:110
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:1664
Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:483
bool is_pseudo_constant_clause(Node *clause)
Definition: clauses.c:2141
struct RangeQueryClause * next
Definition: clausesel.c:33
static void addRangeClause(RangeQueryClause **rqlist, Node *clause, bool varonleft, bool isLTsel, Selectivity s2)
Definition: clausesel.c:286
Selectivity hibound
Definition: clausesel.c:38
Expr * clause
Definition: relation.h:1679
Selectivity lobound
Definition: clausesel.c:37
RegProcedure get_oprrest(Oid opno)
Definition: lsyscache.c:1329
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:604
char * s2
Relids right_relids
Definition: relation.h:1707
#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:495
List * args
Definition: primnodes.h:501
int NumRelids(Node *clause)
Definition: clauses.c:2183
static bool treat_as_join_clause ( Node clause,
RestrictInfo rinfo,
int  varRelid,
SpecialJoinInfo sjinfo 
)
inlinestatic

Definition at line 405 of file clausesel.c.

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

Referenced by clause_selectivity().

407 {
408  if (varRelid != 0)
409  {
410  /*
411  * Caller is forcing restriction mode (eg, because we are examining an
412  * inner indexscan qual).
413  */
414  return false;
415  }
416  else if (sjinfo == NULL)
417  {
418  /*
419  * It must be a restriction clause, since it's being evaluated at a
420  * scan node.
421  */
422  return false;
423  }
424  else
425  {
426  /*
427  * Otherwise, it's a join if there's more than one relation used. We
428  * can optimize this calculation if an rinfo was passed.
429  *
430  * XXX Since we know the clause is being evaluated at a join, the
431  * only way it could be single-relation is if it was delayed by outer
432  * joins. Although we can make use of the restriction qual estimators
433  * anyway, it seems likely that we ought to account for the
434  * probability of injected nulls somehow.
435  */
436  if (rinfo)
437  return (bms_membership(rinfo->clause_relids) == BMS_MULTIPLE);
438  else
439  return (NumRelids(clause) > 1);
440  }
441 }
Relids clause_relids
Definition: relation.h:1694
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:604
#define NULL
Definition: c.h:229
int NumRelids(Node *clause)
Definition: clauses.c:2183