PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
selfuncs.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <math.h>
#include "access/gin.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "catalog/index.h"
#include "catalog/pg_am.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "mb/pg_wchar.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "optimizer/predtest.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/var.h"
#include "parser/parse_clause.h"
#include "parser/parse_coerce.h"
#include "parser/parsetree.h"
#include "utils/builtins.h"
#include "utils/bytea.h"
#include "utils/date.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/index_selfuncs.h"
#include "utils/lsyscache.h"
#include "utils/nabstime.h"
#include "utils/pg_locale.h"
#include "utils/rel.h"
#include "utils/selfuncs.h"
#include "utils/spccache.h"
#include "utils/syscache.h"
#include "utils/timestamp.h"
#include "utils/tqual.h"
#include "utils/typcache.h"
#include "utils/varlena.h"
Include dependency graph for selfuncs.c:

Go to the source code of this file.

Data Structures

struct  GroupVarInfo
 
struct  GinQualCounts
 

Macros

#define FIXED_CHAR_SEL   0.20 /* about 1/5 */
 
#define CHAR_RANGE_SEL   0.25
 
#define ANY_CHAR_SEL   0.9 /* not 1, since it won't match end-of-string */
 
#define FULL_WILDCARD_SEL   5.0
 
#define PARTIAL_WILDCARD_SEL   2.0
 

Functions

static double var_eq_const (VariableStatData *vardata, Oid operator, Datum constval, bool constisnull, bool varonleft)
 
static double var_eq_non_const (VariableStatData *vardata, Oid operator, Node *other, bool varonleft)
 
static double ineq_histogram_selectivity (PlannerInfo *root, VariableStatData *vardata, FmgrInfo *opproc, bool isgt, Datum constval, Oid consttype)
 
static double eqjoinsel_inner (Oid operator, VariableStatData *vardata1, VariableStatData *vardata2)
 
static double eqjoinsel_semi (Oid operator, VariableStatData *vardata1, VariableStatData *vardata2, RelOptInfo *inner_rel)
 
static bool convert_to_scalar (Datum value, Oid valuetypid, double *scaledvalue, Datum lobound, Datum hibound, Oid boundstypid, double *scaledlobound, double *scaledhibound)
 
static double convert_numeric_to_scalar (Datum value, Oid typid)
 
static void convert_string_to_scalar (char *value, double *scaledvalue, char *lobound, double *scaledlobound, char *hibound, double *scaledhibound)
 
static void convert_bytea_to_scalar (Datum value, double *scaledvalue, Datum lobound, double *scaledlobound, Datum hibound, double *scaledhibound)
 
static double convert_one_string_to_scalar (char *value, int rangelo, int rangehi)
 
static double convert_one_bytea_to_scalar (unsigned char *value, int valuelen, int rangelo, int rangehi)
 
static char * convert_string_datum (Datum value, Oid typid)
 
static double convert_timevalue_to_scalar (Datum value, Oid typid)
 
static void examine_simple_variable (PlannerInfo *root, Var *var, VariableStatData *vardata)
 
static bool get_variable_range (PlannerInfo *root, VariableStatData *vardata, Oid sortop, Datum *min, Datum *max)
 
static bool get_actual_variable_range (PlannerInfo *root, VariableStatData *vardata, Oid sortop, Datum *min, Datum *max)
 
static RelOptInfofind_join_input_rel (PlannerInfo *root, Relids relids)
 
static Selectivity prefix_selectivity (PlannerInfo *root, VariableStatData *vardata, Oid vartype, Oid opfamily, Const *prefixcon)
 
static Selectivity like_selectivity (const char *patt, int pattlen, bool case_insensitive)
 
static Selectivity regex_selectivity (const char *patt, int pattlen, bool case_insensitive, int fixed_prefix_len)
 
static Datum string_to_datum (const char *str, Oid datatype)
 
static Conststring_to_const (const char *str, Oid datatype)
 
static Conststring_to_bytea_const (const char *str, size_t str_len)
 
static Listadd_predicate_to_quals (IndexOptInfo *index, List *indexQuals)
 
Datum eqsel (PG_FUNCTION_ARGS)
 
Datum neqsel (PG_FUNCTION_ARGS)
 
static double scalarineqsel (PlannerInfo *root, Oid operator, bool isgt, VariableStatData *vardata, Datum constval, Oid consttype)
 
double mcv_selectivity (VariableStatData *vardata, FmgrInfo *opproc, Datum constval, bool varonleft, double *sumcommonp)
 
double histogram_selectivity (VariableStatData *vardata, FmgrInfo *opproc, Datum constval, bool varonleft, int min_hist_size, int n_skip, int *hist_size)
 
Datum scalarltsel (PG_FUNCTION_ARGS)
 
Datum scalargtsel (PG_FUNCTION_ARGS)
 
