PostgreSQL Source Code  git master
clausesel.c File Reference
#include "postgres.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/optimizer.h"
#include "optimizer/pathnode.h"
#include "optimizer/plancat.h"
#include "statistics/statistics.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)
 
static RelOptInfofind_single_rel_for_clauses (PlannerInfo *root, List *clauses)
 
Selectivity clauselist_selectivity (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
Selectivity clauselist_selectivity_simple (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, Bitmapset *estimatedclauses)
 
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

◆ RangeQueryClause

Function Documentation

◆ addRangeClause()

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

Definition at line 360 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_simple().

362 {
363  RangeQueryClause *rqelem;
364  Node *var;
365  bool is_lobound;
366 
367  if (varonleft)
368  {
369  var = get_leftop((Expr *) clause);
370  is_lobound = !isLTsel; /* x < something is high bound */
371  }
372  else
373  {
374  var = get_rightop((Expr *) clause);
375  is_lobound = isLTsel; /* something < x is low bound */
376  }
377 
378  for (rqelem = *rqlist; rqelem; rqelem = rqelem->next)
379  {
380  /*
381  * We use full equal() here because the "var" might be a function of
382  * one or more attributes of the same relation...
383  */
384  if (!equal(var, rqelem->var))
385  continue;
386  /* Found the right group to put this clause in */
387  if (is_lobound)
388  {
389  if (!rqelem->have_lobound)
390  {
391  rqelem->have_lobound = true;
392  rqelem->lobound = s2;
393  }
394  else
395  {
396 
397  /*------
398  * We have found two similar clauses, such as
399  * x < y AND x <= z.
400  * Keep only the more restrictive one.
401  *------
402  */
403  if (rqelem->lobound > s2)
404  rqelem->lobound = s2;
405  }
406  }
407  else
408  {
409  if (!rqelem->have_hibound)
410  {
411  rqelem->have_hibound = true;
412  rqelem->hibound = s2;
413  }
414  else
415  {
416 
417  /*------
418  * We have found two similar clauses, such as
419  * x > y AND x >= z.
420  * Keep only the more restrictive one.
421  *------
422  */
423  if (rqelem->hibound > s2)
424  rqelem->hibound = s2;
425  }
426  }
427  return;
428  }
429 
430  /* No matching var found, so make a new clause-pair data structure */
431  rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause));
432  rqelem->var = var;
433  if (is_lobound)
434  {
435  rqelem->have_lobound = true;
436  rqelem->have_hibound = false;
437  rqelem->lobound = s2;
438  }
439  else
440  {
441  rqelem->have_lobound = false;
442  rqelem->have_hibound = true;
443  rqelem->hibound = s2;
444  }
445  rqelem->next = *rqlist;
446  *rqlist = rqelem;
447 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3011
Definition: nodes.h:525
static Node * get_leftop(const void *clause)
Definition: nodeFuncs.h:70
struct RangeQueryClause * next
Definition: clausesel.c:35
Selectivity hibound
Definition: clausesel.c:40
Selectivity lobound
Definition: clausesel.c:39
char * s2
static Node * get_rightop(const void *clause)
Definition: nodeFuncs.h:82
void * palloc(Size size)
Definition: mcxt.c:949

◆ bms_is_subset_singleton()

static bool bms_is_subset_singleton ( const Bitmapset s,
int  x 
)
static

Definition at line 501 of file clausesel.c.

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

Referenced by clause_selectivity().

502 {
503  switch (bms_membership(s))
504  {
505  case BMS_EMPTY_SET:
506  return true;
507  case BMS_SINGLETON:
508  return bms_is_member(x, s);
509  case BMS_MULTIPLE:
510  return false;
511  }
512  /* can't get here... */
513  return false;
514 }
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:672
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427

◆ clause_selectivity()

Selectivity clause_selectivity ( PlannerInfo root,
Node clause,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo 
)

Definition at line 600 of file clausesel.c.

References arg, generate_unaccent_rules::args, FuncExpr::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(), FuncExpr::funcid, function_selectivity(), get_notclausearg(), FuncExpr::inputcollid, OpExpr::inputcollid, is_andclause(), is_funcclause(), is_notclause(), is_opclause(), is_orclause(), IsA, JOIN_INNER, join_selectivity(), lfirst, RestrictInfo::norm_selec, nulltestsel(), OpExpr::opno, 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_simple(), consider_new_or_clause(), and dependencies_clauselist_selectivity().