static double patternsel (PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
 
Datum regexeqsel (PG_FUNCTION_ARGS)
 
Datum icregexeqsel (PG_FUNCTION_ARGS)
 
Datum likesel (PG_FUNCTION_ARGS)
 
Datum iclikesel (PG_FUNCTION_ARGS)
 
Datum regexnesel (PG_FUNCTION_ARGS)
 
Datum icregexnesel (PG_FUNCTION_ARGS)
 
Datum nlikesel (PG_FUNCTION_ARGS)
 
Datum icnlikesel (PG_FUNCTION_ARGS)
 
Selectivity boolvarsel (PlannerInfo *root, Node *arg, int varRelid)
 
Selectivity booltestsel (PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
Selectivity nulltestsel (PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
static Nodestrip_array_coercion (Node *node)
 
Selectivity scalararraysel (PlannerInfo *root, ScalarArrayOpExpr *clause, bool is_join_clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
int estimate_array_length (Node *arrayexpr)
 
Selectivity rowcomparesel (PlannerInfo *root, RowCompareExpr *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
Datum eqjoinsel (PG_FUNCTION_ARGS)
 
Datum neqjoinsel (PG_FUNCTION_ARGS)
 
Datum scalarltjoinsel (PG_FUNCTION_ARGS)
 
Datum scalargtjoinsel (PG_FUNCTION_ARGS)
 
static double patternjoinsel (PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
 
Datum regexeqjoinsel (PG_FUNCTION_ARGS)
 
Datum icregexeqjoinsel (PG_FUNCTION_ARGS)
 
Datum likejoinsel (PG_FUNCTION_ARGS)
 
Datum iclikejoinsel (PG_FUNCTION_ARGS)
 
Datum regexnejoinsel (PG_FUNCTION_ARGS)
 
Datum icregexnejoinsel (PG_FUNCTION_ARGS)
 
Datum nlikejoinsel (PG_FUNCTION_ARGS)
 
Datum icnlikejoinsel (PG_FUNCTION_ARGS)
 
void mergejoinscansel (PlannerInfo *root, Node *clause, Oid opfamily, int strategy, bool nulls_first, Selectivity *leftstart, Selectivity *leftend, Selectivity *rightstart, Selectivity *rightend)
 
static Listadd_unique_group_var (PlannerInfo *root, List *varinfos, Node *var, VariableStatData *vardata)
 
double estimate_num_groups (PlannerInfo *root, List *groupExprs, double input_rows, List **pgset)
 
Selectivity estimate_hash_bucketsize (PlannerInfo *root, Node *hashkey, double nbuckets)
 
bool get_restriction_variable (PlannerInfo *root, List *args, int varRelid, VariableStatData *vardata, Node **other, bool *varonleft)
 
void get_join_variables (PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo, VariableStatData *vardata1, VariableStatData *vardata2, bool *join_is_reversed)
 
void examine_variable (PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata)
 
double get_variable_numdistinct (VariableStatData *vardata, bool *isdefault)
 
static int pattern_char_isalpha (char c, bool is_multibyte, pg_locale_t locale, bool locale_is_c)
 
static Pattern_Prefix_Status like_fixed_prefix (Const *patt_const, bool case_insensitive, Oid collation, Const **prefix_const, Selectivity *rest_selec)
 
static Pattern_Prefix_Status regex_fixed_prefix (Const *patt_const, bool case_insensitive, Oid collation, Const **prefix_const, Selectivity *rest_selec)
 
Pattern_Prefix_Status pattern_fixed_prefix (Const *patt, Pattern_Type ptype, Oid collation, Const **prefix, Selectivity *rest_selec)
 
static Selectivity regex_selectivity_sub (const char *patt, int pattlen, bool case_insensitive)
 
static bool byte_increment (unsigned char *ptr, int len)
 
Constmake_greater_string (const Const *str_const, FmgrInfo *ltproc, Oid collation)
 
Listdeconstruct_indexquals (IndexPath *path)
 
static Cost other_operands_eval_cost (PlannerInfo *root, List *qinfos)
 
static Cost orderby_operands_eval_cost (PlannerInfo *root, IndexPath *path)
 
void genericcostestimate (PlannerInfo *root, IndexPath *path, double loop_count, List *qinfos, GenericCosts *costs)
 
void btcostestimate (PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
 
void hashcostestimate (PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
 
void gistcostestimate (PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
 
void spgcostestimate (PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
 
static bool gincost_pattern (IndexOptInfo *index, int indexcol, Oid clause_op, Datum query, GinQualCounts *counts)
 
static bool gincost_opexpr (PlannerInfo *root, IndexOptInfo *index, IndexQualInfo *qinfo, GinQualCounts *counts)
 
static bool gincost_scalararrayopexpr (PlannerInfo *root, IndexOptInfo *index, IndexQualInfo *qinfo, double numIndexEntries, GinQualCounts *counts)
 
void gincostestimate (PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
 
void brincostestimate (PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
 

Variables

get_relation_stats_hook_type get_relation_stats_hook = NULL
 
get_index_stats_hook_type get_index_stats_hook = NULL
 

Macro Definition Documentation

#define ANY_CHAR_SEL   0.9 /* not 1, since it won't match end-of-string */

Definition at line 5635 of file selfuncs.c.

Referenced by like_selectivity(), and regex_selectivity_sub().

#define CHAR_RANGE_SEL   0.25

Definition at line 5634 of file selfuncs.c.

Referenced by regex_selectivity_sub().

#define FIXED_CHAR_SEL   0.20 /* about 1/5 */

Definition at line 5633 of file selfuncs.c.

Referenced by like_selectivity(), regex_selectivity(), and regex_selectivity_sub().

#define FULL_WILDCARD_SEL   5.0

Definition at line 5636 of file selfuncs.c.

Referenced by like_selectivity(), and regex_selectivity().

#define PARTIAL_WILDCARD_SEL   2.0

Definition at line 5637 of file selfuncs.c.

Referenced by regex_selectivity_sub().

Function Documentation

static List * add_predicate_to_quals ( IndexOptInfo index,
List indexQuals 
)
static

Definition at line 6449 of file selfuncs.c.

References IndexOptInfo::indpred, lfirst, list_concat(), list_make1, NIL, and predicate_implied_by().

Referenced by btcostestimate(), and genericcostestimate().

6450 {
6451  List *predExtraQuals = NIL;
6452  ListCell *lc;
6453 
6454  if (index->indpred == NIL)
6455  return indexQuals;
6456 
6457  foreach(lc, index->indpred)
6458  {
6459  Node *predQual = (Node *) lfirst(lc);
6460  List *oneQual = list_make1(predQual);
6461 
6462  if (!predicate_implied_by(oneQual, indexQuals))
6463  predExtraQuals = list_concat(predExtraQuals, oneQual);
6464  }
6465  /* list_concat avoids modifying the passed-in indexQuals list */
6466  return list_concat(predExtraQuals, indexQuals);
6467 }
#define NIL
Definition: pg_list.h:69
bool predicate_implied_by(List *predicate_list, List *restrictinfo_list)
Definition: predtest.c:128
Definition: nodes.h:508
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define list_make1(x1)
Definition: pg_list.h:133
#define lfirst(lc)
Definition: pg_list.h:106
List * indpred
Definition: relation.h:611
Definition: pg_list.h:45
static List* add_unique_group_var ( PlannerInfo root,
List varinfos,
Node var,
VariableStatData vardata 
)
static

Definition at line 3154 of file selfuncs.c.

References equal(), exprs_known_equal(), get_variable_numdistinct(), lappend(), lfirst, list_delete_ptr(), list_head(), lnext, GroupVarInfo::ndistinct, palloc(), VariableStatData::rel, GroupVarInfo::rel, and GroupVarInfo::var.

Referenced by estimate_num_groups().

3156 {
3157  GroupVarInfo *varinfo;
3158  double ndistinct;
3159  bool isdefault;
3160  ListCell *lc;
3161 
3162  ndistinct = get_variable_numdistinct(vardata, &isdefault);
3163 
3164  /* cannot use foreach here because of possible list_delete */
3165  lc = list_head(varinfos);
3166  while (lc)
3167  {
3168  varinfo = (GroupVarInfo *) lfirst(lc);
3169 
3170  /* must advance lc before list_delete possibly pfree's it */
3171  lc = lnext(lc);
3172 
3173  /* Drop exact duplicates */
3174  if (equal(var, varinfo->var))
3175  return varinfos;
3176 
3177  /*
3178  * Drop known-equal vars, but only if they belong to different
3179  * relations (see comments for estimate_num_groups)
3180  */
3181  if (vardata->rel != varinfo->rel &&
3182  exprs_known_equal(root, var, varinfo->var))
3183  {
3184  if (varinfo->ndistinct <= ndistinct)
3185  {
3186  /* Keep older item, forget new one */
3187  return varinfos;
3188  }
3189  else
3190  {
3191  /* Delete the older item */
3192  varinfos = list_delete_ptr(varinfos, varinfo);
3193  }
3194  }
3195  }
3196 
3197  varinfo = (GroupVarInfo *) palloc(sizeof(GroupVarInfo));
3198 
3199  varinfo->var = var;
3200  varinfo->rel = vardata->rel;
3201  varinfo->ndistinct = ndistinct;
3202  varinfos = lappend(varinfos, varinfo);
3203  return varinfos;
3204 }
bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2)
Definition: equivclass.c:1943
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
RelOptInfo * rel
Definition: selfuncs.h:70
List * list_delete_ptr(List *list, void *datum)
Definition: list.c:590
double ndistinct
Definition: selfuncs.c:3150
double get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
Definition: selfuncs.c:4753
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
Node * var
Definition: selfuncs.c:3148
#define lnext(lc)
Definition: pg_list.h:105
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
void * palloc(Size size)
Definition: mcxt.c:891
RelOptInfo * rel
Definition: selfuncs.c:3149
Selectivity booltestsel ( PlannerInfo root,
BoolTestType  booltesttype,
Node arg,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo 
)

Definition at line 1494 of file selfuncs.c.

References VariableStatData::atttype, VariableStatData::atttypmod, CLAMP_PROBABILITY, clause_selectivity(), DatumGetBool, DEFAULT_NOT_UNK_SEL, DEFAULT_UNK_SEL, elog, ERROR, examine_variable(), free_attstatsslot(), get_attstatsslot(), GETSTRUCT, HeapTupleIsValid, InvalidOid, IS_FALSE, IS_NOT_FALSE, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_TRUE, IS_UNKNOWN, NULL, ReleaseVariableStats, STATISTIC_KIND_MCV, VariableStatData::statsTuple, and values.

Referenced by clause_selectivity().

1496 {
1497  VariableStatData vardata;
1498  double selec;
1499 
1500  examine_variable(root, arg, varRelid, &vardata);
1501 
1502  if (HeapTupleIsValid(vardata.statsTuple))
1503  {
1504  Form_pg_statistic stats;
1505  double freq_null;
1506  Datum *values;
1507  int nvalues;
1508  float4 *numbers;
1509  int nnumbers;
1510 
1511  stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
1512  freq_null = stats->stanullfrac;
1513 
1514  if (get_attstatsslot(vardata.statsTuple,
1515  vardata.atttype, vardata.atttypmod,
1517  NULL,
1518  &values, &nvalues,
1519  &numbers, &nnumbers)
1520  && nnumbers > 0)
1521  {
1522  double freq_true;
1523  double freq_false;
1524 
1525  /*
1526  * Get first MCV frequency and derive frequency for true.
1527  */
1528  if (DatumGetBool(values[0]))
1529  freq_true = numbers[0];
1530  else
1531  freq_true = 1.0 - numbers[0] - freq_null;
1532 
1533  /*
1534  * Next derive frequency for false. Then use these as appropriate
1535  * to derive frequency for each case.
1536  */
1537  freq_false = 1.0 - freq_true - freq_null;
1538 
1539  switch (booltesttype)
1540  {
1541  case IS_UNKNOWN:
1542  /* select only NULL values */
1543  selec = freq_null;
1544  break;
1545  case IS_NOT_UNKNOWN:
1546  /* select non-NULL values */
1547  selec = 1.0 - freq_null;
1548  break;
1549  case IS_TRUE:
1550  /* select only TRUE values */
1551  selec = freq_true;
1552  break;
1553  case IS_NOT_TRUE:
1554  /* select non-TRUE values */
1555  selec = 1.0 - freq_true;
1556  break;
1557  case IS_FALSE:
1558  /* select only FALSE values */
1559  selec = freq_false;
1560  break;
1561  case IS_NOT_FALSE:
1562  /* select non-FALSE values */
1563  selec = 1.0 - freq_false;
1564  break;
1565  default:
1566  elog(ERROR, "unrecognized booltesttype: %d",
1567  (int) booltesttype);
1568  selec = 0.0; /* Keep compiler quiet */
1569  break;
1570  }
1571 
1572  free_attstatsslot(vardata.atttype, values, nvalues,
1573  numbers, nnumbers);
1574  }
1575  else
1576  {
1577  /*
1578  * No most-common-value info available. Still have null fraction
1579  * information, so use it for IS [NOT] UNKNOWN. Otherwise adjust
1580  * for null fraction and assume a 50-50 split of TRUE and FALSE.
1581  */
1582  switch (booltesttype)
1583  {
1584  case IS_UNKNOWN:
1585  /* select only NULL values */
1586  selec = freq_null;
1587  break;
1588  case IS_NOT_UNKNOWN:
1589  /* select non-NULL values */
1590  selec = 1.0 - freq_null;
1591  break;
1592  case IS_TRUE:
1593  case IS_FALSE:
1594  /* Assume we select half of the non-NULL values */
1595  selec = (1.0 - freq_null) / 2.0;
1596  break;
1597  case IS_NOT_TRUE:
1598  case IS_NOT_FALSE:
1599  /* Assume we select NULLs plus half of the non-NULLs */
1600  /* equiv. to freq_null + (1.0 - freq_null) / 2.0 */
1601  selec = (freq_null + 1.0) / 2.0;
1602  break;
1603  default:
1604  elog(ERROR, "unrecognized booltesttype: %d",
1605  (int) booltesttype);
1606  selec = 0.0; /* Keep compiler quiet */
1607  break;
1608  }
1609  }
1610  }
1611  else
1612  {
1613  /*
1614  * If we can't get variable statistics for the argument, perhaps
1615  * clause_selectivity can do something with it. We ignore the
1616  * possibility of a NULL value when using clause_selectivity, and just
1617  * assume the value is either TRUE or FALSE.
1618  */
1619  switch (booltesttype)
1620  {
1621  case IS_UNKNOWN:
1622  selec = DEFAULT_UNK_SEL;
1623  break;
1624  case IS_NOT_UNKNOWN:
1625  selec = DEFAULT_NOT_UNK_SEL;
1626  break;
1627  case IS_TRUE:
1628  case IS_NOT_FALSE:
1629  selec = (double) clause_selectivity(root, arg,
1630  varRelid,
1631  jointype, sjinfo);
1632  break;
1633  case IS_FALSE:
1634  case IS_NOT_TRUE:
1635  selec = 1.0 - (double) clause_selectivity(root, arg,
1636  varRelid,
1637  jointype, sjinfo);
1638  break;
1639  default:
1640  elog(ERROR, "unrecognized booltesttype: %d",
1641  (int) booltesttype);
1642  selec = 0.0; /* Keep compiler quiet */
1643  break;
1644  }
1645  }
1646 
1647  ReleaseVariableStats(vardata);
1648 
1649  /* result should be in range, but make sure... */
1650  CLAMP_PROBABILITY(selec);
1651 
1652  return (Selectivity) selec;
1653 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
HeapTuple statsTuple
Definition: selfuncs.h:71
double Selectivity
Definition: nodes.h:631
bool get_attstatsslot(HeapTuple statstuple, Oid atttype, int32 atttypmod, int reqkind, Oid reqop, Oid *actualop, Datum **values, int *nvalues, float4 **numbers, int *nnumbers)
Definition: lsyscache.c:2854
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:129
int32 atttypmod
Definition: selfuncs.h:76
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:57
#define DEFAULT_NOT_UNK_SEL
Definition: selfuncs.h:50
#define ERROR
Definition: elog.h:43
Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:483
#define DatumGetBool(X)
Definition: postgres.h:401
#define STATISTIC_KIND_MCV
Definition: pg_statistic.h:204
#define DEFAULT_UNK_SEL
Definition: selfuncs.h:49
float float4
Definition: c.h:377
uintptr_t Datum
Definition: postgres.h:374
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void examine_variable(PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata)
Definition: selfuncs.c:4409
#define NULL
Definition: c.h:226
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:80
#define elog
Definition: elog.h:219
void free_attstatsslot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers)
Definition: lsyscache.c:2978
Selectivity boolvarsel ( PlannerInfo root,
Node arg,
int  varRelid 
)

Definition at line 1455 of file selfuncs.c.

References BooleanEqualOperator, BoolGetDatum, examine_variable(), HeapTupleIsValid, is_funcclause, ReleaseVariableStats, VariableStatData::statsTuple, and var_eq_const().

Referenced by clause_selectivity().

1456 {
1457  VariableStatData vardata;
1458  double selec;
1459 
1460  examine_variable(root, arg, varRelid, &vardata);
1461  if (HeapTupleIsValid(vardata.statsTuple))
1462  {
1463  /*
1464  * A boolean variable V is equivalent to the clause V = 't', so we
1465  * compute the selectivity as if that is what we have.
1466  */
1467  selec = var_eq_const(&vardata, BooleanEqualOperator,
1468  BoolGetDatum(true), false, true);
1469  }
1470  else if (is_funcclause(arg))
1471  {
1472  /*
1473  * If we have no stats and it's a function call, estimate 0.3333333.
1474  * This seems a pretty unprincipled choice, but Postgres has been
1475  * using that estimate for function calls since 1992. The hoariness
1476  * of this behavior suggests that we should not be in too much hurry
1477  * to use another value.
1478  */
1479  selec = 0.3333333;
1480  }
1481  else
1482  {
1483  /* Otherwise, the default estimate is 0.5 */
1484  selec = 0.5;
1485  }
1486  ReleaseVariableStats(vardata);
1487  return selec;
1488 }
HeapTuple statsTuple
Definition: selfuncs.h:71
#define is_funcclause(clause)
Definition: clauses.h:21
#define BooleanEqualOperator
Definition: pg_operator.h:114
static double var_eq_const(VariableStatData *vardata, Oid operator, Datum constval, bool constisnull, bool varonleft)
Definition: selfuncs.c:264
#define BoolGetDatum(X)
Definition: postgres.h:410
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void examine_variable(PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata)
Definition: selfuncs.c:4409
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:80
void brincostestimate ( PlannerInfo root,
IndexPath path,
double  loop_count,
Cost indexStartupCost,
Cost indexTotalCost,
Selectivity indexSelectivity,
double *  indexCorrelation,
double *  indexPages 
)

Definition at line 7555 of file selfuncs.c.

References clauselist_selectivity(), cpu_index_tuple_cost, cpu_operator_cost, deconstruct_indexquals(), get_tablespace_page_costs(), IndexPath::indexinfo, IndexPath::indexorderbys, IndexPath::indexquals, JOIN_INNER, list_length(), NULL, orderby_operands_eval_cost(), other_operands_eval_cost(), IndexOptInfo::pages, IndexOptInfo::rel, RelOptInfo::relid, IndexOptInfo::reltablespace, and IndexOptInfo::tuples.

Referenced by brinhandler().

7559 {
7560  IndexOptInfo *index = path->indexinfo;
7561  List *indexQuals = path->indexquals;
7562  List *indexOrderBys = path->indexorderbys;
7563  double numPages = index->pages;
7564  double numTuples = index->tuples;
7565  List *qinfos;
7566  Cost spc_seq_page_cost;
7567  Cost spc_random_page_cost;
7568  double qual_op_cost;
7569  double qual_arg_cost;
7570 
7571  /* Do preliminary analysis of indexquals */
7572  qinfos = deconstruct_indexquals(path);
7573 
7574  /* fetch estimated page cost for tablespace containing index */
7576  &spc_random_page_cost,
7577  &spc_seq_page_cost);
7578 
7579  /*
7580  * BRIN indexes are always read in full; use that as startup cost.
7581  *
7582  * XXX maybe only include revmap pages here?
7583  */
7584  *indexStartupCost = spc_seq_page_cost * numPages * loop_count;
7585 
7586  /*
7587  * To read a BRIN index there might be a bit of back and forth over
7588  * regular pages, as revmap might point to them out of sequential order;
7589  * calculate this as reading the whole index in random order.
7590  */
7591  *indexTotalCost = spc_random_page_cost * numPages * loop_count;
7592 
7593  *indexSelectivity =
7594  clauselist_selectivity(root, indexQuals,
7595  path->indexinfo->rel->relid,
7596  JOIN_INNER, NULL);
7597  *indexCorrelation = 1;
7598 
7599  /*
7600  * Add on index qual eval costs, much as in genericcostestimate.
7601  */
7602  qual_arg_cost = other_operands_eval_cost(root, qinfos) +
7603  orderby_operands_eval_cost(root, path);
7604  qual_op_cost = cpu_operator_cost *
7605  (list_length(indexQuals) + list_length(indexOrderBys));
7606 
7607  *indexStartupCost += qual_arg_cost;
7608  *indexTotalCost += qual_arg_cost;
7609  *indexTotalCost += (numTuples * *indexSelectivity) * (cpu_index_tuple_cost + qual_op_cost);
7610  *indexPages = index->pages;
7611 
7612  /* XXX what about pages_per_range? */
7613 }
IndexOptInfo * indexinfo
Definition: relation.h:972
Oid reltablespace
Definition: relation.h:589
static Cost other_operands_eval_cost(PlannerInfo *root, List *qinfos)
Definition: selfuncs.c:6176
double tuples
Definition: relation.h:594
List * deconstruct_indexquals(IndexPath *path)
Definition: selfuncs.c:6081
static Cost orderby_operands_eval_cost(PlannerInfo *root, IndexPath *path)
Definition: selfuncs.c:6201
Definition: type.h:90
BlockNumber pages
Definition: relation.h:593
List * indexquals
Definition: relation.h:974
RelOptInfo * rel
Definition: relation.h:590
double cpu_operator_cost
Definition: costsize.c:108
void get_tablespace_page_costs(Oid spcid, double *spc_random_page_cost, double *spc_seq_page_cost)
Definition: spccache.c:178
Index relid
Definition: relation.h:518
List * indexorderbys
Definition: relation.h:976
#define NULL
Definition: c.h:226
static int list_length(const List *l)
Definition: pg_list.h:89
Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:92
Definition: pg_list.h:45
double cpu_index_tuple_cost
Definition: costsize.c:107
double Cost
Definition: nodes.h:632
void btcostestimate ( PlannerInfo root,
IndexPath path,
double  loop_count,
Cost indexStartupCost,
Cost indexTotalCost,
Selectivity indexSelectivity,
double *  indexCorrelation,
double *  indexPages 
)

Definition at line 6471 of file selfuncs.c.

References add_predicate_to_quals(), Assert, BoolGetDatum, BTEqualStrategyNumber, BTLessStrategyNumber, RestrictInfo::clause, IndexQualInfo::clause_op, clauselist_selectivity(), cpu_operator_cost, deconstruct_indexquals(), elog, ERROR, estimate_array_length(), free_attstatsslot(), VariableStatData::freefunc, genericcostestimate(), get_attstatsslot(), get_index_stats_hook, get_op_opfamily_strategy(), get_opfamily_member(), get_relation_stats_hook, HeapTupleIsValid, IndexQualInfo::indexcol, GenericCosts::indexCorrelation, IndexPath::indexinfo, IndexOptInfo::indexkeys, IndexOptInfo::indexoid, GenericCosts::indexSelectivity, GenericCosts::indexStartupCost, GenericCosts::indexTotalCost, RangeTblEntry::inh, Int16GetDatum, InvalidOid, IS_NULL, IsA, JOIN_INNER, lappend(), lfirst, MemSet, IndexOptInfo::ncolumns, NIL, NULL, NullTest::nulltesttype, GenericCosts::num_sa_scans, GenericCosts::numIndexPages, GenericCosts::numIndexTuples, ObjectIdGetDatum, OidIsValid, IndexOptInfo::opcintype, IndexOptInfo::opfamily, IndexQualInfo::other_operand, planner_rt_fetch, IndexOptInfo::rel, ReleaseSysCache(), ReleaseVariableStats, RelOptInfo::relid, RangeTblEntry::relid, IndexOptInfo::reverse_sort, IndexQualInfo::rinfo, rint(), RTE_RELATION, RangeTblEntry::rtekind, SearchSysCache3, STATISTIC_KIND_CORRELATION, STATRELATTINH, VariableStatData::statsTuple, IndexOptInfo::tree_height, RelOptInfo::tuples, IndexOptInfo::tuples, and IndexOptInfo::unique.

Referenced by bthandler().

6475 {
6476  IndexOptInfo *index = path->indexinfo;
6477  List *qinfos;
6478  GenericCosts costs;
6479  Oid relid;
6480  AttrNumber colnum;
6481  VariableStatData vardata;
6482  double numIndexTuples;
6483  Cost descentCost;
6484  List *indexBoundQuals;
6485  int indexcol;
6486  bool eqQualHere;
6487  bool found_saop;
6488  bool found_is_null_op;
6489  double num_sa_scans;
6490  ListCell *lc;
6491 
6492  /* Do preliminary analysis of indexquals */
6493  qinfos = deconstruct_indexquals(path);
6494 
6495  /*
6496  * For a btree scan, only leading '=' quals plus inequality quals for the
6497  * immediately next attribute contribute to index selectivity (these are
6498  * the "boundary quals" that determine the starting and stopping points of
6499  * the index scan). Additional quals can suppress visits to the heap, so
6500  * it's OK to count them in indexSelectivity, but they should not count
6501  * for estimating numIndexTuples. So we must examine the given indexquals
6502  * to find out which ones count as boundary quals. We rely on the
6503  * knowledge that they are given in index column order.
6504  *
6505  * For a RowCompareExpr, we consider only the first column, just as
6506  * rowcomparesel() does.
6507  *
6508  * If there's a ScalarArrayOpExpr in the quals, we'll actually perform N
6509  * index scans not one, but the ScalarArrayOpExpr's operator can be
6510  * considered to act the same as it normally does.
6511  */
6512  indexBoundQuals = NIL;
6513  indexcol = 0;
6514  eqQualHere = false;
6515  found_saop = false;
6516  found_is_null_op = false;
6517  num_sa_scans = 1;
6518  foreach(lc, qinfos)
6519  {
6520  IndexQualInfo *qinfo = (IndexQualInfo *) lfirst(lc);
6521  RestrictInfo *rinfo = qinfo->rinfo;
6522  Expr *clause = rinfo->clause;
6523  Oid clause_op;
6524  int op_strategy;
6525 
6526  if (indexcol != qinfo->indexcol)
6527  {
6528  /* Beginning of a new column's quals */
6529  if (!eqQualHere)
6530  break; /* done if no '=' qual for indexcol */
6531  eqQualHere = false;
6532  indexcol++;
6533  if (indexcol != qinfo->indexcol)
6534  break; /* no quals at all for indexcol */
6535  }
6536 
6537  if (IsA(clause, ScalarArrayOpExpr))
6538  {
6539  int alength = estimate_array_length(qinfo->other_operand);
6540 
6541  found_saop = true;
6542  /* count up number of SA scans induced by indexBoundQuals only */
6543  if (alength > 1)
6544  num_sa_scans *= alength;
6545  }
6546  else if (IsA(clause, NullTest))
6547  {
6548  NullTest *nt = (NullTest *) clause;
6549 
6550  if (nt->nulltesttype == IS_NULL)
6551  {
6552  found_is_null_op = true;
6553  /* IS NULL is like = for selectivity determination purposes */
6554  eqQualHere = true;
6555  }
6556  }
6557 
6558  /*
6559  * We would need to commute the clause_op if not varonleft, except
6560  * that we only care if it's equality or not, so that refinement is
6561  * unnecessary.
6562  */
6563  clause_op = qinfo->clause_op;
6564 
6565  /* check for equality operator */
6566  if (OidIsValid(clause_op))
6567  {
6568  op_strategy = get_op_opfamily_strategy(clause_op,
6569  index->opfamily[indexcol]);
6570  Assert(op_strategy != 0); /* not a member of opfamily?? */
6571  if (op_strategy == BTEqualStrategyNumber)
6572  eqQualHere = true;
6573  }
6574 
6575  indexBoundQuals = lappend(indexBoundQuals, rinfo);
6576  }
6577 
6578  /*
6579  * If index is unique and we found an '=' clause for each column, we can
6580  * just assume numIndexTuples = 1 and skip the expensive
6581  * clauselist_selectivity calculations. However, a ScalarArrayOp or
6582  * NullTest invalidates that theory, even though it sets eqQualHere.
6583  */
6584  if (index->unique &&
6585  indexcol == index->ncolumns - 1 &&
6586  eqQualHere &&
6587  !found_saop &&
6588  !found_is_null_op)
6589  numIndexTuples = 1.0;
6590  else
6591  {
6592  List *selectivityQuals;
6593  Selectivity btreeSelectivity;
6594 
6595  /*
6596  * If the index is partial, AND the index predicate with the
6597  * index-bound quals to produce a more accurate idea of the number of
6598  * rows covered by the bound conditions.
6599  */
6600  selectivityQuals = add_predicate_to_quals(index, indexBoundQuals);
6601 
6602  btreeSelectivity = clauselist_selectivity(root, selectivityQuals,
6603  index->rel->relid,
6604  JOIN_INNER,
6605  NULL);
6606  numIndexTuples = btreeSelectivity * index->rel->tuples;
6607 
6608  /*
6609  * As in genericcostestimate(), we have to adjust for any
6610  * ScalarArrayOpExpr quals included in indexBoundQuals, and then round
6611  * to integer.
6612  */
6613  numIndexTuples = rint(numIndexTuples / num_sa_scans);
6614  }
6615 
6616  /*
6617  * Now do generic index cost estimation.
6618  */
6619  MemSet(&costs, 0, sizeof(costs));
6620  costs.numIndexTuples = numIndexTuples;
6621 
6622  genericcostestimate(root, path, loop_count, qinfos, &costs);
6623 
6624  /*
6625  * Add a CPU-cost component to represent the costs of initial btree
6626  * descent. We don't charge any I/O cost for touching upper btree levels,
6627  * since they tend to stay in cache, but we still have to do about log2(N)
6628  * comparisons to descend a btree of N leaf tuples. We charge one
6629  * cpu_operator_cost per comparison.
6630  *
6631  * If there are ScalarArrayOpExprs, charge this once per SA scan. The
6632  * ones after the first one are not startup cost so far as the overall
6633  * plan is concerned, so add them only to "total" cost.
6634  */
6635  if (index->tuples > 1) /* avoid computing log(0) */
6636  {
6637  descentCost = ceil(log(index->tuples) / log(2.0)) * cpu_operator_cost;
6638  costs.indexStartupCost += descentCost;
6639  costs.indexTotalCost += costs.num_sa_scans * descentCost;
6640  }
6641 
6642  /*
6643  * Even though we're not charging I/O cost for touching upper btree pages,
6644  * it's still reasonable to charge some CPU cost per page descended
6645  * through. Moreover, if we had no such charge at all, bloated indexes
6646  * would appear to have the same search cost as unbloated ones, at least
6647  * in cases where only a single leaf page is expected to be visited. This
6648  * cost is somewhat arbitrarily set at 50x cpu_operator_cost per page
6649  * touched. The number of such pages is btree tree height plus one (ie,
6650  * we charge for the leaf page too). As above, charge once per SA scan.
6651  */
6652  descentCost = (index->tree_height + 1) * 50.0 * cpu_operator_cost;
6653  costs.indexStartupCost += descentCost;
6654  costs.indexTotalCost += costs.num_sa_scans * descentCost;
6655 
6656  /*
6657  * If we can get an estimate of the first column's ordering correlation C
6658  * from pg_statistic, estimate the index correlation as C for a
6659  * single-column index, or C * 0.75 for multiple columns. (The idea here
6660  * is that multiple columns dilute the importance of the first column's
6661  * ordering, but don't negate it entirely. Before 8.0 we divided the
6662  * correlation by the number of columns, but that seems too strong.)
6663  */
6664  MemSet(&vardata, 0, sizeof(vardata));
6665 
6666  if (index->indexkeys[0] != 0)
6667  {
6668  /* Simple variable --- look to stats for the underlying table */
6669  RangeTblEntry *rte = planner_rt_fetch(index->rel->relid, root);
6670 
6671  Assert(rte->rtekind == RTE_RELATION);
6672  relid = rte->relid;
6673  Assert(relid != InvalidOid);
6674  colnum = index->indexkeys[0];
6675 
6677  (*get_relation_stats_hook) (root, rte, colnum, &vardata))
6678  {
6679  /*
6680  * The hook took control of acquiring a stats tuple. If it did
6681  * supply a tuple, it'd better have supplied a freefunc.
6682  */
6683  if (HeapTupleIsValid(vardata.statsTuple) &&
6684  !vardata.freefunc)
6685  elog(ERROR, "no function provided to release variable stats with");
6686  }
6687  else
6688  {
6690  ObjectIdGetDatum(relid),
6691  Int16GetDatum(colnum),
6692  BoolGetDatum(rte->inh));
6693  vardata.freefunc = ReleaseSysCache;
6694  }
6695  }
6696  else
6697  {
6698  /* Expression --- maybe there are stats for the index itself */
6699  relid = index->indexoid;
6700  colnum = 1;
6701 
6702  if (get_index_stats_hook &&
6703  (*get_index_stats_hook) (root, relid, colnum, &vardata))
6704  {
6705  /*
6706  * The hook took control of acquiring a stats tuple. If it did
6707  * supply a tuple, it'd better have supplied a freefunc.
6708  */
6709  if (HeapTupleIsValid(vardata.statsTuple) &&
6710  !vardata.freefunc)
6711  elog(ERROR, "no function provided to release variable stats with");
6712  }
6713  else
6714  {
6716  ObjectIdGetDatum(relid),
6717  Int16GetDatum(colnum),
6718  BoolGetDatum(false));
6719  vardata.freefunc = ReleaseSysCache;
6720  }
6721  }
6722 
6723  if (HeapTupleIsValid(vardata.statsTuple))
6724  {
6725  Oid sortop;
6726  float4 *numbers;
6727  int nnumbers;
6728 
6729  sortop = get_opfamily_member(index->opfamily[0],
6730  index->opcintype[0],
6731  index->opcintype[0],
6733  if (OidIsValid(sortop) &&
6736  sortop,
6737  NULL,
6738  NULL, NULL,
6739  &numbers, &nnumbers))
6740  {
6741  double varCorrelation;
6742 
6743  Assert(nnumbers == 1);
6744  varCorrelation = numbers[0];
6745 
6746  if (index->reverse_sort[0])
6747  varCorrelation = -varCorrelation;
6748 
6749  if (index->ncolumns > 1)
6750  costs.indexCorrelation = varCorrelation * 0.75;
6751  else
6752  costs.indexCorrelation = varCorrelation;
6753 
6754  free_attstatsslot(InvalidOid, NULL, 0, numbers, nnumbers);
6755  }
6756  }
6757 
6758  ReleaseVariableStats(vardata);
6759 
6760  *indexStartupCost = costs.indexStartupCost;
6761  *indexTotalCost = costs.indexTotalCost;
6762  *indexSelectivity = costs.indexSelectivity;
6763  *indexCorrelation = costs.indexCorrelation;
6764  *indexPages = costs.numIndexPages;
6765 }
Selectivity indexSelectivity
Definition: selfuncs.h:130
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
IndexOptInfo * indexinfo
Definition: relation.h:972
HeapTuple statsTuple
Definition: selfuncs.h:71
double tuples
Definition: relation.h:529
static List * add_predicate_to_quals(IndexOptInfo *index, List *indexQuals)
Definition: selfuncs.c:6449
#define Int16GetDatum(X)
Definition: postgres.h:459
#define MemSet(start, val, len)
Definition: c.h:853
double Selectivity
Definition: nodes.h:631
bool get_attstatsslot(HeapTuple statstuple, Oid atttype, int32 atttypmod, int reqkind, Oid reqop, Oid *actualop, Datum **values, int *nvalues, float4 **numbers, int *nnumbers)
Definition: lsyscache.c:2854
double tuples
Definition: relation.h:594
unsigned int Oid
Definition: postgres_ext.h:31
int tree_height
Definition: relation.h:595
#define OidIsValid(objectId)
Definition: c.h:534
RestrictInfo * rinfo
Definition: selfuncs.h:105
List * deconstruct_indexquals(IndexPath *path)
Definition: selfuncs.c:6081
bool unique
Definition: relation.h:621
Definition: type.h:90
int estimate_array_length(Node *arrayexpr)
Definition: selfuncs.c:2078
RelOptInfo * rel
Definition: relation.h:590
#define planner_rt_fetch(rti, root)
Definition: relation.h:320
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
double num_sa_scans
Definition: selfuncs.h:137
#define STATISTIC_KIND_CORRELATION
Definition: pg_statistic.h:233
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
double cpu_operator_cost
Definition: costsize.c:108
Cost indexTotalCost
Definition: selfuncs.h:129
get_relation_stats_hook_type get_relation_stats_hook
Definition: selfuncs.c:148
double rint(double x)
Definition: rint.c:22
int ncolumns
Definition: relation.h:598
Index relid
Definition: relation.h:518
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1637
float float4
Definition: c.h:377
double indexCorrelation
Definition: selfuncs.h:131
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
NullTestType nulltesttype
Definition: primnodes.h:1157
#define BoolGetDatum(X)
Definition: postgres.h:410
#define InvalidOid
Definition: postgres_ext.h:36
double numIndexTuples
Definition: selfuncs.h:135
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
get_index_stats_hook_type get_index_stats_hook
Definition: selfuncs.c:149
Oid * opcintype
Definition: relation.h:602
Cost indexStartupCost
Definition: selfuncs.h:128
Oid * opfamily
Definition: relation.h:601
RTEKind rtekind
Definition: parsenodes.h:882
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:80
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:80
Node * other_operand
Definition: selfuncs.h:109
#define SearchSysCache3(cacheId, key1, key2, key3)
Definition: syscache.h:153
int * indexkeys
Definition: relation.h:599
#define elog
Definition: elog.h:219
Oid indexoid
Definition: relation.h:588
Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:92
void(* freefunc)(HeapTuple tuple)
Definition: selfuncs.h:73
bool * reverse_sort
Definition: relation.h:604
#define BTLessStrategyNumber
Definition: stratnum.h:29
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
void free_attstatsslot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers)
Definition: lsyscache.c:2978
#define BTEqualStrategyNumber
Definition: stratnum.h:31
double Cost
Definition: nodes.h:632
void genericcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, List *qinfos, GenericCosts *costs)
Definition: selfuncs.c:6230
double numIndexPages
Definition: selfuncs.h:134
static bool byte_increment ( unsigned char *  ptr,
int  len 
)
static

Definition at line 5804 of file selfuncs.c.

Referenced by make_greater_string().

5805 {
5806  if (*ptr >= 255)
5807  return false;
5808  (*ptr)++;
5809  return true;
5810 }
static void convert_bytea_to_scalar ( Datum  value,
double *  scaledvalue,
Datum  lobound,
double *  scaledlobound,
Datum  hibound,
double *  scaledhibound 
)
static

Definition at line 4108 of file selfuncs.c.

References convert_one_bytea_to_scalar(), DatumGetPointer, i, Min, VARDATA, VARHDRSZ, and VARSIZE.

Referenced by convert_to_scalar().

4114 {
4115  int rangelo,
4116  rangehi,
4117  valuelen = VARSIZE(DatumGetPointer(value)) - VARHDRSZ,
4118  loboundlen = VARSIZE(DatumGetPointer(lobound)) - VARHDRSZ,
4119  hiboundlen = VARSIZE(DatumGetPointer(hibound)) - VARHDRSZ,
4120  i,
4121  minlen;
4122  unsigned char *valstr = (unsigned char *) VARDATA(DatumGetPointer(value)),
4123  *lostr = (unsigned char *) VARDATA(DatumGetPointer(lobound)),
4124  *histr = (unsigned char *) VARDATA(DatumGetPointer(hibound));
4125 
4126  /*
4127  * Assume bytea data is uniformly distributed across all byte values.
4128  */
4129  rangelo = 0;
4130  rangehi = 255;
4131 
4132  /*
4133  * Now strip any common prefix of the three strings.
4134  */
4135  minlen = Min(Min(valuelen, loboundlen), hiboundlen);
4136  for (i = 0; i < minlen; i++)
4137  {
4138  if (*lostr != *histr || *lostr != *valstr)
4139  break;
4140  lostr++, histr++, valstr++;
4141  loboundlen--, hiboundlen--, valuelen--;
4142  }
4143 
4144  /*
4145  * Now we can do the conversions.
4146  */
4147  *scaledvalue = convert_one_bytea_to_scalar(valstr, valuelen, rangelo, rangehi);
4148  *scaledlobound = convert_one_bytea_to_scalar(lostr, loboundlen, rangelo, rangehi);
4149  *scaledhibound = convert_one_bytea_to_scalar(histr, hiboundlen, rangelo, rangehi);
4150 }
static struct @76 value
#define VARDATA(PTR)
Definition: postgres.h:305
#define VARSIZE(PTR)
Definition: postgres.h:306
#define VARHDRSZ
Definition: c.h:441
#define Min(x, y)
Definition: c.h:802
static double convert_one_bytea_to_scalar(unsigned char *value, int valuelen, int rangelo, int rangehi)
Definition: selfuncs.c:4153
#define DatumGetPointer(X)
Definition: postgres.h:557
int i
static double convert_numeric_to_scalar ( Datum  value,
Oid  typid 
)
static

Definition at line 3816 of file selfuncs.c.

References BOOLOID, DatumGetBool, DatumGetFloat4, DatumGetFloat8, DatumGetInt16, DatumGetInt32, DatumGetInt64, DatumGetObjectId, DirectFunctionCall1, elog, ERROR, FLOAT4OID, FLOAT8OID, INT2OID, INT4OID, INT8OID, numeric_float8_no_overflow(), NUMERICOID, OIDOID, REGCLASSOID, REGCONFIGOID, REGDICTIONARYOID, REGNAMESPACEOID, REGOPERATOROID, REGOPEROID, REGPROCEDUREOID, REGPROCOID, REGROLEOID, and REGTYPEOID.

Referenced by convert_to_scalar().

3817 {
3818  switch (typid)
3819  {
3820  case BOOLOID:
3821  return (double) DatumGetBool(value);
3822  case INT2OID:
3823  return (double) DatumGetInt16(value);
3824  case INT4OID:
3825  return (double) DatumGetInt32(value);
3826  case INT8OID:
3827  return (double) DatumGetInt64(value);
3828  case FLOAT4OID:
3829  return (double) DatumGetFloat4(value);
3830  case FLOAT8OID:
3831  return (double) DatumGetFloat8(value);
3832  case NUMERICOID:
3833  /* Note: out-of-range values will be clamped to +-HUGE_VAL */
3834  return (double)
3836  value));
3837  case OIDOID:
3838  case REGPROCOID:
3839  case REGPROCEDUREOID:
3840  case REGOPEROID:
3841  case REGOPERATOROID:
3842  case REGCLASSOID:
3843  case REGTYPEOID:
3844  case REGCONFIGOID:
3845  case REGDICTIONARYOID:
3846  case REGROLEOID:
3847  case REGNAMESPACEOID:
3848  /* we can treat OIDs as integers... */
3849  return (double) DatumGetObjectId(value);
3850  }
3851 
3852  /*
3853  * Can't get here unless someone tries to use scalarltsel/scalargtsel on
3854  * an operator with one numeric and one non-numeric operand.
3855  */
3856  elog(ERROR, "unsupported type: %u", typid);
3857  return 0;
3858 }
#define REGCLASSOID
Definition: pg_type.h:565
static struct @76 value
#define DatumGetInt32(X)
Definition: postgres.h:480
#define REGROLEOID
Definition: pg_type.h:573
#define OIDOID
Definition: pg_type.h:328
#define NUMERICOID
Definition: pg_type.h:542
#define DatumGetObjectId(X)
Definition: postgres.h:508
#define INT4OID
Definition: pg_type.h:316
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
#define REGTYPEOID
Definition: pg_type.h:569
#define REGOPEROID
Definition: pg_type.h:557
#define ERROR
Definition: elog.h:43
#define DatumGetInt64(X)
Definition: postgres.h:615
#define INT2OID
Definition: pg_type.h:308
#define DatumGetInt16(X)
Definition: postgres.h:452
#define DatumGetBool(X)
Definition: postgres.h:401
#define REGDICTIONARYOID
Definition: pg_type.h:615
#define FLOAT4OID
Definition: pg_type.h:408
#define DatumGetFloat8(X)
Definition: postgres.h:736
#define INT8OID
Definition: pg_type.h:304
#define DatumGetFloat4(X)
Definition: postgres.h:688
Datum numeric_float8_no_overflow(PG_FUNCTION_ARGS)
Definition: numeric.c:3118
#define FLOAT8OID
Definition: pg_type.h:411
#define BOOLOID
Definition: pg_type.h:288
#define REGCONFIGOID
Definition: pg_type.h:612
#define elog
Definition: elog.h:219
#define REGPROCEDUREOID
Definition: pg_type.h:553
#define REGNAMESPACEOID
Definition: pg_type.h:577
#define REGOPERATOROID
Definition: pg_type.h:561
#define REGPROCOID
Definition: pg_type.h:320
static double convert_one_bytea_to_scalar ( unsigned char *  value,
int  valuelen,
int  rangelo,
int  rangehi 
)
static

Definition at line 4153 of file selfuncs.c.

Referenced by convert_bytea_to_scalar().

4155 {
4156  double num,
4157  denom,
4158  base;
4159 
4160  if (valuelen <= 0)
4161  return 0.0; /* empty string has scalar value 0 */
4162 
4163  /*
4164  * Since base is 256, need not consider more than about 10 chars (even
4165  * this many seems like overkill)
4166  */
4167  if (valuelen > 10)
4168  valuelen = 10;
4169 
4170  /* Convert initial characters to fraction */
4171  base = rangehi - rangelo + 1;
4172  num = 0.0;
4173  denom = base;
4174  while (valuelen-- > 0)
4175  {
4176  int ch = *value++;
4177 
4178  if (ch < rangelo)
4179  ch = rangelo - 1;
4180  else if (ch > rangehi)
4181  ch = rangehi + 1;
4182  num += ((double) (ch - rangelo)) / denom;
4183  denom *= base;
4184  }
4185 
4186  return num;
4187 }
static struct @76 value
static double convert_one_string_to_scalar ( char *  value,
int  rangelo,
int  rangehi 
)
static

Definition at line 3961 of file selfuncs.c.

Referenced by convert_string_to_scalar().

3962 {
3963  int slen = strlen(value);
3964  double num,
3965  denom,
3966  base;
3967 
3968  if (slen <= 0)
3969  return 0.0; /* empty string has scalar value 0 */
3970 
3971  /*
3972  * There seems little point in considering more than a dozen bytes from
3973  * the string. Since base is at least 10, that will give us nominal
3974  * resolution of at least 12 decimal digits, which is surely far more
3975  * precision than this estimation technique has got anyway (especially in
3976  * non-C locales). Also, even with the maximum possible base of 256, this
3977  * ensures denom cannot grow larger than 256^13 = 2.03e31, which will not
3978  * overflow on any known machine.
3979  */
3980  if (slen > 12)
3981  slen = 12;
3982 
3983  /* Convert initial characters to fraction */
3984  base = rangehi - rangelo + 1;
3985  num = 0.0;
3986  denom = base;
3987  while (slen-- > 0)
3988  {
3989  int ch = (unsigned char) *value++;
3990 
3991  if (ch < rangelo)
3992  ch = rangelo - 1;
3993  else if (ch > rangehi)
3994  ch = rangehi + 1;
3995  num += ((double) (ch - rangelo)) / denom;
3996  denom *= base;
3997  }
3998 
3999  return num;
4000 }
static struct @76 value
static char * convert_string_datum ( Datum  value,
Oid  typid 
)
static

Definition at line 4009 of file selfuncs.c.

References Assert, BPCHAROID, CHAROID, DatumGetChar, DatumGetPointer, DEFAULT_COLLATION_OID, elog, ERROR, lc_collate_is_c(), NAMEOID, NameStr, NULL, palloc(), pfree(), PG_USED_FOR_ASSERTS_ONLY, pstrdup(), TextDatumGetCString, TEXTOID, val, and VARCHAROID.

Referenced by convert_to_scalar().

4010 {
4011  char *val;
4012 
4013  switch (typid)
4014  {
4015  case CHAROID:
4016  val = (char *) palloc(2);
4017  val[0] = DatumGetChar(value);
4018  val[1] = '\0';
4019  break;
4020  case BPCHAROID:
4021  case VARCHAROID:
4022  case TEXTOID:
4023  val = TextDatumGetCString(value);
4024  break;
4025  case NAMEOID:
4026  {
4028 
4029  val = pstrdup(NameStr(*nm));
4030  break;
4031  }
4032  default:
4033 
4034  /*
4035  * Can't get here unless someone tries to use scalarltsel on an
4036  * operator with one string and one non-string operand.
4037  */
4038  elog(ERROR, "unsupported type: %u", typid);
4039  return NULL;
4040  }
4041 
4043  {
4044  char *xfrmstr;
4045  size_t xfrmlen;
4046  size_t xfrmlen2 PG_USED_FOR_ASSERTS_ONLY;
4047 
4048  /*
4049  * XXX: We could guess at a suitable output buffer size and only call
4050  * strxfrm twice if our guess is too small.
4051  *
4052  * XXX: strxfrm doesn't support UTF-8 encoding on Win32, it can return
4053  * bogus data or set an error. This is not really a problem unless it
4054  * crashes since it will only give an estimation error and nothing
4055  * fatal.
4056  */
4057 #if _MSC_VER == 1400 /* VS.Net 2005 */
4058 
4059  /*
4060  *
4061  * http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?
4062  * FeedbackID=99694 */
4063  {
4064  char x[1];
4065 
4066  xfrmlen = strxfrm(x, val, 0);
4067  }
4068 #else
4069  xfrmlen = strxfrm(NULL, val, 0);
4070 #endif
4071 #ifdef WIN32
4072 
4073  /*
4074  * On Windows, strxfrm returns INT_MAX when an error occurs. Instead
4075  * of trying to allocate this much memory (and fail), just return the
4076  * original string unmodified as if we were in the C locale.
4077  */
4078  if (xfrmlen == INT_MAX)
4079  return val;
4080 #endif
4081  xfrmstr = (char *) palloc(xfrmlen + 1);
4082  xfrmlen2 = strxfrm(xfrmstr, val, xfrmlen + 1);
4083 
4084  /*
4085  * Some systems (e.g., glibc) can return a smaller value from the
4086  * second call than the first; thus the Assert must be <= not ==.
4087  */
4088  Assert(xfrmlen2 <= xfrmlen);
4089  pfree(val);
4090  val = xfrmstr;
4091  }
4092 
4093  return val;
4094 }
static struct @76 value
#define BPCHAROID
Definition: pg_type.h:492
#define NAMEOID
Definition: pg_type.h:300
#define TEXTOID
Definition: pg_type.h:324
char * pstrdup(const char *in)
Definition: mcxt.c:1165
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
bool lc_collate_is_c(Oid collation)
Definition: pg_locale.c:1123
Definition: c.h:489
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:68
#define VARCHAROID
Definition: pg_type.h:495
#define TextDatumGetCString(d)
Definition: builtins.h:91
#define DatumGetChar(X)
Definition: postgres.h:417
#define CHAROID
Definition: pg_type.h:296
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define DatumGetPointer(X)
Definition: postgres.h:557
void * palloc(Size size)
Definition: mcxt.c:891
#define NameStr(name)
Definition: c.h:495
#define elog
Definition: elog.h:219
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:986
long val
Definition: informix.c:689
static void convert_string_to_scalar ( char *  value,
double *  scaledvalue,
char *  lobound,
double *  scaledlobound,
char *  hibound,
double *  scaledhibound 
)
static

Definition at line 3881 of file selfuncs.c.

References convert_one_string_to_scalar().

Referenced by convert_to_scalar().

3887 {
3888  int rangelo,
3889  rangehi;
3890  char *sptr;
3891 
3892  rangelo = rangehi = (unsigned char) hibound[0];
3893  for (sptr = lobound; *sptr; sptr++)
3894  {
3895  if (rangelo > (unsigned char) *sptr)
3896  rangelo = (unsigned char) *sptr;
3897  if (rangehi < (unsigned char) *sptr)
3898  rangehi = (unsigned char) *sptr;
3899  }
3900  for (sptr = hibound; *sptr; sptr++)
3901  {
3902  if (rangelo > (unsigned char) *sptr)
3903  rangelo = (unsigned char) *sptr;
3904  if (rangehi < (unsigned char) *sptr)
3905  rangehi = (unsigned char) *sptr;
3906  }
3907  /* If range includes any upper-case ASCII chars, make it include all */
3908  if (rangelo <= 'Z' && rangehi >= 'A')
3909  {
3910  if (rangelo > 'A')
3911  rangelo = 'A';
3912  if (rangehi < 'Z')
3913  rangehi = 'Z';
3914  }
3915  /* Ditto lower-case */
3916  if (rangelo <= 'z' && rangehi >= 'a')
3917  {
3918  if (rangelo > 'a')
3919  rangelo = 'a';
3920  if (rangehi < 'z')
3921  rangehi = 'z';
3922  }
3923  /* Ditto digits */
3924  if (rangelo <= '9' && rangehi >= '0')
3925  {
3926  if (rangelo > '0')
3927  rangelo = '0';
3928  if (rangehi < '9')
3929  rangehi = '9';
3930  }
3931 
3932  /*
3933  * If range includes less than 10 chars, assume we have not got enough
3934  * data, and make it include regular ASCII set.
3935  */
3936  if (rangehi - rangelo < 9)
3937  {
3938  rangelo = ' ';
3939  rangehi = 127;
3940  }
3941 
3942  /*
3943  * Now strip any common prefix of the three strings.
3944  */
3945  while (*lobound)
3946  {
3947  if (*lobound != *hibound || *lobound != *value)
3948  break;
3949  lobound++, hibound++, value++;
3950  }
3951 
3952  /*
3953  * Now we can do the conversions.
3954  */
3955  *scaledvalue = convert_one_string_to_scalar(value, rangelo, rangehi);
3956  *scaledlobound = convert_one_string_to_scalar(lobound, rangelo, rangehi);
3957  *scaledhibound = convert_one_string_to_scalar(hibound, rangelo, rangehi);
3958 }
static struct @76 value
static double convert_one_string_to_scalar(char *value, int rangelo, int rangehi)
Definition: selfuncs.c:3961
static double convert_timevalue_to_scalar ( Datum  value,
Oid  typid 
)
static

Definition at line 4193 of file selfuncs.c.

References abstime_timestamp(), ABSTIMEOID, TimeIntervalData::data, date2timestamp_no_overflow(), DATEOID, DatumGetDateADT, DatumGetIntervalP, DatumGetRelativeTime, DatumGetTimeADT, DatumGetTimeInterval, DatumGetTimestamp, DatumGetTimestampTz, DatumGetTimeTzADTP, Interval::day, DAYS_PER_YEAR, DirectFunctionCall1, elog, ERROR, INTERVALOID, Interval::month, MONTHS_PER_YEAR, RELTIMEOID, SECS_PER_DAY, TimeIntervalData::status, TimeTzADT::time, Interval::time, TIMEOID, TIMESTAMPOID, TIMESTAMPTZOID, TIMETZOID, TINTERVALOID, USECS_PER_DAY, and TimeTzADT::zone.

Referenced by convert_to_scalar().

4194 {
4195  switch (typid)
4196  {
4197  case TIMESTAMPOID:
4198  return DatumGetTimestamp(value);
4199  case TIMESTAMPTZOID:
4200  return DatumGetTimestampTz(value);
4201  case ABSTIMEOID:
4203  value));
4204  case DATEOID:
4206  case INTERVALOID:
4207  {
4209 
4210  /*
4211  * Convert the month part of Interval to days using assumed
4212  * average month length of 365.25/12.0 days. Not too
4213  * accurate, but plenty good enough for our purposes.
4214  */
4215 #ifdef HAVE_INT64_TIMESTAMP
4216  return interval->time + interval->day * (double) USECS_PER_DAY +
4217  interval->month * ((DAYS_PER_YEAR / (double) MONTHS_PER_YEAR) * USECS_PER_DAY);
4218 #else
4219  return interval->time + interval->day * SECS_PER_DAY +
4220  interval->month * ((DAYS_PER_YEAR / (double) MONTHS_PER_YEAR) * (double) SECS_PER_DAY);
4221 #endif
4222  }
4223  case RELTIMEOID:
4224 #ifdef HAVE_INT64_TIMESTAMP
4225  return (DatumGetRelativeTime(value) * 1000000.0);
4226 #else
4227  return DatumGetRelativeTime(value);
4228 #endif
4229  case TINTERVALOID:
4230  {
4232 
4233 #ifdef HAVE_INT64_TIMESTAMP
4234  if (tinterval->status != 0)
4235  return ((tinterval->data[1] - tinterval->data[0]) * 1000000.0);
4236 #else
4237  if (tinterval->status != 0)
4238  return tinterval->data[1] - tinterval->data[0];
4239 #endif
4240  return 0; /* for lack of a better idea */
4241  }
4242  case TIMEOID:
4243  return DatumGetTimeADT(value);
4244  case TIMETZOID:
4245  {
4246  TimeTzADT *timetz = DatumGetTimeTzADTP(value);
4247 
4248  /* use GMT-equivalent time */
4249 #ifdef HAVE_INT64_TIMESTAMP
4250  return (double) (timetz->time + (timetz->zone * 1000000.0));
4251 #else
4252  return (double) (timetz->time + timetz->zone);
4253 #endif
4254  }
4255  }
4256 
4257  /*
4258  * Can't get here unless someone tries to use scalarltsel/scalargtsel on
4259  * an operator with one timevalue and one non-timevalue operand.
4260  */
4261  elog(ERROR, "unsupported type: %u", typid);
4262  return 0;
4263 }
#define TIMESTAMPTZOID
Definition: pg_type.h:513
#define TIMEOID
Definition: pg_type.h:502
static struct @76 value
#define DATEOID
Definition: pg_type.h:499
#define DatumGetDateADT(X)
Definition: date.h:73
#define DatumGetIntervalP(X)
Definition: timestamp.h:49
TimeADT time
Definition: date.h:32
#define DatumGetTimeTzADTP(X)
Definition: date.h:75
#define TINTERVALOID
Definition: pg_type.h:420
double date2timestamp_no_overflow(DateADT dateVal)
Definition: date.c:666
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
int32 day
Definition: timestamp.h:60
#define MONTHS_PER_YEAR
Definition: timestamp.h:81
#define DAYS_PER_YEAR
Definition: timestamp.h:80
#define TIMESTAMPOID
Definition: pg_type.h:507
#define ERROR
Definition: elog.h:43
#define SECS_PER_DAY
Definition: timestamp.h:98
int32 zone
Definition: date.h:33
#define DatumGetRelativeTime(X)
Definition: nabstime.h:51
#define DatumGetTimestampTz(X)
Definition: timestamp.h:48
#define INTERVALOID
Definition: pg_type.h:517
TimeOffset time
Definition: timestamp.h:58
#define USECS_PER_DAY
Definition: timestamp.h:103
int32 month
Definition: timestamp.h:61
Datum abstime_timestamp(PG_FUNCTION_ARGS)
Definition: nabstime.c:466
#define DatumGetTimeADT(X)
Definition: date.h:74
AbsoluteTime data[2]
Definition: nabstime.h:42
#define TIMETZOID
Definition: pg_type.h:524
#define DatumGetTimeInterval(X)
Definition: nabstime.h:52
#define elog
Definition: elog.h:219
#define ABSTIMEOID
Definition: pg_type.h:414
Definition: date.h:30
#define DatumGetTimestamp(X)
Definition: timestamp.h:47
#define RELTIMEOID
Definition: pg_type.h:417
static bool convert_to_scalar ( Datum  value,
Oid  valuetypid,
double *  scaledvalue,
Datum  lobound,
Datum  hibound,
Oid  boundstypid,
double *  scaledlobound,
double *  scaledhibound 
)
static

Definition at line 3699 of file selfuncs.c.

References ABSTIMEOID, BOOLOID, BPCHAROID, BYTEAOID, CHAROID, CIDROID, convert_bytea_to_scalar(), convert_network_to_scalar(), convert_numeric_to_scalar(), convert_string_datum(), convert_string_to_scalar(), convert_timevalue_to_scalar(), DATEOID, FLOAT4OID, FLOAT8OID, INETOID, INT2OID, INT4OID, INT8OID, INTERVALOID, MACADDROID, NAMEOID, NUMERICOID, OIDOID, pfree(), REGCLASSOID, REGCONFIGOID, REGDICTIONARYOID, REGNAMESPACEOID, REGOPERATOROID, REGOPEROID, REGPROCEDUREOID, REGPROCOID, REGROLEOID, REGTYPEOID, RELTIMEOID, TEXTOID, TIMEOID, TIMESTAMPOID, TIMESTAMPTZOID, TIMETZOID, TINTERVALOID, and VARCHAROID.

Referenced by ineq_histogram_selectivity().

3702 {
3703  /*
3704  * Both the valuetypid and the boundstypid should exactly match the
3705  * declared input type(s) of the operator we are invoked for, so we just
3706  * error out if either is not recognized.
3707  *
3708  * XXX The histogram we are interpolating between points of could belong
3709  * to a column that's only binary-compatible with the declared type. In
3710  * essence we are assuming that the semantics of binary-compatible types
3711  * are enough alike that we can use a histogram generated with one type's
3712  * operators to estimate selectivity for the other's. This is outright
3713  * wrong in some cases --- in particular signed versus unsigned
3714  * interpretation could trip us up. But it's useful enough in the
3715  * majority of cases that we do it anyway. Should think about more
3716  * rigorous ways to do it.
3717  */
3718  switch (valuetypid)
3719  {
3720  /*
3721  * Built-in numeric types
3722  */
3723  case BOOLOID:
3724  case INT2OID:
3725  case INT4OID:
3726  case INT8OID:
3727  case FLOAT4OID:
3728  case FLOAT8OID:
3729  case NUMERICOID:
3730  case OIDOID:
3731  case REGPROCOID:
3732  case REGPROCEDUREOID:
3733  case REGOPEROID:
3734  case REGOPERATOROID:
3735  case REGCLASSOID:
3736  case REGTYPEOID:
3737  case REGCONFIGOID:
3738  case REGDICTIONARYOID:
3739  case REGROLEOID:
3740  case REGNAMESPACEOID:
3741  *scaledvalue = convert_numeric_to_scalar(value, valuetypid);
3742  *scaledlobound = convert_numeric_to_scalar(lobound, boundstypid);
3743  *scaledhibound = convert_numeric_to_scalar(hibound, boundstypid);
3744  return true;
3745 
3746  /*
3747  * Built-in string types
3748  */
3749  case CHAROID:
3750  case BPCHAROID:
3751  case VARCHAROID:
3752  case TEXTOID:
3753  case NAMEOID:
3754  {
3755  char *valstr = convert_string_datum(value, valuetypid);
3756  char *lostr = convert_string_datum(lobound, boundstypid);
3757  char *histr = convert_string_datum(hibound, boundstypid);
3758 
3759  convert_string_to_scalar(valstr, scaledvalue,
3760  lostr, scaledlobound,
3761  histr, scaledhibound);
3762  pfree(valstr);
3763  pfree(lostr);
3764  pfree(histr);
3765  return true;
3766  }
3767 
3768  /*
3769  * Built-in bytea type
3770  */
3771  case BYTEAOID:
3772  {
3773  convert_bytea_to_scalar(value, scaledvalue,
3774  lobound, scaledlobound,
3775  hibound, scaledhibound);
3776  return true;
3777  }
3778 
3779  /*
3780  * Built-in time types
3781  */
3782  case TIMESTAMPOID:
3783  case TIMESTAMPTZOID:
3784  case ABSTIMEOID:
3785  case DATEOID:
3786  case INTERVALOID:
3787  case RELTIMEOID:
3788  case TINTERVALOID:
3789  case TIMEOID:
3790  case TIMETZOID:
3791  *scaledvalue = convert_timevalue_to_scalar(value, valuetypid);
3792  *scaledlobound = convert_timevalue_to_scalar(lobound, boundstypid);
3793  *scaledhibound = convert_timevalue_to_scalar(hibound, boundstypid);
3794  return true;
3795 
3796  /*
3797  * Built-in network types
3798  */
3799  case INETOID:
3800  case CIDROID:
3801  case MACADDROID:
3802  *scaledvalue = convert_network_to_scalar(value, valuetypid);
3803  *scaledlobound = convert_network_to_scalar(lobound, boundstypid);
3804  *scaledhibound = convert_network_to_scalar(hibound, boundstypid);
3805  return true;
3806  }
3807  /* Don't know how to convert */
3808  *scaledvalue = *scaledlobound = *scaledhibound = 0;
3809  return false;
3810 }
#define CIDROID
Definition: pg_type.h:443
#define TIMESTAMPTZOID
Definition: pg_type.h:513
#define TIMEOID
Definition: pg_type.h:502
#define REGCLASSOID
Definition: pg_type.h:565
static struct @76 value
#define BPCHAROID
Definition: pg_type.h:492
#define DATEOID
Definition: pg_type.h:499
#define NAMEOID
Definition: pg_type.h:300
#define REGROLEOID
Definition: pg_type.h:573
#define OIDOID
Definition: pg_type.h:328
#define TEXTOID
Definition: pg_type.h:324
#define INETOID
Definition: pg_type.h:440
#define NUMERICOID
Definition: pg_type.h:542
static double convert_numeric_to_scalar(Datum value, Oid typid)
Definition: selfuncs.c:3816
#define INT4OID
Definition: pg_type.h:316
#define TINTERVALOID
Definition: pg_type.h:420
#define REGTYPEOID
Definition: pg_type.h:569
#define REGOPEROID
Definition: pg_type.h:557
void pfree(void *pointer)
Definition: mcxt.c:992
#define TIMESTAMPOID
Definition: pg_type.h:507
double convert_network_to_scalar(Datum value, Oid typid)
Definition: network.c:897
#define INT2OID
Definition: pg_type.h:308
#define INTERVALOID
Definition: pg_type.h:517
#define REGDICTIONARYOID
Definition: pg_type.h:615
#define VARCHAROID
Definition: pg_type.h:495
#define FLOAT4OID
Definition: pg_type.h:408
#define CHAROID
Definition: pg_type.h:296
#define INT8OID
Definition: pg_type.h:304
static char * convert_string_datum(Datum value, Oid typid)
Definition: selfuncs.c:4009
#define TIMETZOID
Definition: pg_type.h:524
#define FLOAT8OID
Definition: pg_type.h:411
#define BOOLOID
Definition: pg_type.h:288
static double convert_timevalue_to_scalar(Datum value, Oid typid)
Definition: selfuncs.c:4193
#define BYTEAOID
Definition: pg_type.h:292
#define REGCONFIGOID
Definition: pg_type.h:612
static void convert_bytea_to_scalar(Datum value, double *scaledvalue, Datum lobound, double *scaledlobound, Datum hibound, double *scaledhibound)
Definition: selfuncs.c:4108
#define MACADDROID
Definition: pg_type.h:437
#define REGPROCEDUREOID
Definition: pg_type.h:553
#define ABSTIMEOID
Definition: pg_type.h:414
#define REGNAMESPACEOID
Definition: pg_type.h:577
static void convert_string_to_scalar(char *value, double *scaledvalue, char *lobound, double *scaledlobound, char *hibound, double *scaledhibound)
Definition: selfuncs.c:3881
#define REGOPERATOROID
Definition: pg_type.h:561
#define REGPROCOID
Definition: pg_type.h:320
#define RELTIMEOID
Definition: pg_type.h:417
List* deconstruct_indexquals ( IndexPath path)

Definition at line 6081 of file selfuncs.c.

References arg, ScalarArrayOpExpr::args, Assert, castNode, RestrictInfo::clause, IndexQualInfo::clause_op, elog, ERROR, forboth, get_leftop(), get_rightop(), IndexQualInfo::indexcol, IndexPath::indexinfo, IndexPath::indexqualcols, IndexPath::indexquals, InvalidOid, IsA, lappend(), RowCompareExpr::largs, lfirst, lfirst_int, linitial, linitial_oid, lsecond, match_index_to_operand(), NIL, nodeTag, NULL, ScalarArrayOpExpr::opno, RowCompareExpr::opnos, IndexQualInfo::other_operand, palloc(), RowCompareExpr::rargs, IndexQualInfo::rinfo, and IndexQualInfo::varonleft.

Referenced by blcostestimate(), brincostestimate(), btcostestimate(), gincostestimate(), gistcostestimate(), hashcostestimate(), and spgcostestimate().

6082 {
6083  List *result = NIL;
6084  IndexOptInfo *index = path->indexinfo;
6085  ListCell *lcc,
6086  *lci;
6087 
6088  forboth(lcc, path->indexquals, lci, path->indexqualcols)
6089  {
6090  RestrictInfo *rinfo = castNode(RestrictInfo, lfirst(lcc));
6091  int indexcol = lfirst_int(lci);
6092  Expr *clause;
6093  Node *leftop,
6094  *rightop;
6095  IndexQualInfo *qinfo;
6096 
6097  clause = rinfo->clause;
6098 
6099  qinfo = (IndexQualInfo *) palloc(sizeof(IndexQualInfo));
6100  qinfo->rinfo = rinfo;
6101  qinfo->indexcol = indexcol;
6102 
6103  if (IsA(clause, OpExpr))
6104  {
6105  qinfo->clause_op = ((OpExpr *) clause)->opno;
6106  leftop = get_leftop(clause);
6107  rightop = get_rightop(clause);
6108  if (match_index_to_operand(leftop, indexcol, index))
6109  {
6110  qinfo->varonleft = true;
6111  qinfo->other_operand = rightop;
6112  }
6113  else
6114  {
6115  Assert(match_index_to_operand(rightop, indexcol, index));
6116  qinfo->varonleft = false;
6117  qinfo->other_operand = leftop;
6118  }
6119  }
6120  else if (IsA(clause, RowCompareExpr))
6121  {
6122  RowCompareExpr *rc = (RowCompareExpr *) clause;
6123 
6124  qinfo->clause_op = linitial_oid(rc->opnos);
6125  /* Examine only first columns to determine left/right sides */
6127  indexcol, index))
6128  {
6129  qinfo->varonleft = true;
6130  qinfo->other_operand = (Node *) rc->rargs;
6131  }
6132  else
6133  {
6135  indexcol, index));
6136  qinfo->varonleft = false;
6137  qinfo->other_operand = (Node *) rc->largs;
6138  }
6139  }
6140  else if (IsA(clause, ScalarArrayOpExpr))
6141  {
6142  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
6143 
6144  qinfo->clause_op = saop->opno;
6145  /* index column is always on the left in this case */
6147  indexcol, index));
6148  qinfo->varonleft = true;
6149  qinfo->other_operand = (Node *) lsecond(saop->args);
6150  }
6151  else if (IsA(clause, NullTest))
6152  {
6153  qinfo->clause_op = InvalidOid;
6154  Assert(match_index_to_operand((Node *) ((NullTest *) clause)->arg,
6155  indexcol, index));
6156  qinfo->varonleft = true;
6157  qinfo->other_operand = NULL;
6158  }
6159  else
6160  {
6161  elog(ERROR, "unsupported indexqual type: %d",
6162  (int) nodeTag(clause));
6163  }
6164 
6165  result = lappend(result, qinfo);
6166  }
6167  return result;
6168 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
IndexOptInfo * indexinfo
Definition: relation.h:972
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3161
Definition: nodes.h:508
RestrictInfo * rinfo
Definition: selfuncs.h:105
#define lsecond(l)
Definition: pg_list.h:114
Definition: type.h:90
List * indexquals
Definition: relation.h:974
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:107
Node * get_leftop(const Expr *clause)
Definition: clauses.c:198
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1637
bool varonleft
Definition: selfuncs.h:107
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
#define linitial_oid(l)
Definition: pg_list.h:112
#define nodeTag(nodeptr)
Definition: nodes.h:513
Node * get_rightop(const Expr *clause)
Definition: clauses.c:215
List * indexqualcols
Definition: relation.h:975
void * palloc(Size size)
Definition: mcxt.c:891
Node * other_operand
Definition: selfuncs.h:109
void * arg
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Datum eqjoinsel ( PG_FUNCTION_ARGS  )

Definition at line 2183 of file selfuncs.c.

References generate_unaccent_rules::args, CLAMP_PROBABILITY, elog, eqjoinsel_inner(), eqjoinsel_semi(), ERROR, find_join_input_rel(), get_commutator(), get_join_variables(), JOIN_ANTI, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_SEMI, SpecialJoinInfo::jointype, SpecialJoinInfo::min_righthand, PG_GETARG_INT16, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_FLOAT8, and ReleaseVariableStats.

Referenced by neqjoinsel().

2184 {
2185  PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
2186  Oid operator = PG_GETARG_OID(1);
2187  List *args = (List *) PG_GETARG_POINTER(2);
2188 
2189 #ifdef NOT_USED
2190  JoinType jointype = (JoinType) PG_GETARG_INT16(3);
2191 #endif
2193  double selec;
2194  VariableStatData vardata1;
2195  VariableStatData vardata2;
2196  bool join_is_reversed;
2197  RelOptInfo *inner_rel;
2198 
2199  get_join_variables(root, args, sjinfo,
2200  &vardata1, &vardata2, &join_is_reversed);
2201 
2202  switch (sjinfo->jointype)
2203  {
2204  case JOIN_INNER:
2205  case JOIN_LEFT:
2206  case JOIN_FULL:
2207  selec = eqjoinsel_inner(operator, &vardata1, &vardata2);
2208  break;
2209  case JOIN_SEMI:
2210  case JOIN_ANTI:
2211 
2212  /*
2213  * Look up the join's inner relation. min_righthand is sufficient
2214  * information because neither SEMI nor ANTI joins permit any
2215  * reassociation into or out of their RHS, so the righthand will
2216  * always be exactly that set of rels.
2217  */
2218  inner_rel = find_join_input_rel(root, sjinfo->min_righthand);
2219 
2220  if (!join_is_reversed)
2221  selec = eqjoinsel_semi(operator, &vardata1, &vardata2,
2222  inner_rel);
2223  else
2224  selec = eqjoinsel_semi(get_commutator(operator),
2225  &vardata2, &vardata1,
2226  inner_rel);
2227  break;
2228  default:
2229  /* other values not expected here */
2230  elog(ERROR, "unrecognized join type: %d",
2231  (int) sjinfo->jointype);
2232  selec = 0; /* keep compiler quiet */
2233  break;
2234  }
2235 
2236  ReleaseVariableStats(vardata1);
2237  ReleaseVariableStats(vardata2);
2238 
2239  CLAMP_PROBABILITY(selec);
2240 
2241  PG_RETURN_FLOAT8((float8) selec);
2242 }
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1281
Relids min_righthand
Definition: relation.h:1808
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:310
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
unsigned int Oid
Definition: postgres_ext.h:31
JoinType
Definition: nodes.h:665
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:57
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:378
void get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo, VariableStatData *vardata1, VariableStatData *vardata2, bool *join_is_reversed)
Definition: selfuncs.c:4350
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
static double eqjoinsel_semi(Oid operator, VariableStatData *vardata1, VariableStatData *vardata2, RelOptInfo *inner_rel)
Definition: selfuncs.c:2477
#define PG_GETARG_INT16(n)
Definition: fmgr.h:227
static RelOptInfo * find_join_input_rel(PlannerInfo *root, Relids relids)
Definition: selfuncs.c:5233
JoinType jointype
Definition: relation.h:1811
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:80
static double eqjoinsel_inner(Oid operator, VariableStatData *vardata1, VariableStatData *vardata2)
Definition: selfuncs.c:2251
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static double eqjoinsel_inner ( Oid  operator,
VariableStatData vardata1,
VariableStatData vardata2 
)
static