605 {
606  Selectivity s1 = 0.5; /* default for any unhandled clause type */
607  RestrictInfo *rinfo = NULL;
608  bool cacheable = false;
609 
610  if (clause == NULL) /* can this still happen? */
611  return s1;
612 
613  if (IsA(clause, RestrictInfo))
614  {
615  rinfo = (RestrictInfo *) clause;
616 
617  /*
618  * If the clause is marked pseudoconstant, then it will be used as a
619  * gating qual and should not affect selectivity estimates; hence
620  * return 1.0. The only exception is that a constant FALSE may be
621  * taken as having selectivity 0.0, since it will surely mean no rows
622  * out of the plan. This case is simple enough that we need not
623  * bother caching the result.
624  */
625  if (rinfo->pseudoconstant)
626  {
627  if (!IsA(rinfo->clause, Const))
628  return (Selectivity) 1.0;
629  }
630 
631  /*
632  * If the clause is marked redundant, always return 1.0.
633  */
634  if (rinfo->norm_selec > 1)
635  return (Selectivity) 1.0;
636 
637  /*
638  * If possible, cache the result of the selectivity calculation for
639  * the clause. We can cache if varRelid is zero or the clause
640  * contains only vars of that relid --- otherwise varRelid will affect
641  * the result, so mustn't cache. Outer join quals might be examined
642  * with either their join's actual jointype or JOIN_INNER, so we need
643  * two cache variables to remember both cases. Note: we assume the
644  * result won't change if we are switching the input relations or
645  * considering a unique-ified case, so we only need one cache variable
646  * for all non-JOIN_INNER cases.
647  */
648  if (varRelid == 0 ||
649  bms_is_subset_singleton(rinfo->clause_relids, varRelid))
650  {
651  /* Cacheable --- do we already have the result? */
652  if (jointype == JOIN_INNER)
653  {
654  if (rinfo->norm_selec >= 0)
655  return rinfo->norm_selec;
656  }
657  else
658  {
659  if (rinfo->outer_selec >= 0)
660  return rinfo->outer_selec;
661  }
662  cacheable = true;
663  }
664 
665  /*
666  * Proceed with examination of contained clause. If the clause is an
667  * OR-clause, we want to look at the variant with sub-RestrictInfos,
668  * so that per-subclause selectivities can be cached.
669  */
670  if (rinfo->orclause)
671  clause = (Node *) rinfo->orclause;
672  else
673  clause = (Node *) rinfo->clause;
674  }
675 
676  if (IsA(clause, Var))
677  {
678  Var *var = (Var *) clause;
679 
680  /*
681  * We probably shouldn't ever see an uplevel Var here, but if we do,
682  * return the default selectivity...
683  */
684  if (var->varlevelsup == 0 &&
685  (varRelid == 0 || varRelid == (int) var->varno))
686  {
687  /* Use the restriction selectivity function for a bool Var */
688  s1 = boolvarsel(root, (Node *) var, varRelid);
689  }
690  }
691  else if (IsA(clause, Const))
692  {
693  /* bool constant is pretty easy... */
694  Const *con = (Const *) clause;
695 
696  s1 = con->constisnull ? 0.0 :
697  DatumGetBool(con->constvalue) ? 1.0 : 0.0;
698  }
699  else if (IsA(clause, Param))
700  {
701  /* see if we can replace the Param */
702  Node *subst = estimate_expression_value(root, clause);
703 
704  if (IsA(subst, Const))
705  {
706  /* bool constant is pretty easy... */
707  Const *con = (Const *) subst;
708 
709  s1 = con->constisnull ? 0.0 :
710  DatumGetBool(con->constvalue) ? 1.0 : 0.0;
711  }
712  else
713  {
714  /* XXX any way to do better than default? */
715  }
716  }
717  else if (is_notclause(clause))
718  {
719  /* inverse of the selectivity of the underlying clause */
720  s1 = 1.0 - clause_selectivity(root,
721  (Node *) get_notclausearg((Expr *) clause),
722  varRelid,
723  jointype,
724  sjinfo);
725  }
726  else if (is_andclause(clause))
727  {
728  /* share code with clauselist_selectivity() */
729  s1 = clauselist_selectivity(root,
730  ((BoolExpr *) clause)->args,
731  varRelid,
732  jointype,
733  sjinfo);
734  }
735  else if (is_orclause(clause))
736  {
737  /*
738  * Selectivities for an OR clause are computed as s1+s2 - s1*s2 to
739  * account for the probable overlap of selected tuple sets.
740  *
741  * XXX is this too conservative?
742  */
743  ListCell *arg;
744 
745  s1 = 0.0;
746  foreach(arg, ((BoolExpr *) clause)->args)
747  {
749  (Node *) lfirst(arg),
750  varRelid,
751  jointype,
752  sjinfo);
753 
754  s1 = s1 + s2 - s1 * s2;
755  }
756  }
757  else if (is_opclause(clause) || IsA(clause, DistinctExpr))
758  {
759  OpExpr *opclause = (OpExpr *) clause;
760  Oid opno = opclause->opno;
761 
762  if (treat_as_join_clause(clause, rinfo, varRelid, sjinfo))
763  {
764  /* Estimate selectivity for a join clause. */
765  s1 = join_selectivity(root, opno,
766  opclause->args,
767  opclause->inputcollid,
768  jointype,
769  sjinfo);
770  }
771  else
772  {
773  /* Estimate selectivity for a restriction clause. */
774  s1 = restriction_selectivity(root, opno,
775  opclause->args,
776  opclause->inputcollid,
777  varRelid);
778  }
779 
780  /*
781  * DistinctExpr has the same representation as OpExpr, but the
782  * contained operator is "=" not "<>", so we must negate the result.
783  * This estimation method doesn't give the right behavior for nulls,
784  * but it's better than doing nothing.
785  */
786  if (IsA(clause, DistinctExpr))
787  s1 = 1.0 - s1;
788  }
789  else if (is_funcclause(clause))
790  {
791  FuncExpr *funcclause = (FuncExpr *) clause;
792 
793  /* Try to get an estimate from the support function, if any */
794  s1 = function_selectivity(root,
795  funcclause->funcid,
796  funcclause->args,
797  funcclause->inputcollid,
798  treat_as_join_clause(clause, rinfo,
799  varRelid, sjinfo),
800  varRelid,
801  jointype,
802  sjinfo);
803  }
804  else if (IsA(clause, ScalarArrayOpExpr))
805  {
806  /* Use node specific selectivity calculation function */
807  s1 = scalararraysel(root,
808  (ScalarArrayOpExpr *) clause,
809  treat_as_join_clause(clause, rinfo,
810  varRelid, sjinfo),
811  varRelid,
812  jointype,
813  sjinfo);
814  }
815  else if (IsA(clause, RowCompareExpr))
816  {
817  /* Use node specific selectivity calculation function */
818  s1 = rowcomparesel(root,
819  (RowCompareExpr *) clause,
820  varRelid,
821  jointype,
822  sjinfo);
823  }
824  else if (IsA(clause, NullTest))
825  {
826  /* Use node specific selectivity calculation function */
827  s1 = nulltestsel(root,
828  ((NullTest *) clause)->nulltesttype,
829  (Node *) ((NullTest *) clause)->arg,
830  varRelid,
831  jointype,
832  sjinfo);
833  }
834  else if (IsA(clause, BooleanTest))
835  {
836  /* Use node specific selectivity calculation function */
837  s1 = booltestsel(root,
838  ((BooleanTest *) clause)->booltesttype,
839  (Node *) ((BooleanTest *) clause)->arg,
840  varRelid,
841  jointype,
842  sjinfo);
843  }
844  else if (IsA(clause, CurrentOfExpr))
845  {
846  /* CURRENT OF selects at most one row of its table */
847  CurrentOfExpr *cexpr = (CurrentOfExpr *) clause;
848  RelOptInfo *crel = find_base_rel(root, cexpr->cvarno);
849 
850  if (crel->tuples > 0)
851  s1 = 1.0 / crel->tuples;
852  }
853  else if (IsA(clause, RelabelType))
854  {
855  /* Not sure this case is needed, but it can't hurt */
856  s1 = clause_selectivity(root,
857  (Node *) ((RelabelType *) clause)->arg,
858  varRelid,
859  jointype,
860  sjinfo);
861  }
862  else if (IsA(clause, CoerceToDomain))
863  {
864  /* Not sure this case is needed, but it can't hurt */
865  s1 = clause_selectivity(root,
866  (Node *) ((CoerceToDomain *) clause)->arg,
867  varRelid,
868  jointype,
869  sjinfo);
870  }
871  else
872  {
873  /*
874  * For anything else, see if we can consider it as a boolean variable.
875  * This only works if it's an immutable expression in Vars of a single
876  * relation; but there's no point in us checking that here because
877  * boolvarsel() will do it internally, and return a suitable default
878  * selectivity if not.
879  */
880  s1 = boolvarsel(root, clause, varRelid);
881  }
882 
883  /* Cache the result if possible */
884  if (cacheable)
885  {
886  if (jointype == JOIN_INNER)
887  rinfo->norm_selec = s1;
888  else
889  rinfo->outer_selec = s1;
890  }
891 
892 #ifdef SELECTIVITY_DEBUG
893  elog(DEBUG4, "clause_selectivity: s1 %f", s1);
894 #endif /* SELECTIVITY_DEBUG */
895 
896  return s1;
897 }
Datum constvalue
Definition: primnodes.h:200
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Index varlevelsup
Definition: primnodes.h:177
List * args
Definition: primnodes.h:463
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2286
static bool is_orclause(const void *clause)
Definition: nodeFuncs.h:103
Expr * orclause
Definition: pathnodes.h:1976
Selectivity restriction_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, int varRelid)
Definition: plancat.c:1763
double tuples
Definition: pathnodes.h:683
Selectivity rowcomparesel(PlannerInfo *root, RowCompareExpr *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1929
Relids clause_relids
Definition: pathnodes.h:1960
bool pseudoconstant
Definition: pathnodes.h:1953
static bool is_andclause(const void *clause)
Definition: nodeFuncs.h:94
Definition: nodes.h:525
double Selectivity
Definition: nodes.h:658
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:167
#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:1572
static bool is_funcclause(const void *clause)
Definition: nodeFuncs.h:56
Selectivity norm_selec
Definition: pathnodes.h:1983
static bool treat_as_join_clause(Node *clause, RestrictInfo *rinfo, int varRelid, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:522
static bool bms_is_subset_singleton(const Bitmapset *s, int x)
Definition: clausesel.c:501
Oid funcid
Definition: primnodes.h:455
char * s1
Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1454
Selectivity function_selectivity(PlannerInfo *root, Oid funcid, List *args, Oid inputcollid, bool is_join, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: plancat.c:1843
Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:600
#define DatumGetBool(X)
Definition: postgres.h:393
Selectivity outer_selec
Definition: pathnodes.h:1986
Expr * clause
Definition: pathnodes.h:1945
Index varno
Definition: primnodes.h:170
static bool is_notclause(const void *clause)
Definition: nodeFuncs.h:112
char * s2
static Expr * get_notclausearg(const void *notclause)
Definition: nodeFuncs.h:121
Oid inputcollid
Definition: primnodes.h:462
#define lfirst(lc)
Definition: pg_list.h:190
Oid inputcollid
Definition: primnodes.h:507
#define elog(elevel,...)
Definition: elog.h:228
void * arg
Selectivity join_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: plancat.c:1802
Oid opno
Definition: primnodes.h:502
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:63
Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:69
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:363
List * args
Definition: primnodes.h:508
Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1296
Selectivity boolvarsel(PlannerInfo *root, Node *arg, int varRelid)
Definition: selfuncs.c:1268
bool constisnull
Definition: primnodes.h:201

◆ clauselist_selectivity()

Selectivity clauselist_selectivity ( PlannerInfo root,
List clauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo 
)

Definition at line 69 of file clausesel.c.

References clauselist_selectivity_simple(), find_single_rel_for_clauses(), NIL, RTE_RELATION, RelOptInfo::rtekind, s1, statext_clauselist_selectivity(), and RelOptInfo::statlist.

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

74 {
75  Selectivity s1 = 1.0;
76  RelOptInfo *rel;
77  Bitmapset *estimatedclauses = NULL;
78 
79  /*
80  * Determine if these clauses reference a single relation. If so, and if
81  * it has extended statistics, try to apply those.
82  */
83  rel = find_single_rel_for_clauses(root, clauses);
84  if (rel && rel->rtekind == RTE_RELATION && rel->statlist != NIL)
85  {
86  /*
87  * Estimate as many clauses as possible using extended statistics.
88  *
89  * 'estimatedclauses' tracks the 0-based list position index of
90  * clauses that we've estimated using extended statistics, and that
91  * should be ignored.
92  */
93  s1 *= statext_clauselist_selectivity(root, clauses, varRelid,
94  jointype, sjinfo, rel,
95  &estimatedclauses);
96  }
97 
98  /*
99  * Apply normal selectivity estimates for the remaining clauses, passing
100  * 'estimatedclauses' so that it skips already estimated ones.
101  */
102  return s1 * clauselist_selectivity_simple(root, clauses, varRelid,
103  jointype, sjinfo,
104  estimatedclauses);
105 }
#define NIL
Definition: pg_list.h:65
List * statlist
Definition: pathnodes.h:681
double Selectivity
Definition: nodes.h:658
Selectivity clauselist_selectivity_simple(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, Bitmapset *estimatedclauses)
Definition: clausesel.c:150
char * s1
Selectivity statext_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
RTEKind rtekind
Definition: pathnodes.h:673
static RelOptInfo * find_single_rel_for_clauses(PlannerInfo *root, List *clauses)
Definition: clausesel.c:456

◆ clauselist_selectivity_simple()

Selectivity clauselist_selectivity_simple ( PlannerInfo root,
List clauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo,
Bitmapset estimatedclauses 
)

Definition at line 150 of file clausesel.c.

References addRangeClause(), generate_unaccent_rules::args, OpExpr::args, bms_is_member(), bms_membership(), bms_num_members(), 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, nulltestsel(), NumRelids(), OpExpr::opno, pfree(), RestrictInfo::pseudoconstant, RestrictInfo::right_relids, s1, s2, and RangeQueryClause::var.

Referenced by clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

156 {
157  Selectivity s1 = 1.0;
158  RangeQueryClause *rqlist = NULL;
159  ListCell *l;
160  int listidx;
161 
162  /*
163  * If there's exactly one clause (and it was not estimated yet), just go
164  * directly to clause_selectivity(). None of what we might do below is
165  * relevant.
166  */
167  if ((list_length(clauses) == 1) &&
168  bms_num_members(estimatedclauses) == 0)
169  return clause_selectivity(root, (Node *) linitial(clauses),
170  varRelid, jointype, sjinfo);
171 
172  /*
173  * Anything that doesn't look like a potential rangequery clause gets
174  * multiplied into s1 and forgotten. Anything that does gets inserted into
175  * an rqlist entry.
176  */
177  listidx = -1;
178  foreach(l, clauses)
179  {
180  Node *clause = (Node *) lfirst(l);
181  RestrictInfo *rinfo;
182  Selectivity s2;
183 
184  listidx++;
185 
186  /*
187  * Skip this clause if it's already been estimated by some other
188  * statistics above.
189  */
190  if (bms_is_member(listidx, estimatedclauses))
191  continue;
192 
193  /* Always compute the selectivity using clause_selectivity */
194  s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo);
195 
196  /*
197  * Check for being passed a RestrictInfo.
198  *
199  * If it's a pseudoconstant RestrictInfo, then s2 is either 1.0 or
200  * 0.0; just use that rather than looking for range pairs.
201  */
202  if (IsA(clause, RestrictInfo))
203  {
204  rinfo = (RestrictInfo *) clause;
205  if (rinfo->pseudoconstant)
206  {
207  s1 = s1 * s2;
208  continue;
209  }
210  clause = (Node *) rinfo->clause;
211  }
212  else
213  rinfo = NULL;
214 
215  /*
216  * See if it looks like a restriction clause with a pseudoconstant on
217  * one side. (Anything more complicated than that might not behave in
218  * the simple way we are expecting.) Most of the tests here can be
219  * done more efficiently with rinfo than without.
220  */
221  if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
222  {
223  OpExpr *expr = (OpExpr *) clause;
224  bool varonleft = true;
225  bool ok;
226 
227  if (rinfo)
228  {
229  ok = (bms_membership(rinfo->clause_relids) == BMS_SINGLETON) &&
231  rinfo->right_relids) ||
232  (varonleft = false,
234  rinfo->left_relids)));
235  }
236  else
237  {
238  ok = (NumRelids(clause) == 1) &&
240  (varonleft = false,
242  }
243 
244  if (ok)
245  {
246  /*
247  * If it's not a "<"/"<="/">"/">=" operator, just merge the
248  * selectivity in generically. But if it's the right oprrest,
249  * add the clause to rqlist for later processing.
250  */
251  switch (get_oprrest(expr->opno))
252  {
253  case F_SCALARLTSEL:
254  case F_SCALARLESEL:
255  addRangeClause(&rqlist, clause,
256  varonleft, true, s2);
257  break;
258  case F_SCALARGTSEL:
259  case F_SCALARGESEL:
260  addRangeClause(&rqlist, clause,
261  varonleft, false, s2);
262  break;
263  default:
264  /* Just merge the selectivity in generically */
265  s1 = s1 * s2;
266  break;
267  }
268  continue; /* drop to loop bottom */
269  }
270  }
271 
272  /* Not the right form, so treat it generically. */
273  s1 = s1 * s2;
274  }
275 
276  /*
277  * Now scan the rangequery pair list.
278  */
279  while (rqlist != NULL)
280  {
281  RangeQueryClause *rqnext;
282 
283  if (rqlist->have_lobound && rqlist->have_hibound)
284  {
285  /* Successfully matched a pair of range clauses */
286  Selectivity s2;
287 
288  /*
289  * Exact equality to the default value probably means the
290  * selectivity function punted. This is not airtight but should
291  * be good enough.
292  */
293  if (rqlist->hibound == DEFAULT_INEQ_SEL ||
294  rqlist->lobound == DEFAULT_INEQ_SEL)
295  {
297  }
298  else
299  {
300  s2 = rqlist->hibound + rqlist->lobound - 1.0;
301 
302  /* Adjust for double-exclusion of NULLs */
303  s2 += nulltestsel(root, IS_NULL, rqlist->var,
304  varRelid, jointype, sjinfo);
305 
306  /*
307  * A zero or slightly negative s2 should be converted into a
308  * small positive value; we probably are dealing with a very
309  * tight range and got a bogus result due to roundoff errors.
310  * However, if s2 is very negative, then we probably have
311  * default selectivity estimates on one or both sides of the
312  * range that we failed to recognize above for some reason.
313  */
314  if (s2 <= 0.0)
315  {
316  if (s2 < -0.01)
317  {
318  /*
319  * No data available --- use a default estimate that
320  * is small, but not real small.
321  */
323  }
324  else
325  {
326  /*
327  * It's just roundoff error; use a small positive
328  * value
329  */
330  s2 = 1.0e-10;
331  }
332  }
333  }
334  /* Merge in the selectivity of the pair of clauses */
335  s1 *= s2;
336  }
337  else
338  {
339  /* Only found one of a pair, merge it in generically */
340  if (rqlist->have_lobound)
341  s1 *= rqlist->lobound;
342  else
343  s1 *= rqlist->hibound;
344  }
345  /* release storage and advance */
346  rqnext = rqlist->next;
347  pfree(rqlist);
348  rqlist = rqnext;
349  }
350 
351  return s1;
352 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
bool is_pseudo_constant_clause_relids(Node *clause, Relids relids)
Definition: clauses.c:2109
#define DEFAULT_INEQ_SEL
Definition: selfuncs.h:37
Relids clause_relids
Definition: pathnodes.h:1960
bool pseudoconstant
Definition: pathnodes.h:1953
Definition: nodes.h:525
Relids left_relids
Definition: pathnodes.h:1972
double Selectivity
Definition: nodes.h:658
#define lsecond(l)
Definition: pg_list.h:200
void pfree(void *pointer)
Definition: mcxt.c:1056
#define linitial(l)
Definition: pg_list.h:195
char * s1
Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1454
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:600
bool is_pseudo_constant_clause(Node *clause)
Definition: clauses.c:2089
struct RangeQueryClause * next
Definition: clausesel.c:35
static void addRangeClause(RangeQueryClause **rqlist, Node *clause, bool varonleft, bool isLTsel, Selectivity s2)
Definition: clausesel.c:360
Selectivity hibound
Definition: clausesel.c:40
Expr * clause
Definition: pathnodes.h:1945
Selectivity lobound
Definition: clausesel.c:39
RegProcedure get_oprrest(Oid opno)
Definition: lsyscache.c:1359
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:672
char * s2
Relids right_relids
Definition: pathnodes.h:1973
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
#define DEFAULT_RANGE_INEQ_SEL
Definition: selfuncs.h:40
Oid opno
Definition: primnodes.h:502
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:63
List * args
Definition: primnodes.h:508
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
int NumRelids(Node *clause)
Definition: clauses.c:2131

◆ find_single_rel_for_clauses()

static RelOptInfo * find_single_rel_for_clauses ( PlannerInfo root,
List clauses 
)
static

Definition at line 456 of file clausesel.c.

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

Referenced by clauselist_selectivity().

457 {
458  int lastrelid = 0;
459  ListCell *l;
460 
461  foreach(l, clauses)
462  {
463  RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
464  int relid;
465 
466  /*
467  * If we have a list of bare clauses rather than RestrictInfos, we
468  * could pull out their relids the hard way with pull_varnos().
469  * However, currently the extended-stats machinery won't do anything
470  * with non-RestrictInfo clauses anyway, so there's no point in
471  * spending extra cycles; just fail if that's what we have.
472  */
473  if (!IsA(rinfo, RestrictInfo))
474  return NULL;
475 
476  if (bms_is_empty(rinfo->clause_relids))
477  continue; /* we can ignore variable-free clauses */
478  if (!bms_get_singleton_member(rinfo->clause_relids, &relid))
479  return NULL; /* multiple relations in this clause */
480  if (lastrelid == 0)
481  lastrelid = relid; /* first clause referencing a relation */
482  else if (relid != lastrelid)
483  return NULL; /* relation not same as last one */
484  }
485 
486  if (lastrelid != 0)
487  return find_base_rel(root, lastrelid);
488 
489  return NULL; /* no clauses */
490 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Relids clause_relids
Definition: pathnodes.h:1960
bool bms_get_singleton_member(const Bitmapset *a, int *member)
Definition: bitmapset.c:615
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
#define lfirst(lc)
Definition: pg_list.h:190
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:363

◆ treat_as_join_clause()

static bool treat_as_join_clause ( Node clause,
RestrictInfo rinfo,
int  varRelid,
SpecialJoinInfo sjinfo 
)
inlinestatic

Definition at line 522 of file clausesel.c.

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

Referenced by clause_selectivity().

524 {
525  if (varRelid != 0)
526  {
527  /*
528  * Caller is forcing restriction mode (eg, because we are examining an
529  * inner indexscan qual).
530  */
531  return false;
532  }
533  else if (sjinfo == NULL)
534  {
535  /*
536  * It must be a restriction clause, since it's being evaluated at a
537  * scan node.
538  */
539  return false;
540  }
541  else
542  {
543  /*
544  * Otherwise, it's a join if there's more than one relation used. We
545  * can optimize this calculation if an rinfo was passed.
546  *
547  * XXX Since we know the clause is being evaluated at a join, the
548  * only way it could be single-relation is if it was delayed by outer
549  * joins. Although we can make use of the restriction qual estimators
550  * anyway, it seems likely that we ought to account for the
551  * probability of injected nulls somehow.
552  */
553  if (rinfo)
554  return (bms_membership(rinfo->clause_relids) == BMS_MULTIPLE);
555  else
556  return (NumRelids(clause) > 1);
557  }
558 }
Relids clause_relids
Definition: pathnodes.h:1960
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:672
int NumRelids(Node *clause)
Definition: clauses.c:2131