Definition at line 2251 of file selfuncs.c.

References VariableStatData::atttype, VariableStatData::atttypmod, CLAMP_PROBABILITY, DatumGetBool, DEFAULT_COLLATION_OID, fmgr_info(), free_attstatsslot(), FunctionCall2Coll(), get_attstatsslot(), get_opcode(), get_variable_numdistinct(), GETSTRUCT, HeapTupleIsValid, i, InvalidOid, NULL, palloc0(), pfree(), STATISTIC_KIND_MCV, and VariableStatData::statsTuple.

Referenced by eqjoinsel().

2253 {
2254  double selec;
2255  double nd1;
2256  double nd2;
2257  bool isdefault1;
2258  bool isdefault2;
2259  Form_pg_statistic stats1 = NULL;
2260  Form_pg_statistic stats2 = NULL;
2261  bool have_mcvs1 = false;
2262  Datum *values1 = NULL;
2263  int nvalues1 = 0;
2264  float4 *numbers1 = NULL;
2265  int nnumbers1 = 0;
2266  bool have_mcvs2 = false;
2267  Datum *values2 = NULL;
2268  int nvalues2 = 0;
2269  float4 *numbers2 = NULL;
2270  int nnumbers2 = 0;
2271 
2272  nd1 = get_variable_numdistinct(vardata1, &isdefault1);
2273  nd2 = get_variable_numdistinct(vardata2, &isdefault2);
2274 
2275  if (HeapTupleIsValid(vardata1->statsTuple))
2276  {
2277  stats1 = (Form_pg_statistic) GETSTRUCT(vardata1->statsTuple);
2278  have_mcvs1 = get_attstatsslot(vardata1->statsTuple,
2279  vardata1->atttype,
2280  vardata1->atttypmod,
2282  InvalidOid,
2283  NULL,
2284  &values1, &nvalues1,
2285  &numbers1, &nnumbers1);
2286  }
2287 
2288  if (HeapTupleIsValid(vardata2->statsTuple))
2289  {
2290  stats2 = (Form_pg_statistic) GETSTRUCT(vardata2->statsTuple);
2291  have_mcvs2 = get_attstatsslot(vardata2->statsTuple,
2292  vardata2->atttype,
2293  vardata2->atttypmod,
2295  InvalidOid,
2296  NULL,
2297  &values2, &nvalues2,
2298  &numbers2, &nnumbers2);
2299  }
2300 
2301  if (have_mcvs1 && have_mcvs2)
2302  {
2303  /*
2304  * We have most-common-value lists for both relations. Run through
2305  * the lists to see which MCVs actually join to each other with the
2306  * given operator. This allows us to determine the exact join
2307  * selectivity for the portion of the relations represented by the MCV
2308  * lists. We still have to estimate for the remaining population, but
2309  * in a skewed distribution this gives us a big leg up in accuracy.
2310  * For motivation see the analysis in Y. Ioannidis and S.
2311  * Christodoulakis, "On the propagation of errors in the size of join
2312  * results", Technical Report 1018, Computer Science Dept., University
2313  * of Wisconsin, Madison, March 1991 (available from ftp.cs.wisc.edu).
2314  */
2315  FmgrInfo eqproc;
2316  bool *hasmatch1;
2317  bool *hasmatch2;
2318  double nullfrac1 = stats1->stanullfrac;
2319  double nullfrac2 = stats2->stanullfrac;
2320  double matchprodfreq,
2321  matchfreq1,
2322  matchfreq2,
2323  unmatchfreq1,
2324  unmatchfreq2,
2325  otherfreq1,
2326  otherfreq2,
2327  totalsel1,
2328  totalsel2;
2329  int i,
2330  nmatches;
2331 
2332  fmgr_info(get_opcode(operator), &eqproc);
2333  hasmatch1 = (bool *) palloc0(nvalues1 * sizeof(bool));
2334  hasmatch2 = (bool *) palloc0(nvalues2 * sizeof(bool));
2335 
2336  /*
2337  * Note we assume that each MCV will match at most one member of the
2338  * other MCV list. If the operator isn't really equality, there could
2339  * be multiple matches --- but we don't look for them, both for speed
2340  * and because the math wouldn't add up...
2341  */
2342  matchprodfreq = 0.0;
2343  nmatches = 0;
2344  for (i = 0; i < nvalues1; i++)
2345  {
2346  int j;
2347 
2348  for (j = 0; j < nvalues2; j++)
2349  {
2350  if (hasmatch2[j])
2351  continue;
2352  if (DatumGetBool(FunctionCall2Coll(&eqproc,
2354  values1[i],
2355  values2[j])))
2356  {
2357  hasmatch1[i] = hasmatch2[j] = true;
2358  matchprodfreq += numbers1[i] * numbers2[j];
2359  nmatches++;
2360  break;
2361  }
2362  }
2363  }
2364  CLAMP_PROBABILITY(matchprodfreq);
2365  /* Sum up frequencies of matched and unmatched MCVs */
2366  matchfreq1 = unmatchfreq1 = 0.0;
2367  for (i = 0; i < nvalues1; i++)
2368  {
2369  if (hasmatch1[i])
2370  matchfreq1 += numbers1[i];
2371  else
2372  unmatchfreq1 += numbers1[i];
2373  }
2374  CLAMP_PROBABILITY(matchfreq1);
2375  CLAMP_PROBABILITY(unmatchfreq1);
2376  matchfreq2 = unmatchfreq2 = 0.0;
2377  for (i = 0; i < nvalues2; i++)
2378  {
2379  if (hasmatch2[i])
2380  matchfreq2 += numbers2[i];
2381  else
2382  unmatchfreq2 += numbers2[i];
2383  }
2384  CLAMP_PROBABILITY(matchfreq2);
2385  CLAMP_PROBABILITY(unmatchfreq2);
2386  pfree(hasmatch1);
2387  pfree(hasmatch2);
2388 
2389  /*
2390  * Compute total frequency of non-null values that are not in the MCV
2391  * lists.
2392  */
2393  otherfreq1 = 1.0 - nullfrac1 - matchfreq1 - unmatchfreq1;
2394  otherfreq2 = 1.0 - nullfrac2 - matchfreq2 - unmatchfreq2;
2395  CLAMP_PROBABILITY(otherfreq1);
2396  CLAMP_PROBABILITY(otherfreq2);
2397 
2398  /*
2399  * We can estimate the total selectivity from the point of view of
2400  * relation 1 as: the known selectivity for matched MCVs, plus
2401  * unmatched MCVs that are assumed to match against random members of
2402  * relation 2's non-MCV population, plus non-MCV values that are
2403  * assumed to match against random members of relation 2's unmatched
2404  * MCVs plus non-MCV values.
2405  */
2406  totalsel1 = matchprodfreq;
2407  if (nd2 > nvalues2)
2408  totalsel1 += unmatchfreq1 * otherfreq2 / (nd2 - nvalues2);
2409  if (nd2 > nmatches)
2410  totalsel1 += otherfreq1 * (otherfreq2 + unmatchfreq2) /
2411  (nd2 - nmatches);
2412  /* Same estimate from the point of view of relation 2. */
2413  totalsel2 = matchprodfreq;
2414  if (nd1 > nvalues1)
2415  totalsel2 += unmatchfreq2 * otherfreq1 / (nd1 - nvalues1);
2416  if (nd1 > nmatches)
2417  totalsel2 += otherfreq2 * (otherfreq1 + unmatchfreq1) /
2418  (nd1 - nmatches);
2419 
2420  /*
2421  * Use the smaller of the two estimates. This can be justified in
2422  * essentially the same terms as given below for the no-stats case: to
2423  * a first approximation, we are estimating from the point of view of
2424  * the relation with smaller nd.
2425  */
2426  selec = (totalsel1 < totalsel2) ? totalsel1 : totalsel2;
2427  }
2428  else
2429  {
2430  /*
2431  * We do not have MCV lists for both sides. Estimate the join
2432  * selectivity as MIN(1/nd1,1/nd2)*(1-nullfrac1)*(1-nullfrac2). This
2433  * is plausible if we assume that the join operator is strict and the
2434  * non-null values are about equally distributed: a given non-null
2435  * tuple of rel1 will join to either zero or N2*(1-nullfrac2)/nd2 rows
2436  * of rel2, so total join rows are at most
2437  * N1*(1-nullfrac1)*N2*(1-nullfrac2)/nd2 giving a join selectivity of
2438  * not more than (1-nullfrac1)*(1-nullfrac2)/nd2. By the same logic it
2439  * is not more than (1-nullfrac1)*(1-nullfrac2)/nd1, so the expression
2440  * with MIN() is an upper bound. Using the MIN() means we estimate
2441  * from the point of view of the relation with smaller nd (since the
2442  * larger nd is determining the MIN). It is reasonable to assume that
2443  * most tuples in this rel will have join partners, so the bound is
2444  * probably reasonably tight and should be taken as-is.
2445  *
2446  * XXX Can we be smarter if we have an MCV list for just one side? It
2447  * seems that if we assume equal distribution for the other side, we
2448  * end up with the same answer anyway.
2449  */
2450  double nullfrac1 = stats1 ? stats1->stanullfrac : 0.0;
2451  double nullfrac2 = stats2 ? stats2->stanullfrac : 0.0;
2452 
2453  selec = (1.0 - nullfrac1) * (1.0 - nullfrac2);
2454  if (nd1 > nd2)
2455  selec /= nd1;
2456  else
2457  selec /= nd2;
2458  }
2459 
2460  if (have_mcvs1)
2461  free_attstatsslot(vardata1->atttype, values1, nvalues1,
2462  numbers1, nnumbers1);
2463  if (have_mcvs2)
2464  free_attstatsslot(vardata2->atttype, values2, nvalues2,
2465  numbers2, nnumbers2);
2466 
2467  return selec;
2468 }
Definition: fmgr.h:53
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
HeapTuple statsTuple
Definition: selfuncs.h:71
bool get_attstatsslot(HeapTuple statstuple, Oid atttype, int32 atttypmod, int reqkind, Oid reqop, Oid *actualop, Datum **values, int *nvalues, float4 **numbers, int *nnumbers)
Definition: lsyscache.c:2854
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1306
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:129
int32 atttypmod
Definition: selfuncs.h:76
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:57
void pfree(void *pointer)
Definition: mcxt.c:992
double get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
Definition: selfuncs.c:4753
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:159
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:68
#define DatumGetBool(X)
Definition: postgres.h:401
#define STATISTIC_KIND_MCV
Definition: pg_statistic.h:204
float float4
Definition: c.h:377
void * palloc0(Size size)
Definition: mcxt.c:920
uintptr_t Datum
Definition: postgres.h:374
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
int i
void free_attstatsslot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers)
Definition: lsyscache.c:2978
static double eqjoinsel_semi ( Oid  operator,
VariableStatData vardata1,
VariableStatData vardata2,
RelOptInfo inner_rel 
)
static

Definition at line 2477 of file selfuncs.c.

References VariableStatData::atttype, VariableStatData::atttypmod, CLAMP_PROBABILITY, DatumGetBool, DEFAULT_COLLATION_OID, fmgr_info(), free_attstatsslot(), FunctionCall2Coll(), get_attstatsslot(), get_opcode(), get_variable_numdistinct(), GETSTRUCT, HeapTupleIsValid, i, InvalidOid, Min, NULL, OidIsValid, palloc0(), pfree(), VariableStatData::rel, RelOptInfo::rows, STATISTIC_KIND_MCV, and VariableStatData::statsTuple.

Referenced by eqjoinsel().

2480 {
2481  double selec;
2482  double nd1;
2483  double nd2;
2484  bool isdefault1;
2485  bool isdefault2;
2486  Form_pg_statistic stats1 = NULL;
2487  bool have_mcvs1 = false;
2488  Datum *values1 = NULL;
2489  int nvalues1 = 0;
2490  float4 *numbers1 = NULL;
2491  int nnumbers1 = 0;
2492  bool have_mcvs2 = false;
2493  Datum *values2 = NULL;
2494  int nvalues2 = 0;
2495  float4 *numbers2 = NULL;
2496  int nnumbers2 = 0;
2497 
2498  nd1 = get_variable_numdistinct(vardata1, &isdefault1);
2499  nd2 = get_variable_numdistinct(vardata2, &isdefault2);
2500 
2501  /*
2502  * We clamp nd2 to be not more than what we estimate the inner relation's
2503  * size to be. This is intuitively somewhat reasonable since obviously
2504  * there can't be more than that many distinct values coming from the
2505  * inner rel. The reason for the asymmetry (ie, that we don't clamp nd1
2506  * likewise) is that this is the only pathway by which restriction clauses
2507  * applied to the inner rel will affect the join result size estimate,
2508  * since set_joinrel_size_estimates will multiply SEMI/ANTI selectivity by
2509  * only the outer rel's size. If we clamped nd1 we'd be double-counting
2510  * the selectivity of outer-rel restrictions.
2511  *
2512  * We can apply this clamping both with respect to the base relation from
2513  * which the join variable comes (if there is just one), and to the
2514  * immediate inner input relation of the current join.
2515  *
2516  * If we clamp, we can treat nd2 as being a non-default estimate; it's not
2517  * great, maybe, but it didn't come out of nowhere either. This is most
2518  * helpful when the inner relation is empty and consequently has no stats.
2519  */
2520  if (vardata2->rel)
2521  {
2522  if (nd2 >= vardata2->rel->rows)
2523  {
2524  nd2 = vardata2->rel->rows;
2525  isdefault2 = false;
2526  }
2527  }
2528  if (nd2 >= inner_rel->rows)
2529  {
2530  nd2 = inner_rel->rows;
2531  isdefault2 = false;
2532  }
2533 
2534  if (HeapTupleIsValid(vardata1->statsTuple))
2535  {
2536  stats1 = (Form_pg_statistic) GETSTRUCT(vardata1->statsTuple);
2537  have_mcvs1 = get_attstatsslot(vardata1->statsTuple,
2538  vardata1->atttype,
2539  vardata1->atttypmod,
2541  InvalidOid,
2542  NULL,
2543  &values1, &nvalues1,
2544  &numbers1, &nnumbers1);
2545  }
2546 
2547  if (HeapTupleIsValid(vardata2->statsTuple))
2548  {
2549  have_mcvs2 = get_attstatsslot(vardata2->statsTuple,
2550  vardata2->atttype,
2551  vardata2->atttypmod,
2553  InvalidOid,
2554  NULL,
2555  &values2, &nvalues2,
2556  &numbers2, &nnumbers2);
2557  }
2558 
2559  if (have_mcvs1 && have_mcvs2 && OidIsValid(operator))
2560  {
2561  /*
2562  * We have most-common-value lists for both relations. Run through
2563  * the lists to see which MCVs actually join to each other with the
2564  * given operator. This allows us to determine the exact join
2565  * selectivity for the portion of the relations represented by the MCV
2566  * lists. We still have to estimate for the remaining population, but
2567  * in a skewed distribution this gives us a big leg up in accuracy.
2568  */
2569  FmgrInfo eqproc;
2570  bool *hasmatch1;
2571  bool *hasmatch2;
2572  double nullfrac1 = stats1->stanullfrac;
2573  double matchfreq1,
2574  uncertainfrac,
2575  uncertain;
2576  int i,
2577  nmatches,
2578  clamped_nvalues2;
2579 
2580  /*
2581  * The clamping above could have resulted in nd2 being less than
2582  * nvalues2; in which case, we assume that precisely the nd2 most
2583  * common values in the relation will appear in the join input, and so
2584  * compare to only the first nd2 members of the MCV list. Of course
2585  * this is frequently wrong, but it's the best bet we can make.
2586  */
2587  clamped_nvalues2 = Min(nvalues2, nd2);
2588 
2589  fmgr_info(get_opcode(operator), &eqproc);
2590  hasmatch1 = (bool *) palloc0(nvalues1 * sizeof(bool));
2591  hasmatch2 = (bool *) palloc0(clamped_nvalues2 * sizeof(bool));
2592 
2593  /*
2594  * Note we assume that each MCV will match at most one member of the
2595  * other MCV list. If the operator isn't really equality, there could
2596  * be multiple matches --- but we don't look for them, both for speed
2597  * and because the math wouldn't add up...
2598  */
2599  nmatches = 0;
2600  for (i = 0; i < nvalues1; i++)
2601  {
2602  int j;
2603 
2604  for (j = 0; j < clamped_nvalues2; j++)
2605  {
2606  if (hasmatch2[j])
2607  continue;
2608  if (DatumGetBool(FunctionCall2Coll(&eqproc,
2610  values1[i],
2611  values2[j])))
2612  {
2613  hasmatch1[i] = hasmatch2[j] = true;
2614  nmatches++;
2615  break;
2616  }
2617  }
2618  }
2619  /* Sum up frequencies of matched MCVs */
2620  matchfreq1 = 0.0;
2621  for (i = 0; i < nvalues1; i++)
2622  {
2623  if (hasmatch1[i])
2624  matchfreq1 += numbers1[i];
2625  }
2626  CLAMP_PROBABILITY(matchfreq1);
2627  pfree(hasmatch1);
2628  pfree(hasmatch2);
2629 
2630  /*
2631  * Now we need to estimate the fraction of relation 1 that has at
2632  * least one join partner. We know for certain that the matched MCVs
2633  * do, so that gives us a lower bound, but we're really in the dark
2634  * about everything else. Our crude approach is: if nd1 <= nd2 then
2635  * assume all non-null rel1 rows have join partners, else assume for
2636  * the uncertain rows that a fraction nd2/nd1 have join partners. We
2637  * can discount the known-matched MCVs from the distinct-values counts
2638  * before doing the division.
2639  *
2640  * Crude as the above is, it's completely useless if we don't have
2641  * reliable ndistinct values for both sides. Hence, if either nd1 or
2642  * nd2 is default, punt and assume half of the uncertain rows have
2643  * join partners.
2644  */
2645  if (!isdefault1 && !isdefault2)
2646  {
2647  nd1 -= nmatches;
2648  nd2 -= nmatches;
2649  if (nd1 <= nd2 || nd2 < 0)
2650  uncertainfrac = 1.0;
2651  else
2652  uncertainfrac = nd2 / nd1;
2653  }
2654  else
2655  uncertainfrac = 0.5;
2656  uncertain = 1.0 - matchfreq1 - nullfrac1;
2657  CLAMP_PROBABILITY(uncertain);
2658  selec = matchfreq1 + uncertainfrac * uncertain;
2659  }
2660  else
2661  {
2662  /*
2663  * Without MCV lists for both sides, we can only use the heuristic
2664  * about nd1 vs nd2.
2665  */
2666  double nullfrac1 = stats1 ? stats1->stanullfrac : 0.0;
2667 
2668  if (!isdefault1 && !isdefault2)
2669  {
2670  if (nd1 <= nd2 || nd2 < 0)
2671  selec = 1.0 - nullfrac1;
2672  else
2673  selec = (nd2 / nd1) * (1.0 - nullfrac1);
2674  }
2675  else
2676  selec = 0.5 * (1.0 - nullfrac1);
2677  }
2678 
2679  if (have_mcvs1)
2680  free_attstatsslot(vardata1->atttype, values1, nvalues1,
2681  numbers1, nnumbers1);
2682  if (have_mcvs2)
2683  free_attstatsslot(vardata2->atttype, values2, nvalues2,
2684  numbers2, nnumbers2);
2685 
2686  return selec;
2687 }
Definition: fmgr.h:53
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
HeapTuple statsTuple
Definition: selfuncs.h:71
RelOptInfo * rel
Definition: selfuncs.h:70
#define Min(x, y)
Definition: c.h:802
bool get_attstatsslot(HeapTuple statstuple, Oid atttype, int32 atttypmod, int reqkind, Oid reqop, Oid *actualop, Datum **values, int *nvalues, float4 **numbers, int *nnumbers)
Definition: lsyscache.c:2854
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1306
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:129
#define OidIsValid(objectId)
Definition: c.h:534
int32 atttypmod
Definition: selfuncs.h:76
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:57
void pfree(void *pointer)
Definition: mcxt.c:992
double get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
Definition: selfuncs.c:4753
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:159
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:68
#define DatumGetBool(X)
Definition: postgres.h:401
#define STATISTIC_KIND_MCV
Definition: pg_statistic.h:204
float float4
Definition: c.h:377
void * palloc0(Size size)
Definition: mcxt.c:920
uintptr_t Datum
Definition: postgres.h:374
double rows
Definition: relation.h:493
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
int i
void free_attstatsslot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers)
Definition: lsyscache.c:2978
Datum eqsel ( PG_FUNCTION_ARGS  )

Definition at line 220 of file selfuncs.c.

References generate_unaccent_rules::args, DEFAULT_EQ_SEL, get_restriction_variable(), IsA, PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_FLOAT8, ReleaseVariableStats, var_eq_const(), and var_eq_non_const().

Referenced by neqsel().

221 {
223  Oid operator = PG_GETARG_OID(1);
224  List *args = (List *) PG_GETARG_POINTER(2);
225  int varRelid = PG_GETARG_INT32(3);
226  VariableStatData vardata;
227  Node *other;
228  bool varonleft;
229  double selec;
230 
231  /*
232  * If expression is not variable = something or something = variable, then
233  * punt and return a default estimate.
234  */
235  if (!get_restriction_variable(root, args, varRelid,
236  &vardata, &other, &varonleft))
238 
239  /*
240  * We can do a lot better if the something is a constant. (Note: the
241  * Const might result from estimation rather than being a simple constant
242  * in the query.)
243  */
244  if (IsA(other, Const))
245  selec = var_eq_const(&vardata, operator,
246  ((Const *) other)->constvalue,
247  ((Const *) other)->constisnull,
248  varonleft);
249  else
250  selec = var_eq_non_const(&vardata, operator, other,
251  varonleft);
252 
253  ReleaseVariableStats(vardata);
254 
255  PG_RETURN_FLOAT8((float8) selec);
256 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
bool get_restriction_variable(PlannerInfo *root, List *args, int varRelid, VariableStatData *vardata, Node **other, bool *varonleft)
Definition: selfuncs.c:4290
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:310
Definition: nodes.h:508
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
unsigned int Oid
Definition: postgres_ext.h:31
double float8
Definition: c.h:378
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
static double var_eq_const(VariableStatData *vardata, Oid operator, Datum constval, bool constisnull, bool varonleft)
Definition: selfuncs.c:264
#define DEFAULT_EQ_SEL
Definition: selfuncs.h:34
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:80
static double var_eq_non_const(VariableStatData *vardata, Oid operator, Node *other, bool varonleft)
Definition: selfuncs.c:406
Definition: pg_list.h:45
int estimate_array_length ( Node arrayexpr)

Definition at line 2078 of file selfuncs.c.

References ARR_DIMS, ARR_NDIM, ArrayGetNItems(), DatumGetArrayTypeP, IsA, list_length(), and strip_array_coercion().

Referenced by btcostestimate(), cost_qual_eval_walker(), cost_tidscan(), genericcostestimate(), and gincost_scalararrayopexpr().

2079 {
2080  /* look through any binary-compatible relabeling of arrayexpr */
2081  arrayexpr = strip_array_coercion(arrayexpr);
2082 
2083  if (arrayexpr && IsA(arrayexpr, Const))
2084  {
2085  Datum arraydatum = ((Const *) arrayexpr)->constvalue;
2086  bool arrayisnull = ((Const *) arrayexpr)->constisnull;
2087  ArrayType *arrayval;
2088 
2089  if (arrayisnull)
2090  return 0;
2091  arrayval = DatumGetArrayTypeP(arraydatum);
2092  return ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval));
2093  }
2094  else if (arrayexpr && IsA(arrayexpr, ArrayExpr) &&
2095  !((ArrayExpr *) arrayexpr)->multidims)
2096  {
2097  return list_length(((ArrayExpr *) arrayexpr)->elements);
2098  }
2099  else
2100  {
2101  /* default guess --- see also scalararraysel */
2102  return 10;
2103  }
2104 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_DIMS(a)
Definition: array.h:275
uintptr_t Datum
Definition: postgres.h:374
static int list_length(const List *l)
Definition: pg_list.h:89
#define ARR_NDIM(a)
Definition: array.h:271
static Node * strip_array_coercion(Node *node)
Definition: selfuncs.c:1735
#define DatumGetArrayTypeP(X)
Definition: array.h:242
Selectivity estimate_hash_bucketsize ( PlannerInfo root,
Node hashkey,
double  nbuckets 
)

Definition at line 3554 of file selfuncs.c.

References VariableStatData::atttype, VariableStatData::atttypmod, clamp_row_est(), examine_variable(), free_attstatsslot(), get_attstatsslot(), get_variable_numdistinct(), GETSTRUCT, HeapTupleIsValid, InvalidOid, NULL, VariableStatData::rel, ReleaseVariableStats, RelOptInfo::rows, STATISTIC_KIND_MCV, VariableStatData::statsTuple, and RelOptInfo::tuples.

Referenced by final_cost_hashjoin().

3555 {
3556  VariableStatData vardata;
3557  double estfract,
3558  ndistinct,
3559  stanullfrac,
3560  mcvfreq,
3561  avgfreq;
3562  bool isdefault;
3563  float4 *numbers;
3564  int nnumbers;
3565 
3566  examine_variable(root, hashkey, 0, &vardata);
3567 
3568  /* Get number of distinct values */
3569  ndistinct = get_variable_numdistinct(&vardata, &isdefault);
3570 
3571  /* If ndistinct isn't real, punt and return 0.1, per comments above */
3572  if (isdefault)
3573  {
3574  ReleaseVariableStats(vardata);
3575  return (Selectivity) 0.1;
3576  }
3577 
3578  /* Get fraction that are null */
3579  if (HeapTupleIsValid(vardata.statsTuple))
3580  {
3581  Form_pg_statistic stats;
3582 
3583  stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
3584  stanullfrac = stats->stanullfrac;
3585  }
3586  else
3587  stanullfrac = 0.0;
3588 
3589  /* Compute avg freq of all distinct data values in raw relation */
3590  avgfreq = (1.0 - stanullfrac) / ndistinct;
3591 
3592  /*
3593  * Adjust ndistinct to account for restriction clauses. Observe we are
3594  * assuming that the data distribution is affected uniformly by the
3595  * restriction clauses!
3596  *
3597  * XXX Possibly better way, but much more expensive: multiply by
3598  * selectivity of rel's restriction clauses that mention the target Var.
3599  */
3600  if (vardata.rel && vardata.rel->tuples > 0)
3601  {
3602  ndistinct *= vardata.rel->rows / vardata.rel->tuples;
3603  ndistinct = clamp_row_est(ndistinct);
3604  }
3605 
3606  /*
3607  * Initial estimate of bucketsize fraction is 1/nbuckets as long as the
3608  * number of buckets is less than the expected number of distinct values;
3609  * otherwise it is 1/ndistinct.
3610  */
3611  if (ndistinct > nbuckets)
3612  estfract = 1.0 / nbuckets;
3613  else
3614  estfract = 1.0 / ndistinct;
3615 
3616  /*
3617  * Look up the frequency of the most common value, if available.
3618  */
3619  mcvfreq = 0.0;
3620 
3621  if (HeapTupleIsValid(vardata.statsTuple))
3622  {
3623  if (get_attstatsslot(vardata.statsTuple,
3624  vardata.atttype, vardata.atttypmod,
3626  NULL,
3627  NULL, NULL,
3628  &numbers, &nnumbers))
3629  {
3630  /*
3631  * The first MCV stat is for the most common value.
3632  */
3633  if (nnumbers > 0)
3634  mcvfreq = numbers[0];
3635  free_attstatsslot(vardata.atttype, NULL, 0,
3636  numbers, nnumbers);
3637  }
3638  }
3639 
3640  /*
3641  * Adjust estimated bucketsize upward to account for skewed distribution.
3642  */
3643  if (avgfreq > 0.0 && mcvfreq > avgfreq)
3644  estfract *= mcvfreq / avgfreq;
3645 
3646  /*
3647  * Clamp bucketsize to sane range (the above adjustment could easily
3648  * produce an out-of-range result). We set the lower bound a little above
3649  * zero, since zero isn't a very sane result.
3650  */
3651  if (estfract < 1.0e-6)
3652  estfract = 1.0e-6;
3653  else if (estfract > 1.0)
3654  estfract = 1.0;
3655 
3656  ReleaseVariableStats(vardata);
3657 
3658  return (Selectivity) estfract;
3659 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
HeapTuple statsTuple
Definition: selfuncs.h:71
double tuples
Definition: relation.h:529
RelOptInfo * rel
Definition: selfuncs.h:70
double Selectivity
Definition: nodes.h:631
bool get_attstatsslot(HeapTuple statstuple, Oid atttype, int32 atttypmod, int reqkind, Oid reqop, Oid *actualop, Datum **values, int *nvalues, float4 **numbers, int *nnumbers)
Definition: lsyscache.c:2854
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:129
int32 atttypmod
Definition: selfuncs.h:76
double get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
Definition: selfuncs.c:4753
#define STATISTIC_KIND_MCV
Definition: pg_statistic.h:204
float float4
Definition: c.h:377
double rows
Definition: relation.h:493
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void examine_variable(PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata)
Definition: selfuncs.c:4409
#define NULL
Definition: c.h:226
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:80
e
Definition: preproc-init.c:82
double clamp_row_est(double nrows)
Definition: costsize.c:172
void free_attstatsslot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers)
Definition: lsyscache.c:2978
double estimate_num_groups ( PlannerInfo root,
List groupExprs,
double  input_rows,
List **  pgset 
)

Definition at line 3272 of file selfuncs.c.

References add_unique_group_var(), Assert, BOOLOID, clamp_row_est(), contain_volatile_functions(), examine_variable(), exprType(), for_each_cell, HeapTupleIsValid, i, VariableStatData::isunique, lcons(), lfirst, linitial, list_head(), list_length(), list_member_int(), lnext, GroupVarInfo::ndistinct, NIL, pull_var_clause(), PVC_RECURSE_AGGREGATES, PVC_RECURSE_PLACEHOLDERS, PVC_RECURSE_WINDOWFUNCS, GroupVarInfo::rel, ReleaseVariableStats, RELOPT_BASEREL, RelOptInfo::reloptkind, RelOptInfo::rows, VariableStatData::statsTuple, and RelOptInfo::tuples.

Referenced by adjust_rowcount_for_semijoins(), create_distinct_paths(), create_unique_path(), estimate_path_cost_size(), get_number_of_groups(), and recurse_set_operations().

3274 {
3275  List *varinfos = NIL;
3276  double numdistinct;
3277  ListCell *l;
3278  int i;
3279 
3280  /*
3281  * We don't ever want to return an estimate of zero groups, as that tends
3282  * to lead to division-by-zero and other unpleasantness. The input_rows
3283  * estimate is usually already at least 1, but clamp it just in case it
3284  * isn't.
3285  */
3286  input_rows = clamp_row_est(input_rows);
3287 
3288  /*
3289  * If no grouping columns, there's exactly one group. (This can't happen
3290  * for normal cases with GROUP BY or DISTINCT, but it is possible for
3291  * corner cases with set operations.)
3292  */
3293  if (groupExprs == NIL || (pgset && list_length(*pgset) < 1))
3294  return 1.0;
3295 
3296  /*
3297  * Count groups derived from boolean grouping expressions. For other
3298  * expressions, find the unique Vars used, treating an expression as a Var
3299  * if we can find stats for it. For each one, record the statistical
3300  * estimate of number of distinct values (total in its table, without
3301  * regard for filtering).
3302  */
3303  numdistinct = 1.0;
3304 
3305  i = 0;
3306  foreach(l, groupExprs)
3307  {
3308  Node *groupexpr = (Node *) lfirst(l);
3309  VariableStatData vardata;
3310  List *varshere;
3311  ListCell *l2;
3312 
3313  /* is expression in this grouping set? */
3314  if (pgset && !list_member_int(*pgset, i++))
3315  continue;
3316 
3317  /* Short-circuit for expressions returning boolean */
3318  if (exprType(groupexpr) == BOOLOID)
3319  {
3320  numdistinct *= 2.0;
3321  continue;
3322  }
3323 
3324  /*
3325  * If examine_variable is able to deduce anything about the GROUP BY
3326  * expression, treat it as a single variable even if it's really more
3327  * complicated.
3328  */
3329  examine_variable(root, groupexpr, 0, &vardata);
3330  if (HeapTupleIsValid(vardata.statsTuple) || vardata.isunique)
3331  {
3332  varinfos = add_unique_group_var(root, varinfos,
3333  groupexpr, &vardata);
3334  ReleaseVariableStats(vardata);
3335  continue;
3336  }
3337  ReleaseVariableStats(vardata);
3338 
3339  /*
3340  * Else pull out the component Vars. Handle PlaceHolderVars by
3341  * recursing into their arguments (effectively assuming that the
3342  * PlaceHolderVar doesn't change the number of groups, which boils
3343  * down to ignoring the possible addition of nulls to the result set).
3344  */
3345  varshere = pull_var_clause(groupexpr,
3349 
3350  /*
3351  * If we find any variable-free GROUP BY item, then either it is a
3352  * constant (and we can ignore it) or it contains a volatile function;
3353  * in the latter case we punt and assume that each input row will
3354  * yield a distinct group.
3355  */
3356  if (varshere == NIL)
3357  {
3358  if (contain_volatile_functions(groupexpr))
3359  return input_rows;
3360  continue;
3361  }
3362 
3363  /*
3364  * Else add variables to varinfos list
3365  */
3366  foreach(l2, varshere)
3367  {
3368  Node *var = (Node *) lfirst(l2);
3369 
3370  examine_variable(root, var, 0, &vardata);
3371  varinfos = add_unique_group_var(root, varinfos, var, &vardata);
3372  ReleaseVariableStats(vardata);
3373  }
3374  }
3375 
3376  /*
3377  * If now no Vars, we must have an all-constant or all-boolean GROUP BY
3378  * list.
3379  */
3380  if (varinfos == NIL)
3381  {
3382  /* Guard against out-of-range answers */
3383  if (numdistinct > input_rows)
3384  numdistinct = input_rows;
3385  return numdistinct;
3386  }
3387 
3388  /*
3389  * Group Vars by relation and estimate total numdistinct.
3390  *
3391  * For each iteration of the outer loop, we process the frontmost Var in
3392  * varinfos, plus all other Vars in the same relation. We remove these
3393  * Vars from the newvarinfos list for the next iteration. This is the
3394  * easiest way to group Vars of same rel together.
3395  */
3396  do
3397  {
3398  GroupVarInfo *varinfo1 = (GroupVarInfo *) linitial(varinfos);
3399  RelOptInfo *rel = varinfo1->rel;
3400  double reldistinct = varinfo1->ndistinct;
3401  double relmaxndistinct = reldistinct;
3402  int relvarcount = 1;
3403  List *newvarinfos = NIL;
3404 
3405  /*
3406  * Get the product of numdistinct estimates of the Vars for this rel.
3407  * Also, construct new varinfos list of remaining Vars.
3408  */
3409  for_each_cell(l, lnext(list_head(varinfos)))
3410  {
3411  GroupVarInfo *varinfo2 = (GroupVarInfo *) lfirst(l);
3412 
3413  if (varinfo2->rel == varinfo1->rel)
3414  {
3415  reldistinct *= varinfo2->ndistinct;
3416  if (relmaxndistinct < varinfo2->ndistinct)
3417  relmaxndistinct = varinfo2->ndistinct;
3418  relvarcount++;
3419  }
3420  else
3421  {
3422  /* not time to process varinfo2 yet */
3423  newvarinfos = lcons(varinfo2, newvarinfos);
3424  }
3425  }
3426 
3427  /*
3428  * Sanity check --- don't divide by zero if empty relation.
3429  */
3430  Assert(rel->reloptkind == RELOPT_BASEREL);
3431  if (rel->tuples > 0)
3432  {
3433  /*
3434  * Clamp to size of rel, or size of rel / 10 if multiple Vars. The
3435  * fudge factor is because the Vars are probably correlated but we
3436  * don't know by how much. We should never clamp to less than the
3437  * largest ndistinct value for any of the Vars, though, since
3438  * there will surely be at least that many groups.
3439  */
3440  double clamp = rel->tuples;
3441 
3442  if (relvarcount > 1)
3443  {
3444  clamp *= 0.1;
3445  if (clamp < relmaxndistinct)
3446  {
3447  clamp = relmaxndistinct;
3448  /* for sanity in case some ndistinct is too large: */
3449  if (clamp > rel->tuples)
3450  clamp = rel->tuples;
3451  }
3452  }
3453  if (reldistinct > clamp)
3454  reldistinct = clamp;
3455 
3456  /*
3457  * Update the estimate based on the restriction selectivity,
3458  * guarding against division by zero when reldistinct is zero.
3459  * Also skip this if we know that we are returning all rows.
3460  */
3461  if (reldistinct > 0 && rel->rows < rel->tuples)
3462  {
3463  /*
3464  * Given a table containing N rows with n distinct values in a
3465  * uniform distribution, if we select p rows at random then
3466  * the expected number of distinct values selected is
3467  *
3468  * n * (1 - product((N-N/n-i)/(N-i), i=0..p-1))
3469  *
3470  * = n * (1 - (N-N/n)! / (N-N/n-p)! * (N-p)! / N!)
3471  *
3472  * See "Approximating block accesses in database
3473  * organizations", S. B. Yao, Communications of the ACM,
3474  * Volume 20 Issue 4, April 1977 Pages 260-261.
3475  *
3476  * Alternatively, re-arranging the terms from the factorials,
3477  * this may be written as
3478  *
3479  * n * (1 - product((N-p-i)/(N-i), i=0..N/n-1))
3480  *
3481  * This form of the formula is more efficient to compute in
3482  * the common case where p is larger than N/n. Additionally,
3483  * as pointed out by Dell'Era, if i << N for all terms in the
3484  * product, it can be approximated by
3485  *
3486  * n * (1 - ((N-p)/N)^(N/n))
3487  *
3488  * See "Expected distinct values when selecting from a bag
3489  * without replacement", Alberto Dell'Era,
3490  * http://www.adellera.it/investigations/distinct_balls/.
3491  *
3492  * The condition i << N is equivalent to n >> 1, so this is a
3493  * good approximation when the number of distinct values in
3494  * the table is large. It turns out that this formula also
3495  * works well even when n is small.
3496  */
3497  reldistinct *=
3498  (1 - pow((rel->tuples - rel->rows) / rel->tuples,
3499  rel->tuples / reldistinct));
3500  }
3501  reldistinct = clamp_row_est(reldistinct);
3502 
3503  /*
3504  * Update estimate of total distinct groups.
3505  */
3506  numdistinct *= reldistinct;
3507  }
3508 
3509  varinfos = newvarinfos;
3510  } while (varinfos != NIL);
3511 
3512  numdistinct = ceil(numdistinct);
3513 
3514  /* Guard against out-of-range answers */
3515  if (numdistinct > input_rows)
3516  numdistinct = input_rows;
3517  if (numdistinct < 1.0)
3518  numdistinct = 1.0;
3519 
3520  return numdistinct;
3521 }
#define NIL
Definition: pg_list.h:69
#define PVC_RECURSE_AGGREGATES
Definition: var.h:21
RelOptKind reloptkind
Definition: relation.h:487
HeapTuple statsTuple
Definition: selfuncs.h:71
double tuples
Definition: relation.h:529
Definition: nodes.h:508
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:950
double ndistinct
Definition: selfuncs.c:3150
#define PVC_RECURSE_PLACEHOLDERS
Definition: var.h:26
#define linitial(l)
Definition: pg_list.h:110
bool list_member_int(const List *list, int datum)
Definition: list.c:485
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define PVC_RECURSE_WINDOWFUNCS
Definition: var.h:23
#define lnext(lc)
Definition: pg_list.h:105
static List * add_unique_group_var(PlannerInfo *root, List *varinfos, Node *var, VariableStatData *vardata)
Definition: selfuncs.c:3154
double rows
Definition: relation.h:493
List * lcons(void *datum, List *list)
Definition: list.c:259
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void examine_variable(PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata)
Definition: selfuncs.c:4409
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
#define for_each_cell(cell, initcell)
Definition: pg_list.h:163
#define BOOLOID
Definition: pg_type.h:288
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:80
int i
double clamp_row_est(double nrows)
Definition: costsize.c:172
Definition: pg_list.h:45
RelOptInfo * rel
Definition: selfuncs.c:3149
static void examine_simple_variable ( PlannerInfo root,
Var var,
VariableStatData vardata 
)
static

Definition at line 4596 of file selfuncs.c.

References Alias::aliasname, Assert, BoolGetDatum, Query::distinctClause, elog, RangeTblEntry::eref, ERROR, TargetEntry::expr, find_base_rel(), VariableStatData::freefunc, get_relation_stats_hook, get_tle_by_resno(), Query::groupClause, HeapTupleIsValid, RangeTblEntry::inh, Int16GetDatum, InvalidAttrNumber, InvalidOid, IsA, VariableStatData::isunique, list_length(), NULL, ObjectIdGetDatum, PlannerInfo::parse, ReleaseSysCache(), RangeTblEntry::relid, TargetEntry::resjunk, RTE_RELATION, RTE_SUBQUERY, RangeTblEntry::rtekind, SearchSysCache3, RangeTblEntry::security_barrier, Query::setOperations, PlannerInfo::simple_rte_array, STATRELATTINH, VariableStatData::statsTuple, RangeTblEntry::subquery, RelOptInfo::subroot, targetIsInSortList(), Query::targetList, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by examine_variable().

4598 {
4599  RangeTblEntry *rte = root->simple_rte_array[var->varno];
4600 
4601  Assert(IsA(rte, RangeTblEntry));
4602 
4604  (*get_relation_stats_hook) (root, rte, var->varattno, vardata))
4605  {
4606  /*
4607  * The hook took control of acquiring a stats tuple. If it did supply
4608  * a tuple, it'd better have supplied a freefunc.
4609  */
4610  if (HeapTupleIsValid(vardata->statsTuple) &&
4611  !vardata->freefunc)
4612  elog(ERROR, "no function provided to release variable stats with");
4613  }
4614  else if (rte->rtekind == RTE_RELATION)
4615  {
4616  /*
4617  * Plain table or parent of an inheritance appendrel, so look up the
4618  * column in pg_statistic
4619  */
4621  ObjectIdGetDatum(rte->relid),
4622  Int16GetDatum(var->varattno),
4623  BoolGetDatum(rte->inh));
4624  vardata->freefunc = ReleaseSysCache;
4625  }
4626  else if (rte->rtekind == RTE_SUBQUERY && !rte->inh)
4627  {
4628  /*
4629  * Plain subquery (not one that was converted to an appendrel).
4630  */
4631  Query *subquery = rte->subquery;
4632  RelOptInfo *rel;
4633  TargetEntry *ste;
4634 
4635  /*
4636  * Punt if it's a whole-row var rather than a plain column reference.
4637  */
4638  if (var->varattno == InvalidAttrNumber)
4639  return;
4640 
4641  /*
4642  * Punt if subquery uses set operations or GROUP BY, as these will
4643  * mash underlying columns' stats beyond recognition. (Set ops are
4644  * particularly nasty; if we forged ahead, we would return stats
4645  * relevant to only the leftmost subselect...) DISTINCT is also
4646  * problematic, but we check that later because there is a possibility
4647  * of learning something even with it.
4648  */
4649  if (subquery->setOperations ||
4650  subquery->groupClause)
4651  return;
4652 
4653  /*
4654  * OK, fetch RelOptInfo for subquery. Note that we don't change the
4655  * rel returned in vardata, since caller expects it to be a rel of the
4656  * caller's query level. Because we might already be recursing, we
4657  * can't use that rel pointer either, but have to look up the Var's
4658  * rel afresh.
4659  */
4660  rel = find_base_rel(root, var->varno);
4661 
4662  /* If the subquery hasn't been planned yet, we have to punt */
4663  if (rel->subroot == NULL)
4664  return;
4665  Assert(IsA(rel->subroot, PlannerInfo));
4666 
4667  /*
4668  * Switch our attention to the subquery as mangled by the planner. It
4669  * was okay to look at the pre-planning version for the tests above,
4670  * but now we need a Var that will refer to the subroot's live
4671  * RelOptInfos. For instance, if any subquery pullup happened during
4672  * planning, Vars in the targetlist might have gotten replaced, and we
4673  * need to see the replacement expressions.
4674  */
4675  subquery = rel->subroot->parse;
4676  Assert(IsA(subquery, Query));
4677 
4678  /* Get the subquery output expression referenced by the upper Var */
4679  ste = get_tle_by_resno(subquery->targetList, var->varattno);
4680  if (ste == NULL || ste->resjunk)
4681  elog(ERROR, "subquery %s does not have attribute %d",
4682  rte->eref->aliasname, var->varattno);
4683  var = (Var *) ste->expr;
4684 
4685  /*
4686  * If subquery uses DISTINCT, we can't make use of any stats for the
4687  * variable ... but, if it's the only DISTINCT column, we are entitled
4688  * to consider it unique. We do the test this way so that it works
4689  * for cases involving DISTINCT ON.
4690  */
4691  if (subquery->distinctClause)
4692  {
4693  if (list_length(subquery->distinctClause) == 1 &&
4694  targetIsInSortList(ste, InvalidOid, subquery->distinctClause))
4695  vardata->isunique = true;
4696  /* cannot go further */
4697  return;
4698  }
4699 
4700  /*
4701  * If the sub-query originated from a view with the security_barrier
4702  * attribute, we must not look at the variable's statistics, though it
4703  * seems all right to notice the existence of a DISTINCT clause. So
4704  * stop here.
4705  *
4706  * This is probably a harsher restriction than necessary; it's
4707  * certainly OK for the selectivity estimator (which is a C function,
4708  * and therefore omnipotent anyway) to look at the statistics. But
4709  * many selectivity estimators will happily *invoke the operator
4710  * function* to try to work out a good estimate - and that's not OK.
4711  * So for now, don't dig down for stats.
4712  */
4713  if (rte->security_barrier)
4714  return;
4715 
4716  /* Can only handle a simple Var of subquery's query level */
4717  if (var && IsA(var, Var) &&
4718  var->varlevelsup == 0)
4719  {
4720  /*
4721  * OK, recurse into the subquery. Note that the original setting
4722  * of vardata->isunique (which will surely be false) is left
4723  * unchanged in this situation. That's what we want, since even
4724  * if the underlying column is unique, the subquery may have
4725  * joined to other tables in a way that creates duplicates.
4726  */
4727  examine_simple_variable(rel->subroot, var, vardata);
4728  }
4729  }
4730  else
4731  {
4732  /*
4733  * Otherwise, the Var comes from a FUNCTION, VALUES, or CTE RTE. (We
4734  * won't see RTE_JOIN here because join alias Vars have already been
4735  * flattened.) There's not much we can do with function outputs, but
4736  * maybe someday try to be smarter about VALUES and/or CTEs.
4737  */
4738  }
4739 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Query * parse
Definition: relation.h:152
Index varlevelsup
Definition: primnodes.h:151
HeapTuple statsTuple
Definition: selfuncs.h:71
#define Int16GetDatum(X)
Definition: postgres.h:459
AttrNumber varattno
Definition: primnodes.h:146
Definition: primnodes.h:141
static void examine_simple_variable(PlannerInfo *root, Var *var, VariableStatData *vardata)
Definition: selfuncs.c:4596
List * targetList
Definition: parsenodes.h:131
PlannerInfo * subroot
Definition: relation.h:531
bool resjunk
Definition: primnodes.h:1337
List * distinctClause
Definition: parsenodes.h:145
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
get_relation_stats_hook_type get_relation_stats_hook
Definition: selfuncs.c:148
RangeTblEntry ** simple_rte_array
Definition: relation.h:185
Index varno
Definition: primnodes.h:144
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
bool security_barrier
Definition: parsenodes.h:901
#define BoolGetDatum(X)
Definition: postgres.h:410
#define InvalidOid
Definition: postgres_ext.h:36
bool targetIsInSortList(TargetEntry *tle, Oid sortop, List *sortList)
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
char * aliasname
Definition: primnodes.h:41
Expr * expr
Definition: primnodes.h:1330
static int list_length(const List *l)
Definition: pg_list.h:89
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:882
Node * setOperations
Definition: parsenodes.h:154
Query * subquery
Definition: parsenodes.h:900
List * groupClause
Definition: parsenodes.h:137
#define SearchSysCache3(cacheId, key1, key2, key3)
Definition: syscache.h:153
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define elog
Definition: elog.h:219
Alias * eref
Definition: parsenodes.h:961
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:219
void(* freefunc)(HeapTuple tuple)
Definition: selfuncs.h:73
void examine_variable ( PlannerInfo root,
Node node,
int  varRelid,
VariableStatData vardata 
)

Definition at line 4409 of file selfuncs.c.

References arg, VariableStatData::atttype, VariableStatData::atttypmod, BMS_EMPTY_SET, bms_free(), bms_is_member(), bms_membership(), BMS_MULTIPLE, BMS_SINGLETON, bms_singleton_member(), BoolGetDatum, elog, equal(), ERROR, examine_simple_variable(), exprType(), exprTypmod(), find_base_rel(), find_join_rel(), VariableStatData::freefunc, get_index_stats_hook, has_unique_index(), HeapTupleIsValid, IndexOptInfo::indexkeys, RelOptInfo::indexlist, IndexOptInfo::indexoid, IndexOptInfo::indexprs, IndexOptInfo::indpred, Int16GetDatum, IsA, VariableStatData::isunique, lfirst, list_head(), lnext, MemSet, IndexOptInfo::ncolumns, NIL, NULL, ObjectIdGetDatum, IndexOptInfo::predOK, pull_varnos(), VariableStatData::rel, ReleaseSysCache(), SearchSysCache3, STATRELATTINH, VariableStatData::statsTuple, IndexOptInfo::unique, VariableStatData::var, Var::varattno, Var::varno, VariableStatData::vartype, Var::vartype, and Var::vartypmod.

Referenced by booltestsel(), boolvarsel(), estimate_hash_bucketsize(), estimate_num_groups(), get_join_variables(), get_restriction_variable(), mergejoinscansel(), nulltestsel(), and scalararraysel_containment().

4411 {
4412  Node *basenode;
4413  Relids varnos;
4414  RelOptInfo *onerel;
4415 
4416  /* Make sure we don't return dangling pointers in vardata */
4417  MemSet(vardata, 0, sizeof(VariableStatData));
4418 
4419  /* Save the exposed type of the expression */
4420  vardata->vartype = exprType(node);
4421 
4422  /* Look inside any binary-compatible relabeling */
4423 
4424  if (IsA(node, RelabelType))
4425  basenode = (Node *) ((RelabelType *) node)->arg;
4426  else
4427  basenode = node;
4428 
4429  /* Fast path for a simple Var */
4430 
4431  if (IsA(basenode, Var) &&
4432  (varRelid == 0 || varRelid == ((Var *) basenode)->varno))
4433  {
4434  Var *var = (Var *) basenode;
4435 
4436  /* Set up result fields other than the stats tuple */
4437  vardata->var = basenode; /* return Var without relabeling */
4438  vardata->rel = find_base_rel(root, var->varno);
4439  vardata->atttype = var->vartype;
4440  vardata->atttypmod = var->vartypmod;
4441  vardata->isunique = has_unique_index(vardata->rel, var->varattno);
4442 
4443  /* Try to locate some stats */
4444  examine_simple_variable(root, var, vardata);
4445 
4446  return;
4447  }
4448 
4449  /*
4450  * Okay, it's a more complicated expression. Determine variable
4451  * membership. Note that when varRelid isn't zero, only vars of that
4452  * relation are considered "real" vars.
4453  */
4454  varnos = pull_varnos(basenode);
4455 
4456  onerel = NULL;
4457 
4458  switch (bms_membership(varnos))
4459  {
4460  case BMS_EMPTY_SET:
4461  /* No Vars at all ... must be pseudo-constant clause */
4462  break;
4463  case BMS_SINGLETON:
4464  if (varRelid == 0 || bms_is_member(varRelid, varnos))
4465  {
4466  onerel = find_base_rel(root,
4467  (varRelid ? varRelid : bms_singleton_member(varnos)));
4468  vardata->rel = onerel;
4469  node = basenode; /* strip any relabeling */
4470  }
4471  /* else treat it as a constant */
4472  break;
4473  case BMS_MULTIPLE:
4474  if (varRelid == 0)
4475  {
4476  /* treat it as a variable of a join relation */
4477  vardata->rel = find_join_rel(root, varnos);
4478  node = basenode; /* strip any relabeling */
4479  }
4480  else if (bms_is_member(varRelid, varnos))
4481  {
4482  /* ignore the vars belonging to other relations */
4483  vardata->rel = find_base_rel(root, varRelid);
4484  node = basenode; /* strip any relabeling */
4485  /* note: no point in expressional-index search here */
4486  }
4487  /* else treat it as a constant */
4488  break;
4489  }
4490 
4491  bms_free(varnos);
4492 
4493  vardata->var = node;
4494  vardata->atttype = exprType(node);
4495  vardata->atttypmod = exprTypmod(node);
4496 
4497  if (onerel)
4498  {
4499  /*
4500  * We have an expression in vars of a single relation. Try to match
4501  * it to expressional index columns, in hopes of finding some
4502  * statistics.
4503  *
4504  * XXX it's conceivable that there are multiple matches with different
4505  * index opfamilies; if so, we need to pick one that matches the
4506  * operator we are estimating for. FIXME later.
4507  */
4508  ListCell *ilist;
4509 
4510  foreach(ilist, onerel->indexlist)
4511  {
4512  IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);
4513  ListCell *indexpr_item;
4514  int pos;
4515 
4516  indexpr_item = list_head(index->indexprs);
4517  if (indexpr_item == NULL)
4518  continue; /* no expressions here... */
4519 
4520  for (pos = 0; pos < index->ncolumns; pos++)
4521  {
4522  if (index->indexkeys[pos] == 0)
4523  {
4524  Node *indexkey;
4525 
4526  if (indexpr_item == NULL)
4527  elog(ERROR, "too few entries in indexprs list");
4528  indexkey = (Node *) lfirst(indexpr_item);
4529  if (indexkey && IsA(indexkey, RelabelType))
4530  indexkey = (Node *) ((RelabelType *) indexkey)->arg;
4531  if (equal(node, indexkey))
4532  {
4533  /*
4534  * Found a match ... is it a unique index? Tests here
4535  * should match has_unique_index().
4536  */
4537  if (index->unique &&
4538  index->ncolumns == 1 &&
4539  (index->indpred == NIL || index->predOK))
4540  vardata->isunique = true;
4541 
4542  /*
4543  * Has it got stats? We only consider stats for
4544  * non-partial indexes, since partial indexes probably
4545  * don't reflect whole-relation statistics; the above
4546  * check for uniqueness is the only info we take from
4547  * a partial index.
4548  *
4549  * An index stats hook, however, must make its own
4550  * decisions about what to do with partial indexes.
4551  */
4552  if (get_index_stats_hook &&
4553  (*get_index_stats_hook) (root, index->indexoid,
4554  pos + 1, vardata))
4555  {
4556  /*
4557  * The hook took control of acquiring a stats
4558  * tuple. If it did supply a tuple, it'd better
4559  * have supplied a freefunc.
4560  */
4561  if (HeapTupleIsValid(vardata->statsTuple) &&
4562  !vardata->freefunc)
4563  elog(ERROR, "no function provided to release variable stats with");
4564  }
4565  else if (index->indpred == NIL)
4566  {
4567  vardata->statsTuple =
4569  ObjectIdGetDatum(index->indexoid),
4570  Int16GetDatum(pos + 1),
4571  BoolGetDatum(false));
4572  vardata->freefunc = ReleaseSysCache;
4573  }
4574  if (vardata->statsTuple)
4575  break;
4576  }
4577  indexpr_item = lnext(indexpr_item);
4578  }
4579  }
4580  if (vardata->statsTuple)
4581  break;
4582  }
4583  }
4584 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
bool predOK
Definition: relation.h:620
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Definition: relnode.c:284
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
HeapTuple statsTuple
Definition: selfuncs.h:71
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:273
RelOptInfo * rel
Definition: selfuncs.h:70
#define Int16GetDatum(X)
Definition: postgres.h:459
Definition: nodes.h:508
#define MemSet(start, val, len)
Definition: c.h:853
AttrNumber varattno
Definition: primnodes.h:146
Definition: primnodes.h:141
static void examine_simple_variable(PlannerInfo *root, Var *var, VariableStatData *vardata)
Definition: selfuncs.c:4596
int32 atttypmod
Definition: selfuncs.h:76
bool unique
Definition: relation.h:621
Definition: type.h:90
bool has_unique_index(RelOptInfo *rel, AttrNumber attno)
Definition: plancat.c:1649
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Oid vartype
Definition: primnodes.h:148
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
int ncolumns
Definition: relation.h:598
#define lnext(lc)
Definition: pg_list.h:105
Relids pull_varnos(Node *node)
Definition: var.c:95
Index varno
Definition: primnodes.h:144
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:604
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
int bms_singleton_member(const Bitmapset *a)
Definition: bitmapset.c:496
List * indexlist
Definition: relation.h:527
#define BoolGetDatum(X)
Definition: postgres.h:410
void bms_free(Bitmapset *a)
Definition: bitmapset.c:200
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
get_index_stats_hook_type get_index_stats_hook
Definition: selfuncs.c:149
#define SearchSysCache3(cacheId, key1, key2, key3)
Definition: syscache.h:153
void * arg
int * indexkeys
Definition: relation.h:599
#define elog
Definition: elog.h:219
Oid indexoid
Definition: relation.h:588
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:219
void(* freefunc)(HeapTuple tuple)
Definition: selfuncs.h:73
List * indpred
Definition: relation.h:611
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
List * indexprs
Definition: relation.h:610
int32 vartypmod
Definition: primnodes.h:149
static RelOptInfo * find_join_input_rel ( PlannerInfo root,
Relids  relids 
)
static

Definition at line 5233 of file selfuncs.c.

References BMS_EMPTY_SET, bms_membership(), BMS_MULTIPLE, BMS_SINGLETON, bms_singleton_member(), elog, ERROR, find_base_rel(), find_join_rel(), and NULL.

Referenced by eqjoinsel().

5234 {
5235  RelOptInfo *rel = NULL;
5236 
5237  switch (bms_membership(relids))
5238  {
5239  case BMS_EMPTY_SET:
5240  /* should not happen */
5241  break;
5242  case BMS_SINGLETON:
5243  rel = find_base_rel(root, bms_singleton_member(relids));
5244  break;
5245  case BMS_MULTIPLE:
5246  rel = find_join_rel(root, relids);
5247  break;
5248  }
5249 
5250  if (rel == NULL)
5251  elog(ERROR, "could not find RelOptInfo for given relids");
5252 
5253  return rel;
5254 }
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Definition: relnode.c:284
#define ERROR
Definition: elog.h:43
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:604
int bms_singleton_member(const Bitmapset *a)
Definition: bitmapset.c:496
#define NULL
Definition: c.h:226
#define elog
Definition: elog.h:219
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:219
void genericcostestimate ( PlannerInfo root,
IndexPath path,
double  loop_count,
List qinfos,
GenericCosts costs 
)

Definition at line 6230 of file selfuncs.c.

References add_predicate_to_quals(), ScalarArrayOpExpr::args, RestrictInfo::clause, clauselist_selectivity(), cpu_index_tuple_cost, cpu_operator_cost, estimate_array_length(), get_tablespace_page_costs(), index_pages_fetched(), GenericCosts::indexCorrelation, IndexPath::indexinfo, IndexPath::indexorderbys, IndexPath::indexquals, GenericCosts::indexSelectivity, GenericCosts::indexStartupCost, GenericCosts::indexTotalCost, IsA, JOIN_INNER, lfirst, list_length(), lsecond, NULL, GenericCosts::num_sa_scans, GenericCosts::numIndexPages, GenericCosts::numIndexTuples, orderby_operands_eval_cost(), other_operands_eval_cost(), IndexOptInfo::pages, IndexOptInfo::rel, RelOptInfo::relid, IndexOptInfo::reltablespace, rint(), GenericCosts::spc_random_page_cost, RelOptInfo::tuples, and IndexOptInfo::tuples.

Referenced by blcostestimate(), btcostestimate(), gistcostestimate(), hashcostestimate(), and spgcostestimate().

6235 {
6236  IndexOptInfo *index = path->indexinfo;
6237  List *indexQuals = path->indexquals;
6238  List *indexOrderBys = path->indexorderbys;
6239  Cost indexStartupCost;
6240  Cost indexTotalCost;
6241  Selectivity indexSelectivity;
6242  double indexCorrelation;
6243  double numIndexPages;
6244  double numIndexTuples;
6245  double spc_random_page_cost;
6246  double num_sa_scans;
6247  double num_outer_scans;
6248  double num_scans;
6249  double qual_op_cost;
6250  double qual_arg_cost;
6251  List *selectivityQuals;
6252  ListCell *l;
6253 
6254  /*
6255  * If the index is partial, AND the index predicate with the explicitly
6256  * given indexquals to produce a more accurate idea of the index
6257  * selectivity.
6258  */
6259  selectivityQuals = add_predicate_to_quals(index, indexQuals);
6260 
6261  /*
6262  * Check for ScalarArrayOpExpr index quals, and estimate the number of
6263  * index scans that will be performed.
6264  */
6265  num_sa_scans = 1;
6266  foreach(l, indexQuals)
6267  {
6268  RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
6269 
6270  if (IsA(rinfo->clause, ScalarArrayOpExpr))
6271  {
6272  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) rinfo->clause;
6273  int alength = estimate_array_length(lsecond(saop->args));
6274 
6275  if (alength > 1)
6276  num_sa_scans *= alength;
6277  }
6278  }
6279 
6280  /* Estimate the fraction of main-table tuples that will be visited */
6281  indexSelectivity = clauselist_selectivity(root, selectivityQuals,
6282  index->rel->relid,
6283  JOIN_INNER,
6284  NULL);
6285 
6286  /*
6287  * If caller didn't give us an estimate, estimate the number of index
6288  * tuples that will be visited. We do it in this rather peculiar-looking
6289  * way in order to get the right answer for partial indexes.
6290  */
6291  numIndexTuples = costs->numIndexTuples;
6292  if (numIndexTuples <= 0.0)
6293  {
6294  numIndexTuples = indexSelectivity * index->rel->tuples;
6295 
6296  /*
6297  * The above calculation counts all the tuples visited across all
6298  * scans induced by ScalarArrayOpExpr nodes. We want to consider the
6299  * average per-indexscan number, so adjust. This is a handy place to
6300  * round to integer, too. (If caller supplied tuple estimate, it's
6301  * responsible for handling these considerations.)
6302  */
6303  numIndexTuples = rint(numIndexTuples / num_sa_scans);
6304  }
6305 
6306  /*
6307  * We can bound the number of tuples by the index size in any case. Also,
6308  * always estimate at least one tuple is touched, even when
6309  * indexSelectivity estimate is tiny.
6310  */
6311  if (numIndexTuples > index->tuples)
6312  numIndexTuples = index->tuples;
6313  if (numIndexTuples < 1.0)
6314  numIndexTuples = 1.0;
6315 
6316  /*
6317  * Estimate the number of index pages that will be retrieved.
6318  *
6319  * We use the simplistic method of taking a pro-rata fraction of the total
6320  * number of index pages. In effect, this counts only leaf pages and not
6321  * any overhead such as index metapage or upper tree levels.
6322  *
6323  * In practice access to upper index levels is often nearly free because
6324  * those tend to stay in cache under load; moreover, the cost involved is
6325  * highly dependent on index type. We therefore ignore such costs here
6326  * and leave it to the caller to add a suitable charge if needed.
6327  */
6328  if (index->pages > 1 && index->tuples > 1)
6329  numIndexPages = ceil(numIndexTuples * index->pages / index->tuples);
6330  else
6331  numIndexPages = 1.0;
6332 
6333  /* fetch estimated page cost for tablespace containing index */
6335  &spc_random_page_cost,
6336  NULL);
6337 
6338  /*
6339  * Now compute the disk access costs.
6340  *
6341  * The above calculations are all per-index-scan. However, if we are in a
6342  * nestloop inner scan, we can expect the scan to be repeated (with
6343  * different search keys) for each row of the outer relation. Likewise,
6344  * ScalarArrayOpExpr quals result in multiple index scans. This creates
6345  * the potential for cache effects to reduce the number of disk page
6346  * fetches needed. We want to estimate the average per-scan I/O cost in
6347  * the presence of caching.
6348  *
6349  * We use the Mackert-Lohman formula (see costsize.c for details) to
6350  * estimate the total number of page fetches that occur. While this
6351  * wasn't what it was designed for, it seems a reasonable model anyway.
6352  * Note that we are counting pages not tuples anymore, so we take N = T =
6353  * index size, as if there were one "tuple" per page.
6354  */
6355  num_outer_scans = loop_count;
6356  num_scans = num_sa_scans * num_outer_scans;
6357 
6358  if (num_scans > 1)
6359  {
6360  double pages_fetched;
6361 
6362  /* total page fetches ignoring cache effects */
6363  pages_fetched = numIndexPages * num_scans;
6364 
6365  /* use Mackert and Lohman formula to adjust for cache effects */
6366  pages_fetched = index_pages_fetched(pages_fetched,
6367  index->pages,
6368  (double) index->pages,
6369  root);
6370 
6371  /*
6372  * Now compute the total disk access cost, and then report a pro-rated
6373  * share for each outer scan. (Don't pro-rate for ScalarArrayOpExpr,
6374  * since that's internal to the indexscan.)
6375  */
6376  indexTotalCost = (pages_fetched * spc_random_page_cost)
6377  / num_outer_scans;
6378  }
6379  else
6380  {
6381  /*
6382  * For a single index scan, we just charge spc_random_page_cost per
6383  * page touched.
6384  */
6385  indexTotalCost = numIndexPages * spc_random_page_cost;
6386  }
6387 
6388  /*
6389  * CPU cost: any complex expressions in the indexquals will need to be
6390  * evaluated once at the start of the scan to reduce them to runtime keys
6391  * to pass to the index AM (see nodeIndexscan.c). We model the per-tuple
6392  * CPU costs as cpu_index_tuple_cost plus one cpu_operator_cost per
6393  * indexqual operator. Because we have numIndexTuples as a per-scan
6394  * number, we have to multiply by num_sa_scans to get the correct result
6395  * for ScalarArrayOpExpr cases. Similarly add in costs for any index
6396  * ORDER BY expressions.
6397  *
6398  * Note: this neglects the possible costs of rechecking lossy operators.
6399  * Detecting that that might be needed seems more expensive than it's
6400  * worth, though, considering all the other inaccuracies here ...
6401  */
6402  qual_arg_cost = other_operands_eval_cost(root, qinfos) +
6403  orderby_operands_eval_cost(root, path);
6404  qual_op_cost = cpu_operator_cost *
6405  (list_length(indexQuals) + list_length(indexOrderBys));
6406 
6407  indexStartupCost = qual_arg_cost;
6408  indexTotalCost += qual_arg_cost;
6409  indexTotalCost += numIndexTuples * num_sa_scans * (cpu_index_tuple_cost + qual_op_cost);
6410 
6411  /*
6412  * Generic assumption about index correlation: there isn't any.
6413  */
6414  indexCorrelation = 0.0;
6415 
6416  /*
6417  * Return everything to caller.
6418  */
6419  costs->indexStartupCost = indexStartupCost;
6420  costs->indexTotalCost = indexTotalCost;
6421  costs->indexSelectivity = indexSelectivity;
6422  costs->indexCorrelation = indexCorrelation;
6423  costs->numIndexPages = numIndexPages;
6424  costs->numIndexTuples = numIndexTuples;
6425  costs->spc_random_page_cost = spc_random_page_cost;
6426  costs->num_sa_scans = num_sa_scans;
6427 }
Selectivity indexSelectivity
Definition: selfuncs.h:130
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
IndexOptInfo * indexinfo
Definition: relation.h:972
double tuples
Definition: relation.h:529
static List * add_predicate_to_quals(IndexOptInfo *index, List *indexQuals)
Definition: selfuncs.c:6449
Oid reltablespace
Definition: relation.h:589
static Cost other_operands_eval_cost(PlannerInfo *root, List *qinfos)
Definition: selfuncs.c:6176
double Selectivity
Definition: nodes.h:631
double tuples
Definition: relation.h:594
#define lsecond(l)
Definition: pg_list.h:114
static Cost orderby_operands_eval_cost(PlannerInfo *root, IndexPath *path)
Definition: selfuncs.c:6201
Definition: type.h:90
BlockNumber pages
Definition: relation.h:593
List * indexquals
Definition: relation.h:974
int estimate_array_length(Node *arrayexpr)
Definition: selfuncs.c:2078
RelOptInfo * rel
Definition: relation.h:590
double num_sa_scans
Definition: selfuncs.h:137
double cpu_operator_cost
Definition: costsize.c:108
Cost indexTotalCost
Definition: selfuncs.h:129
double rint(double x)
Definition: rint.c:22
void get_tablespace_page_costs(Oid spcid, double *spc_random_page_cost, double *spc_seq_page_cost)
Definition: spccache.c:178
Index relid
Definition: relation.h:518
Expr * clause
Definition: relation.h:1637
double indexCorrelation
Definition: selfuncs.h:131
List * indexorderbys
Definition: relation.h:976
double spc_random_page_cost
Definition: selfuncs.h:136
double numIndexTuples
Definition: selfuncs.h:135
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
Cost indexStartupCost
Definition: selfuncs.h:128
Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:92
Definition: pg_list.h:45
double cpu_index_tuple_cost
Definition: costsize.c:107
double index_pages_fetched(double tuples_fetched, BlockNumber pages, double index_pages, PlannerInfo *root)
Definition: costsize.c:738
double Cost
Definition: nodes.h:632
double numIndexPages
Definition: selfuncs.h:134
static bool get_actual_variable_range ( PlannerInfo root,
VariableStatData vardata,
Oid  sortop,
Datum min,
Datum max 
)
static

Definition at line 5007 of file selfuncs.c.

References AccessShareLock, Assert, VariableStatData::atttype, BackwardScanDirection, BTGreaterStrategyNumber, BTLessStrategyNumber, BTREE_AM_OID, BuildIndexInfo(), CreateExecutorState(), datumCopy(), ExprContext::ecxt_per_tuple_memory, ExprContext::ecxt_scantuple, elog, ERROR, ExecDropSingleTupleTableSlot(), ExecStoreTuple(), FormIndexDatum(), ForwardScanDirection, FreeExecutorState(), get_op_opfamily_strategy(), get_typlenbyval(), GetPerTupleExprContext, heap_close, heap_open(), IndexOptInfo::hypothetical, index_beginscan(), index_close(), index_endscan(), index_getnext(), INDEX_MAX_KEYS, index_open(), index_rescan(), RelOptInfo::indexlist, IndexOptInfo::indexoid, IndexOptInfo::indpred, InitDirtySnapshot, InvalidBuffer, InvalidOid, InvalidStrategy, lfirst, MakeSingleTupleTableSlot(), match_index_to_operand(), MemoryContextSwitchTo(), NIL, NoLock, NULL, VariableStatData::rel, IndexOptInfo::relam, RelationGetDescr, RelationGetRelationName, RelOptInfo::relid, RangeTblEntry::relid, IndexOptInfo::reverse_sort, RTE_RELATION, RangeTblEntry::rtekind, ScanKeyEntryInitialize(), PlannerInfo::simple_rte_array, SK_ISNULL, SK_SEARCHNOTNULL, IndexOptInfo::sortopfamily, values, and VariableStatData::var.

Referenced by get_variable_range(), and ineq_histogram_selectivity().

5010 {
5011  bool have_data = false;
5012  RelOptInfo *rel = vardata->rel;
5013  RangeTblEntry *rte;
5014  ListCell *lc;
5015 
5016  /* No hope if no relation or it doesn't have indexes */
5017  if (rel == NULL || rel->indexlist == NIL)
5018  return false;
5019  /* If it has indexes it must be a plain relation */
5020  rte = root->simple_rte_array[rel->relid];
5021  Assert(rte->rtekind == RTE_RELATION);
5022 
5023  /* Search through the indexes to see if any match our problem */
5024  foreach(lc, rel->indexlist)
5025  {
5027  ScanDirection indexscandir;
5028 
5029  /* Ignore non-btree indexes */
5030  if (index->relam != BTREE_AM_OID)
5031  continue;
5032 
5033  /*
5034  * Ignore partial indexes --- we only want stats that cover the entire
5035  * relation.
5036  */
5037  if (index->indpred != NIL)
5038  continue;
5039 
5040  /*
5041  * The index list might include hypothetical indexes inserted by a
5042  * get_relation_info hook --- don't try to access them.
5043  */
5044  if (index->hypothetical)
5045  continue;
5046 
5047  /*
5048  * The first index column must match the desired variable and sort
5049  * operator --- but we can use a descending-order index.
5050  */
5051  if (!match_index_to_operand(vardata->var, 0, index))
5052  continue;
5053  switch (get_op_opfamily_strategy(sortop, index->sortopfamily[0]))
5054  {
5055  case BTLessStrategyNumber:
5056  if (index->reverse_sort[0])
5057  indexscandir = BackwardScanDirection;
5058  else
5059  indexscandir = ForwardScanDirection;
5060  break;
5062  if (index->reverse_sort[0])
5063  indexscandir = ForwardScanDirection;
5064  else
5065  indexscandir = BackwardScanDirection;
5066  break;
5067  default:
5068  /* index doesn't match the sortop */
5069  continue;
5070  }
5071 
5072  /*
5073  * Found a suitable index to extract data from. We'll need an EState
5074  * and a bunch of other infrastructure.
5075  */
5076  {
5077  EState *estate;
5078  ExprContext *econtext;
5079  MemoryContext tmpcontext;
5080  MemoryContext oldcontext;
5081  Relation heapRel;
5082  Relation indexRel;
5083  IndexInfo *indexInfo;
5084  TupleTableSlot *slot;
5085  int16 typLen;
5086  bool typByVal;
5087  ScanKeyData scankeys[1];
5088  IndexScanDesc index_scan;
5089  HeapTuple tup;
5091  bool isnull[INDEX_MAX_KEYS];
5092  SnapshotData SnapshotDirty;
5093 
5094  estate = CreateExecutorState();
5095  econtext = GetPerTupleExprContext(estate);
5096  /* Make sure any cruft is generated in the econtext's memory */
5097  tmpcontext = econtext->ecxt_per_tuple_memory;
5098  oldcontext = MemoryContextSwitchTo(tmpcontext);
5099 
5100  /*
5101  * Open the table and index so we can read from them. We should
5102  * already have at least AccessShareLock on the table, but not
5103  * necessarily on the index.
5104  */
5105  heapRel = heap_open(rte->relid, NoLock);
5106  indexRel = index_open(index->indexoid, AccessShareLock);
5107 
5108  /* extract index key information from the index's pg_index info */
5109  indexInfo = BuildIndexInfo(indexRel);
5110 
5111  /* some other stuff */
5112  slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRel));
5113  econtext->ecxt_scantuple = slot;
5114  get_typlenbyval(vardata->atttype, &typLen, &typByVal);
5115  InitDirtySnapshot(SnapshotDirty);
5116 
5117  /* set up an IS NOT NULL scan key so that we ignore nulls */
5118  ScanKeyEntryInitialize(&scankeys[0],
5120  1, /* index col to scan */
5121  InvalidStrategy, /* no strategy */
5122  InvalidOid, /* no strategy subtype */
5123  InvalidOid, /* no collation */
5124  InvalidOid, /* no reg proc for this */
5125  (Datum) 0); /* constant */
5126 
5127  have_data = true;
5128 
5129  /* If min is requested ... */
5130  if (min)
5131  {
5132  /*
5133  * In principle, we should scan the index with our current
5134  * active snapshot, which is the best approximation we've got
5135  * to what the query will see when executed. But that won't
5136  * be exact if a new snap is taken before running the query,
5137  * and it can be very expensive if a lot of uncommitted rows
5138  * exist at the end of the index (because we'll laboriously
5139  * fetch each one and reject it). What seems like a good
5140  * compromise is to use SnapshotDirty. That will accept
5141  * uncommitted rows, and thus avoid fetching multiple heap
5142  * tuples in this scenario. On the other hand, it will reject
5143  * known-dead rows, and thus not give a bogus answer when the
5144  * extreme value has been deleted; that case motivates not
5145  * using SnapshotAny here.
5146  */
5147  index_scan = index_beginscan(heapRel, indexRel, &SnapshotDirty,
5148  1, 0);
5149  index_rescan(index_scan, scankeys, 1, NULL, 0);
5150 
5151  /* Fetch first tuple in sortop's direction */
5152  if ((tup = index_getnext(index_scan,
5153  indexscandir)) != NULL)
5154  {
5155  /* Extract the index column values from the heap tuple */
5156  ExecStoreTuple(tup, slot, InvalidBuffer, false);
5157  FormIndexDatum(indexInfo, slot, estate,
5158  values, isnull);
5159 
5160  /* Shouldn't have got a null, but be careful */
5161  if (isnull[0])
5162  elog(ERROR, "found unexpected null value in index \"%s\"",
5163  RelationGetRelationName(indexRel));
5164 
5165  /* Copy the index column value out to caller's context */
5166  MemoryContextSwitchTo(oldcontext);
5167  *min = datumCopy(values[0], typByVal, typLen);
5168  MemoryContextSwitchTo(tmpcontext);
5169  }
5170  else
5171  have_data = false;
5172 
5173  index_endscan(index_scan);
5174  }
5175 
5176  /* If max is requested, and we didn't find the index is empty */
5177  if (max && have_data)
5178  {
5179  index_scan = index_beginscan(heapRel, indexRel, &SnapshotDirty,
5180  1, 0);
5181  index_rescan(index_scan, scankeys, 1, NULL, 0);
5182 
5183  /* Fetch first tuple in reverse direction */
5184  if ((tup = index_getnext(index_scan,
5185  -indexscandir)) != NULL)
5186  {
5187  /* Extract the index column values from the heap tuple */
5188  ExecStoreTuple(tup, slot, InvalidBuffer, false);
5189  FormIndexDatum(indexInfo, slot, estate,
5190  values, isnull);
5191 
5192  /* Shouldn't have got a null, but be careful */
5193  if (isnull[0])
5194  elog(ERROR, "found unexpected null value in index \"%s\"",
5195  RelationGetRelationName(indexRel));
5196 
5197  /* Copy the index column value out to caller's context */
5198  MemoryContextSwitchTo(oldcontext);
5199  *max = datumCopy(values[0], typByVal, typLen);
5200  MemoryContextSwitchTo(tmpcontext);
5201  }
5202  else
5203  have_data = false;
5204 
5205  index_endscan(index_scan);
5206  }
5207 
5208  /* Clean everything up */
5210 
5211  index_close(indexRel, AccessShareLock);
5212  heap_close(heapRel, NoLock);
5213 
5214  MemoryContextSwitchTo(oldcontext);
5215  FreeExecutorState(estate);
5216 
5217  /* And we're done */
5218  break;
5219  }
5220  }
5221 
5222  return have_data;
5223 }
signed short int16
Definition: c.h:252
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:1764
#define InvalidStrategy
Definition: stratnum.h:24
#define NIL
Definition: pg_list.h:69
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define RelationGetDescr(relation)
Definition: rel.h:425
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3161
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
RelOptInfo * rel
Definition: selfuncs.h:70
#define BTREE_AM_OID
Definition: pg_am.h:70
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
#define InvalidBuffer
Definition: buf.h:25
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
Oid * sortopfamily
Definition: relation.h:603
bool hypothetical
Definition: relation.h:623
#define heap_close(r, l)
Definition: heapam.h:97
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:1639
Definition: type.h:90
void FreeExecutorState(EState *estate)
Definition: execUtils.c:168
#define GetPerTupleExprContext(estate)
Definition: executor.h:338
#define ERROR
Definition: elog.h:43
#define InitDirtySnapshot(snapshotdata)
Definition: tqual.h:100
#define NoLock
Definition: lockdefs.h:34
void ScanKeyEntryInitialize(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, Oid subtype, Oid collation, RegProcedure procedure, Datum argument)
Definition: scankey.c:32
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:216
ScanDirection
Definition: sdir.h:22
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define SK_SEARCHNOTNULL
Definition: skey.h:122
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:199
void index_endscan(IndexScanDesc scan)
Definition: indexam.c:340
#define SK_ISNULL
Definition: skey.h:115
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
EState * CreateExecutorState(void)
Definition: execUtils.c:72
Index relid
Definition: relation.h:518
RangeTblEntry ** simple_rte_array
Definition: relation.h:185
uintptr_t Datum
Definition: postgres.h:374
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
List * indexlist
Definition: relation.h:527
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
#define INDEX_MAX_KEYS
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:1969
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:128
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
RTEKind rtekind
Definition: parsenodes.h:882
static Datum values[MAXATTR]
Definition: bootstrap.c:162
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:80
#define elog
Definition: elog.h:219
Oid indexoid
Definition: relation.h:588
bool * reverse_sort
Definition: relation.h:604
#define BTLessStrategyNumber
Definition: stratnum.h:29
List * indpred
Definition: relation.h:611
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
HeapTuple index_getnext(IndexScanDesc scan, ScanDirection direction)
Definition: indexam.c:659
IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, int norderbys)
Definition: indexam.c:221
void get_join_variables ( PlannerInfo root,
List args,
SpecialJoinInfo sjinfo,
VariableStatData vardata1,
VariableStatData vardata2,
bool join_is_reversed 
)

Definition at line 4350 of file selfuncs.c.

References bms_is_subset(), elog, ERROR, examine_variable(), linitial, list_length(), lsecond, VariableStatData::rel, RelOptInfo::relids, SpecialJoinInfo::syn_lefthand, and SpecialJoinInfo::syn_righthand.

Referenced by eqjoinsel(), and networkjoinsel().

4353 {
4354  Node *left,
4355  *right;
4356 
4357  if (list_length(args) != 2)
4358  elog(ERROR, "join operator should take two arguments");
4359 
4360  left = (Node *) linitial(args);
4361  right = (Node *) lsecond(args);
4362 
4363  examine_variable(root, left, 0, vardata1);
4364  examine_variable(root, right, 0, vardata2);
4365 
4366  if (vardata1->rel &&
4367  bms_is_subset(vardata1->rel->relids, sjinfo->syn_righthand))
4368  *join_is_reversed = true; /* var1 is on RHS */
4369  else if (vardata2->rel &&
4370  bms_is_subset(vardata2->rel->relids, sjinfo->syn_lefthand))
4371  *join_is_reversed = true; /* var2 is on LHS */
4372  else
4373  *join_is_reversed = false;
4374 }
RelOptInfo * rel
Definition: selfuncs.h:70
Definition: nodes.h:508
#define lsecond(l)
Definition: pg_list.h:114
Relids syn_lefthand
Definition: relation.h:1809
Relids syn_righthand
Definition: relation.h:1810
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:307
Relids relids
Definition: relation.h:490
void examine_variable(PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata)
Definition: selfuncs.c:4409
static int list_length(const List *l)
Definition: pg_list.h:89
#define elog
Definition: elog.h:219
bool get_restriction_variable ( PlannerInfo root,
List args,
int  varRelid,
VariableStatData vardata,
Node **  other,
bool varonleft 
)

Definition at line 4290 of file selfuncs.c.

References estimate_expression_value(), examine_variable(), linitial, list_length(), lsecond, NULL, VariableStatData::rel, ReleaseVariableStats, and VariableStatData::var.

Referenced by _int_matchsel(), arraycontsel(), eqsel(), ltreeparentsel(), networksel(), patternsel(), rangesel(), scalargtsel(), scalarltsel(), and tsmatchsel().

4293 {
4294  Node *left,
4295  *right;
4296  VariableStatData rdata;
4297 
4298  /* Fail if not a binary opclause (probably shouldn't happen) */
4299  if (list_length(args) != 2)
4300  return false;
4301 
4302  left = (Node *) linitial(args);
4303  right = (Node *) lsecond(args);
4304 
4305  /*
4306  * Examine both sides. Note that when varRelid is nonzero, Vars of other
4307  * relations will be treated as pseudoconstants.
4308  */
4309  examine_variable(root, left, varRelid, vardata);
4310  examine_variable(root, right, varRelid, &rdata);
4311 
4312  /*
4313  * If one side is a variable and the other not, we win.
4314  */
4315  if (vardata->rel && rdata.rel == NULL)
4316  {
4317  *varonleft = true;
4318  *other = estimate_expression_value(root, rdata.var);
4319  /* Assume we need no ReleaseVariableStats(rdata) here */
4320  return true;
4321  }
4322 
4323  if (vardata->rel == NULL && rdata.rel)
4324  {
4325  *varonleft = false;
4326  *other = estimate_expression_value(root, vardata->var);
4327  /* Assume we need no ReleaseVariableStats(*vardata) here */
4328  *vardata = rdata;
4329  return true;
4330  }
4331 
4332  /* Ooops, clause has wrong structure (probably var op var) */
4333  ReleaseVariableStats(*vardata);
4334  ReleaseVariableStats(rdata);
4335 
4336  return false;
4337 }
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2399
RelOptInfo * rel
Definition: selfuncs.h:70
Definition: nodes.h:508
#define lsecond(l)
Definition: pg_list.h:114
#define linitial(l)
Definition: pg_list.h:110
void examine_variable(PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata)
Definition: selfuncs.c:4409
#define NULL
Definition: c.h:226
static int list_length(const List *l)
Definition: pg_list.h:89
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:80
double get_variable_numdistinct ( VariableStatData vardata,
bool isdefault 
)

Definition at line 4753 of file selfuncs.c.

References BOOLOID, clamp_row_est(), DEFAULT_NUM_DISTINCT, GETSTRUCT, HeapTupleIsValid, IsA, VariableStatData::isunique, NULL, ObjectIdAttributeNumber, VariableStatData::rel, SelfItemPointerAttributeNumber, VariableStatData::statsTuple, TableOidAttributeNumber, RelOptInfo::tuples, VariableStatData::var, and VariableStatData::vartype.

Referenced by add_unique_group_var(), eqjoinsel_inner(), eqjoinsel_semi(), estimate_hash_bucketsize(), var_eq_const(), and var_eq_non_const().

4754 {
4755  double stadistinct;
4756  double stanullfrac = 0.0;
4757  double ntuples;
4758 
4759  *isdefault = false;
4760 
4761  /*
4762  * Determine the stadistinct value to use. There are cases where we can
4763  * get an estimate even without a pg_statistic entry, or can get a better
4764  * value than is in pg_statistic. Grab stanullfrac too if we can find it
4765  * (otherwise, assume no nulls, for lack of any better idea).
4766  */
4767  if (HeapTupleIsValid(vardata->statsTuple))
4768  {
4769  /* Use the pg_statistic entry */
4770  Form_pg_statistic stats;
4771 
4772  stats = (Form_pg_statistic) GETSTRUCT(vardata->statsTuple);
4773  stadistinct = stats->stadistinct;
4774  stanullfrac = stats->stanullfrac;
4775  }
4776  else if (vardata->vartype == BOOLOID)
4777  {
4778  /*
4779  * Special-case boolean columns: presumably, two distinct values.
4780  *
4781  * Are there any other datatypes we should wire in special estimates
4782  * for?
4783  */
4784  stadistinct = 2.0;
4785  }
4786  else
4787  {
4788  /*
4789  * We don't keep statistics for system columns, but in some cases we
4790  * can infer distinctness anyway.
4791  */
4792  if (vardata->var && IsA(vardata->var, Var))
4793  {
4794  switch (((Var *) vardata->var)->varattno)
4795  {
4798  stadistinct = -1.0; /* unique (and all non null) */
4799  break;
4801  stadistinct = 1.0; /* only 1 value */
4802  break;
4803  default:
4804  stadistinct = 0.0; /* means "unknown" */
4805  break;
4806  }
4807  }
4808  else
4809  stadistinct = 0.0; /* means "unknown" */
4810 
4811  /*
4812  * XXX consider using estimate_num_groups on expressions?
4813  */
4814  }
4815 
4816  /*
4817  * If there is a unique index or DISTINCT clause for the variable, assume
4818  * it is unique no matter what pg_statistic says; the statistics could be
4819  * out of date, or we might have found a partial unique index that proves
4820  * the var is unique for this query. However, we'd better still believe
4821  * the null-fraction statistic.
4822  */
4823  if (vardata->isunique)
4824  stadistinct = -1.0 * (1.0 - stanullfrac);
4825 
4826  /*
4827  * If we had an absolute estimate, use that.
4828  */
4829  if (stadistinct > 0.0)
4830  return clamp_row_est(stadistinct);
4831 
4832  /*
4833  * Otherwise we need to get the relation size; punt if not available.
4834  */
4835  if (vardata->rel == NULL)
4836  {
4837  *isdefault = true;
4838  return DEFAULT_NUM_DISTINCT;
4839  }
4840  ntuples = vardata->rel->tuples;
4841  if (ntuples <= 0.0)
4842  {
4843  *isdefault = true;
4844  return DEFAULT_NUM_DISTINCT;
4845  }
4846 
4847  /*
4848  * If we had a relative estimate, use that.
4849  */
4850  if (stadistinct < 0.0)
4851  return clamp_row_est(-stadistinct * ntuples);
4852 
4853  /*
4854  * With no data, estimate ndistinct = ntuples if the table is small, else
4855  * use default. We use DEFAULT_NUM_DISTINCT as the cutoff for "small" so
4856  * that the behavior isn't discontinuous.
4857  */
4858  if (ntuples < DEFAULT_NUM_DISTINCT)
4859  return clamp_row_est(ntuples);
4860 
4861  *isdefault = true;
4862  return DEFAULT_NUM_DISTINCT;
4863 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
HeapTuple statsTuple
Definition: selfuncs.h:71
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
double tuples
Definition: relation.h:529
RelOptInfo * rel
Definition: selfuncs.h:70
Definition: primnodes.h:141
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:129
#define TableOidAttributeNumber
Definition: sysattr.h:27
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define BOOLOID
Definition: pg_type.h:288
#define DEFAULT_NUM_DISTINCT
Definition: selfuncs.h:46
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
double clamp_row_est(double nrows)
Definition: costsize.c:172
static bool get_variable_range ( PlannerInfo root,
VariableStatData vardata,
Oid  sortop,
Datum min,
Datum max 
)
static

Definition at line 4875 of file selfuncs.c.

References VariableStatData::atttype, VariableStatData::atttypmod, datumCopy(), DatumGetBool, DEFAULT_COLLATION_OID, fmgr_info(), free_attstatsslot(), FunctionCall2Coll(), get_actual_variable_range(), get_attstatsslot(), get_opcode(), get_typlenbyval(), HeapTupleIsValid, i, InvalidOid, NULL, STATISTIC_KIND_HISTOGRAM, STATISTIC_KIND_MCV, VariableStatData::statsTuple, and values.

Referenced by mergejoinscansel().

4877 {
4878  Datum tmin = 0;
4879  Datum tmax = 0;
4880  bool have_data = false;
4881  int16 typLen;
4882  bool typByVal;
4883  Datum *values;
4884  int nvalues;
4885  int i;
4886 
4887  /*
4888  * XXX It's very tempting to try to use the actual column min and max, if
4889  * we can get them relatively-cheaply with an index probe. However, since
4890  * this function is called many times during join planning, that could
4891  * have unpleasant effects on planning speed. Need more investigation
4892  * before enabling this.
4893  */
4894 #ifdef NOT_USED
4895  if (get_actual_variable_range(root, vardata, sortop, min, max))
4896  return true;
4897 #endif
4898 
4899  if (!HeapTupleIsValid(vardata->statsTuple))
4900  {
4901  /* no stats available, so default result */
4902  return false;
4903  }
4904 
4905  get_typlenbyval(vardata->atttype, &typLen, &typByVal);
4906 
4907  /*
4908  * If there is a histogram, grab the first and last values.
4909  *
4910  * If there is a histogram that is sorted with some other operator than
4911  * the one we want, fail --- this suggests that there is data we can't
4912  * use.
4913  */
4914  if (get_attstatsslot(vardata->statsTuple,
4915  vardata->atttype, vardata->atttypmod,
4916  STATISTIC_KIND_HISTOGRAM, sortop,
4917  NULL,
4918  &values, &nvalues,
4919  NULL, NULL))
4920  {
4921  if (nvalues > 0)
4922  {
4923  tmin = datumCopy(values[0], typByVal, typLen);
4924  tmax = datumCopy(values[nvalues - 1], typByVal, typLen);
4925  have_data = true;
4926  }
4927  free_attstatsslot(vardata->atttype, values, nvalues, NULL, 0);
4928  }
4929  else if (get_attstatsslot(vardata->statsTuple,
4930  vardata->atttype, vardata->atttypmod,
4932  NULL,
4933  &values, &nvalues,
4934  NULL, NULL))
4935  {
4936  free_attstatsslot(vardata->atttype, values, nvalues, NULL, 0);
4937  return false;
4938  }
4939 
4940  /*
4941  * If we have most-common-values info, look for extreme MCVs. This is
4942  * needed even if we also have a histogram, since the histogram excludes
4943  * the MCVs. However, usually the MCVs will not be the extreme values, so
4944  * avoid unnecessary data copying.
4945  */
4946  if (get_attstatsslot(vardata->statsTuple,
4947  vardata->atttype, vardata->atttypmod,
4949  NULL,
4950  &values, &nvalues,
4951  NULL, NULL))
4952  {
4953  bool tmin_is_mcv = false;
4954  bool tmax_is_mcv = false;
4955  FmgrInfo opproc;
4956 
4957  fmgr_info(get_opcode(sortop), &opproc);
4958 
4959  for (i = 0; i < nvalues; i++)
4960  {
4961  if (!have_data)
4962  {
4963  tmin = tmax = values[i];
4964  tmin_is_mcv = tmax_is_mcv = have_data = true;
4965  continue;
4966  }
4967  if (DatumGetBool(FunctionCall2Coll(&opproc,
4969  values[i], tmin)))
4970  {
4971  tmin = values[i];
4972  tmin_is_mcv = true;
4973  }
4974  if (DatumGetBool(FunctionCall2Coll(&opproc,
4976  tmax, values[i])))
4977  {
4978  tmax = values[i];
4979  tmax_is_mcv = true;
4980  }
4981  }
4982  if (tmin_is_mcv)
4983  tmin = datumCopy(tmin, typByVal, typLen);
4984  if (tmax_is_mcv)
4985  tmax = datumCopy(tmax, typByVal, typLen);
4986  free_attstatsslot(vardata->atttype, values, nvalues, NULL, 0);
4987  }
4988 
4989  *min = tmin;
4990  *max = tmax;
4991  return have_data;
4992 }
signed short int16
Definition: c.h:252
Definition: fmgr.h:53
HeapTuple statsTuple
Definition: selfuncs.h:71
#define STATISTIC_KIND_HISTOGRAM
Definition: pg_statistic.h:222
bool get_attstatsslot(HeapTuple statstuple, Oid atttype, int32 atttypmod, int reqkind, Oid reqop, Oid *actualop, Datum **values, int *nvalues, float4 **numbers, int *nnumbers)
Definition: lsyscache.c:2854
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1306
int32 atttypmod
Definition: selfuncs.h:76
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:159
static bool get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, Oid sortop, Datum *min, Datum *max)
Definition: selfuncs.c:5007
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:68
#define DatumGetBool(X)
Definition: postgres.h:401
#define STATISTIC_KIND_MCV
Definition: pg_statistic.h:204
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:374
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:1969
static Datum values[MAXATTR]
Definition: bootstrap.c:162
int i
void free_attstatsslot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers)
Definition: lsyscache.c:2978
static bool gincost_opexpr ( PlannerInfo root,
IndexOptInfo index,
IndexQualInfo qinfo,
GinQualCounts counts 
)
static

Definition at line 7059 of file selfuncs.c.

References arg, IndexQualInfo::clause_op, estimate_expression_value(), GinQualCounts::exactEntries, get_commutator(), gincost_pattern(), IndexQualInfo::indexcol, IsA, IndexQualInfo::other_operand, GinQualCounts::searchEntries, and IndexQualInfo::varonleft.

Referenced by gincostestimate().

7063 {
7064  int indexcol = qinfo->indexcol;
7065  Oid clause_op = qinfo->clause_op;
7066  Node *operand = qinfo->other_operand;
7067 
7068  if (!qinfo->varonleft)
7069  {
7070  /* must commute the operator */
7071  clause_op = get_commutator(clause_op);
7072  }
7073 
7074  /* aggressively reduce to a constant, and look through relabeling */
7075  operand = estimate_expression_value(root, operand);
7076 
7077  if (IsA(operand, RelabelType))
7078  operand = (Node *) ((RelabelType *) operand)->arg;
7079 
7080  /*
7081  * It's impossible to call extractQuery method for unknown operand. So
7082  * unless operand is a Const we can't do much; just assume there will be
7083  * one ordinary search entry from the operand at runtime.
7084  */
7085  if (!IsA(operand, Const))
7086  {
7087  counts->exactEntries++;
7088  counts->searchEntries++;
7089  return true;
7090  }
7091 
7092  /* If Const is null, there can be no matches */
7093  if (((Const *) operand)->constisnull)
7094  return false;
7095 
7096  /* Otherwise, apply extractQuery and get the actual term counts */
7097  return gincost_pattern(index, indexcol, clause_op,
7098  ((Const *) operand)->constvalue,
7099  counts);
7100 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1281
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2399
Definition: nodes.h:508
double searchEntries
Definition: selfuncs.c:6947
unsigned int Oid
Definition: postgres_ext.h:31
double exactEntries
Definition: selfuncs.c:6946
bool varonleft
Definition: selfuncs.h:107
Node * other_operand
Definition: selfuncs.h:109
void * arg
static bool gincost_pattern(IndexOptInfo *index, int indexcol, Oid clause_op, Datum query, GinQualCounts *counts)
Definition: selfuncs.c:6957
static bool gincost_pattern ( IndexOptInfo index,
int  indexcol,
Oid  clause_op,
Datum  query,
GinQualCounts counts 
)
static

Definition at line 6957 of file selfuncs.c.

References DEFAULT_COLLATION_OID, elog, ERROR, GinQualCounts::exactEntries, get_op_opfamily_properties(), get_opfamily_proc(), get_rel_name(), GIN_EXTRACTQUERY_PROC, GIN_SEARCH_MODE_DEFAULT, GIN_SEARCH_MODE_INCLUDE_EMPTY, GinQualCounts::haveFullScan, i, IndexOptInfo::indexcollations, IndexOptInfo::indexoid, NULL, OidFunctionCall7Coll(), OidIsValid, IndexOptInfo::opcintype, IndexOptInfo::opfamily, GinQualCounts::partialEntries, PointerGetDatum, GinQualCounts::searchEntries, and UInt16GetDatum.

Referenced by gincost_opexpr(), and gincost_scalararrayopexpr().

6960 {
6961  Oid extractProcOid;
6962  Oid collation;
6963  int strategy_op;
6964  Oid lefttype,
6965  righttype;
6966  int32 nentries = 0;
6967  bool *partial_matches = NULL;
6968  Pointer *extra_data = NULL;
6969  bool *nullFlags = NULL;
6970  int32 searchMode = GIN_SEARCH_MODE_DEFAULT;
6971  int32 i;
6972 
6973  /*
6974  * Get the operator's strategy number and declared input data types within
6975  * the index opfamily. (We don't need the latter, but we use
6976  * get_op_opfamily_properties because it will throw error if it fails to
6977  * find a matching pg_amop entry.)
6978  */
6979  get_op_opfamily_properties(clause_op, index->opfamily[indexcol], false,
6980  &strategy_op, &lefttype, &righttype);
6981 
6982  /*
6983  * GIN always uses the "default" support functions, which are those with
6984  * lefttype == righttype == the opclass' opcintype (see
6985  * IndexSupportInitialize in relcache.c).
6986  */
6987  extractProcOid = get_opfamily_proc(index->opfamily[indexcol],
6988  index->opcintype[indexcol],
6989  index->opcintype[indexcol],
6991 
6992  if (!OidIsValid(extractProcOid))
6993  {
6994  /* should not happen; throw same error as index_getprocinfo */
6995  elog(ERROR, "missing support function %d for attribute %d of index \"%s\"",
6996  GIN_EXTRACTQUERY_PROC, indexcol + 1,
6997  get_rel_name(index->indexoid));
6998  }
6999 
7000  /*
7001  * Choose collation to pass to extractProc (should match initGinState).
7002  */
7003  if (OidIsValid(index->indexcollations[indexcol]))
7004  collation = index->indexcollations[indexcol];
7005  else
7006  collation = DEFAULT_COLLATION_OID;
7007 
7008  OidFunctionCall7Coll(extractProcOid,
7009  collation,
7010  query,
7011  PointerGetDatum(&nentries),
7012  UInt16GetDatum(strategy_op),
7013  PointerGetDatum(&partial_matches),
7014  PointerGetDatum(&extra_data),
7015  PointerGetDatum(&nullFlags),
7016  PointerGetDatum(&searchMode));
<