PostgreSQL Source Code  git master
indxpath.c File Reference
#include "postgres.h"
#include <math.h>
#include "access/stratnum.h"
#include "access/sysattr.h"
#include "catalog/pg_am.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/predtest.h"
#include "optimizer/prep.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/var.h"
#include "utils/builtins.h"
#include "utils/bytea.h"
#include "utils/lsyscache.h"
#include "utils/pg_locale.h"
#include "utils/selfuncs.h"
Include dependency graph for indxpath.c:

Go to the source code of this file.

Data Structures

struct  IndexClauseSet
 
struct  PathClauseUsage
 
struct  ec_member_matches_arg
 

Macros

#define IndexCollMatchesExprColl(idxcollation, exprcollation)   ((idxcollation) == InvalidOid || (idxcollation) == (exprcollation))
 

Enumerations

enum  ScanTypeControl { ST_INDEXSCAN, ST_BITMAPSCAN, ST_ANYSCAN }
 

Functions

static void consider_index_join_clauses (PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths)
 
static void consider_index_join_outer_rels (PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths, List *indexjoinclauses, int considered_clauses, List **considered_relids)
 
static void get_join_index_paths (PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths, Relids relids, List **considered_relids)
 
static bool eclass_already_used (EquivalenceClass *parent_ec, Relids oldrelids, List *indexjoinclauses)
 
static bool bms_equal_any (Relids relids, List *relids_list)
 
static void get_index_paths (PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, List **bitindexpaths)
 
static Listbuild_index_paths (PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, bool useful_predicate, ScanTypeControl scantype, bool *skip_nonnative_saop, bool *skip_lower_saop)
 
static Listbuild_paths_for_OR (PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
 
static Listgenerate_bitmap_or_paths (PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
 
static Pathchoose_bitmap_and (PlannerInfo *root, RelOptInfo *rel, List *paths)
 
static int path_usage_comparator (const void *a, const void *b)
 
static Cost bitmap_scan_cost_est (PlannerInfo *root, RelOptInfo *rel, Path *ipath)
 
static Cost bitmap_and_cost_est (PlannerInfo *root, RelOptInfo *rel, List *paths)
 
static PathClauseUsageclassify_index_clause_usage (Path *path, List **clauselist)
 
static Relids get_bitmap_tree_required_outer (Path *bitmapqual)
 
static void find_indexpath_quals (Path *bitmapqual, List **quals, List **preds)
 
static int find_list_position (Node *node, List **nodelist)
 
static bool check_index_only (RelOptInfo *rel, IndexOptInfo *index)
 
static double get_loop_count (PlannerInfo *root, Index cur_relid, Relids outer_relids)
 
static double adjust_rowcount_for_semijoins (PlannerInfo *root, Index cur_relid, Index outer_relid, double rowcount)
 
static double approximate_joinrel_size (PlannerInfo *root, Relids relids)
 
static void match_restriction_clauses_to_index (RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauseset)
 
static void match_join_clauses_to_index (PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauseset, List **joinorclauses)
 
static void match_eclass_clauses_to_index (PlannerInfo *root, IndexOptInfo *index, IndexClauseSet *clauseset)
 
static void match_clauses_to_index (IndexOptInfo *index, List *clauses, IndexClauseSet *clauseset)
 
static void match_clause_to_index (IndexOptInfo *index, RestrictInfo *rinfo, IndexClauseSet *clauseset)
 
static bool match_clause_to_indexcol (IndexOptInfo *index, int indexcol, RestrictInfo *rinfo)
 
static bool is_indexable_operator (Oid expr_op, Oid opfamily, bool indexkey_on_left)
 
static bool match_rowcompare_to_indexcol (IndexOptInfo *index, int indexcol, Oid opfamily, Oid idxcollation, RowCompareExpr *clause)
 
static void match_pathkeys_to_index (IndexOptInfo *index, List *pathkeys, List **orderby_clauses_p, List **clause_columns_p)
 
static Exprmatch_clause_to_ordering_op (IndexOptInfo *index, int indexcol, Expr *clause, Oid pk_opfamily)
 
static bool ec_member_matches_indexcol (PlannerInfo *root, RelOptInfo *rel, EquivalenceClass *ec, EquivalenceMember *em, void *arg)
 
static bool match_boolean_index_clause (Node *clause, int indexcol, IndexOptInfo *index)
 
static bool match_special_index_operator (Expr *clause, Oid opfamily, Oid idxcollation, bool indexkey_on_left)
 
static Exprexpand_boolean_index_clause (Node *clause, int indexcol, IndexOptInfo *index)
 
static Listexpand_indexqual_opclause (RestrictInfo *rinfo, Oid opfamily, Oid idxcollation)
 
static RestrictInfoexpand_indexqual_rowcompare (RestrictInfo *rinfo, IndexOptInfo *index, int indexcol)
 
static Listprefix_quals (Node *leftop, Oid opfamily, Oid collation, Const *prefix, Pattern_Prefix_Status pstatus)
 
static Listnetwork_prefix_quals (Node *leftop, Oid expr_op, Oid opfamily, Datum rightop)
 
static Datum string_to_datum (const char *str, Oid datatype)
 
static Conststring_to_const (const char *str, Oid datatype)
 
void create_index_paths (PlannerInfo *root, RelOptInfo *rel)
 
void check_index_predicates (PlannerInfo *root, RelOptInfo *rel)
 
bool relation_has_unique_index_for (PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List *exprlist, List *oprlist)
 
bool indexcol_is_bool_constant_for_query (IndexOptInfo *index, int indexcol)
 
bool match_index_to_operand (Node *operand, int indexcol, IndexOptInfo *index)
 
void expand_indexqual_conditions (IndexOptInfo *index, List *indexclauses, List *indexclausecols, List **indexquals_p, List **indexqualcols_p)
 
Expradjust_rowcompare_for_index (RowCompareExpr *clause, IndexOptInfo *index, int indexcol, List **indexcolnos, bool *var_on_left_p)
 

Macro Definition Documentation

◆ IndexCollMatchesExprColl

#define IndexCollMatchesExprColl (   idxcollation,
  exprcollation 
)    ((idxcollation) == InvalidOid || (idxcollation) == (exprcollation))

Enumeration Type Documentation

◆ ScanTypeControl

Enumerator
ST_INDEXSCAN 
ST_BITMAPSCAN 
ST_ANYSCAN 

Definition at line 48 of file indxpath.c.

49 {
50  ST_INDEXSCAN, /* must support amgettuple */
51  ST_BITMAPSCAN, /* must support amgetbitmap */
52  ST_ANYSCAN /* either is okay */
ScanTypeControl
Definition: indxpath.c:48

Function Documentation

◆ adjust_rowcompare_for_index()

Expr* adjust_rowcompare_for_index ( RowCompareExpr clause,
IndexOptInfo index,
int  indexcol,
List **  indexcolnos,
bool var_on_left_p 
)

Definition at line 3855 of file indxpath.c.

References Assert, bms_is_member(), BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, BTLessStrategyNumber, contain_volatile_functions(), copyObject, elog, ERROR, get_commutator(), get_op_opfamily_properties(), get_op_opfamily_strategy(), get_opfamily_member(), i, IndexOptInfo::indexcollations, IndexCollMatchesExprColl, RowCompareExpr::inputcollids, InvalidOid, lappend_int(), lappend_oid(), RowCompareExpr::largs, lfirst, lfirst_oid, linitial, linitial_oid, list_copy(), list_head(), list_length(), list_make1_int, list_make1_oid, list_truncate(), lnext, make_opclause(), makeNode, match_index_to_operand(), IndexOptInfo::ncolumns, NIL, IndexOptInfo::nkeycolumns, OidIsValid, RowCompareExpr::opfamilies, IndexOptInfo::opfamily, RowCompareExpr::opnos, pull_varnos(), RowCompareExpr::rargs, RowCompareExpr::rctype, IndexOptInfo::rel, RelOptInfo::relid, ROWCOMPARE_GE, and ROWCOMPARE_LE.

Referenced by expand_indexqual_rowcompare(), and fix_indexqual_references().

3860 {
3861  bool var_on_left;
3862  int op_strategy;
3863  Oid op_lefttype;
3864  Oid op_righttype;
3865  int matching_cols;
3866  Oid expr_op;
3867  List *opfamilies;
3868  List *lefttypes;
3869  List *righttypes;
3870  List *new_ops;
3871  ListCell *largs_cell;
3872  ListCell *rargs_cell;
3873  ListCell *opnos_cell;
3874  ListCell *collids_cell;
3875 
3876  /* We have to figure out (again) how the first col matches */
3877  var_on_left = match_index_to_operand((Node *) linitial(clause->largs),
3878  indexcol, index);
3879  Assert(var_on_left ||
3881  indexcol, index));
3882  *var_on_left_p = var_on_left;
3883 
3884  expr_op = linitial_oid(clause->opnos);
3885  if (!var_on_left)
3886  expr_op = get_commutator(expr_op);
3887  get_op_opfamily_properties(expr_op, index->opfamily[indexcol], false,
3888  &op_strategy,
3889  &op_lefttype,
3890  &op_righttype);
3891 
3892  /* Initialize returned list of which index columns are used */
3893  *indexcolnos = list_make1_int(indexcol);
3894 
3895  /* Build lists of the opfamilies and operator datatypes in case needed */
3896  opfamilies = list_make1_oid(index->opfamily[indexcol]);
3897  lefttypes = list_make1_oid(op_lefttype);
3898  righttypes = list_make1_oid(op_righttype);
3899 
3900  /*
3901  * See how many of the remaining columns match some index column in the
3902  * same way. As in match_clause_to_indexcol(), the "other" side of any
3903  * potential index condition is OK as long as it doesn't use Vars from the
3904  * indexed relation.
3905  */
3906  matching_cols = 1;
3907  largs_cell = lnext(list_head(clause->largs));
3908  rargs_cell = lnext(list_head(clause->rargs));
3909  opnos_cell = lnext(list_head(clause->opnos));
3910  collids_cell = lnext(list_head(clause->inputcollids));
3911 
3912  while (largs_cell != NULL)
3913  {
3914  Node *varop;
3915  Node *constop;
3916  int i;
3917 
3918  expr_op = lfirst_oid(opnos_cell);
3919  if (var_on_left)
3920  {
3921  varop = (Node *) lfirst(largs_cell);
3922  constop = (Node *) lfirst(rargs_cell);
3923  }
3924  else
3925  {
3926  varop = (Node *) lfirst(rargs_cell);
3927  constop = (Node *) lfirst(largs_cell);
3928  /* indexkey is on right, so commute the operator */
3929  expr_op = get_commutator(expr_op);
3930  if (expr_op == InvalidOid)
3931  break; /* operator is not usable */
3932  }
3933  if (bms_is_member(index->rel->relid, pull_varnos(constop)))
3934  break; /* no good, Var on wrong side */
3935  if (contain_volatile_functions(constop))
3936  break; /* no good, volatile comparison value */
3937 
3938  /*
3939  * The Var side can match any column of the index.
3940  */
3941  for (i = 0; i < index->nkeycolumns; i++)
3942  {
3943  if (match_index_to_operand(varop, i, index) &&
3944  get_op_opfamily_strategy(expr_op,
3945  index->opfamily[i]) == op_strategy &&
3947  lfirst_oid(collids_cell)))
3948 
3949  break;
3950  }
3951  if (i >= index->ncolumns)
3952  break; /* no match found */
3953 
3954  /* Add column number to returned list */
3955  *indexcolnos = lappend_int(*indexcolnos, i);
3956 
3957  /* Add opfamily and datatypes to lists */
3958  get_op_opfamily_properties(expr_op, index->opfamily[i], false,
3959  &op_strategy,
3960  &op_lefttype,
3961  &op_righttype);
3962  opfamilies = lappend_oid(opfamilies, index->opfamily[i]);
3963  lefttypes = lappend_oid(lefttypes, op_lefttype);
3964  righttypes = lappend_oid(righttypes, op_righttype);
3965 
3966  /* This column matches, keep scanning */
3967  matching_cols++;
3968  largs_cell = lnext(largs_cell);
3969  rargs_cell = lnext(rargs_cell);
3970  opnos_cell = lnext(opnos_cell);
3971  collids_cell = lnext(collids_cell);
3972  }
3973 
3974  /* Return clause as-is if it's all usable as index quals */
3975  if (matching_cols == list_length(clause->opnos))
3976  return (Expr *) clause;
3977 
3978  /*
3979  * We have to generate a subset rowcompare (possibly just one OpExpr). The
3980  * painful part of this is changing < to <= or > to >=, so deal with that
3981  * first.
3982  */
3983  if (op_strategy == BTLessEqualStrategyNumber ||
3984  op_strategy == BTGreaterEqualStrategyNumber)
3985  {
3986  /* easy, just use the same operators */
3987  new_ops = list_truncate(list_copy(clause->opnos), matching_cols);
3988  }
3989  else
3990  {
3991  ListCell *opfamilies_cell;
3992  ListCell *lefttypes_cell;
3993  ListCell *righttypes_cell;
3994 
3995  if (op_strategy == BTLessStrategyNumber)
3996  op_strategy = BTLessEqualStrategyNumber;
3997  else if (op_strategy == BTGreaterStrategyNumber)
3998  op_strategy = BTGreaterEqualStrategyNumber;
3999  else
4000  elog(ERROR, "unexpected strategy number %d", op_strategy);
4001  new_ops = NIL;
4002  lefttypes_cell = list_head(lefttypes);
4003  righttypes_cell = list_head(righttypes);
4004  foreach(opfamilies_cell, opfamilies)
4005  {
4006  Oid opfam = lfirst_oid(opfamilies_cell);
4007  Oid lefttype = lfirst_oid(lefttypes_cell);
4008  Oid righttype = lfirst_oid(righttypes_cell);
4009 
4010  expr_op = get_opfamily_member(opfam, lefttype, righttype,
4011  op_strategy);
4012  if (!OidIsValid(expr_op)) /* should not happen */
4013  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
4014  op_strategy, lefttype, righttype, opfam);
4015  if (!var_on_left)
4016  {
4017  expr_op = get_commutator(expr_op);
4018  if (!OidIsValid(expr_op)) /* should not happen */
4019  elog(ERROR, "could not find commutator of operator %d(%u,%u) of opfamily %u",
4020  op_strategy, lefttype, righttype, opfam);
4021  }
4022  new_ops = lappend_oid(new_ops, expr_op);
4023  lefttypes_cell = lnext(lefttypes_cell);
4024  righttypes_cell = lnext(righttypes_cell);
4025  }
4026  }
4027 
4028  /* If we have more than one matching col, create a subset rowcompare */
4029  if (matching_cols > 1)
4030  {
4032 
4033  if (var_on_left)
4034  rc->rctype = (RowCompareType) op_strategy;
4035  else
4036  rc->rctype = (op_strategy == BTLessEqualStrategyNumber) ?
4038  rc->opnos = new_ops;
4040  matching_cols);
4042  matching_cols);
4043  rc->largs = list_truncate(copyObject(clause->largs),
4044  matching_cols);
4045  rc->rargs = list_truncate(copyObject(clause->rargs),
4046  matching_cols);
4047  return (Expr *) rc;
4048  }
4049  else
4050  {
4051  return make_opclause(linitial_oid(new_ops), BOOLOID, false,
4052  copyObject(linitial(clause->largs)),
4053  copyObject(linitial(clause->rargs)),
4054  InvalidOid,
4055  linitial_oid(clause->inputcollids));
4056  }
4057 }
#define NIL
Definition: pg_list.h:69
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1298
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
Oid * indexcollations
Definition: relation.h:767
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3206
RowCompareType rctype
Definition: primnodes.h:1039
List * opfamilies
Definition: primnodes.h:1041
List * list_truncate(List *list, int new_size)
Definition: list.c:350
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:517
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: clauses.c:173
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:958
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:605
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
RelOptInfo * rel
Definition: relation.h:755
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
#define IndexCollMatchesExprColl(idxcollation, exprcollation)
Definition: indxpath.c:44
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define list_make1_int(x1)
Definition: pg_list.h:145
int ncolumns
Definition: relation.h:763
#define lnext(lc)
Definition: pg_list.h:105
Relids pull_varnos(Node *node)
Definition: var.c:95
List * lappend_int(List *list, int datum)
Definition: list.c:146
Index relid
Definition: relation.h:640
#define list_make1_oid(x1)
Definition: pg_list.h:151
#define InvalidOid
Definition: postgres_ext.h:36
RowCompareType
Definition: primnodes.h:1025
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
#define linitial_oid(l)
Definition: pg_list.h:113
static int list_length(const List *l)
Definition: pg_list.h:89
int nkeycolumns
Definition: relation.h:764
Oid * opfamily
Definition: relation.h:768
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:80
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:133
int i
#define elog
Definition: elog.h:219
#define copyObject(obj)
Definition: nodes.h:630
List * inputcollids
Definition: primnodes.h:1042
#define BTLessStrategyNumber
Definition: stratnum.h:29
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ adjust_rowcount_for_semijoins()

static double adjust_rowcount_for_semijoins ( PlannerInfo root,
Index  cur_relid,
Index  outer_relid,
double  rowcount 
)
static

Definition at line 2027 of file indxpath.c.

References approximate_joinrel_size(), bms_is_member(), estimate_num_groups(), PlannerInfo::join_info_list, JOIN_SEMI, SpecialJoinInfo::jointype, lfirst, SpecialJoinInfo::semi_rhs_exprs, SpecialJoinInfo::syn_lefthand, and SpecialJoinInfo::syn_righthand.

Referenced by get_loop_count().

2031 {
2032  ListCell *lc;
2033 
2034  foreach(lc, root->join_info_list)
2035  {
2036  SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
2037 
2038  if (sjinfo->jointype == JOIN_SEMI &&
2039  bms_is_member(cur_relid, sjinfo->syn_lefthand) &&
2040  bms_is_member(outer_relid, sjinfo->syn_righthand))
2041  {
2042  /* Estimate number of unique-ified rows */
2043  double nraw;
2044  double nunique;
2045 
2046  nraw = approximate_joinrel_size(root, sjinfo->syn_righthand);
2047  nunique = estimate_num_groups(root,
2048  sjinfo->semi_rhs_exprs,
2049  nraw,
2050  NULL);
2051  if (rowcount > nunique)
2052  rowcount = nunique;
2053  }
2054  }
2055  return rowcount;
2056 }
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset)
Definition: selfuncs.c:3419
List * join_info_list
Definition: relation.h:264
static double approximate_joinrel_size(PlannerInfo *root, Relids relids)
Definition: indxpath.c:2070
Relids syn_lefthand
Definition: relation.h:2068
Relids syn_righthand
Definition: relation.h:2069
List * semi_rhs_exprs
Definition: relation.h:2077
#define lfirst(lc)
Definition: pg_list.h:106
JoinType jointype
Definition: relation.h:2070
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486

◆ approximate_joinrel_size()

static double approximate_joinrel_size ( PlannerInfo root,
Relids  relids 
)
static

Definition at line 2070 of file indxpath.c.

References Assert, bms_next_member(), IS_DUMMY_REL, RelOptInfo::relid, RelOptInfo::rows, PlannerInfo::simple_rel_array, and PlannerInfo::simple_rel_array_size.

Referenced by adjust_rowcount_for_semijoins().

2071 {
2072  double rowcount = 1.0;
2073  int relid;
2074 
2075  relid = -1;
2076  while ((relid = bms_next_member(relids, relid)) >= 0)
2077  {
2078  RelOptInfo *rel;
2079 
2080  /* Paranoia: ignore bogus relid indexes */
2081  if (relid >= root->simple_rel_array_size)
2082  continue;
2083  rel = root->simple_rel_array[relid];
2084  if (rel == NULL)
2085  continue;
2086  Assert(rel->relid == relid); /* sanity check on array */
2087 
2088  /* Relation could be proven empty, if so ignore */
2089  if (IS_DUMMY_REL(rel))
2090  continue;
2091 
2092  /* Otherwise, rel's rows estimate should be valid by now */
2093  Assert(rel->rows > 0);
2094 
2095  /* Accumulate product */
2096  rowcount *= rel->rows;
2097  }
2098  return rowcount;
2099 }
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1075
struct RelOptInfo ** simple_rel_array
Definition: relation.h:193
#define IS_DUMMY_REL(r)
Definition: relation.h:1317
int simple_rel_array_size
Definition: relation.h:194
Index relid
Definition: relation.h:640
double rows
Definition: relation.h:615
#define Assert(condition)
Definition: c.h:699

◆ bitmap_and_cost_est()

static Cost bitmap_and_cost_est ( PlannerInfo root,
RelOptInfo rel,
List paths 
)
static

Definition at line 1640 of file indxpath.c.

References BitmapHeapPath::bitmapqual, BitmapAndPath::bitmapquals, cost_bitmap_and_node(), cost_bitmap_heap_scan(), get_baserel_parampathinfo(), get_bitmap_tree_required_outer(), get_loop_count(), NIL, Path::parallel_workers, Path::param_info, Path::parent, BitmapHeapPath::path, BitmapAndPath::path, Path::pathkeys, Path::pathtarget, Path::pathtype, RelOptInfo::relid, RelOptInfo::reltarget, T_BitmapAnd, T_BitmapAndPath, T_BitmapHeapPath, T_BitmapHeapScan, Path::total_cost, and Path::type.

Referenced by choose_bitmap_and().

1641 {
1642  BitmapAndPath apath;
1643  BitmapHeapPath bpath;
1644  Relids required_outer;
1645 
1646  /* Set up a dummy BitmapAndPath */
1647  apath.path.type = T_BitmapAndPath;
1648  apath.path.pathtype = T_BitmapAnd;
1649  apath.path.parent = rel;
1650  apath.path.pathtarget = rel->reltarget;
1651  apath.path.param_info = NULL; /* not used in bitmap trees */
1652  apath.path.pathkeys = NIL;
1653  apath.bitmapquals = paths;
1654  cost_bitmap_and_node(&apath, root);
1655 
1656  /* Identify required outer rels, in case it's a parameterized scan */
1657  required_outer = get_bitmap_tree_required_outer((Path *) &apath);
1658 
1659  /* Set up a dummy BitmapHeapPath */
1660  bpath.path.type = T_BitmapHeapPath;
1661  bpath.path.pathtype = T_BitmapHeapScan;
1662  bpath.path.parent = rel;
1663  bpath.path.pathtarget = rel->reltarget;
1664  bpath.path.param_info = get_baserel_parampathinfo(root, rel,
1665  required_outer);
1666  bpath.path.pathkeys = NIL;
1667  bpath.bitmapqual = (Path *) &apath;
1668 
1669  /*
1670  * Check the cost of temporary path without considering parallelism.
1671  * Parallel bitmap heap path will be considered at later stage.
1672  */
1673  bpath.path.parallel_workers = 0;
1674 
1675  /* Now we can do cost_bitmap_heap_scan */
1676  cost_bitmap_heap_scan(&bpath.path, root, rel,
1677  bpath.path.param_info,
1678  (Path *) &apath,
1679  get_loop_count(root, rel->relid, required_outer));
1680 
1681  return bpath.path.total_cost;
1682 }
#define NIL
Definition: pg_list.h:69
PathTarget * pathtarget
Definition: relation.h:1079
void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, Path *bitmapqual, double loop_count)
Definition: costsize.c:945
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
Definition: relnode.c:1261
NodeTag type
Definition: relation.h:1074
int parallel_workers
Definition: relation.h:1085
void cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root)
Definition: costsize.c:1089
ParamPathInfo * param_info
Definition: relation.h:1081
List * bitmapquals
Definition: relation.h:1198
NodeTag pathtype
Definition: relation.h:1076
RelOptInfo * parent
Definition: relation.h:1078
Path * bitmapqual
Definition: relation.h:1186
Index relid
Definition: relation.h:640
static double get_loop_count(PlannerInfo *root, Index cur_relid, Relids outer_relids)
Definition: indxpath.c:1974
Cost total_cost
Definition: relation.h:1090
List * pathkeys
Definition: relation.h:1092
static Relids get_bitmap_tree_required_outer(Path *bitmapqual)
Definition: indxpath.c:1747
struct PathTarget * reltarget
Definition: relation.h:623

◆ bitmap_scan_cost_est()

static Cost bitmap_scan_cost_est ( PlannerInfo root,
RelOptInfo rel,
Path ipath 
)
static

Definition at line 1604 of file indxpath.c.

References BitmapHeapPath::bitmapqual, cost_bitmap_heap_scan(), get_baserel_parampathinfo(), get_bitmap_tree_required_outer(), get_loop_count(), NIL, Path::parallel_workers, Path::param_info, Path::parent, BitmapHeapPath::path, Path::pathkeys, Path::pathtarget, Path::pathtype, RelOptInfo::relid, RelOptInfo::reltarget, T_BitmapHeapPath, T_BitmapHeapScan, Path::total_cost, and Path::type.

Referenced by choose_bitmap_and().

1605 {
1606  BitmapHeapPath bpath;
1607  Relids required_outer;
1608 
1609  /* Identify required outer rels, in case it's a parameterized scan */
1610  required_outer = get_bitmap_tree_required_outer(ipath);
1611 
1612  /* Set up a dummy BitmapHeapPath */
1613  bpath.path.type = T_BitmapHeapPath;
1614  bpath.path.pathtype = T_BitmapHeapScan;
1615  bpath.path.parent = rel;
1616  bpath.path.pathtarget = rel->reltarget;
1617  bpath.path.param_info = get_baserel_parampathinfo(root, rel,
1618  required_outer);
1619  bpath.path.pathkeys = NIL;
1620  bpath.bitmapqual = ipath;
1621 
1622  /*
1623  * Check the cost of temporary path without considering parallelism.
1624  * Parallel bitmap heap path will be considered at later stage.
1625  */
1626  bpath.path.parallel_workers = 0;
1627  cost_bitmap_heap_scan(&bpath.path, root, rel,
1628  bpath.path.param_info,
1629  ipath,
1630  get_loop_count(root, rel->relid, required_outer));
1631 
1632  return bpath.path.total_cost;
1633 }
#define NIL
Definition: pg_list.h:69
PathTarget * pathtarget
Definition: relation.h:1079
void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, Path *bitmapqual, double loop_count)
Definition: costsize.c:945
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
Definition: relnode.c:1261
NodeTag type
Definition: relation.h:1074
int parallel_workers
Definition: relation.h:1085
ParamPathInfo * param_info
Definition: relation.h:1081
NodeTag pathtype
Definition: relation.h:1076
RelOptInfo * parent
Definition: relation.h:1078
Path * bitmapqual
Definition: relation.h:1186
Index relid
Definition: relation.h:640
static double get_loop_count(PlannerInfo *root, Index cur_relid, Relids outer_relids)
Definition: indxpath.c:1974
Cost total_cost
Definition: relation.h:1090
List * pathkeys
Definition: relation.h:1092
static Relids get_bitmap_tree_required_outer(Path *bitmapqual)
Definition: indxpath.c:1747
struct PathTarget * reltarget
Definition: relation.h:623

◆ bms_equal_any()

static bool bms_equal_any ( Relids  relids,
List relids_list 
)
static

Definition at line 706 of file indxpath.c.

References bms_equal(), and lfirst.

Referenced by consider_index_join_outer_rels(), create_index_paths(), and get_join_index_paths().

707 {
708  ListCell *lc;
709 
710  foreach(lc, relids_list)
711  {
712  if (bms_equal(relids, (Relids) lfirst(lc)))
713  return true;
714  }
715  return false;
716 }
#define lfirst(lc)
Definition: pg_list.h:106
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:153

◆ build_index_paths()

static List * build_index_paths ( PlannerInfo root,
RelOptInfo rel,
IndexOptInfo index,
IndexClauseSet clauses,
bool  useful_predicate,
ScanTypeControl  scantype,
bool skip_nonnative_saop,
bool skip_lower_saop 
)
static

Definition at line 857 of file indxpath.c.

References add_partial_path(), IndexOptInfo::amcanorderbyop, IndexOptInfo::amcanparallel, IndexOptInfo::amhasgetbitmap, IndexOptInfo::amhasgettuple, IndexOptInfo::amoptionalkey, IndexOptInfo::amsearcharray, Assert, BackwardScanDirection, bms_add_members(), bms_copy(), bms_del_member(), bms_is_empty(), build_index_pathkeys(), check_index_only(), RestrictInfo::clause, RestrictInfo::clause_relids, RelOptInfo::consider_parallel, create_index_path(), ForwardScanDirection, get_loop_count(), has_useful_pathkeys(), IndexClauseSet::indexclauses, IsA, lappend(), lappend_int(), RelOptInfo::lateral_relids, lfirst, match_pathkeys_to_index(), IndexOptInfo::ncolumns, NIL, NoMovementScanDirection, Path::parallel_workers, IndexPath::path, pfree(), PlannerInfo::query_pathkeys, RelOptInfo::relid, IndexOptInfo::sortopfamily, ST_ANYSCAN, ST_BITMAPSCAN, ST_INDEXSCAN, and truncate_useless_pathkeys().

Referenced by build_paths_for_OR(), and get_index_paths().

863 {
864  List *result = NIL;
865  IndexPath *ipath;
866  List *index_clauses;
867  List *clause_columns;
868  Relids outer_relids;
869  double loop_count;
870  List *orderbyclauses;
871  List *orderbyclausecols;
872  List *index_pathkeys;
873  List *useful_pathkeys;
874  bool found_lower_saop_clause;
875  bool pathkeys_possibly_useful;
876  bool index_is_ordered;
877  bool index_only_scan;
878  int indexcol;
879 
880  /*
881  * Check that index supports the desired scan type(s)
882  */
883  switch (scantype)
884  {
885  case ST_INDEXSCAN:
886  if (!index->amhasgettuple)
887  return NIL;
888  break;
889  case ST_BITMAPSCAN:
890  if (!index->amhasgetbitmap)
891  return NIL;
892  break;
893  case ST_ANYSCAN:
894  /* either or both are OK */
895  break;
896  }
897 
898  /*
899  * 1. Collect the index clauses into a single list.
900  *
901  * We build a list of RestrictInfo nodes for clauses to be used with this
902  * index, along with an integer list of the index column numbers (zero
903  * based) that each clause should be used with. The clauses are ordered
904  * by index key, so that the column numbers form a nondecreasing sequence.
905  * (This order is depended on by btree and possibly other places.) The
906  * lists can be empty, if the index AM allows that.
907  *
908  * found_lower_saop_clause is set true if we accept a ScalarArrayOpExpr
909  * index clause for a non-first index column. This prevents us from
910  * assuming that the scan result is ordered. (Actually, the result is
911  * still ordered if there are equality constraints for all earlier
912  * columns, but it seems too expensive and non-modular for this code to be
913  * aware of that refinement.)
914  *
915  * We also build a Relids set showing which outer rels are required by the
916  * selected clauses. Any lateral_relids are included in that, but not
917  * otherwise accounted for.
918  */
919  index_clauses = NIL;
920  clause_columns = NIL;
921  found_lower_saop_clause = false;
922  outer_relids = bms_copy(rel->lateral_relids);
923  for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
924  {
925  ListCell *lc;
926 
927  foreach(lc, clauses->indexclauses[indexcol])
928  {
929  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
930 
931  if (IsA(rinfo->clause, ScalarArrayOpExpr))
932  {
933  if (!index->amsearcharray)
934  {
935  if (skip_nonnative_saop)
936  {
937  /* Ignore because not supported by index */
938  *skip_nonnative_saop = true;
939  continue;
940  }
941  /* Caller had better intend this only for bitmap scan */
942  Assert(scantype == ST_BITMAPSCAN);
943  }
944  if (indexcol > 0)
945  {
946  if (skip_lower_saop)
947  {
948  /* Caller doesn't want to lose index ordering */
949  *skip_lower_saop = true;
950  continue;
951  }
952  found_lower_saop_clause = true;
953  }
954  }
955  index_clauses = lappend(index_clauses, rinfo);
956  clause_columns = lappend_int(clause_columns, indexcol);
957  outer_relids = bms_add_members(outer_relids,
958  rinfo->clause_relids);
959  }
960 
961  /*
962  * If no clauses match the first index column, check for amoptionalkey
963  * restriction. We can't generate a scan over an index with
964  * amoptionalkey = false unless there's at least one index clause.
965  * (When working on columns after the first, this test cannot fail. It
966  * is always okay for columns after the first to not have any
967  * clauses.)
968  */
969  if (index_clauses == NIL && !index->amoptionalkey)
970  return NIL;
971  }
972 
973  /* We do not want the index's rel itself listed in outer_relids */
974  outer_relids = bms_del_member(outer_relids, rel->relid);
975  /* Enforce convention that outer_relids is exactly NULL if empty */
976  if (bms_is_empty(outer_relids))
977  outer_relids = NULL;
978 
979  /* Compute loop_count for cost estimation purposes */
980  loop_count = get_loop_count(root, rel->relid, outer_relids);
981 
982  /*
983  * 2. Compute pathkeys describing index's ordering, if any, then see how
984  * many of them are actually useful for this query. This is not relevant
985  * if we are only trying to build bitmap indexscans, nor if we have to
986  * assume the scan is unordered.
987  */
988  pathkeys_possibly_useful = (scantype != ST_BITMAPSCAN &&
989  !found_lower_saop_clause &&
990  has_useful_pathkeys(root, rel));
991  index_is_ordered = (index->sortopfamily != NULL);
992  if (index_is_ordered && pathkeys_possibly_useful)
993  {
994  index_pathkeys = build_index_pathkeys(root, index,
996  useful_pathkeys = truncate_useless_pathkeys(root, rel,
997  index_pathkeys);
998  orderbyclauses = NIL;
999  orderbyclausecols = NIL;
1000  }
1001  else if (index->amcanorderbyop && pathkeys_possibly_useful)
1002  {
1003  /* see if we can generate ordering operators for query_pathkeys */
1005  &orderbyclauses,
1006  &orderbyclausecols);
1007  if (orderbyclauses)
1008  useful_pathkeys = root->query_pathkeys;
1009  else
1010  useful_pathkeys = NIL;
1011  }
1012  else
1013  {
1014  useful_pathkeys = NIL;
1015  orderbyclauses = NIL;
1016  orderbyclausecols = NIL;
1017  }
1018 
1019  /*
1020  * 3. Check if an index-only scan is possible. If we're not building
1021  * plain indexscans, this isn't relevant since bitmap scans don't support
1022  * index data retrieval anyway.
1023  */
1024  index_only_scan = (scantype != ST_BITMAPSCAN &&
1025  check_index_only(rel, index));
1026 
1027  /*
1028  * 4. Generate an indexscan path if there are relevant restriction clauses
1029  * in the current clauses, OR the index ordering is potentially useful for
1030  * later merging or final output ordering, OR the index has a useful
1031  * predicate, OR an index-only scan is possible.
1032  */
1033  if (index_clauses != NIL || useful_pathkeys != NIL || useful_predicate ||
1034  index_only_scan)
1035  {
1036  ipath = create_index_path(root, index,
1037  index_clauses,
1038  clause_columns,
1039  orderbyclauses,
1040  orderbyclausecols,
1041  useful_pathkeys,
1042  index_is_ordered ?
1045  index_only_scan,
1046  outer_relids,
1047  loop_count,
1048  false);
1049  result = lappend(result, ipath);
1050 
1051  /*
1052  * If appropriate, consider parallel index scan. We don't allow
1053  * parallel index scan for bitmap index scans.
1054  */
1055  if (index->amcanparallel &&
1056  rel->consider_parallel && outer_relids == NULL &&
1057  scantype != ST_BITMAPSCAN)
1058  {
1059  ipath = create_index_path(root, index,
1060  index_clauses,
1061  clause_columns,
1062  orderbyclauses,
1063  orderbyclausecols,
1064  useful_pathkeys,
1065  index_is_ordered ?
1068  index_only_scan,
1069  outer_relids,
1070  loop_count,
1071  true);
1072 
1073  /*
1074  * if, after costing the path, we find that it's not worth using
1075  * parallel workers, just free it.
1076  */
1077  if (ipath->path.parallel_workers > 0)
1078  add_partial_path(rel, (Path *) ipath);
1079  else
1080  pfree(ipath);
1081  }
1082  }
1083 
1084  /*
1085  * 5. If the index is ordered, a backwards scan might be interesting.
1086  */
1087  if (index_is_ordered && pathkeys_possibly_useful)
1088  {
1089  index_pathkeys = build_index_pathkeys(root, index,
1091  useful_pathkeys = truncate_useless_pathkeys(root, rel,
1092  index_pathkeys);
1093  if (useful_pathkeys != NIL)
1094  {
1095  ipath = create_index_path(root, index,
1096  index_clauses,
1097  clause_columns,
1098  NIL,
1099  NIL,
1100  useful_pathkeys,
1102  index_only_scan,
1103  outer_relids,
1104  loop_count,
1105  false);
1106  result = lappend(result, ipath);
1107 
1108  /* If appropriate, consider parallel index scan */
1109  if (index->amcanparallel &&
1110  rel->consider_parallel && outer_relids == NULL &&
1111  scantype != ST_BITMAPSCAN)
1112  {
1113  ipath = create_index_path(root, index,
1114  index_clauses,
1115  clause_columns,
1116  NIL,
1117  NIL,
1118  useful_pathkeys,
1120  index_only_scan,
1121  outer_relids,
1122  loop_count,
1123  true);
1124 
1125  /*
1126  * if, after costing the path, we find that it's not worth
1127  * using parallel workers, just free it.
1128  */
1129  if (ipath->path.parallel_workers > 0)
1130  add_partial_path(rel, (Path *) ipath);
1131  else
1132  pfree(ipath);
1133  }
1134  }
1135  }
1136 
1137  return result;
1138 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Path path
Definition: relation.h:1154
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:133
static void match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys, List **orderby_clauses_p, List **clause_columns_p)
Definition: indxpath.c:2567
List * query_pathkeys
Definition: relation.h:274
static bool check_index_only(RelOptInfo *rel, IndexOptInfo *index)
Definition: indxpath.c:1862
List * build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index, ScanDirection scandir)
Definition: pathkeys.c:462
Relids clause_relids
Definition: relation.h:1895
int parallel_workers
Definition: relation.h:1085
Oid * sortopfamily
Definition: relation.h:770
IndexPath * create_index_path(PlannerInfo *root, IndexOptInfo *index, List *indexclauses, List *indexclausecols, List *indexorderbys, List *indexorderbycols, List *pathkeys, ScanDirection indexscandir, bool indexonly, Relids required_outer, double loop_count, bool partial_path)
Definition: pathnode.c:1024
List * truncate_useless_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
Definition: pathkeys.c:1619
Relids lateral_relids
Definition: relation.h:637
void pfree(void *pointer)
Definition: mcxt.c:1031
bool amoptionalkey
Definition: relation.h:795
bool amcanorderbyop
Definition: relation.h:794
List * indexclauses[INDEX_MAX_KEYS]
Definition: indxpath.c:60
int ncolumns
Definition: relation.h:763
bool amhasgetbitmap
Definition: relation.h:799
List * lappend_int(List *list, int datum)
Definition: list.c:146
Index relid
Definition: relation.h:640
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1880
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
static double get_loop_count(PlannerInfo *root, Index cur_relid, Relids outer_relids)
Definition: indxpath.c:1974
bool amhasgettuple
Definition: relation.h:798
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
bool amsearcharray
Definition: relation.h:796
bool consider_parallel
Definition: relation.h:620
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:762
bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel)
Definition: pathkeys.c:1659
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:801
Definition: pg_list.h:45
bool amcanparallel
Definition: relation.h:800
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:821

◆ build_paths_for_OR()

static List * build_paths_for_OR ( PlannerInfo root,
RelOptInfo rel,
List clauses,
List other_clauses 
)
static

Definition at line 1167 of file indxpath.c.

References IndexOptInfo::amhasgetbitmap, build_index_paths(), RelOptInfo::indexlist, IndexOptInfo::indpred, lfirst, list_concat(), list_copy(), match_clauses_to_index(), MemSet, NIL, IndexClauseSet::nonempty, predicate_implied_by(), IndexOptInfo::predOK, and ST_BITMAPSCAN.

Referenced by generate_bitmap_or_paths().

1169 {
1170  List *result = NIL;
1171  List *all_clauses = NIL; /* not computed till needed */
1172  ListCell *lc;
1173 
1174  foreach(lc, rel->indexlist)
1175  {
1177  IndexClauseSet clauseset;
1178  List *indexpaths;
1179  bool useful_predicate;
1180 
1181  /* Ignore index if it doesn't support bitmap scans */
1182  if (!index->amhasgetbitmap)
1183  continue;
1184 
1185  /*
1186  * Ignore partial indexes that do not match the query. If a partial
1187  * index is marked predOK then we know it's OK. Otherwise, we have to
1188  * test whether the added clauses are sufficient to imply the
1189  * predicate. If so, we can use the index in the current context.
1190  *
1191  * We set useful_predicate to true iff the predicate was proven using
1192  * the current set of clauses. This is needed to prevent matching a
1193  * predOK index to an arm of an OR, which would be a legal but
1194  * pointlessly inefficient plan. (A better plan will be generated by
1195  * just scanning the predOK index alone, no OR.)
1196  */
1197  useful_predicate = false;
1198  if (index->indpred != NIL)
1199  {
1200  if (index->predOK)
1201  {
1202  /* Usable, but don't set useful_predicate */
1203  }
1204  else
1205  {
1206  /* Form all_clauses if not done already */
1207  if (all_clauses == NIL)
1208  all_clauses = list_concat(list_copy(clauses),
1209  other_clauses);
1210 
1211  if (!predicate_implied_by(index->indpred, all_clauses, false))
1212  continue; /* can't use it at all */
1213 
1214  if (!predicate_implied_by(index->indpred, other_clauses, false))
1215  useful_predicate = true;
1216  }
1217  }
1218 
1219  /*
1220  * Identify the restriction clauses that can match the index.
1221  */
1222  MemSet(&clauseset, 0, sizeof(clauseset));
1223  match_clauses_to_index(index, clauses, &clauseset);
1224 
1225  /*
1226  * If no matches so far, and the index predicate isn't useful, we
1227  * don't want it.
1228  */
1229  if (!clauseset.nonempty && !useful_predicate)
1230  continue;
1231 
1232  /*
1233  * Add "other" restriction clauses to the clauseset.
1234  */
1235  match_clauses_to_index(index, other_clauses, &clauseset);
1236 
1237  /*
1238  * Construct paths if possible.
1239  */
1240  indexpaths = build_index_paths(root, rel,
1241  index, &clauseset,
1242  useful_predicate,
1243  ST_BITMAPSCAN,
1244  NULL,
1245  NULL);
1246  result = list_concat(result, indexpaths);
1247  }
1248 
1249  return result;
1250 }
#define NIL
Definition: pg_list.h:69
bool predOK
Definition: relation.h:788
bool nonempty
Definition: indxpath.c:58
static List * build_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, bool useful_predicate, ScanTypeControl scantype, bool *skip_nonnative_saop, bool *skip_lower_saop)
Definition: indxpath.c:857
List * list_copy(const List *oldlist)
Definition: list.c:1160
#define MemSet(start, val, len)
Definition: c.h:908
List * list_concat(List *list1, List *list2)
Definition: list.c:321
Definition: type.h:89
bool amhasgetbitmap
Definition: relation.h:799
List * indexlist
Definition: relation.h:649
#define lfirst(lc)
Definition: pg_list.h:106
static void match_clauses_to_index(IndexOptInfo *index, List *clauses, IndexClauseSet *clauseset)
Definition: indxpath.c:2194
List * indpred
Definition: relation.h:778
bool predicate_implied_by(List *predicate_list, List *clause_list, bool weak)
Definition: predtest.c:149
Definition: pg_list.h:45

◆ check_index_only()

static bool check_index_only ( RelOptInfo rel,
IndexOptInfo index 
)
static

Definition at line 1862 of file indxpath.c.

References bms_add_member(), bms_del_members(), bms_free(), bms_is_subset(), IndexOptInfo::canreturn, RestrictInfo::clause, enable_indexonlyscan, PathTarget::exprs, FirstLowInvalidHeapAttributeNumber, i, IndexOptInfo::indexkeys, IndexOptInfo::indrestrictinfo, lfirst, IndexOptInfo::ncolumns, pull_varattnos(), RelOptInfo::relid, and RelOptInfo::reltarget.

Referenced by build_index_paths().

1863 {
1864  bool result;
1865  Bitmapset *attrs_used = NULL;
1866  Bitmapset *index_canreturn_attrs = NULL;
1867  Bitmapset *index_cannotreturn_attrs = NULL;
1868  ListCell *lc;
1869  int i;
1870 
1871  /* Index-only scans must be enabled */
1872  if (!enable_indexonlyscan)
1873  return false;
1874 
1875  /*
1876  * Check that all needed attributes of the relation are available from the
1877  * index.
1878  */
1879 
1880  /*
1881  * First, identify all the attributes needed for joins or final output.
1882  * Note: we must look at rel's targetlist, not the attr_needed data,
1883  * because attr_needed isn't computed for inheritance child rels.
1884  */
1885  pull_varattnos((Node *) rel->reltarget->exprs, rel->relid, &attrs_used);
1886 
1887  /*
1888  * Add all the attributes used by restriction clauses; but consider only
1889  * those clauses not implied by the index predicate, since ones that are
1890  * so implied don't need to be checked explicitly in the plan.
1891  *
1892  * Note: attributes used only in index quals would not be needed at
1893  * runtime either, if we are certain that the index is not lossy. However
1894  * it'd be complicated to account for that accurately, and it doesn't
1895  * matter in most cases, since we'd conclude that such attributes are
1896  * available from the index anyway.
1897  */
1898  foreach(lc, index->indrestrictinfo)
1899  {
1900  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1901 
1902  pull_varattnos((Node *) rinfo->clause, rel->relid, &attrs_used);
1903  }
1904 
1905  /*
1906  * Construct a bitmapset of columns that the index can return back in an
1907  * index-only scan. If there are multiple index columns containing the
1908  * same attribute, all of them must be capable of returning the value,
1909  * since we might recheck operators on any of them. (Potentially we could
1910  * be smarter about that, but it's such a weird situation that it doesn't
1911  * seem worth spending a lot of sweat on.)
1912  */
1913  for (i = 0; i < index->ncolumns; i++)
1914  {
1915  int attno = index->indexkeys[i];
1916 
1917  /*
1918  * For the moment, we just ignore index expressions. It might be nice
1919  * to do something with them, later.
1920  */
1921  if (attno == 0)
1922  continue;
1923 
1924  if (index->canreturn[i])
1925  index_canreturn_attrs =
1926  bms_add_member(index_canreturn_attrs,
1928  else
1929  index_cannotreturn_attrs =
1930  bms_add_member(index_cannotreturn_attrs,
1932  }
1933 
1934  index_canreturn_attrs = bms_del_members(index_canreturn_attrs,
1935  index_cannotreturn_attrs);
1936 
1937  /* Do we have all the necessary attributes? */
1938  result = bms_is_subset(attrs_used, index_canreturn_attrs);
1939 
1940  bms_free(attrs_used);
1941  bms_free(index_canreturn_attrs);
1942  bms_free(index_cannotreturn_attrs);
1943 
1944  return result;
1945 }
Definition: nodes.h:517
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:219
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:374
int ncolumns
Definition: relation.h:763
Index relid
Definition: relation.h:640
Expr * clause
Definition: relation.h:1880
List * exprs
Definition: relation.h:1008
List * indrestrictinfo
Definition: relation.h:782
void bms_free(Bitmapset *a)
Definition: bitmapset.c:267
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:955
int i
int * indexkeys
Definition: relation.h:765
bool * canreturn
Definition: relation.h:773
struct PathTarget * reltarget
Definition: relation.h:623
bool enable_indexonlyscan
Definition: costsize.c:127

◆ check_index_predicates()

void check_index_predicates ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 2795 of file indxpath.c.

References PlannerInfo::all_baserels, Assert, RelOptInfo::baserestrictinfo, bms_difference(), bms_is_empty(), bms_union(), RestrictInfo::clause, contain_mutable_functions(), find_childrel_parents(), generate_join_implied_equalities(), get_plan_rowmark(), RelOptInfo::indexlist, IndexOptInfo::indpred, IndexOptInfo::indrestrictinfo, IS_SIMPLE_REL, join_clause_is_movable_to(), RelOptInfo::joininfo, lappend(), lfirst, list_concat(), list_copy(), list_make1, NIL, PlannerInfo::parse, predicate_implied_by(), IndexOptInfo::predOK, RelOptInfo::relid, RelOptInfo::relids, RELOPT_OTHER_MEMBER_REL, RelOptInfo::reloptkind, Query::resultRelation, and PlannerInfo::rowMarks.

Referenced by set_plain_rel_size(), and set_tablesample_rel_size().

2796 {
2797  List *clauselist;
2798  bool have_partial;
2799  bool is_target_rel;
2800  Relids otherrels;
2801  ListCell *lc;
2802 
2803  /* Indexes are available only on base or "other" member relations. */
2804  Assert(IS_SIMPLE_REL(rel));
2805 
2806  /*
2807  * Initialize the indrestrictinfo lists to be identical to
2808  * baserestrictinfo, and check whether there are any partial indexes. If
2809  * not, this is all we need to do.
2810  */
2811  have_partial = false;
2812  foreach(lc, rel->indexlist)
2813  {
2815 
2816  index->indrestrictinfo = rel->baserestrictinfo;
2817  if (index->indpred)
2818  have_partial = true;
2819  }
2820  if (!have_partial)
2821  return;
2822 
2823  /*
2824  * Construct a list of clauses that we can assume true for the purpose of
2825  * proving the index(es) usable. Restriction clauses for the rel are
2826  * always usable, and so are any join clauses that are "movable to" this
2827  * rel. Also, we can consider any EC-derivable join clauses (which must
2828  * be "movable to" this rel, by definition).
2829  */
2830  clauselist = list_copy(rel->baserestrictinfo);
2831 
2832  /* Scan the rel's join clauses */
2833  foreach(lc, rel->joininfo)
2834  {
2835  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
2836 
2837  /* Check if clause can be moved to this rel */
2838  if (!join_clause_is_movable_to(rinfo, rel))
2839  continue;
2840 
2841  clauselist = lappend(clauselist, rinfo);
2842  }
2843 
2844  /*
2845  * Add on any equivalence-derivable join clauses. Computing the correct
2846  * relid sets for generate_join_implied_equalities is slightly tricky
2847  * because the rel could be a child rel rather than a true baserel, and in
2848  * that case we must remove its parents' relid(s) from all_baserels.
2849  */
2850  if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
2851  otherrels = bms_difference(root->all_baserels,
2852  find_childrel_parents(root, rel));
2853  else
2854  otherrels = bms_difference(root->all_baserels, rel->relids);
2855 
2856  if (!bms_is_empty(otherrels))
2857  clauselist =
2858  list_concat(clauselist,
2860  bms_union(rel->relids,
2861  otherrels),
2862  otherrels,
2863  rel));
2864 
2865  /*
2866  * Normally we remove quals that are implied by a partial index's
2867  * predicate from indrestrictinfo, indicating that they need not be
2868  * checked explicitly by an indexscan plan using this index. However, if
2869  * the rel is a target relation of UPDATE/DELETE/SELECT FOR UPDATE, we
2870  * cannot remove such quals from the plan, because they need to be in the
2871  * plan so that they will be properly rechecked by EvalPlanQual testing.
2872  * Some day we might want to remove such quals from the main plan anyway
2873  * and pass them through to EvalPlanQual via a side channel; but for now,
2874  * we just don't remove implied quals at all for target relations.
2875  */
2876  is_target_rel = (rel->relid == root->parse->resultRelation ||
2877  get_plan_rowmark(root->rowMarks, rel->relid) != NULL);
2878 
2879  /*
2880  * Now try to prove each index predicate true, and compute the
2881  * indrestrictinfo lists for partial indexes. Note that we compute the
2882  * indrestrictinfo list even for non-predOK indexes; this might seem
2883  * wasteful, but we may be able to use such indexes in OR clauses, cf
2884  * generate_bitmap_or_paths().
2885  */
2886  foreach(lc, rel->indexlist)
2887  {
2888  IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
2889  ListCell *lcr;
2890 
2891  if (index->indpred == NIL)
2892  continue; /* ignore non-partial indexes here */
2893 
2894  if (!index->predOK) /* don't repeat work if already proven OK */
2895  index->predOK = predicate_implied_by(index->indpred, clauselist,
2896  false);
2897 
2898  /* If rel is an update target, leave indrestrictinfo as set above */
2899  if (is_target_rel)
2900  continue;
2901 
2902  /* Else compute indrestrictinfo as the non-implied quals */
2903  index->indrestrictinfo = NIL;
2904  foreach(lcr, rel->baserestrictinfo)
2905  {
2906  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcr);
2907 
2908  /* predicate_implied_by() assumes first arg is immutable */
2909  if (contain_mutable_functions((Node *) rinfo->clause) ||
2911  index->indpred, false))
2912  index->indrestrictinfo = lappend(index->indrestrictinfo, rinfo);
2913  }
2914  }
2915 }
#define NIL
Definition: pg_list.h:69
List * rowMarks
Definition: relation.h:268
Query * parse
Definition: relation.h:169
bool predOK
Definition: relation.h:788
RelOptKind reloptkind
Definition: relation.h:609
List * baserestrictinfo
Definition: relation.h:672
int resultRelation
Definition: parsenodes.h:122
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:350
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:517
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define IS_SIMPLE_REL(rel)
Definition: relation.h:585
Definition: type.h:89
#define list_make1(x1)
Definition: pg_list.h:139
Relids all_baserels
Definition: relation.h:210
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
Definition: equivclass.c:1072
List * joininfo
Definition: relation.h:676
Relids relids
Definition: relation.h:612
Index relid
Definition: relation.h:640
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1880
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
List * indrestrictinfo
Definition: relation.h:782
Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:1226
List * indexlist
Definition: relation.h:649
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
bool join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel)
Definition: restrictinfo.c:438
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:424
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:879
List * indpred
Definition: relation.h:778
bool predicate_implied_by(List *predicate_list, List *clause_list, bool weak)
Definition: predtest.c:149
Definition: pg_list.h:45

◆ choose_bitmap_and()

static Path * choose_bitmap_and ( PlannerInfo root,
RelOptInfo rel,
List paths 
)
static

Definition at line 1370 of file indxpath.c.

References Assert, bitmap_and_cost_est(), bitmap_scan_cost_est(), bms_add_members(), bms_copy(), bms_equal(), bms_overlap(), classify_index_clause_usage(), PathClauseUsage::clauseids, cost_bitmap_tree_node(), create_bitmap_and_path(), i, lappend(), lfirst, linitial, list_concat(), list_copy(), list_delete_cell(), list_free(), list_head(), list_length(), list_make1, lnext, NIL, palloc(), PathClauseUsage::path, path_usage_comparator(), predicate_implied_by(), PathClauseUsage::preds, qsort, and PathClauseUsage::quals.

Referenced by create_index_paths(), and generate_bitmap_or_paths().

1371 {
1372  int npaths = list_length(paths);
1373  PathClauseUsage **pathinfoarray;
1374  PathClauseUsage *pathinfo;
1375  List *clauselist;
1376  List *bestpaths = NIL;
1377  Cost bestcost = 0;
1378  int i,
1379  j;
1380  ListCell *l;
1381 
1382  Assert(npaths > 0); /* else caller error */
1383  if (npaths == 1)
1384  return (Path *) linitial(paths); /* easy case */
1385 
1386  /*
1387  * In theory we should consider every nonempty subset of the given paths.
1388  * In practice that seems like overkill, given the crude nature of the
1389  * estimates, not to mention the possible effects of higher-level AND and
1390  * OR clauses. Moreover, it's completely impractical if there are a large
1391  * number of paths, since the work would grow as O(2^N).
1392  *
1393  * As a heuristic, we first check for paths using exactly the same sets of
1394  * WHERE clauses + index predicate conditions, and reject all but the
1395  * cheapest-to-scan in any such group. This primarily gets rid of indexes
1396  * that include the interesting columns but also irrelevant columns. (In
1397  * situations where the DBA has gone overboard on creating variant
1398  * indexes, this can make for a very large reduction in the number of
1399  * paths considered further.)
1400  *
1401  * We then sort the surviving paths with the cheapest-to-scan first, and
1402  * for each path, consider using that path alone as the basis for a bitmap
1403  * scan. Then we consider bitmap AND scans formed from that path plus
1404  * each subsequent (higher-cost) path, adding on a subsequent path if it
1405  * results in a reduction in the estimated total scan cost. This means we
1406  * consider about O(N^2) rather than O(2^N) path combinations, which is
1407  * quite tolerable, especially given than N is usually reasonably small
1408  * because of the prefiltering step. The cheapest of these is returned.
1409  *
1410  * We will only consider AND combinations in which no two indexes use the
1411  * same WHERE clause. This is a bit of a kluge: it's needed because
1412  * costsize.c and clausesel.c aren't very smart about redundant clauses.
1413  * They will usually double-count the redundant clauses, producing a
1414  * too-small selectivity that makes a redundant AND step look like it
1415  * reduces the total cost. Perhaps someday that code will be smarter and
1416  * we can remove this limitation. (But note that this also defends
1417  * against flat-out duplicate input paths, which can happen because
1418  * match_join_clauses_to_index will find the same OR join clauses that
1419  * extract_restriction_or_clauses has pulled OR restriction clauses out
1420  * of.)
1421  *
1422  * For the same reason, we reject AND combinations in which an index
1423  * predicate clause duplicates another clause. Here we find it necessary
1424  * to be even stricter: we'll reject a partial index if any of its
1425  * predicate clauses are implied by the set of WHERE clauses and predicate
1426  * clauses used so far. This covers cases such as a condition "x = 42"
1427  * used with a plain index, followed by a clauseless scan of a partial
1428  * index "WHERE x >= 40 AND x < 50". The partial index has been accepted
1429  * only because "x = 42" was present, and so allowing it would partially
1430  * double-count selectivity. (We could use predicate_implied_by on
1431  * regular qual clauses too, to have a more intelligent, but much more
1432  * expensive, check for redundancy --- but in most cases simple equality
1433  * seems to suffice.)
1434  */
1435 
1436  /*
1437  * Extract clause usage info and detect any paths that use exactly the
1438  * same set of clauses; keep only the cheapest-to-scan of any such groups.
1439  * The surviving paths are put into an array for qsort'ing.
1440  */
1441  pathinfoarray = (PathClauseUsage **)
1442  palloc(npaths * sizeof(PathClauseUsage *));
1443  clauselist = NIL;
1444  npaths = 0;
1445  foreach(l, paths)
1446  {
1447  Path *ipath = (Path *) lfirst(l);
1448 
1449  pathinfo = classify_index_clause_usage(ipath, &clauselist);
1450  for (i = 0; i < npaths; i++)
1451  {
1452  if (bms_equal(pathinfo->clauseids, pathinfoarray[i]->clauseids))
1453  break;
1454  }
1455  if (i < npaths)
1456  {
1457  /* duplicate clauseids, keep the cheaper one */
1458  Cost ncost;
1459  Cost ocost;
1460  Selectivity nselec;
1461  Selectivity oselec;
1462 
1463  cost_bitmap_tree_node(pathinfo->path, &ncost, &nselec);
1464  cost_bitmap_tree_node(pathinfoarray[i]->path, &ocost, &oselec);
1465  if (ncost < ocost)
1466  pathinfoarray[i] = pathinfo;
1467  }
1468  else
1469  {
1470  /* not duplicate clauseids, add to array */
1471  pathinfoarray[npaths++] = pathinfo;
1472  }
1473  }
1474 
1475  /* If only one surviving path, we're done */
1476  if (npaths == 1)
1477  return pathinfoarray[0]->path;
1478 
1479  /* Sort the surviving paths by index access cost */
1480  qsort(pathinfoarray, npaths, sizeof(PathClauseUsage *),
1482 
1483  /*
1484  * For each surviving index, consider it as an "AND group leader", and see
1485  * whether adding on any of the later indexes results in an AND path with
1486  * cheaper total cost than before. Then take the cheapest AND group.
1487  */
1488  for (i = 0; i < npaths; i++)
1489  {
1490  Cost costsofar;
1491  List *qualsofar;
1492  Bitmapset *clauseidsofar;
1493  ListCell *lastcell;
1494 
1495  pathinfo = pathinfoarray[i];
1496  paths = list_make1(pathinfo->path);
1497  costsofar = bitmap_scan_cost_est(root, rel, pathinfo->path);
1498  qualsofar = list_concat(list_copy(pathinfo->quals),
1499  list_copy(pathinfo->preds));
1500  clauseidsofar = bms_copy(pathinfo->clauseids);
1501  lastcell = list_head(paths); /* for quick deletions */
1502 
1503  for (j = i + 1; j < npaths; j++)
1504  {
1505  Cost newcost;
1506 
1507  pathinfo = pathinfoarray[j];
1508  /* Check for redundancy */
1509  if (bms_overlap(pathinfo->clauseids, clauseidsofar))
1510  continue; /* consider it redundant */
1511  if (pathinfo->preds)
1512  {
1513  bool redundant = false;
1514 
1515  /* we check each predicate clause separately */
1516  foreach(l, pathinfo->preds)
1517  {
1518  Node *np = (Node *) lfirst(l);
1519 
1520  if (predicate_implied_by(list_make1(np), qualsofar, false))
1521  {
1522  redundant = true;
1523  break; /* out of inner foreach loop */
1524  }
1525  }
1526  if (redundant)
1527  continue;
1528  }
1529  /* tentatively add new path to paths, so we can estimate cost */
1530  paths = lappend(paths, pathinfo->path);
1531  newcost = bitmap_and_cost_est(root, rel, paths);
1532  if (newcost < costsofar)
1533  {
1534  /* keep new path in paths, update subsidiary variables */
1535  costsofar = newcost;
1536  qualsofar = list_concat(qualsofar,
1537  list_copy(pathinfo->quals));
1538  qualsofar = list_concat(qualsofar,
1539  list_copy(pathinfo->preds));
1540  clauseidsofar = bms_add_members(clauseidsofar,
1541  pathinfo->clauseids);
1542  lastcell = lnext(lastcell);
1543  }
1544  else
1545  {
1546  /* reject new path, remove it from paths list */
1547  paths = list_delete_cell(paths, lnext(lastcell), lastcell);
1548  }
1549  Assert(lnext(lastcell) == NULL);
1550  }
1551 
1552  /* Keep the cheapest AND-group (or singleton) */
1553  if (i == 0 || costsofar < bestcost)
1554  {
1555  bestpaths = paths;
1556  bestcost = costsofar;
1557  }
1558 
1559  /* some easy cleanup (we don't try real hard though) */
1560  list_free(qualsofar);
1561  }
1562 
1563  if (list_length(bestpaths) == 1)
1564  return (Path *) linitial(bestpaths); /* no need for AND */
1565  return (Path *) create_bitmap_and_path(root, rel, bestpaths);
1566 }
#define NIL
Definition: pg_list.h:69
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:133
Path * path
Definition: indxpath.c:66
List * quals
Definition: indxpath.c:67
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:517
List * list_concat(List *list1, List *list2)
Definition: list.c:321
double Selectivity
Definition: nodes.h:647
static Cost bitmap_scan_cost_est(PlannerInfo *root, RelOptInfo *rel, Path *ipath)
Definition: indxpath.c:1604
Bitmapset * clauseids
Definition: indxpath.c:69
#define list_make1(x1)
Definition: pg_list.h:139
#define linitial(l)
Definition: pg_list.h:111
static int path_usage_comparator(const void *a, const void *b)
Definition: indxpath.c:1570
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths)
Definition: indxpath.c:1640
List * lappend(List *list, void *datum)
Definition: list.c:128
BitmapAndPath * create_bitmap_and_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
Definition: pathnode.c:1116
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
List * preds
Definition: indxpath.c:68
#define Assert(condition)
Definition: c.h:699
static PathClauseUsage * classify_index_clause_usage(Path *path, List **clauselist)
Definition: indxpath.c:1700
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:509
void * palloc(Size size)
Definition: mcxt.c:924
void list_free(List *list)
Definition: list.c:1133
int i
#define qsort(a, b, c, d)
Definition: port.h:421
bool predicate_implied_by(List *predicate_list, List *clause_list, bool weak)
Definition: predtest.c:149
Definition: pg_list.h:45
double Cost
Definition: nodes.h:648
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:821
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:153
void cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec)
Definition: costsize.c:1046

◆ classify_index_clause_usage()

static PathClauseUsage * classify_index_clause_usage ( Path path,
List **  clauselist 
)
static

Definition at line 1700 of file indxpath.c.

References bms_add_member(), PathClauseUsage::clauseids, find_indexpath_quals(), find_list_position(), lfirst, NIL, palloc(), PathClauseUsage::path, PathClauseUsage::preds, and PathClauseUsage::quals.

Referenced by choose_bitmap_and().

1701 {
1702  PathClauseUsage *result;
1703  Bitmapset *clauseids;
1704  ListCell *lc;
1705 
1706  result = (PathClauseUsage *) palloc(sizeof(PathClauseUsage));
1707  result->path = path;
1708 
1709  /* Recursively find the quals and preds used by the path */
1710  result->quals = NIL;
1711  result->preds = NIL;
1712  find_indexpath_quals(path, &result->quals, &result->preds);
1713 
1714  /* Build up a bitmapset representing the quals and preds */
1715  clauseids = NULL;
1716  foreach(lc, result->quals)
1717  {
1718  Node *node = (Node *) lfirst(lc);
1719 
1720  clauseids = bms_add_member(clauseids,
1721  find_list_position(node, clauselist));
1722  }
1723  foreach(lc, result->preds)
1724  {
1725  Node *node = (Node *) lfirst(lc);
1726 
1727  clauseids = bms_add_member(clauseids,
1728  find_list_position(node, clauselist));
1729  }
1730  result->clauseids = clauseids;
1731 
1732  return result;
1733 }
#define NIL
Definition: pg_list.h:69
static int find_list_position(Node *node, List **nodelist)
Definition: indxpath.c:1836
Path * path
Definition: indxpath.c:66
List * quals
Definition: indxpath.c:67
Definition: nodes.h:517
Bitmapset * clauseids
Definition: indxpath.c:69
static void find_indexpath_quals(Path *bitmapqual, List **quals, List **preds)
Definition: indxpath.c:1795
List * preds
Definition: indxpath.c:68
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
void * palloc(Size size)
Definition: mcxt.c:924

◆ consider_index_join_clauses()

static void consider_index_join_clauses ( PlannerInfo root,
RelOptInfo rel,
IndexOptInfo index,
IndexClauseSet rclauseset,
IndexClauseSet jclauseset,
IndexClauseSet eclauseset,
List **  bitindexpaths 
)
static

Definition at line 437 of file indxpath.c.

References consider_index_join_outer_rels(), IndexClauseSet::indexclauses, list_length(), IndexOptInfo::ncolumns, and NIL.

Referenced by create_index_paths().

443 {
444  int considered_clauses = 0;
445  List *considered_relids = NIL;
446  int indexcol;
447 
448  /*
449  * The strategy here is to identify every potentially useful set of outer
450  * rels that can provide indexable join clauses. For each such set,
451  * select all the join clauses available from those outer rels, add on all
452  * the indexable restriction clauses, and generate plain and/or bitmap
453  * index paths for that set of clauses. This is based on the assumption
454  * that it's always better to apply a clause as an indexqual than as a
455  * filter (qpqual); which is where an available clause would end up being
456  * applied if we omit it from the indexquals.
457  *
458  * This looks expensive, but in most practical cases there won't be very
459  * many distinct sets of outer rels to consider. As a safety valve when
460  * that's not true, we use a heuristic: limit the number of outer rel sets
461  * considered to a multiple of the number of clauses considered. (We'll
462  * always consider using each individual join clause, though.)
463  *
464  * For simplicity in selecting relevant clauses, we represent each set of
465  * outer rels as a maximum set of clause_relids --- that is, the indexed
466  * relation itself is also included in the relids set. considered_relids
467  * lists all relids sets we've already tried.
468  */
469  for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
470  {
471  /* Consider each applicable simple join clause */
472  considered_clauses += list_length(jclauseset->indexclauses[indexcol]);
473  consider_index_join_outer_rels(root, rel, index,
474  rclauseset, jclauseset, eclauseset,
475  bitindexpaths,
476  jclauseset->indexclauses[indexcol],
477  considered_clauses,
478  &considered_relids);
479  /* Consider each applicable eclass join clause */
480  considered_clauses += list_length(eclauseset->indexclauses[indexcol]);
481  consider_index_join_outer_rels(root, rel, index,
482  rclauseset, jclauseset, eclauseset,
483  bitindexpaths,
484  eclauseset->indexclauses[indexcol],
485  considered_clauses,
486  &considered_relids);
487  }
488 }
#define NIL
Definition: pg_list.h:69
List * indexclauses[INDEX_MAX_KEYS]
Definition: indxpath.c:60
int ncolumns
Definition: relation.h:763
static void consider_index_join_outer_rels(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths, List *indexjoinclauses, int considered_clauses, List **considered_relids)
Definition: indxpath.c:503
static int list_length(const List *l)
Definition: pg_list.h:89
Definition: pg_list.h:45

◆ consider_index_join_outer_rels()

static void consider_index_join_outer_rels ( PlannerInfo root,
RelOptInfo rel,
IndexOptInfo index,
IndexClauseSet rclauseset,
IndexClauseSet jclauseset,
IndexClauseSet eclauseset,
List **  bitindexpaths,
List indexjoinclauses,
int  considered_clauses,
List **  considered_relids 
)
static

Definition at line 503 of file indxpath.c.

References BMS_DIFFERENT, bms_equal_any(), bms_subset_compare(), bms_union(), RestrictInfo::clause_relids, eclass_already_used(), get_join_index_paths(), lfirst, list_length(), and RestrictInfo::parent_ec.

Referenced by consider_index_join_clauses().

512 {
513  ListCell *lc;
514 
515  /* Examine relids of each joinclause in the given list */
516  foreach(lc, indexjoinclauses)
517  {
518  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
519  Relids clause_relids = rinfo->clause_relids;
520  ListCell *lc2;
521 
522  /* If we already tried its relids set, no need to do so again */
523  if (bms_equal_any(clause_relids, *considered_relids))
524  continue;
525 
526  /*
527  * Generate the union of this clause's relids set with each
528  * previously-tried set. This ensures we try this clause along with
529  * every interesting subset of previous clauses. However, to avoid
530  * exponential growth of planning time when there are many clauses,
531  * limit the number of relid sets accepted to 10 * considered_clauses.
532  *
533  * Note: get_join_index_paths adds entries to *considered_relids, but
534  * it prepends them to the list, so that we won't visit new entries
535  * during the inner foreach loop. No real harm would be done if we
536  * did, since the subset check would reject them; but it would waste
537  * some cycles.
538  */
539  foreach(lc2, *considered_relids)
540  {
541  Relids oldrelids = (Relids) lfirst(lc2);
542 
543  /*
544  * If either is a subset of the other, no new set is possible.
545  * This isn't a complete test for redundancy, but it's easy and
546  * cheap. get_join_index_paths will check more carefully if we
547  * already generated the same relids set.
548  */
549  if (bms_subset_compare(clause_relids, oldrelids) != BMS_DIFFERENT)
550  continue;
551 
552  /*
553  * If this clause was derived from an equivalence class, the
554  * clause list may contain other clauses derived from the same
555  * eclass. We should not consider that combining this clause with
556  * one of those clauses generates a usefully different
557  * parameterization; so skip if any clause derived from the same
558  * eclass would already have been included when using oldrelids.
559  */
560  if (rinfo->parent_ec &&
561  eclass_already_used(rinfo->parent_ec, oldrelids,
562  indexjoinclauses))
563  continue;
564 
565  /*
566  * If the number of relid sets considered exceeds our heuristic
567  * limit, stop considering combinations of clauses. We'll still
568  * consider the current clause alone, though (below this loop).
569  */
570  if (list_length(*considered_relids) >= 10 * considered_clauses)
571  break;
572 
573  /* OK, try the union set */
574  get_join_index_paths(root, rel, index,
575  rclauseset, jclauseset, eclauseset,
576  bitindexpaths,
577  bms_union(clause_relids, oldrelids),
578  considered_relids);
579  }
580 
581  /* Also try this set of relids by itself */
582  get_join_index_paths(root, rel, index,
583  rclauseset, jclauseset, eclauseset,
584  bitindexpaths,
585  clause_relids,
586  considered_relids);
587  }
588 }
Relids clause_relids
Definition: relation.h:1895
static bool bms_equal_any(Relids relids, List *relids_list)
Definition: indxpath.c:706
EquivalenceClass * parent_ec
Definition: relation.h:1914
static void get_join_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths, Relids relids, List **considered_relids)
Definition: indxpath.c:604
Bitmapset * Relids
Definition: relation.h:29
BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:411
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
static int list_length(const List *l)
Definition: pg_list.h:89
static bool eclass_already_used(EquivalenceClass *parent_ec, Relids oldrelids, List *indexjoinclauses)
Definition: indxpath.c:683

◆ create_index_paths()

void create_index_paths ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 230 of file indxpath.c.

References add_path(), Assert, RelOptInfo::baserestrictinfo, bms_equal_any(), bms_is_subset(), choose_bitmap_and(), consider_index_join_clauses(), RelOptInfo::consider_parallel, create_bitmap_heap_path(), create_partial_bitmap_paths(), forboth, generate_bitmap_or_paths(), get_bitmap_tree_required_outer(), get_index_paths(), get_loop_count(), INDEX_MAX_KEYS, RelOptInfo::indexlist, IndexOptInfo::indpred, lappend(), RelOptInfo::lateral_relids, lfirst, list_concat(), match_eclass_clauses_to_index(), match_join_clauses_to_index(), match_restriction_clauses_to_index(), MemSet, IndexOptInfo::ncolumns, NIL, IndexClauseSet::nonempty, IndexOptInfo::predOK, and RelOptInfo::relid.

Referenced by set_plain_rel_pathlist().

231 {
232  List *indexpaths;
233  List *bitindexpaths;
234  List *bitjoinpaths;
235  List *joinorclauses;
236  IndexClauseSet rclauseset;
237  IndexClauseSet jclauseset;
238  IndexClauseSet eclauseset;
239  ListCell *lc;
240 
241  /* Skip the whole mess if no indexes */
242  if (rel->indexlist == NIL)
243  return;
244 
245  /* Bitmap paths are collected and then dealt with at the end */
246  bitindexpaths = bitjoinpaths = joinorclauses = NIL;
247 
248  /* Examine each index in turn */
249  foreach(lc, rel->indexlist)
250  {
252 
253  /* Protect limited-size array in IndexClauseSets */
254  Assert(index->ncolumns <= INDEX_MAX_KEYS);
255 
256  /*
257  * Ignore partial indexes that do not match the query.
258  * (generate_bitmap_or_paths() might be able to do something with
259  * them, but that's of no concern here.)
260  */
261  if (index->indpred != NIL && !index->predOK)
262  continue;
263 
264  /*
265  * Identify the restriction clauses that can match the index.
266  */
267  MemSet(&rclauseset, 0, sizeof(rclauseset));
268  match_restriction_clauses_to_index(rel, index, &rclauseset);
269 
270  /*
271  * Build index paths from the restriction clauses. These will be
272  * non-parameterized paths. Plain paths go directly to add_path(),
273  * bitmap paths are added to bitindexpaths to be handled below.
274  */
275  get_index_paths(root, rel, index, &rclauseset,
276  &bitindexpaths);
277 
278  /*
279  * Identify the join clauses that can match the index. For the moment
280  * we keep them separate from the restriction clauses. Note that this
281  * step finds only "loose" join clauses that have not been merged into
282  * EquivalenceClasses. Also, collect join OR clauses for later.
283  */
284  MemSet(&jclauseset, 0, sizeof(jclauseset));
285  match_join_clauses_to_index(root, rel, index,
286  &jclauseset, &joinorclauses);
287 
288  /*
289  * Look for EquivalenceClasses that can generate joinclauses matching
290  * the index.
291  */
292  MemSet(&eclauseset, 0, sizeof(eclauseset));
293  match_eclass_clauses_to_index(root, index,
294  &eclauseset);
295 
296  /*
297  * If we found any plain or eclass join clauses, build parameterized
298  * index paths using them.
299  */
300  if (jclauseset.nonempty || eclauseset.nonempty)
301  consider_index_join_clauses(root, rel, index,
302  &rclauseset,
303  &jclauseset,
304  &eclauseset,
305  &bitjoinpaths);
306  }
307 
308  /*
309  * Generate BitmapOrPaths for any suitable OR-clauses present in the
310  * restriction list. Add these to bitindexpaths.
311  */
312  indexpaths = generate_bitmap_or_paths(root, rel,
313  rel->baserestrictinfo, NIL);
314  bitindexpaths = list_concat(bitindexpaths, indexpaths);
315 
316  /*
317  * Likewise, generate BitmapOrPaths for any suitable OR-clauses present in
318  * the joinclause list. Add these to bitjoinpaths.
319  */
320  indexpaths = generate_bitmap_or_paths(root, rel,
321  joinorclauses, rel->baserestrictinfo);
322  bitjoinpaths = list_concat(bitjoinpaths, indexpaths);
323 
324  /*
325  * If we found anything usable, generate a BitmapHeapPath for the most
326  * promising combination of restriction bitmap index paths. Note there
327  * will be only one such path no matter how many indexes exist. This
328  * should be sufficient since there's basically only one figure of merit
329  * (total cost) for such a path.
330  */
331  if (bitindexpaths != NIL)
332  {
333  Path *bitmapqual;
334  BitmapHeapPath *bpath;
335 
336  bitmapqual = choose_bitmap_and(root, rel, bitindexpaths);
337  bpath = create_bitmap_heap_path(root, rel, bitmapqual,
338  rel->lateral_relids, 1.0, 0);
339  add_path(rel, (Path *) bpath);
340 
341  /* create a partial bitmap heap path */
342  if (rel->consider_parallel && rel->lateral_relids == NULL)
343  create_partial_bitmap_paths(root, rel, bitmapqual);
344  }
345 
346  /*
347  * Likewise, if we found anything usable, generate BitmapHeapPaths for the
348  * most promising combinations of join bitmap index paths. Our strategy
349  * is to generate one such path for each distinct parameterization seen
350  * among the available bitmap index paths. This may look pretty
351  * expensive, but usually there won't be very many distinct
352  * parameterizations. (This logic is quite similar to that in
353  * consider_index_join_clauses, but we're working with whole paths not
354  * individual clauses.)
355  */
356  if (bitjoinpaths != NIL)
357  {
358  List *path_outer;
359  List *all_path_outers;
360  ListCell *lc;
361 
362  /*
363  * path_outer holds the parameterization of each path in bitjoinpaths
364  * (to save recalculating that several times), while all_path_outers
365  * holds all distinct parameterization sets.
366  */
367  path_outer = all_path_outers = NIL;
368  foreach(lc, bitjoinpaths)
369  {
370  Path *path = (Path *) lfirst(lc);
371  Relids required_outer;
372 
373  required_outer = get_bitmap_tree_required_outer(path);
374  path_outer = lappend(path_outer, required_outer);
375  if (!bms_equal_any(required_outer, all_path_outers))
376  all_path_outers = lappend(all_path_outers, required_outer);
377  }
378 
379  /* Now, for each distinct parameterization set ... */
380  foreach(lc, all_path_outers)
381  {
382  Relids max_outers = (Relids) lfirst(lc);
383  List *this_path_set;
384  Path *bitmapqual;
385  Relids required_outer;
386  double loop_count;
387  BitmapHeapPath *bpath;
388  ListCell *lcp;
389  ListCell *lco;
390 
391  /* Identify all the bitmap join paths needing no more than that */
392  this_path_set = NIL;
393  forboth(lcp, bitjoinpaths, lco, path_outer)
394  {
395  Path *path = (Path *) lfirst(lcp);
396  Relids p_outers = (Relids) lfirst(lco);
397 
398  if (bms_is_subset(p_outers, max_outers))
399  this_path_set = lappend(this_path_set, path);
400  }
401 
402  /*
403  * Add in restriction bitmap paths, since they can be used
404  * together with any join paths.
405  */
406  this_path_set = list_concat(this_path_set, bitindexpaths);
407 
408  /* Select best AND combination for this parameterization */
409  bitmapqual = choose_bitmap_and(root, rel, this_path_set);
410 
411  /* And push that path into the mix */
412  required_outer = get_bitmap_tree_required_outer(bitmapqual);
413  loop_count = get_loop_count(root, rel->relid, required_outer);
414  bpath = create_bitmap_heap_path(root, rel, bitmapqual,
415  required_outer, loop_count, 0);
416  add_path(rel, (Path *) bpath);
417  }
418  }
419 }
#define NIL
Definition: pg_list.h:69
bool predOK
Definition: relation.h:788
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:422
bool nonempty
Definition: indxpath.c:58
List * baserestrictinfo
Definition: relation.h:672
#define MemSet(start, val, len)
Definition: c.h:908
List * list_concat(List *list1, List *list2)
Definition: list.c:321
Definition: type.h:89
static bool bms_equal_any(Relids relids, List *relids_list)
Definition: indxpath.c:706
Relids lateral_relids
Definition: relation.h:637
static void match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, IndexClauseSet *clauseset)
Definition: indxpath.c:2156
static void get_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, List **bitindexpaths)
Definition: indxpath.c:735
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:374
static Path * choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
Definition: indxpath.c:1370
int ncolumns
Definition: relation.h:763
Index relid
Definition: relation.h:640
Bitmapset * Relids
Definition: relation.h:29
List * lappend(List *list, void *datum)
Definition: list.c:128
static double get_loop_count(PlannerInfo *root, Index cur_relid, Relids outer_relids)
Definition: indxpath.c:1974
static void match_restriction_clauses_to_index(RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauseset)
Definition: indxpath.c:2112
static List * generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
Definition: indxpath.c:1263
List * indexlist
Definition: relation.h:649
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
#define INDEX_MAX_KEYS
bool consider_parallel
Definition: relation.h:620
static void match_join_clauses_to_index(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauseset, List **joinorclauses)
Definition: indxpath.c:2126
static Relids get_bitmap_tree_required_outer(Path *bitmapqual)
Definition: indxpath.c:1747
List * indpred
Definition: relation.h:778
void create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual)
Definition: allpaths.c:3403
Definition: pg_list.h:45
BitmapHeapPath * create_bitmap_heap_path(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual, Relids required_outer, double loop_count, int parallel_degree)
Definition: pathnode.c:1083
static void consider_index_join_clauses(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths)
Definition: indxpath.c:437

◆ ec_member_matches_indexcol()

static bool ec_member_matches_indexcol ( PlannerInfo root,
RelOptInfo rel,
EquivalenceClass ec,
EquivalenceMember em,
void *  arg 
)
static

Definition at line 2928 of file indxpath.c.

References Assert, EquivalenceClass::ec_collation, EquivalenceClass::ec_opfamilies, EquivalenceMember::em_expr, IndexOptInfo::indexcollations, IndexCollMatchesExprColl, list_member_oid(), match_index_to_operand(), IndexOptInfo::opfamily, and IndexOptInfo::relam.

Referenced by match_eclass_clauses_to_index().

2931 {
2932  IndexOptInfo *index = ((ec_member_matches_arg *) arg)->index;
2933  int indexcol = ((ec_member_matches_arg *) arg)->indexcol;
2934  Oid curFamily;
2935  Oid curCollation;
2936 
2937  Assert(indexcol < index->nkeycolumns);
2938 
2939  curFamily = index->opfamily[indexcol];
2940  curCollation = index->indexcollations[indexcol];
2941 
2942  /*
2943  * If it's a btree index, we can reject it if its opfamily isn't
2944  * compatible with the EC, since no clause generated from the EC could be
2945  * used with the index. For non-btree indexes, we can't easily tell
2946  * whether clauses generated from the EC could be used with the index, so
2947  * don't check the opfamily. This might mean we return "true" for a
2948  * useless EC, so we have to recheck the results of
2949  * generate_implied_equalities_for_column; see
2950  * match_eclass_clauses_to_index.
2951  */
2952  if (index->relam == BTREE_AM_OID &&
2953  !list_member_oid(ec->ec_opfamilies, curFamily))
2954  return false;
2955 
2956  /* We insist on collation match for all index types, though */
2957  if (!IndexCollMatchesExprColl(curCollation, ec->ec_collation))
2958  return false;
2959 
2960  return match_index_to_operand((Node *) em->em_expr, indexcol, index);
2961 }
Oid * indexcollations
Definition: relation.h:767
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3206
Definition: nodes.h:517
unsigned int Oid
Definition: postgres_ext.h:31
Definition: type.h:89
#define IndexCollMatchesExprColl(idxcollation, exprcollation)
Definition: indxpath.c:44
List * ec_opfamilies
Definition: relation.h:896
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define Assert(condition)
Definition: c.h:699
Oid * opfamily
Definition: relation.h:768
void * arg

◆ eclass_already_used()

static bool eclass_already_used ( EquivalenceClass parent_ec,
Relids  oldrelids,
List indexjoinclauses 
)
static

Definition at line 683 of file indxpath.c.

References bms_is_subset(), RestrictInfo::clause_relids, lfirst, and RestrictInfo::parent_ec.

Referenced by consider_index_join_outer_rels().

685 {
686  ListCell *lc;
687 
688  foreach(lc, indexjoinclauses)
689  {
690  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
691 
692  if (rinfo->parent_ec == parent_ec &&
693  bms_is_subset(rinfo->clause_relids, oldrelids))
694  return true;
695  }
696  return false;
697 }
Relids clause_relids
Definition: relation.h:1895
EquivalenceClass * parent_ec
Definition: relation.h:1914
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:374
#define lfirst(lc)
Definition: pg_list.h:106

◆ expand_boolean_index_clause()

static Expr * expand_boolean_index_clause ( Node clause,
int  indexcol,
IndexOptInfo index 
)
static

Definition at line 3642 of file indxpath.c.

References arg, BooleanTest::arg, Assert, BooleanTest::booltesttype, get_notclausearg(), InvalidOid, IS_FALSE, IS_TRUE, IsA, make_opclause(), makeBoolConst(), match_index_to_operand(), and not_clause().

Referenced by expand_indexqual_conditions().

3645 {
3646  /* Direct match? */
3647  if (match_index_to_operand(clause, indexcol, index))
3648  {
3649  /* convert to indexkey = TRUE */
3650  return make_opclause(BooleanEqualOperator, BOOLOID, false,
3651  (Expr *) clause,
3652  (Expr *) makeBoolConst(true, false),
3654  }
3655  /* NOT clause? */
3656  if (not_clause(clause))
3657  {
3658  Node *arg = (Node *) get_notclausearg((Expr *) clause);
3659 
3660  /* It must have matched the indexkey */
3661  Assert(match_index_to_operand(arg, indexcol, index));
3662  /* convert to indexkey = FALSE */
3663  return make_opclause(BooleanEqualOperator, BOOLOID, false,
3664  (Expr *) arg,
3665  (Expr *) makeBoolConst(false, false),
3667  }
3668  if (clause && IsA(clause, BooleanTest))
3669  {
3670  BooleanTest *btest = (BooleanTest *) clause;
3671  Node *arg = (Node *) btest->arg;
3672 
3673  /* It must have matched the indexkey */
3674  Assert(match_index_to_operand(arg, indexcol, index));
3675  if (btest->booltesttype == IS_TRUE)
3676  {
3677  /* convert to indexkey = TRUE */
3678  return make_opclause(BooleanEqualOperator, BOOLOID, false,
3679  (Expr *) arg,
3680  (Expr *) makeBoolConst(true, false),
3682  }
3683  if (btest->booltesttype == IS_FALSE)
3684  {
3685  /* convert to indexkey = FALSE */
3686  return make_opclause(BooleanEqualOperator, BOOLOID, false,
3687  (Expr *) arg,
3688  (Expr *) makeBoolConst(false, false),
3690  }
3691  /* Oops */
3692  Assert(false);
3693  }
3694 
3695  return NULL;
3696 }
Expr * get_notclausearg(Expr *notclause)
Definition: clauses.c:266
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3206
Definition: nodes.h:517
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: clauses.c:173
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:356
Expr * arg
Definition: primnodes.h:1211
bool not_clause(Node *clause)
Definition: clauses.c:237
BoolTestType booltesttype
Definition: primnodes.h:1212
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:699
void * arg

◆ expand_indexqual_conditions()

void expand_indexqual_conditions ( IndexOptInfo index,
List indexclauses,
List indexclausecols,
List **  indexquals_p,
List **  indexqualcols_p 
)

Definition at line 3552 of file indxpath.c.

References IndexOptInfo::amsearchnulls, Assert, RestrictInfo::clause, elog, ERROR, expand_boolean_index_clause(), expand_indexqual_opclause(), expand_indexqual_rowcompare(), forboth, IndexOptInfo::indexcollations, is_opclause, IsA, lappend(), lappend_int(), lfirst, lfirst_int, list_concat(), list_length(), make_simple_restrictinfo, NIL, nodeTag, and IndexOptInfo::opfamily.

Referenced by create_index_path().

3555 {
3556  List *indexquals = NIL;
3557  List *indexqualcols = NIL;
3558  ListCell *lcc,
3559  *lci;
3560 
3561  forboth(lcc, indexclauses, lci, indexclausecols)
3562  {
3563  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcc);
3564  int indexcol = lfirst_int(lci);
3565  Expr *clause = rinfo->clause;
3566  Oid curFamily;
3567  Oid curCollation;
3568 
3569  Assert(indexcol < index->nkeycolumns);
3570 
3571  curFamily = index->opfamily[indexcol];
3572  curCollation = index->indexcollations[indexcol];
3573 
3574  /* First check for boolean cases */
3575  if (IsBooleanOpfamily(curFamily))
3576  {
3577  Expr *boolqual;
3578 
3579  boolqual = expand_boolean_index_clause((Node *) clause,
3580  indexcol,
3581  index);
3582  if (boolqual)
3583  {
3584  indexquals = lappend(indexquals,
3585  make_simple_restrictinfo(boolqual));
3586  indexqualcols = lappend_int(indexqualcols, indexcol);
3587  continue;
3588  }
3589  }
3590 
3591  /*
3592  * Else it must be an opclause (usual case), ScalarArrayOp,
3593  * RowCompare, or NullTest
3594  */
3595  if (is_opclause(clause))
3596  {
3597  indexquals = list_concat(indexquals,
3599  curFamily,
3600  curCollation));
3601  /* expand_indexqual_opclause can produce multiple clauses */
3602  while (list_length(indexqualcols) < list_length(indexquals))
3603  indexqualcols = lappend_int(indexqualcols, indexcol);
3604  }
3605  else if (IsA(clause, ScalarArrayOpExpr))
3606  {
3607  /* no extra work at this time */
3608  indexquals = lappend(indexquals, rinfo);
3609  indexqualcols = lappend_int(indexqualcols, indexcol);
3610  }
3611  else if (IsA(clause, RowCompareExpr))
3612  {
3613  indexquals = lappend(indexquals,
3615  index,
3616  indexcol));
3617  indexqualcols = lappend_int(indexqualcols, indexcol);
3618  }
3619  else if (IsA(clause, NullTest))
3620  {
3621  Assert(index->amsearchnulls);
3622  indexquals = lappend(indexquals, rinfo);
3623  indexqualcols = lappend_int(indexqualcols, indexcol);
3624  }
3625  else
3626  elog(ERROR, "unsupported indexqual type: %d",
3627  (int) nodeTag(clause));
3628  }
3629 
3630  *indexquals_p = indexquals;
3631  *indexqualcols_p = indexqualcols;
3632 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
Oid * indexcollations
Definition: relation.h:767
Definition: nodes.h:517
List * list_concat(List *list1, List *list2)
Definition: list.c:321
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
#define is_opclause(clause)
Definition: clauses.h:20
#define lfirst_int(lc)
Definition: pg_list.h:107
static Expr * expand_boolean_index_clause(Node *clause, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3642
List * lappend_int(List *list, int datum)
Definition: list.c:146
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1880
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
static RestrictInfo * expand_indexqual_rowcompare(RestrictInfo *rinfo, IndexOptInfo *index, int indexcol)
Definition: indxpath.c:3802
static int list_length(const List *l)
Definition: pg_list.h:89
#define nodeTag(nodeptr)
Definition: nodes.h:522
Oid * opfamily
Definition: relation.h:768
#define elog
Definition: elog.h:219
bool amsearchnulls
Definition: relation.h:797
static List * expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid idxcollation)
Definition: indxpath.c:3708
Definition: pg_list.h:45
#define make_simple_restrictinfo(clause)
Definition: restrictinfo.h:21

◆ expand_indexqual_opclause()

static List * expand_indexqual_opclause ( RestrictInfo rinfo,
Oid  opfamily,
Oid  idxcollation 
)
static

Definition at line 3708 of file indxpath.c.

References RestrictInfo::clause, Const::constvalue, get_leftop(), get_rightop(), list_make1, network_prefix_quals(), op_in_opfamily(), pattern_fixed_prefix(), Pattern_Type_Like, Pattern_Type_Like_IC, Pattern_Type_Regex, Pattern_Type_Regex_IC, and prefix_quals().

Referenced by expand_indexqual_conditions().

3709 {
3710  Expr *clause = rinfo->clause;
3711 
3712  /* we know these will succeed */
3713  Node *leftop = get_leftop(clause);
3714  Node *rightop = get_rightop(clause);
3715  Oid expr_op = ((OpExpr *) clause)->opno;
3716  Oid expr_coll = ((OpExpr *) clause)->inputcollid;
3717  Const *patt = (Const *) rightop;
3718  Const *prefix = NULL;
3719  Pattern_Prefix_Status pstatus;
3720 
3721  /*
3722  * LIKE and regex operators are not members of any btree index opfamily,
3723  * but they can be members of opfamilies for more exotic index types such
3724  * as GIN. Therefore, we should only do expansion if the operator is
3725  * actually not in the opfamily. But checking that requires a syscache
3726  * lookup, so it's best to first see if the operator is one we are
3727  * interested in.
3728  */
3729  switch (expr_op)
3730  {
3731  case OID_TEXT_LIKE_OP:
3732  case OID_BPCHAR_LIKE_OP:
3733  case OID_NAME_LIKE_OP:
3734  case OID_BYTEA_LIKE_OP:
3735  if (!op_in_opfamily(expr_op, opfamily))
3736  {
3737  pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like, expr_coll,
3738  &prefix, NULL);
3739  return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
3740  }
3741  break;
3742 
3743  case OID_TEXT_ICLIKE_OP:
3744  case OID_BPCHAR_ICLIKE_OP:
3745  case OID_NAME_ICLIKE_OP:
3746  if (!op_in_opfamily(expr_op, opfamily))
3747  {
3748  /* the right-hand const is type text for all of these */
3749  pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like_IC, expr_coll,
3750  &prefix, NULL);
3751  return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
3752  }
3753  break;
3754 
3755  case OID_TEXT_REGEXEQ_OP:
3756  case OID_BPCHAR_REGEXEQ_OP:
3757  case OID_NAME_REGEXEQ_OP:
3758  if (!op_in_opfamily(expr_op, opfamily))
3759  {
3760  /* the right-hand const is type text for all of these */
3761  pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex, expr_coll,
3762  &prefix, NULL);
3763  return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
3764  }
3765  break;
3766 
3767  case OID_TEXT_ICREGEXEQ_OP:
3768  case OID_BPCHAR_ICREGEXEQ_OP:
3769  case OID_NAME_ICREGEXEQ_OP:
3770  if (!op_in_opfamily(expr_op, opfamily))
3771  {
3772  /* the right-hand const is type text for all of these */
3773  pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC, expr_coll,
3774  &prefix, NULL);
3775  return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
3776  }
3777  break;
3778 
3779  case OID_INET_SUB_OP:
3780  case OID_INET_SUBEQ_OP:
3781  if (!op_in_opfamily(expr_op, opfamily))
3782  {
3783  return network_prefix_quals(leftop, expr_op, opfamily,
3784  patt->constvalue);
3785  }
3786  break;
3787  }
3788 
3789  /* Default case: just make a list of the unmodified indexqual */
3790  return list_make1(rinfo);
3791 }
Datum constvalue
Definition: primnodes.h:197
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition: lsyscache.c:63
static List * network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop)
Definition: indxpath.c:4192
Definition: nodes.h:517
unsigned int Oid
Definition: postgres_ext.h:31
#define list_make1(x1)
Definition: pg_list.h:139
Node * get_leftop(const Expr *clause)
Definition: clauses.c:200
Expr * clause
Definition: relation.h:1880
static List * prefix_quals(Node *leftop, Oid opfamily, Oid collation, Const *prefix, Pattern_Prefix_Status pstatus)
Definition: indxpath.c:4066
Pattern_Prefix_Status pattern_fixed_prefix(Const *patt, Pattern_Type ptype, Oid collation, Const **prefix, Selectivity *rest_selec)
Definition: selfuncs.c:5946
Node * get_rightop(const Expr *clause)
Definition: clauses.c:217
Pattern_Prefix_Status
Definition: selfuncs.h:97

◆ expand_indexqual_rowcompare()

static RestrictInfo * expand_indexqual_rowcompare ( RestrictInfo rinfo,
IndexOptInfo index,
int  indexcol 
)
static

Definition at line 3802 of file indxpath.c.

References adjust_rowcompare_for_index(), RestrictInfo::clause, and make_simple_restrictinfo.

Referenced by expand_indexqual_conditions().

3805 {
3806  RowCompareExpr *clause = (RowCompareExpr *) rinfo->clause;
3807  Expr *newclause;
3808  List *indexcolnos;
3809  bool var_on_left;
3810 
3811  newclause = adjust_rowcompare_for_index(clause,
3812  index,
3813  indexcol,
3814  &indexcolnos,
3815  &var_on_left);
3816 
3817  /*
3818  * If we didn't have to change the RowCompareExpr, return the original
3819  * RestrictInfo.
3820  */
3821  if (newclause == (Expr *) clause)
3822  return rinfo;
3823 
3824  /* Else we need a new RestrictInfo */
3825  return make_simple_restrictinfo(newclause);
3826 }
Expr * adjust_rowcompare_for_index(RowCompareExpr *clause, IndexOptInfo *index, int indexcol, List **indexcolnos, bool *var_on_left_p)
Definition: indxpath.c:3855
Expr * clause
Definition: relation.h:1880
Definition: pg_list.h:45
#define make_simple_restrictinfo(clause)
Definition: restrictinfo.h:21

◆ find_indexpath_quals()

static void find_indexpath_quals ( Path bitmapqual,
List **  quals,
List **  preds 
)
static

Definition at line 1795 of file indxpath.c.

References BitmapAndPath::bitmapquals, BitmapOrPath::bitmapquals, elog, ERROR, get_actual_clauses(), IndexPath::indexclauses, IndexPath::indexinfo, IndexOptInfo::indpred, IsA, lfirst, list_concat(), list_copy(), and nodeTag.

Referenced by classify_index_clause_usage().

1796 {
1797  if (IsA(bitmapqual, BitmapAndPath))
1798  {
1799  BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
1800  ListCell *l;
1801 
1802  foreach(l, apath->bitmapquals)
1803  {
1804  find_indexpath_quals((Path *) lfirst(l), quals, preds);
1805  }
1806  }
1807  else if (IsA(bitmapqual, BitmapOrPath))
1808  {
1809  BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
1810  ListCell *l;
1811 
1812  foreach(l, opath->bitmapquals)
1813  {
1814  find_indexpath_quals((Path *) lfirst(l), quals, preds);
1815  }
1816  }
1817  else if (IsA(bitmapqual, IndexPath))
1818  {
1819  IndexPath *ipath = (IndexPath *) bitmapqual;
1820 
1821  *quals = list_concat(*quals, get_actual_clauses(ipath->indexclauses));
1822  *preds = list_concat(*preds, list_copy(ipath->indexinfo->indpred));
1823  }
1824  else
1825  elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
1826 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
IndexOptInfo * indexinfo
Definition: relation.h:1155
List * list_copy(const List *oldlist)
Definition: list.c:1160
List * get_actual_clauses(List *restrictinfo_list)
Definition: restrictinfo.c:333
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List * indexclauses
Definition: relation.h:1156
List * bitmapquals
Definition: relation.h:1198
List * bitmapquals
Definition: relation.h:1211
static void find_indexpath_quals(Path *bitmapqual, List **quals, List **preds)
Definition: indxpath.c:1795
#define ERROR
Definition: elog.h:43
#define lfirst(lc)
Definition: pg_list.h:106
#define nodeTag(nodeptr)
Definition: nodes.h:522
#define elog
Definition: elog.h:219
List * indpred
Definition: relation.h:778

◆ find_list_position()

static int find_list_position ( Node node,
List **  nodelist 
)
static

Definition at line 1836 of file indxpath.c.

References equal(), i, lappend(), and lfirst.

Referenced by classify_index_clause_usage().

1837 {
1838  int i;
1839  ListCell *lc;
1840 
1841  i = 0;
1842  foreach(lc, *nodelist)
1843  {
1844  Node *oldnode = (Node *) lfirst(lc);
1845 
1846  if (equal(node, oldnode))
1847  return i;
1848  i++;
1849  }
1850 
1851  *nodelist = lappend(*nodelist, node);
1852 
1853  return i;
1854 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2986
Definition: nodes.h:517
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
int i

◆ generate_bitmap_or_paths()

static List * generate_bitmap_or_paths ( PlannerInfo root,
RelOptInfo rel,
List clauses,
List other_clauses 
)
static

Definition at line 1263 of file indxpath.c.

References and_clause(), Assert, build_paths_for_OR(), castNode, choose_bitmap_and(), create_bitmap_or_path(), lappend(), lfirst, lfirst_node, list_concat(), list_copy(), list_make1, NIL, RestrictInfo::orclause, and restriction_is_or_clause().

Referenced by create_index_paths().

1265 {
1266  List *result = NIL;
1267  List *all_clauses;
1268  ListCell *lc;
1269 
1270  /*
1271  * We can use both the current and other clauses as context for
1272  * build_paths_for_OR; no need to remove ORs from the lists.
1273  */
1274  all_clauses = list_concat(list_copy(clauses), other_clauses);
1275 
1276  foreach(lc, clauses)
1277  {
1278  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
1279  List *pathlist;
1280  Path *bitmapqual;
1281  ListCell *j;
1282 
1283  /* Ignore RestrictInfos that aren't ORs */
1284  if (!restriction_is_or_clause(rinfo))
1285  continue;
1286 
1287  /*
1288  * We must be able to match at least one index to each of the arms of
1289  * the OR, else we can't use it.
1290  */
1291  pathlist = NIL;
1292  foreach(j, ((BoolExpr *) rinfo->orclause)->args)
1293  {
1294  Node *orarg = (Node *) lfirst(j);
1295  List *indlist;
1296 
1297  /* OR arguments should be ANDs or sub-RestrictInfos */
1298  if (and_clause(orarg))
1299  {
1300  List *andargs = ((BoolExpr *) orarg)->args;
1301 
1302  indlist = build_paths_for_OR(root, rel,
1303  andargs,
1304  all_clauses);
1305 
1306  /* Recurse in case there are sub-ORs */
1307  indlist = list_concat(indlist,
1308  generate_bitmap_or_paths(root, rel,
1309  andargs,
1310  all_clauses));
1311  }
1312  else
1313  {
1314  RestrictInfo *rinfo = castNode(RestrictInfo, orarg);
1315  List *orargs;
1316 
1318  orargs = list_make1(rinfo);
1319 
1320  indlist = build_paths_for_OR(root, rel,
1321  orargs,
1322  all_clauses);
1323  }
1324 
1325  /*
1326  * If nothing matched this arm, we can't do anything with this OR
1327  * clause.
1328  */
1329  if (indlist == NIL)
1330  {
1331  pathlist = NIL;
1332  break;
1333  }
1334 
1335  /*
1336  * OK, pick the most promising AND combination, and add it to
1337  * pathlist.
1338  */
1339  bitmapqual = choose_bitmap_and(root, rel, indlist);
1340  pathlist = lappend(pathlist, bitmapqual);
1341  }
1342 
1343  /*
1344  * If we have a match for every arm, then turn them into a
1345  * BitmapOrPath, and add to result list.
1346  */
1347  if (pathlist != NIL)
1348  {
1349  bitmapqual = (Path *) create_bitmap_or_path(root, rel, pathlist);
1350  result = lappend(result, bitmapqual);
1351  }
1352  }
1353 
1354  return result;
1355 }
#define NIL
Definition: pg_list.h:69
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
Expr * orclause
Definition: relation.h:1911
BitmapOrPath * create_bitmap_or_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
Definition: pathnode.c:1152
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:517
List * list_concat(List *list1, List *list2)
Definition: list.c:321
bool restriction_is_or_clause(RestrictInfo *restrictinfo)
Definition: restrictinfo.c:295
#define list_make1(x1)
Definition: pg_list.h:139
#define lfirst_node(type, lc)
Definition: pg_list.h:109
bool and_clause(Node *clause)
Definition: clauses.c:315
static Path * choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
Definition: indxpath.c:1370
List * lappend(List *list, void *datum)
Definition: list.c:128
static List * build_paths_for_OR(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
Definition: indxpath.c:1167
static List * generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
Definition: indxpath.c:1263
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
Definition: pg_list.h:45

◆ get_bitmap_tree_required_outer()

static Relids get_bitmap_tree_required_outer ( Path bitmapqual)
static

Definition at line 1747 of file indxpath.c.

References bms_copy(), bms_join(), elog, ERROR, IsA, lfirst, nodeTag, and PATH_REQ_OUTER.

Referenced by bitmap_and_cost_est(), bitmap_scan_cost_est(), and create_index_paths().

1748 {
1749  Relids result = NULL;
1750  ListCell *lc;
1751 
1752  if (IsA(bitmapqual, IndexPath))
1753  {
1754  return bms_copy(PATH_REQ_OUTER(bitmapqual));
1755  }
1756  else if (IsA(bitmapqual, BitmapAndPath))
1757  {
1758  foreach(lc, ((BitmapAndPath *) bitmapqual)->bitmapquals)
1759  {
1760  result = bms_join(result,
1762  }
1763  }
1764  else if (IsA(bitmapqual, BitmapOrPath))
1765  {
1766  foreach(lc, ((BitmapOrPath *) bitmapqual)->bitmapquals)
1767  {
1768  result = bms_join(result,
1770  }
1771  }
1772  else
1773  elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
1774 
1775  return result;
1776 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:133
#define ERROR
Definition: elog.h:43
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:976
#define lfirst(lc)
Definition: pg_list.h:106
#define PATH_REQ_OUTER(path)
Definition: relation.h:1097
#define nodeTag(nodeptr)
Definition: nodes.h:522
#define elog
Definition: elog.h:219
static Relids get_bitmap_tree_required_outer(Path *bitmapqual)
Definition: indxpath.c:1747

◆ get_index_paths()

static void get_index_paths ( PlannerInfo root,
RelOptInfo rel,
IndexOptInfo index,
IndexClauseSet clauses,
List **  bitindexpaths 
)
static

Definition at line 735 of file indxpath.c.

References add_path(), IndexOptInfo::amhasgetbitmap, IndexOptInfo::amhasgettuple, build_index_paths(), lappend(), lfirst, list_concat(), NIL, Path::pathkeys, IndexOptInfo::predOK, ST_ANYSCAN, and ST_BITMAPSCAN.

Referenced by create_index_paths(), and get_join_index_paths().

738 {
739  List *indexpaths;
740  bool skip_nonnative_saop = false;
741  bool skip_lower_saop = false;
742  ListCell *lc;
743 
744  /*
745  * Build simple index paths using the clauses. Allow ScalarArrayOpExpr
746  * clauses only if the index AM supports them natively, and skip any such
747  * clauses for index columns after the first (so that we produce ordered
748  * paths if possible).
749  */
750  indexpaths = build_index_paths(root, rel,
751  index, clauses,
752  index->predOK,
753  ST_ANYSCAN,
754  &skip_nonnative_saop,
755  &skip_lower_saop);
756 
757  /*
758  * If we skipped any lower-order ScalarArrayOpExprs on an index with an AM
759  * that supports them, then try again including those clauses. This will
760  * produce paths with more selectivity but no ordering.
761  */
762  if (skip_lower_saop)
763  {
764  indexpaths = list_concat(indexpaths,
765  build_index_paths(root, rel,
766  index, clauses,
767  index->predOK,
768  ST_ANYSCAN,
769  &skip_nonnative_saop,
770  NULL));
771  }
772 
773  /*
774  * Submit all the ones that can form plain IndexScan plans to add_path. (A
775  * plain IndexPath can represent either a plain IndexScan or an
776  * IndexOnlyScan, but for our purposes here that distinction does not
777  * matter. However, some of the indexes might support only bitmap scans,
778  * and those we mustn't submit to add_path here.)
779  *
780  * Also, pick out the ones that are usable as bitmap scans. For that, we
781  * must discard indexes that don't support bitmap scans, and we also are
782  * only interested in paths that have some selectivity; we should discard
783  * anything that was generated solely for ordering purposes.
784  */
785  foreach(lc, indexpaths)
786  {
787  IndexPath *ipath = (IndexPath *) lfirst(lc);
788 
789  if (index->amhasgettuple)
790  add_path(rel, (Path *) ipath);
791 
792  if (index->amhasgetbitmap &&
793  (ipath->path.pathkeys == NIL ||
794  ipath->indexselectivity < 1.0))
795  *bitindexpaths = lappend(*bitindexpaths, ipath);
796  }
797 
798  /*
799  * If there were ScalarArrayOpExpr clauses that the index can't handle
800  * natively, generate bitmap scan paths relying on executor-managed
801  * ScalarArrayOpExpr.
802  */
803  if (skip_nonnative_saop)
804  {
805  indexpaths = build_index_paths(root, rel,
806  index, clauses,
807  false,
809  NULL,
810  NULL);
811  *bitindexpaths = list_concat(*bitindexpaths, indexpaths);
812  }
813 }
#define NIL
Definition: pg_list.h:69
bool predOK
Definition: relation.h:788
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:422
Path path
Definition: relation.h:1154
static List * build_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, bool useful_predicate, ScanTypeControl scantype, bool *skip_nonnative_saop, bool *skip_lower_saop)
Definition: indxpath.c:857
List * list_concat(List *list1, List *list2)
Definition: list.c:321
Selectivity indexselectivity
Definition: relation.h:1163
bool amhasgetbitmap
Definition: relation.h:799
List * lappend(List *list, void *datum)
Definition: list.c:128
bool amhasgettuple
Definition: relation.h:798
List * pathkeys
Definition: relation.h:1092
#define lfirst(lc)
Definition: pg_list.h:106
Definition: pg_list.h:45

◆ get_join_index_paths()

static void get_join_index_paths ( PlannerInfo root,
RelOptInfo rel,
IndexOptInfo index,
IndexClauseSet rclauseset,
IndexClauseSet jclauseset,
IndexClauseSet eclauseset,
List **  bitindexpaths,
Relids  relids,
List **  considered_relids 
)
static

Definition at line 604 of file indxpath.c.

References Assert, bms_equal_any(), bms_is_subset(), RestrictInfo::clause_relids, get_index_paths(), IndexClauseSet::indexclauses, lappend(), lcons(), lfirst, list_concat(), MemSet, IndexOptInfo::ncolumns, NIL, and IndexClauseSet::nonempty.

Referenced by consider_index_join_outer_rels().

612 {
613  IndexClauseSet clauseset;
614  int indexcol;
615 
616  /* If we already considered this relids set, don't repeat the work */
617  if (bms_equal_any(relids, *considered_relids))
618  return;
619 
620  /* Identify indexclauses usable with this relids set */
621  MemSet(&clauseset, 0, sizeof(clauseset));
622 
623  for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
624  {
625  ListCell *lc;
626 
627  /* First find applicable simple join clauses */
628  foreach(lc, jclauseset->indexclauses[indexcol])
629  {
630  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
631 
632  if (bms_is_subset(rinfo->clause_relids, relids))
633  clauseset.indexclauses[indexcol] =
634  lappend(clauseset.indexclauses[indexcol], rinfo);
635  }
636 
637  /*
638  * Add applicable eclass join clauses. The clauses generated for each
639  * column are redundant (cf generate_implied_equalities_for_column),
640  * so we need at most one. This is the only exception to the general
641  * rule of using all available index clauses.
642  */
643  foreach(lc, eclauseset->indexclauses[indexcol])
644  {
645  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
646 
647  if (bms_is_subset(rinfo->clause_relids, relids))
648  {
649  clauseset.indexclauses[indexcol] =
650  lappend(clauseset.indexclauses[indexcol], rinfo);
651  break;
652  }
653  }
654 
655  /* Add restriction clauses (this is nondestructive to rclauseset) */
656  clauseset.indexclauses[indexcol] =
657  list_concat(clauseset.indexclauses[indexcol],
658  rclauseset->indexclauses[indexcol]);
659 
660  if (clauseset.indexclauses[indexcol] != NIL)
661  clauseset.nonempty = true;
662  }
663 
664  /* We should have found something, else caller passed silly relids */
665  Assert(clauseset.nonempty);
666 
667  /* Build index path(s) using the collected set of clauses */
668  get_index_paths(root, rel, index, &clauseset, bitindexpaths);
669 
670  /*
671  * Remember we considered paths for this set of relids. We use lcons not
672  * lappend to avoid confusing the loop in consider_index_join_outer_rels.
673  */
674  *considered_relids = lcons(relids, *considered_relids);
675 }
#define NIL
Definition: pg_list.h:69
bool nonempty
Definition: indxpath.c:58
Relids clause_relids
Definition: relation.h:1895
#define MemSet(start, val, len)
Definition: c.h:908
List * list_concat(List *list1, List *list2)
Definition: list.c:321
static bool bms_equal_any(Relids relids, List *relids_list)
Definition: indxpath.c:706
static void get_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, List **bitindexpaths)
Definition: indxpath.c:735
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:374
List * indexclauses[INDEX_MAX_KEYS]
Definition: indxpath.c:60
int ncolumns
Definition: relation.h:763
List * lappend(List *list, void *datum)
Definition: list.c:128
List * lcons(void *datum, List *list)
Definition: list.c:259
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106

◆ get_loop_count()

static double get_loop_count ( PlannerInfo root,
Index  cur_relid,
Relids  outer_relids 
)
static

Definition at line 1974 of file indxpath.c.

References adjust_rowcount_for_semijoins(), Assert, bms_next_member(), IS_DUMMY_REL, RelOptInfo::relid, RelOptInfo::rows, PlannerInfo::simple_rel_array, and PlannerInfo::simple_rel_array_size.

Referenced by bitmap_and_cost_est(), bitmap_scan_cost_est(), build_index_paths(), and create_index_paths().

1975 {
1976  double result;
1977  int outer_relid;
1978 
1979  /* For a non-parameterized path, just return 1.0 quickly */
1980  if (outer_relids == NULL)
1981  return 1.0;
1982 
1983  result = 0.0;
1984  outer_relid = -1;
1985  while ((outer_relid = bms_next_member(outer_relids, outer_relid)) >= 0)
1986  {
1987  RelOptInfo *outer_rel;
1988  double rowcount;
1989 
1990  /* Paranoia: ignore bogus relid indexes */
1991  if (outer_relid >= root->simple_rel_array_size)
1992  continue;
1993  outer_rel = root->simple_rel_array[outer_relid];
1994  if (outer_rel == NULL)
1995  continue;
1996  Assert(outer_rel->relid == outer_relid); /* sanity check on array */
1997 
1998  /* Other relation could be proven empty, if so ignore */
1999  if (IS_DUMMY_REL(outer_rel))
2000  continue;
2001 
2002  /* Otherwise, rel's rows estimate should be valid by now */
2003  Assert(outer_rel->rows > 0);
2004 
2005  /* Check to see if rel is on the inside of any semijoins */
2006  rowcount = adjust_rowcount_for_semijoins(root,
2007  cur_relid,
2008  outer_relid,
2009  outer_rel->rows);
2010 
2011  /* Remember smallest row count estimate among the outer rels */
2012  if (result == 0.0 || result > rowcount)
2013  result = rowcount;
2014  }
2015  /* Return 1.0 if we found no valid relations (shouldn't happen) */
2016  return (result > 0.0) ? result : 1.0;
2017 }
static double adjust_rowcount_for_semijoins(PlannerInfo *root, Index cur_relid, Index outer_relid, double rowcount)
Definition: indxpath.c:2027
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1075
struct RelOptInfo ** simple_rel_array
Definition: relation.h:193
#define IS_DUMMY_REL(r)
Definition: relation.h:1317
int simple_rel_array_size
Definition: relation.h:194
Index relid
Definition: relation.h:640
double rows
Definition: relation.h:615
#define Assert(condition)
Definition: c.h:699

◆ indexcol_is_bool_constant_for_query()

bool indexcol_is_bool_constant_for_query ( IndexOptInfo index,
int  indexcol 
)

Definition at line 3157 of file indxpath.c.

References RelOptInfo::baserestrictinfo, RestrictInfo::clause, lfirst, match_boolean_index_clause(), IndexOptInfo::opfamily, RestrictInfo::pseudoconstant, and IndexOptInfo::rel.

Referenced by build_index_pathkeys().

3158 {
3159  ListCell *lc;
3160 
3161  /* If the index isn't boolean, we can't possibly get a match */
3162  if (!IsBooleanOpfamily(index->opfamily[indexcol]))
3163  return false;
3164 
3165  /* Check each restriction clause for the index's rel */
3166  foreach(lc, index->rel->baserestrictinfo)
3167  {
3168  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3169 
3170  /*
3171  * As in match_clause_to_indexcol, never match pseudoconstants to
3172  * indexes. (It might be semantically okay to do so here, but the
3173  * odds of getting a match are negligible, so don't waste the cycles.)
3174  */
3175  if (rinfo->pseudoconstant)
3176  continue;
3177 
3178  /* See if we can match the clause's expression to the index column */
3179  if (match_boolean_index_clause((Node *) rinfo->clause, indexcol, index))
3180  return true;
3181  }
3182 
3183  return false;
3184 }
List * baserestrictinfo
Definition: relation.h:672
bool pseudoconstant
Definition: relation.h:1888
Definition: nodes.h:517
RelOptInfo * rel
Definition: relation.h:755
static bool match_boolean_index_clause(Node *clause, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3332
Expr * clause
Definition: relation.h:1880
#define lfirst(lc)
Definition: pg_list.h:106
Oid * opfamily
Definition: relation.h:768

◆ is_indexable_operator()

static bool is_indexable_operator ( Oid  expr_op,
Oid  opfamily,
bool  indexkey_on_left 
)
static

Definition at line 2459 of file indxpath.c.

References get_commutator(), InvalidOid, and op_in_opfamily().

Referenced by match_clause_to_indexcol().

2460 {
2461  /* Get the commuted operator if necessary */
2462  if (!indexkey_on_left)
2463  {
2464  expr_op = get_commutator(expr_op);
2465  if (expr_op == InvalidOid)
2466  return false;
2467  }
2468 
2469  /* OK if the (commuted) operator is a member of the index's opfamily */
2470  return op_in_opfamily(expr_op, opfamily);
2471 }
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition: lsyscache.c:63
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1298
#define InvalidOid
Definition: postgres_ext.h:36

◆ match_boolean_index_clause()

static bool match_boolean_index_clause ( Node clause,
int  indexcol,
IndexOptInfo index 
)
static

Definition at line 3332 of file indxpath.c.

References BooleanTest::arg, BooleanTest::booltesttype, get_notclausearg(), IS_FALSE, IS_TRUE, IsA, match_index_to_operand(), and not_clause().

Referenced by indexcol_is_bool_constant_for_query(), and match_clause_to_indexcol().

3335 {
3336  /* Direct match? */
3337  if (match_index_to_operand(clause, indexcol, index))
3338  return true;
3339  /* NOT clause? */
3340  if (not_clause(clause))
3341  {
3342  if (match_index_to_operand((Node *) get_notclausearg((Expr *) clause),
3343  indexcol, index))
3344  return true;
3345  }
3346 
3347  /*
3348  * Since we only consider clauses at top level of WHERE, we can convert
3349  * indexkey IS TRUE and indexkey IS FALSE to index searches as well. The
3350  * different meaning for NULL isn't important.
3351  */
3352  else if (clause && IsA(clause, BooleanTest))
3353  {
3354  BooleanTest *btest = (BooleanTest *) clause;
3355 
3356  if (btest->booltesttype == IS_TRUE ||
3357  btest->booltesttype == IS_FALSE)
3358  if (match_index_to_operand((Node *) btest->arg,
3359  indexcol, index))
3360  return true;
3361  }
3362  return false;
3363 }
Expr * get_notclausearg(Expr *notclause)
Definition: clauses.c:266
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3206
Definition: nodes.h:517
Expr * arg
Definition: primnodes.h:1211
bool not_clause(Node *clause)
Definition: clauses.c:237
BoolTestType booltesttype
Definition: primnodes.h:1212

◆ match_clause_to_index()

static void match_clause_to_index ( IndexOptInfo index,
RestrictInfo rinfo,
IndexClauseSet clauseset 
)
static

Definition at line 2225 of file indxpath.c.

References IndexClauseSet::indexclauses, list_append_unique_ptr(), match_clause_to_indexcol(), IndexOptInfo::nkeycolumns, IndexClauseSet::nonempty, RestrictInfo::pseudoconstant, IndexOptInfo::rel, and restriction_is_securely_promotable().

Referenced by match_clauses_to_index(), and match_join_clauses_to_index().

2228 {
2229  int indexcol;
2230 
2231  /*
2232  * Never match pseudoconstants to indexes. (Normally a match could not
2233  * happen anyway, since a pseudoconstant clause couldn't contain a Var,
2234  * but what if someone builds an expression index on a constant? It's not
2235  * totally unreasonable to do so with a partial index, either.)
2236  */
2237  if (rinfo->pseudoconstant)
2238  return;
2239 
2240  /*
2241  * If clause can't be used as an indexqual because it must wait till after
2242  * some lower-security-level restriction clause, reject it.
2243  */
2244  if (!restriction_is_securely_promotable(rinfo, index->rel))
2245  return;
2246 
2247  /* OK, check each index key column for a match */
2248  for (indexcol = 0; indexcol < index->nkeycolumns; indexcol++)
2249  {
2250  if (match_clause_to_indexcol(index,
2251  indexcol,
2252  rinfo))
2253  {
2254  clauseset->indexclauses[indexcol] =
2255  list_append_unique_ptr(clauseset->indexclauses[indexcol],
2256  rinfo);
2257  clauseset->nonempty = true;
2258  return;
2259  }
2260  }
2261 }
bool nonempty
Definition: indxpath.c:58
bool pseudoconstant
Definition: relation.h:1888
RelOptInfo * rel
Definition: relation.h:755
List * list_append_unique_ptr(List *list, void *datum)
Definition: list.c:975
static bool match_clause_to_indexcol(IndexOptInfo *index, int indexcol, RestrictInfo *rinfo)
Definition: indxpath.c:2326
List * indexclauses[INDEX_MAX_KEYS]
Definition: indxpath.c:60
bool restriction_is_securely_promotable(RestrictInfo *restrictinfo, RelOptInfo *rel)
Definition: restrictinfo.c:310
int nkeycolumns
Definition: relation.h:764

◆ match_clause_to_indexcol()

static bool match_clause_to_indexcol ( IndexOptInfo index,
int  indexcol,
RestrictInfo rinfo 
)
static

Definition at line 2326 of file indxpath.c.

References IndexOptInfo::amsearchnulls, NullTest::arg, NullTest::argisrow, ScalarArrayOpExpr::args, Assert, bms_is_member(), RestrictInfo::clause, contain_volatile_functions(), get_leftop(), get_rightop(), IndexOptInfo::indexcollations, IndexCollMatchesExprColl, ScalarArrayOpExpr::inputcollid, is_indexable_operator(), is_opclause, IsA, RestrictInfo::left_relids, linitial, lsecond, match_boolean_index_clause(), match_index_to_operand(), match_rowcompare_to_indexcol(), match_special_index_operator(), IndexOptInfo::opfamily, ScalarArrayOpExpr::opno, pull_varnos(), IndexOptInfo::rel, RelOptInfo::relid, RestrictInfo::right_relids, and ScalarArrayOpExpr::useOr.

Referenced by match_clause_to_index().

2329 {
2330  Expr *clause = rinfo->clause;
2331  Index index_relid = index->rel->relid;
2332  Oid opfamily;
2333  Oid idxcollation;
2334  Node *leftop,
2335  *rightop;
2336  Relids left_relids;
2337  Relids right_relids;
2338  Oid expr_op;
2339  Oid expr_coll;
2340  bool plain_op;
2341 
2342  Assert(indexcol < index->nkeycolumns);
2343 
2344  opfamily = index->opfamily[indexcol];
2345  idxcollation = index->indexcollations[indexcol];
2346 
2347  /* First check for boolean-index cases. */
2348  if (IsBooleanOpfamily(opfamily))
2349  {
2350  if (match_boolean_index_clause((Node *) clause, indexcol, index))
2351  return true;
2352  }
2353 
2354  /*
2355  * Clause must be a binary opclause, or possibly a ScalarArrayOpExpr
2356  * (which is always binary, by definition). Or it could be a
2357  * RowCompareExpr, which we pass off to match_rowcompare_to_indexcol().
2358  * Or, if the index supports it, we can handle IS NULL/NOT NULL clauses.
2359  */
2360  if (is_opclause(clause))
2361  {
2362  leftop = get_leftop(clause);
2363  rightop = get_rightop(clause);
2364  if (!leftop || !rightop)
2365  return false;
2366  left_relids = rinfo->left_relids;
2367  right_relids = rinfo->right_relids;
2368  expr_op = ((OpExpr *) clause)->opno;
2369  expr_coll = ((OpExpr *) clause)->inputcollid;
2370  plain_op = true;
2371  }
2372  else if (clause && IsA(clause, ScalarArrayOpExpr))
2373  {
2374  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
2375 
2376  /* We only accept ANY clauses, not ALL */
2377  if (!saop->useOr)
2378  return false;
2379  leftop = (Node *) linitial(saop->args);
2380  rightop = (Node *) lsecond(saop->args);
2381  left_relids = NULL; /* not actually needed */
2382  right_relids = pull_varnos(rightop);
2383  expr_op = saop->opno;
2384  expr_coll = saop->inputcollid;
2385  plain_op = false;
2386  }
2387  else if (clause && IsA(clause, RowCompareExpr))
2388  {
2389  return match_rowcompare_to_indexcol(index, indexcol,
2390  opfamily, idxcollation,
2391  (RowCompareExpr *) clause);
2392  }
2393  else if (index->amsearchnulls && IsA(clause, NullTest))
2394  {
2395  NullTest *nt = (NullTest *) clause;
2396 
2397  if (!nt->argisrow &&
2398  match_index_to_operand((Node *) nt->arg, indexcol, index))
2399  return true;
2400  return false;
2401  }
2402  else
2403  return false;
2404 
2405  /*
2406  * Check for clauses of the form: (indexkey operator constant) or
2407  * (constant operator indexkey). See above notes about const-ness.
2408  */
2409  if (match_index_to_operand(leftop, indexcol, index) &&
2410  !bms_is_member(index_relid, right_relids) &&
2411  !contain_volatile_functions(rightop))
2412  {
2413  if (IndexCollMatchesExprColl(idxcollation, expr_coll) &&
2414  is_indexable_operator(expr_op, opfamily, true))
2415  return true;
2416 
2417  /*
2418  * If we didn't find a member of the index's opfamily, see whether it
2419  * is a "special" indexable operator.
2420  */
2421  if (plain_op &&
2422  match_special_index_operator(clause, opfamily,
2423  idxcollation, true))
2424  return true;
2425  return false;
2426  }
2427 
2428  if (plain_op &&
2429  match_index_to_operand(rightop, indexcol, index) &&
2430  !bms_is_member(index_relid, left_relids) &&
2431  !contain_volatile_functions(leftop))
2432  {
2433  if (IndexCollMatchesExprColl(idxcollation, expr_coll) &&
2434  is_indexable_operator(expr_op, opfamily, false))
2435  return true;
2436 
2437  /*
2438  * If we didn't find a member of the index's opfamily, see whether it
2439  * is a "special" indexable operator.
2440  */
2441  if (match_special_index_operator(clause, opfamily,
2442  idxcollation, false))
2443  return true;
2444  return false;
2445  }
2446 
2447  return false;
2448 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Oid * indexcollations
Definition: relation.h:767
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3206
Definition: nodes.h:517
Relids left_relids
Definition: relation.h:1907
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:958
unsigned int Oid
Definition: postgres_ext.h:31
static bool match_rowcompare_to_indexcol(IndexOptInfo *index, int indexcol, Oid opfamily, Oid idxcollation, RowCompareExpr *clause)
Definition: indxpath.c:2479
#define lsecond(l)
Definition: pg_list.h:116
RelOptInfo * rel
Definition: relation.h:755
#define linitial(l)
Definition: pg_list.h:111
#define is_opclause(clause)
Definition: clauses.h:20
Node * get_leftop(const Expr *clause)
Definition: clauses.c:200
static bool match_boolean_index_clause(Node *clause, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3332
Expr * arg
Definition: primnodes.h:1188
#define IndexCollMatchesExprColl(idxcollation, exprcollation)
Definition: indxpath.c:44
Relids pull_varnos(Node *node)
Definition: var.c:95
Index relid
Definition: relation.h:640
Expr * clause
Definition: relation.h:1880
unsigned int Index
Definition: c.h:442
Relids right_relids
Definition: relation.h:1908
#define Assert(condition)
Definition: c.h:699
Node * get_rightop(const Expr *clause)
Definition: clauses.c:217
Oid * opfamily
Definition: relation.h:768
static bool is_indexable_operator(Oid expr_op, Oid opfamily, bool indexkey_on_left)
Definition: indxpath.c:2459
static bool match_special_index_operator(Expr *clause, Oid opfamily, Oid idxcollation, bool indexkey_on_left)
Definition: indxpath.c:3376
bool argisrow
Definition: primnodes.h:1190
bool amsearchnulls
Definition: relation.h:797
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486

◆ match_clause_to_ordering_op()

static Expr * match_clause_to_ordering_op ( IndexOptInfo index,
int  indexcol,
Expr clause,
Oid  pk_opfamily 
)
static

Definition at line 2681 of file indxpath.c.

References OpExpr::args, Assert, contain_var_clause(), contain_volatile_functions(), get_commutator(), get_leftop(), get_op_opfamily_sortfamily(), get_rightop(), IndexOptInfo::indexcollations, IndexCollMatchesExprColl, InvalidOid, is_opclause, list_make2, makeNode, match_index_to_operand(), IndexOptInfo::opfamily, OpExpr::opfuncid, and OpExpr::opno.

Referenced by match_pathkeys_to_index().

2685 {
2686  Oid opfamily;
2687  Oid idxcollation;
2688  Node *leftop,
2689  *rightop;
2690  Oid expr_op;
2691  Oid expr_coll;
2692  Oid sortfamily;
2693  bool commuted;
2694 
2695  Assert(indexcol < index->nkeycolumns);
2696 
2697  opfamily = index->opfamily[indexcol];
2698  idxcollation = index->indexcollations[indexcol];
2699 
2700  /*
2701  * Clause must be a binary opclause.
2702  */
2703  if (!is_opclause(clause))
2704  return NULL;
2705  leftop = get_leftop(clause);
2706  rightop = get_rightop(clause);
2707  if (!leftop || !rightop)
2708  return NULL;
2709  expr_op = ((OpExpr *) clause)->opno;
2710  expr_coll = ((OpExpr *) clause)->inputcollid;
2711 
2712  /*
2713  * We can forget the whole thing right away if wrong collation.
2714  */
2715  if (!IndexCollMatchesExprColl(idxcollation, expr_coll))
2716  return NULL;
2717 
2718  /*
2719  * Check for clauses of the form: (indexkey operator constant) or
2720  * (constant operator indexkey).
2721  */
2722  if (match_index_to_operand(leftop, indexcol, index) &&
2723  !contain_var_clause(rightop) &&
2724  !contain_volatile_functions(rightop))
2725  {
2726  commuted = false;
2727  }
2728  else if (match_index_to_operand(rightop, indexcol, index) &&
2729  !contain_var_clause(leftop) &&
2730  !contain_volatile_functions(leftop))
2731  {
2732  /* Might match, but we need a commuted operator */
2733  expr_op = get_commutator(expr_op);
2734  if (expr_op == InvalidOid)
2735  return NULL;
2736  commuted = true;
2737  }
2738  else
2739  return NULL;
2740 
2741  /*
2742  * Is the (commuted) operator an ordering operator for the opfamily? And
2743  * if so, does it yield the right sorting semantics?
2744  */
2745  sortfamily = get_op_opfamily_sortfamily(expr_op, opfamily);
2746  if (sortfamily != pk_opfamily)
2747  return NULL;
2748 
2749  /* We have a match. Return clause or a commuted version thereof. */
2750  if (commuted)
2751  {
2752  OpExpr *newclause = makeNode(OpExpr);
2753 
2754  /* flat-copy all the fields of clause */
2755  memcpy(newclause, clause, sizeof(OpExpr));
2756 
2757  /* commute it */
2758  newclause->opno = expr_op;
2759  newclause->opfuncid = InvalidOid;
2760  newclause->args = list_make2(rightop, leftop);
2761 
2762  clause = (Expr *) newclause;
2763  }
2764 
2765  return clause;
2766 }
#define list_make2(x1, x2)
Definition: pg_list.h:140
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1298
Oid * indexcollations
Definition: relation.h:767
Oid get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
Definition: lsyscache.c:105
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3206
Definition: nodes.h:517
bool contain_var_clause(Node *node)
Definition: var.c:331
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:958
unsigned int Oid
Definition: postgres_ext.h:31
#define is_opclause(clause)
Definition: clauses.h:20
Node * get_leftop(const Expr *clause)
Definition: clauses.c:200
#define IndexCollMatchesExprColl(idxcollation, exprcollation)
Definition: indxpath.c:44
Oid opfuncid
Definition: primnodes.h:498
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
Node * get_rightop(const Expr *clause)
Definition: clauses.c:217
Oid * opfamily
Definition: relation.h:768
Oid opno
Definition: primnodes.h:497
List * args
Definition: primnodes.h:503

◆ match_clauses_to_index()

static void match_clauses_to_index ( IndexOptInfo index,
List clauses,
IndexClauseSet clauseset 
)
static

Definition at line 2194 of file indxpath.c.

References lfirst_node, and match_clause_to_index().

Referenced by build_paths_for_OR(), match_eclass_clauses_to_index(), and match_restriction_clauses_to_index().

2197 {
2198  ListCell *lc;
2199 
2200  foreach(lc, clauses)
2201  {
2202  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
2203 
2204  match_clause_to_index(index, rinfo, clauseset);
2205  }
2206 }
static void match_clause_to_index(IndexOptInfo *index, RestrictInfo *rinfo, IndexClauseSet *clauseset)
Definition: indxpath.c:2225
#define lfirst_node(type, lc)
Definition: pg_list.h:109

◆ match_eclass_clauses_to_index()

static void match_eclass_clauses_to_index ( PlannerInfo root,
IndexOptInfo index,
IndexClauseSet clauseset 
)
static

Definition at line 2156 of file indxpath.c.

References arg, ec_member_matches_indexcol(), generate_implied_equalities_for_column(), RelOptInfo::has_eclass_joins, ec_member_matches_arg::index, ec_member_matches_arg::indexcol, RelOptInfo::lateral_referencers, match_clauses_to_index(), IndexOptInfo::nkeycolumns, and IndexOptInfo::rel.

Referenced by create_index_paths().

2158 {
2159  int indexcol;
2160 
2161  /* No work if rel is not in any such ECs */
2162  if (!index->rel->has_eclass_joins)
2163  return;
2164 
2165  for (indexcol = 0; indexcol < index->nkeycolumns; indexcol++)
2166  {
2168  List *clauses;
2169 
2170  /* Generate clauses, skipping any that join to lateral_referencers */
2171  arg.index = index;
2172  arg.indexcol = indexcol;
2174  index->rel,
2176  (void *) &arg,
2177  index->rel->lateral_referencers);
2178 
2179  /*
2180  * We have to check whether the results actually do match the index,
2181  * since for non-btree indexes the EC's equality operators might not
2182  * be in the index opclass (cf ec_member_matches_indexcol).
2183  */
2184  match_clauses_to_index(index, clauses, clauseset);
2185  }
2186 }
bool has_eclass_joins
Definition: relation.h:678
static bool ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel, EquivalenceClass *ec, EquivalenceMember *em, void *arg)
Definition: indxpath.c:2928
RelOptInfo * rel
Definition: relation.h:755
Relids lateral_referencers
Definition: relation.h:648
IndexOptInfo * index
Definition: indxpath.c:75
static void match_clauses_to_index(IndexOptInfo *index, List *clauses, IndexClauseSet *clauseset)
Definition: indxpath.c:2194
int nkeycolumns
Definition: relation.h:764
void * arg
Definition: pg_list.h:45
List * generate_implied_equalities_for_column(PlannerInfo *root, RelOptInfo *rel, ec_matches_callback_type callback, void *callback_arg, Relids prohibited_rels)
Definition: equivclass.c:2213

◆ match_index_to_operand()

bool match_index_to_operand ( Node operand,
int  indexcol,
IndexOptInfo index 
)

Definition at line 3206 of file indxpath.c.

References arg, elog, equal(), ERROR, i, IndexOptInfo::indexkeys, IndexOptInfo::indexprs, IsA, lfirst, list_head(), lnext, IndexOptInfo::rel, and RelOptInfo::relid.

Referenced by adjust_rowcompare_for_index(), deconstruct_indexquals(), ec_member_matches_indexcol(), expand_boolean_index_clause(), get_actual_variable_range(), match_boolean_index_clause(), match_clause_to_indexcol(), match_clause_to_ordering_op(), match_rowcompare_to_indexcol(), and relation_has_unique_index_for().

3209 {
3210  int indkey;
3211 
3212  /*
3213  * Ignore any RelabelType node above the operand. This is needed to be
3214  * able to apply indexscanning in binary-compatible-operator cases. Note:
3215  * we can assume there is at most one RelabelType node;
3216  * eval_const_expressions() will have simplified if more than one.
3217  */
3218  if (operand && IsA(operand, RelabelType))
3219  operand = (Node *) ((RelabelType *) operand)->arg;
3220 
3221  indkey = index->indexkeys[indexcol];
3222  if (indkey != 0)
3223  {
3224  /*
3225  * Simple index column; operand must be a matching Var.
3226  */
3227  if (operand && IsA(operand, Var) &&
3228  index->rel->relid == ((Var *) operand)->varno &&
3229  indkey == ((Var *) operand)->varattno)
3230  return true;
3231  }
3232  else
3233  {
3234  /*
3235  * Index expression; find the correct expression. (This search could
3236  * be avoided, at the cost of complicating all the callers of this
3237  * routine; doesn't seem worth it.)
3238  */
3239  ListCell *indexpr_item;
3240  int i;
3241  Node *indexkey;
3242 
3243  indexpr_item = list_head(index->indexprs);
3244  for (i = 0; i < indexcol; i++)
3245  {
3246  if (index->indexkeys[i] == 0)
3247  {
3248  if (indexpr_item == NULL)
3249  elog(ERROR, "wrong number of index expressions");
3250  indexpr_item = lnext(indexpr_item);
3251  }
3252  }
3253  if (indexpr_item == NULL)
3254  elog(ERROR, "wrong number of index expressions");
3255  indexkey = (Node *) lfirst(indexpr_item);
3256 
3257  /*
3258  * Does it match the operand? Again, strip any relabeling.
3259  */
3260  if (indexkey && IsA(indexkey, RelabelType))
3261  indexkey = (Node *) ((RelabelType *) indexkey)->arg;
3262 
3263  if (equal(indexkey, operand))
3264  return true;
3265  }
3266 
3267  return false;
3268 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2986
Definition: nodes.h:517
Definition: primnodes.h:164
RelOptInfo * rel
Definition: relation.h:755
#define ERROR
Definition: elog.h:43
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
Index relid
Definition: relation.h:640
#define lfirst(lc)
Definition: pg_list.h:106
int i
void * arg
int * indexkeys
Definition: relation.h:765
#define elog
Definition: elog.h:219
List * indexprs
Definition: relation.h:777

◆ match_join_clauses_to_index()

static void match_join_clauses_to_index ( PlannerInfo root,
RelOptInfo rel,
IndexOptInfo index,
IndexClauseSet clauseset,
List **  joinorclauses 
)
static

Definition at line 2126 of file indxpath.c.

References join_clause_is_movable_to(), RelOptInfo::joininfo, lappend(), lfirst, match_clause_to_index(), and restriction_is_or_clause().

Referenced by create_index_paths().

2130 {
2131  ListCell *lc;
2132 
2133  /* Scan the rel's join clauses */
2134  foreach(lc, rel->joininfo)
2135  {
2136  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
2137 
2138  /* Check if clause can be moved to this rel */
2139  if (!join_clause_is_movable_to(rinfo, rel))
2140  continue;
2141 
2142  /* Potentially usable, so see if it matches the index or is an OR */
2143  if (restriction_is_or_clause(rinfo))
2144  *joinorclauses = lappend(*joinorclauses, rinfo);
2145  else
2146  match_clause_to_index(index, rinfo, clauseset);
2147  }
2148 }
bool restriction_is_or_clause(RestrictInfo *restrictinfo)
Definition: restrictinfo.c:295
static void match_clause_to_index(IndexOptInfo *index, RestrictInfo *rinfo, IndexClauseSet *clauseset)
Definition: indxpath.c:2225
List * joininfo
Definition: relation.h:676
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
bool join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel)
Definition: restrictinfo.c:438

◆ match_pathkeys_to_index()

static void match_pathkeys_to_index ( IndexOptInfo index,
List pathkeys,
List **  orderby_clauses_p,
List **  clause_columns_p 
)
static

Definition at line 2567 of file indxpath.c.

References IndexOptInfo::amcanorderbyop, bms_equal(), BTLessStrategyNumber, EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, EquivalenceMember::em_expr, EquivalenceMember::em_relids, lappend(), lappend_int(), lfirst, match_clause_to_ordering_op(), member, IndexOptInfo::ncolumns, NIL, PathKey::pk_eclass, PathKey::pk_nulls_first, PathKey::pk_opfamily, PathKey::pk_strategy, IndexOptInfo::rel, and RelOptInfo::relids.

Referenced by build_index_paths().

2570 {
2571  List *orderby_clauses = NIL;
2572  List *clause_columns = NIL;
2573  ListCell *lc1;
2574 
2575  *orderby_clauses_p = NIL; /* set default results */
2576  *clause_columns_p = NIL;
2577 
2578  /* Only indexes with the amcanorderbyop property are interesting here */
2579  if (!index->amcanorderbyop)
2580  return;
2581 
2582  foreach(lc1, pathkeys)
2583  {
2584  PathKey *pathkey = (PathKey *) lfirst(lc1);
2585  bool found = false;
2586  ListCell *lc2;
2587 
2588  /*
2589  * Note: for any failure to match, we just return NIL immediately.
2590  * There is no value in matching just some of the pathkeys.
2591  */
2592 
2593  /* Pathkey must request default sort order for the target opfamily */
2594  if (pathkey->pk_strategy != BTLessStrategyNumber ||
2595  pathkey->pk_nulls_first)
2596  return;
2597 
2598  /* If eclass is volatile, no hope of using an indexscan */
2599  if (pathkey->pk_eclass->ec_has_volatile)
2600  return;
2601 
2602  /*
2603  * Try to match eclass member expression(s) to index. Note that child
2604  * EC members are considered, but only when they belong to the target
2605  * relation. (Unlike regular members, the same expression could be a
2606  * child member of more than one EC. Therefore, the same index could
2607  * be considered to match more than one pathkey list, which is OK
2608  * here. See also get_eclass_for_sort_expr.)
2609  */
2610  foreach(lc2, pathkey->pk_eclass->ec_members)
2611  {
2613  int indexcol;
2614 
2615  /* No possibility of match if it references other relations */
2616  if (!bms_equal(member->em_relids, index->rel->relids))
2617  continue;
2618 
2619  /*
2620  * We allow any column of the index to match each pathkey; they
2621  * don't have to match left-to-right as you might expect. This is
2622  * correct for GiST, which is the sole existing AM supporting
2623  * amcanorderbyop. We might need different logic in future for
2624  * other implementations.
2625  */
2626  for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
2627  {
2628  Expr *expr;
2629 
2630  expr = match_clause_to_ordering_op(index,
2631  indexcol,
2632  member->em_expr,
2633  pathkey->pk_opfamily);
2634  if (expr)
2635  {
2636  orderby_clauses = lappend(orderby_clauses, expr);
2637  clause_columns = lappend_int(clause_columns, indexcol);
2638  found = true;
2639  break;
2640  }
2641  }
2642 
2643  if (found) /* don't want to look at remaining members */
2644  break;
2645  }
2646 
2647  if (!found) /* fail if no match for this pathkey */
2648  return;
2649  }
2650 
2651  *orderby_clauses_p = orderby_clauses; /* success! */
2652  *clause_columns_p = clause_columns;
2653 }
#define NIL
Definition: pg_list.h:69
static Expr * match_clause_to_ordering_op(IndexOptInfo *index, int indexcol, Expr *clause, Oid pk_opfamily)
Definition: indxpath.c:2681
int pk_strategy
Definition: relation.h:977
Oid member
RelOptInfo * rel
Definition: relation.h:755
bool pk_nulls_first
Definition: relation.h:978
bool amcanorderbyop
Definition: relation.h:794
Relids relids
Definition: relation.h:612
int ncolumns
Definition: relation.h:763
List * lappend_int(List *list, int datum)
Definition: list.c:146
List * lappend(List *list, void *datum)
Definition: list.c:128
Relids em_relids
Definition: relation.h:947
#define lfirst(lc)
Definition: pg_list.h:106
EquivalenceClass * pk_eclass
Definition: relation.h:975
bool ec_has_volatile
Definition: relation.h:904
Oid pk_opfamily
Definition: relation.h:976
#define BTLessStrategyNumber
Definition: stratnum.h:29
Definition: pg_list.h:45
List * ec_members
Definition: relation.h:898
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:153

◆ match_restriction_clauses_to_index()

static void match_restriction_clauses_to_index ( RelOptInfo rel,
IndexOptInfo index,
IndexClauseSet clauseset 
)
static

Definition at line 2112 of file indxpath.c.

References IndexOptInfo::indrestrictinfo, and match_clauses_to_index().

Referenced by create_index_paths().

2114 {
2115  /* We can ignore clauses that are implied by the index predicate */
2116  match_clauses_to_index(index, index->indrestrictinfo, clauseset);
2117 }
List * indrestrictinfo
Definition: relation.h:782
static void match_clauses_to_index(IndexOptInfo *index, List *clauses, IndexClauseSet *clauseset)
Definition: indxpath.c:2194

◆ match_rowcompare_to_indexcol()

static bool match_rowcompare_to_indexcol ( IndexOptInfo index,
int  indexcol,
Oid  opfamily,
Oid  idxcollation,
RowCompareExpr clause 
)
static

Definition at line 2479 of file indxpath.c.

References bms_is_member(), BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, BTLessStrategyNumber, contain_volatile_functions(), get_commutator(), get_op_opfamily_strategy(), IndexCollMatchesExprColl, RowCompareExpr::inputcollids, InvalidOid, RowCompareExpr::largs, linitial, linitial_oid, match_index_to_operand(), RowCompareExpr::opnos, pull_varnos(), RowCompareExpr::rargs, IndexOptInfo::rel, IndexOptInfo::relam, and RelOptInfo::relid.

Referenced by match_clause_to_indexcol().

2484 {
2485  Index index_relid = index->rel->relid;
2486  Node *leftop,
2487  *rightop;
2488  Oid expr_op;
2489  Oid expr_coll;
2490 
2491  /* Forget it if we're not dealing with a btree index */
2492  if (index->relam != BTREE_AM_OID)
2493  return false;
2494 
2495  /*
2496  * We could do the matching on the basis of insisting that the opfamily
2497  * shown in the RowCompareExpr be the same as the index column's opfamily,
2498  * but that could fail in the presence of reverse-sort opfamilies: it'd be
2499  * a matter of chance whether RowCompareExpr had picked the forward or
2500  * reverse-sort family. So look only at the operator, and match if it is
2501  * a member of the index's opfamily (after commutation, if the indexkey is
2502  * on the right). We'll worry later about whether any additional
2503  * operators are matchable to the index.
2504  */
2505  leftop = (Node *) linitial(clause->largs);
2506  rightop = (Node *) linitial(clause->rargs);
2507  expr_op = linitial_oid(clause->opnos);
2508  expr_coll = linitial_oid(clause->inputcollids);
2509 
2510  /* Collations must match, if relevant */
2511  if (!IndexCollMatchesExprColl(idxcollation, expr_coll))
2512  return false;
2513 
2514  /*
2515  * These syntactic tests are the same as in match_clause_to_indexcol()
2516  */
2517  if (match_index_to_operand(leftop, indexcol, index) &&
2518  !bms_is_member(index_relid, pull_varnos(rightop)) &&
2519  !contain_volatile_functions(rightop))
2520  {
2521  /* OK, indexkey is on left */
2522  }
2523  else if (match_index_to_operand(rightop, indexcol, index) &&
2524  !bms_is_member(index_relid, pull_varnos(leftop)) &&
2525  !contain_volatile_functions(leftop))
2526  {
2527  /* indexkey is on right, so commute the operator */
2528  expr_op = get_commutator(expr_op);
2529  if (expr_op == InvalidOid)
2530  return false;
2531  }
2532  else
2533  return false;
2534 
2535  /* We're good if the operator is the right type of opfamily member */
2536  switch (get_op_opfamily_strategy(expr_op, opfamily))
2537  {
2538  case BTLessStrategyNumber:
2542  return true;
2543  }
2544 
2545  return false;
2546 }
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1298
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3206
Definition: nodes.h:517
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:958
unsigned int Oid
Definition: postgres_ext.h:31
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
RelOptInfo * rel
Definition: relation.h:755
#define linitial(l)
Definition: pg_list.h:111
#define IndexCollMatchesExprColl(idxcollation, exprcollation)
Definition: indxpath.c:44
Relids pull_varnos(Node *node)
Definition: var.c:95
Index relid
Definition: relation.h:640
unsigned int Index
Definition: c.h:442
#define InvalidOid
Definition: postgres_ext.h:36
#define linitial_oid(l)
Definition: pg_list.h:113
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:80
List * inputcollids
Definition: primnodes.h:1042
#define BTLessStrategyNumber
Definition: stratnum.h:29
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32

◆ match_special_index_operator()

static bool match_special_index_operator ( Expr clause,
Oid  opfamily,
Oid  idxcollation,
bool  indexkey_on_left 
)
static

Definition at line 3376 of file indxpath.c.

References Const::constvalue, DatumGetPointer, get_rightop(), IsA, lc_collate_is_c(), pattern_fixed_prefix(), Pattern_Prefix_Exact, Pattern_Prefix_None, Pattern_Type_Like, Pattern_Type_Like_IC, Pattern_Type_Regex, Pattern_Type_Regex_IC, and pfree().

Referenced by match_clause_to_indexcol().

3378 {
3379  bool isIndexable = false;
3380  Node *rightop;
3381  Oid expr_op;
3382  Oid expr_coll;
3383  Const *patt;
3384  Const *prefix = NULL;
3386 
3387  /*
3388  * Currently, all known special operators require the indexkey on the
3389  * left, but this test could be pushed into the switch statement if some
3390  * are added that do not...
3391  */
3392  if (!indexkey_on_left)
3393  return false;
3394 
3395  /* we know these will succeed */
3396  rightop = get_rightop(clause);
3397  expr_op = ((OpExpr *) clause)->opno;
3398  expr_coll = ((OpExpr *) clause)->inputcollid;
3399 
3400  /* again, required for all current special ops: */
3401  if (!IsA(rightop, Const) ||
3402  ((Const *) rightop)->constisnull)
3403  return false;
3404  patt = (Const *) rightop;
3405 
3406  switch (expr_op)
3407  {
3408  case OID_TEXT_LIKE_OP:
3409  case OID_BPCHAR_LIKE_OP:
3410  case OID_NAME_LIKE_OP:
3411  /* the right-hand const is type text for all of these */
3412  pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like, expr_coll,
3413  &prefix, NULL);
3414  isIndexable = (pstatus != Pattern_Prefix_None);
3415  break;
3416 
3417  case OID_BYTEA_LIKE_OP:
3418  pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like, expr_coll,
3419  &prefix, NULL);
3420  isIndexable = (pstatus != Pattern_Prefix_None);
3421  break;
3422 
3423  case OID_TEXT_ICLIKE_OP:
3424  case OID_BPCHAR_ICLIKE_OP:
3425  case OID_NAME_ICLIKE_OP:
3426  /* the right-hand const is type text for all of these */
3427  pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like_IC, expr_coll,
3428  &prefix, NULL);
3429  isIndexable = (pstatus != Pattern_Prefix_None);
3430  break;
3431 
3432  case OID_TEXT_REGEXEQ_OP:
3433  case OID_BPCHAR_REGEXEQ_OP:
3434  case OID_NAME_REGEXEQ_OP:
3435  /* the right-hand const is type text for all of these */
3436  pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex, expr_coll,
3437  &prefix, NULL);
3438  isIndexable = (pstatus != Pattern_Prefix_None);
3439  break;
3440 
3441  case OID_TEXT_ICREGEXEQ_OP:
3442  case OID_BPCHAR_ICREGEXEQ_OP:
3443  case OID_NAME_ICREGEXEQ_OP:
3444  /* the right-hand const is type text for all of these */
3445  pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC, expr_coll,
3446  &prefix, NULL);
3447  isIndexable = (pstatus != Pattern_Prefix_None);
3448  break;
3449 
3450  case OID_INET_SUB_OP:
3451  case OID_INET_SUBEQ_OP:
3452  isIndexable = true;
3453  break;
3454  }
3455 
3456  if (prefix)
3457  {
3458  pfree(DatumGetPointer(prefix->constvalue));
3459  pfree(prefix);
3460  }
3461 
3462  /* done if the expression doesn't look indexable */
3463  if (!isIndexable)
3464  return false;
3465 
3466  /*
3467  * Must also check that index's opfamily supports the operators we will
3468  * want to apply. (A hash index, for example, will not support ">=".)
3469  * Currently, only btree and spgist support the operators we need.
3470  *
3471  * Note: actually, in the Pattern_Prefix_Exact case, we only need "=" so a
3472  * hash index would work. Currently it doesn't seem worth checking for
3473  * that, however.
3474  *
3475  * We insist on the opfamily being the specific one we expect, else we'd
3476  * do the wrong thing if someone were to make a reverse-sort opfamily with
3477  * the same operators.
3478  *
3479  * The non-pattern opclasses will not sort the way we need in most non-C
3480  * locales. We can use such an index anyway for an exact match (simple
3481  * equality), but not for prefix-match cases. Note that here we are
3482  * looking at the index's collation, not the expression's collation --
3483  * this test is *not* dependent on the LIKE/regex operator's collation.
3484  */
3485  switch (expr_op)
3486  {
3487  case OID_TEXT_LIKE_OP:
3488  case OID_TEXT_ICLIKE_OP:
3489  case OID_TEXT_REGEXEQ_OP:
3490  case OID_TEXT_ICREGEXEQ_OP:
3491  isIndexable =
3492  (opfamily == TEXT_PATTERN_BTREE_FAM_OID) ||
3493  (opfamily == TEXT_SPGIST_FAM_OID) ||
3494  (opfamily == TEXT_BTREE_FAM_OID &&
3495  (pstatus == Pattern_Prefix_Exact ||
3496  lc_collate_is_c(idxcollation)));
3497  break;
3498 
3499  case OID_BPCHAR_LIKE_OP:
3500  case OID_BPCHAR_ICLIKE_OP:
3501  case OID_BPCHAR_REGEXEQ_OP:
3502  case OID_BPCHAR_ICREGEXEQ_OP:
3503  isIndexable =
3504  (opfamily == BPCHAR_PATTERN_BTREE_FAM_OID) ||
3505  (opfamily == BPCHAR_BTREE_FAM_OID &&
3506  (pstatus == Pattern_Prefix_Exact ||
3507  lc_collate_is_c(idxcollation)));
3508  break;
3509 
3510  case OID_NAME_LIKE_OP:
3511  case OID_NAME_ICLIKE_OP:
3512  case OID_NAME_REGEXEQ_OP:
3513  case OID_NAME_ICREGEXEQ_OP:
3514  /* name uses locale-insensitive sorting */
3515  isIndexable = (opfamily == NAME_BTREE_FAM_OID);
3516  break;
3517 
3518  case OID_BYTEA_LIKE_OP:
3519  isIndexable = (opfamily == BYTEA_BTREE_FAM_OID);
3520  break;
3521 
3522  case OID_INET_SUB_OP:
3523  case OID_INET_SUBEQ_OP:
3524  isIndexable = (opfamily == NETWORK_BTREE_FAM_OID);
3525  break;
3526  }
3527 
3528  return isIndexable;
3529 }
Datum constvalue
Definition: primnodes.h:197
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Definition: nodes.h:517
unsigned int Oid
Definition: postgres_ext.h:31
void pfree(void *pointer)
Definition: mcxt.c:1031
bool lc_collate_is_c(Oid collation)
Definition: pg_locale.c:1128
Pattern_Prefix_Status pattern_fixed_prefix(Const *patt, Pattern_Type ptype, Oid collation, Const **prefix, Selectivity *rest_selec)
Definition: selfuncs.c:5946
Node * get_rightop(const Expr *clause)
Definition: clauses.c:217
#define DatumGetPointer(X)
Definition: postgres.h:534
Pattern_Prefix_Status
Definition: selfuncs.h:97

◆ network_prefix_quals()

static List * network_prefix_quals ( Node leftop,
Oid  expr_op,
Oid  opfamily,
Datum  rightop 
)
static

Definition at line 4192 of file indxpath.c.

References BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, elog, ERROR, get_opfamily_member(), InvalidOid, lappend(), list_make1, make_opclause(), make_simple_restrictinfo, makeConst(), network_scan_first(), network_scan_last(), and NIL.

Referenced by expand_indexqual_opclause().

4193 {
4194  bool is_eq;
4195  Oid datatype;
4196  Oid opr1oid;
4197  Oid opr2oid;
4198  Datum opr1right;
4199  Datum opr2right;
4200  List *result;
4201  Expr *expr;
4202 
4203  switch (expr_op)
4204  {
4205  case OID_INET_SUB_OP:
4206  datatype = INETOID;
4207  is_eq = false;
4208  break;
4209  case OID_INET_SUBEQ_OP:
4210  datatype = INETOID;
4211  is_eq = true;
4212  break;
4213  default:
4214  elog(ERROR, "unexpected operator: %u", expr_op);
4215  return NIL;
4216  }
4217 
4218  /*
4219  * create clause "key >= network_scan_first( rightop )", or ">" if the
4220  * operator disallows equality.
4221  */
4222  if (is_eq)
4223  {
4224  opr1oid = get_opfamily_member(opfamily, datatype, datatype,
4226  if (opr1oid == InvalidOid)
4227  elog(ERROR, "no >= operator for opfamily %u", opfamily);
4228  }
4229  else
4230  {
4231  opr1oid = get_opfamily_member(opfamily, datatype, datatype,
4233  if (opr1oid == InvalidOid)
4234  elog(ERROR, "no > operator for opfamily %u", opfamily);
4235  }
4236 
4237  opr1right = network_scan_first(rightop);
4238 
4239  expr = make_opclause(opr1oid, BOOLOID, false,
4240  (Expr *) leftop,
4241  (Expr *) makeConst(datatype, -1,
4242  InvalidOid, /* not collatable */
4243  -1, opr1right,
4244  false, false),
4246  result = list_make1(make_simple_restrictinfo(expr));
4247 
4248  /* create clause "key <= network_scan_last( rightop )" */
4249 
4250  opr2oid = get_opfamily_member(opfamily, datatype, datatype,
4252  if (opr2oid == InvalidOid)
4253  elog(ERROR, "no <= operator for opfamily %u", opfamily);
4254 
4255  opr2right = network_scan_last(rightop);
4256 
4257  expr = make_opclause(opr2oid, BOOLOID, false,
4258  (Expr *) leftop,
4259  (Expr *) makeConst(datatype, -1,
4260  InvalidOid, /* not collatable */
4261  -1, opr2right,
4262  false, false),
4264  result = lappend(result, make_simple_restrictinfo(expr));
4265 
4266  return result;
4267 }
#define NIL
Definition: pg_list.h:69
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
Datum network_scan_last(Datum in)
Definition: network.c:1112
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: clauses.c:173
unsigned int Oid
Definition: postgres_ext.h:31
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:298
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
#define list_make1(x1)
Definition: pg_list.h:139
#define ERROR
Definition: elog.h:43
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
List * lappend(List *list, void *datum)
Definition: list.c:128
Datum network_scan_first(Datum in)
Definition: network.c:1098
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
#define make_simple_restrictinfo(clause)
Definition: restrictinfo.h:21
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32

◆ path_usage_comparator()

static int path_usage_comparator ( const void *  a,
const void *  b 
)
static

Definition at line 1570 of file indxpath.c.

References cost_bitmap_tree_node(), and PathClauseUsage::path.

Referenced by choose_bitmap_and().

1571 {
1572  PathClauseUsage *pa = *(PathClauseUsage *const *) a;
1573  PathClauseUsage *pb = *(PathClauseUsage *const *) b;
1574  Cost acost;
1575  Cost bcost;
1576  Selectivity aselec;
1577  Selectivity bselec;
1578 
1579  cost_bitmap_tree_node(pa->path, &acost, &aselec);
1580  cost_bitmap_tree_node(pb->path, &bcost, &bselec);
1581 
1582  /*
1583  * If costs are the same, sort by selectivity.
1584  */
1585  if (acost < bcost)
1586  return -1;
1587  if (acost > bcost)
1588  return 1;
1589 
1590  if (aselec < bselec)
1591  return -1;
1592  if (aselec > bselec)
1593  return 1;
1594 
1595  return 0;
1596 }
Path * path
Definition: indxpath.c:66
double Selectivity
Definition: nodes.h:647
double Cost
Definition: nodes.h:648
void cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec)
Definition: costsize.c:1046

◆ prefix_quals()

static List * prefix_quals ( Node leftop,
Oid  opfamily,
Oid  collation,
Const prefix,
Pattern_Prefix_Status  pstatus 
)
static

Definition at line 4066 of file indxpath.c.

References Assert, BTEqualStrategyNumber, BTGreaterEqualStrategyNumber, BTLessStrategyNumber, byteaout(), Const::consttype, Const::constvalue, DatumGetCString, DirectFunctionCall1, elog, ERROR, fmgr_info(), get_opcode(), get_opfamily_member(), InvalidOid, lappend(), list_make1, make_greater_string(), make_opclause(), make_simple_restrictinfo, NIL, Pattern_Prefix_Exact, Pattern_Prefix_None, pfree(), string_to_const(), and TextDatumGetCString.

Referenced by expand_indexqual_opclause().

4068 {
4069  List *result;
4070  Oid datatype;
4071  Oid oproid;
4072  Expr *expr;
4073  FmgrInfo ltproc;
4074  Const *greaterstr;
4075 
4076  Assert(pstatus != Pattern_Prefix_None);
4077 
4078  switch (opfamily)
4079  {
4080  case TEXT_BTREE_FAM_OID:
4081  case TEXT_PATTERN_BTREE_FAM_OID:
4082  case TEXT_SPGIST_FAM_OID:
4083  datatype = TEXTOID;
4084  break;
4085 
4086  case BPCHAR_BTREE_FAM_OID:
4087  case BPCHAR_PATTERN_BTREE_FAM_OID:
4088  datatype = BPCHAROID;
4089  break;
4090 
4091  case NAME_BTREE_FAM_OID:
4092  datatype = NAMEOID;
4093  break;
4094 
4095  case BYTEA_BTREE_FAM_OID:
4096  datatype = BYTEAOID;
4097  break;
4098 
4099  default:
4100  /* shouldn't get here */
4101  elog(ERROR, "unexpected opfamily: %u", opfamily);
4102  return NIL;
4103  }
4104 
4105  /*
4106  * If necessary, coerce the prefix constant to the right type. The given
4107  * prefix constant is either text or bytea type.
4108  */
4109  if (prefix_const->consttype != datatype)
4110  {
4111  char *prefix;
4112 
4113  switch (prefix_const->consttype)
4114  {
4115  case TEXTOID:
4116  prefix = TextDatumGetCString(prefix_const->constvalue);
4117  break;
4118  case BYTEAOID:
4120  prefix_const->constvalue));
4121  break;
4122  default:
4123  elog(ERROR, "unexpected const type: %u",
4124  prefix_const->consttype);
4125  return NIL;
4126  }
4127  prefix_const = string_to_const(prefix, datatype);
4128  pfree(prefix);
4129  }
4130 
4131  /*
4132  * If we found an exact-match pattern, generate an "=" indexqual.
4133  */
4134  if (pstatus == Pattern_Prefix_Exact)
4135  {
4136  oproid = get_opfamily_member(opfamily, datatype, datatype,
4138  if (oproid == InvalidOid)
4139  elog(ERROR, "no = operator for opfamily %u", opfamily);
4140  expr = make_opclause(oproid, BOOLOID, false,
4141  (Expr *) leftop, (Expr *) prefix_const,
4142  InvalidOid, collation);
4143  result = list_make1(make_simple_restrictinfo(expr));
4144  return result;
4145  }
4146 
4147  /*
4148  * Otherwise, we have a nonempty required prefix of the values.
4149  *
4150  * We can always say "x >= prefix".
4151  */
4152  oproid = get_opfamily_member(opfamily, datatype, datatype,
4154  if (oproid == InvalidOid)
4155  elog(ERROR, "no >= operator for opfamily %u", opfamily);
4156  expr = make_opclause(oproid, BOOLOID, false,
4157  (Expr *) leftop, (Expr *) prefix_const,
4158  InvalidOid, collation);
4159  result = list_make1(make_simple_restrictinfo(expr));
4160 
4161  /*-------
4162  * If we can create a string larger than the prefix, we can say
4163  * "x < greaterstr". NB: we rely on make_greater_string() to generate
4164  * a guaranteed-greater string, not just a probably-greater string.
4165  * In general this is only guaranteed in C locale, so we'd better be
4166  * using a C-locale index collation.
4167  *-------
4168  */
4169  oproid = get_opfamily_member(opfamily, datatype, datatype,
4171  if (oproid == InvalidOid)
4172  elog(ERROR, "no < operator for opfamily %u", opfamily);
4173  fmgr_info(get_opcode(oproid), &ltproc);
4174  greaterstr = make_greater_string(prefix_const, &ltproc, collation);
4175  if (greaterstr)
4176  {
4177  expr = make_opclause(oproid, BOOLOID, false,
4178  (Expr *) leftop, (Expr *) greaterstr,
4179  InvalidOid, collation);
4180  result = lappend(result, make_simple_restrictinfo(expr));
4181  }
4182 
4183  return result;
4184 }
Datum byteaout(PG_FUNCTION_ARGS)
Definition: varlena.c:351
#define NIL
Definition: pg_list.h:69
Definition: fmgr.h:56
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: clauses.c:173
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
unsigned int Oid
Definition: postgres_ext.h:31
#define list_make1(x1)
Definition: pg_list.h:139
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:551
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:124
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
List * lappend(List *list, void *datum)
Definition: list.c:128
#define TextDatumGetCString(d)
Definition: builtins.h:96
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1079
Const * make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation)
Definition: selfuncs.c:6326
#define Assert(condition)
Definition: c.h:699
static Const * string_to_const(const char *str, Oid datatype)
Definition: indxpath.c:4297
#define elog
Definition: elog.h:219
#define BTLessStrategyNumber
Definition: stratnum.h:29
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define make_simple_restrictinfo(clause)
Definition: restrictinfo.h:21
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32

◆ relation_has_unique_index_for()

bool relation_has_unique_index_for ( PlannerInfo root,
RelOptInfo rel,
List restrictlist,
List exprlist,
List oprlist 
)

Definition at line 2986 of file indxpath.c.

References Assert, RelOptInfo::baserestrictinfo, bms_is_empty(), RestrictInfo::clause, forboth, get_leftop(), get_rightop(), IndexOptInfo::immediate, RelOptInfo::indexlist, IndexOptInfo::indpred, lappend(), RestrictInfo::left_relids, lfirst, lfirst_oid, list_length(), list_member_oid(), match_index_to_operand(), RestrictInfo::mergeopfamilies, IndexOptInfo::ncolumns, NIL, op_in_opfamily(), IndexOptInfo::opfamily, RestrictInfo::outer_is_left, IndexOptInfo::predOK, RestrictInfo::right_relids, and IndexOptInfo::unique.

Referenced by create_unique_path(), and rel_is_distinct_for().

2989 {
2990  ListCell *ic;
2991 
2992  Assert(list_length(exprlist) == list_length(oprlist));
2993 
2994  /* Short-circuit if no indexes... */
2995  if (rel->indexlist == NIL)
2996  return false;
2997 
2998  /*
2999  * Examine the rel's restriction clauses for usable var = const clauses
3000  * that we can add to the restrictlist.
3001  */
3002  foreach(ic, rel->baserestrictinfo)
3003  {
3004  RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(ic);
3005 
3006  /*
3007  * Note: can_join won't be set for a restriction clause, but
3008  * mergeopfamilies will be if it has a mergejoinable operator and
3009  * doesn't contain volatile functions.
3010  */
3011  if (restrictinfo->mergeopfamilies == NIL)
3012  continue; /* not mergejoinable */
3013 
3014  /*
3015  * The clause certainly doesn't refer to anything but the given rel.
3016  * If either side is pseudoconstant then we can use it.
3017  */
3018  if (bms_is_empty(restrictinfo->left_relids))
3019  {
3020  /* righthand side is inner */
3021  restrictinfo->outer_is_left = true;
3022  }
3023  else if (bms_is_empty(restrictinfo->right_relids))
3024  {
3025  /* lefthand side is inner */
3026  restrictinfo->outer_is_left = false;
3027  }
3028  else
3029  continue;
3030 
3031  /* OK, add to list */
3032  restrictlist = lappend(restrictlist, restrictinfo);
3033  }
3034 
3035  /* Short-circuit the easy case */
3036  if (restrictlist == NIL && exprlist == NIL)
3037  return false;
3038 
3039  /* Examine each index of the relation ... */
3040  foreach(ic, rel->indexlist)
3041  {
3042  IndexOptInfo *ind = (IndexOptInfo *) lfirst(ic);
3043  int c;
3044 
3045  /*
3046  * If the index is not unique, or not immediately enforced, or if it's
3047  * a partial index that doesn't match the query, it's useless here.
3048  */
3049  if (!ind->unique || !ind->immediate ||
3050  (ind->indpred != NIL && !ind->predOK))
3051  continue;
3052 
3053  /*
3054  * Try to find each index column in the lists of conditions. This is
3055  * O(N^2) or worse, but we expect all the lists to be short.
3056  */
3057  for (c = 0; c < ind->ncolumns; c++)
3058  {
3059  bool matched = false;
3060  ListCell *lc;
3061  ListCell *lc2;
3062 
3063  foreach(lc, restrictlist)
3064  {
3065  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3066  Node *rexpr;
3067 
3068  /*
3069  * The condition's equality operator must be a member of the
3070  * index opfamily, else it is not asserting the right kind of
3071  * equality behavior for this index. We check this first
3072  * since it's probably cheaper than match_index_to_operand().
3073  */
3074  if (!list_member_oid(rinfo->mergeopfamilies, ind->opfamily[c]))
3075  continue;
3076 
3077  /*
3078  * XXX at some point we may need to check collations here too.
3079  * For the moment we assume all collations reduce to the same
3080  * notion of equality.
3081  */
3082 
3083  /* OK, see if the condition operand matches the index key */
3084  if (rinfo->outer_is_left)
3085  rexpr = get_rightop(rinfo->clause);
3086  else
3087  rexpr = get_leftop(rinfo->clause);
3088 
3089  if (match_index_to_operand(rexpr, c, ind))
3090  {
3091  matched = true; /* column is unique */
3092  break;
3093  }
3094  }
3095 
3096  if (matched)
3097  continue;
3098 
3099  forboth(lc, exprlist, lc2, oprlist)
3100  {
3101  Node *expr = (Node *) lfirst(lc);
3102  Oid opr = lfirst_oid(lc2);
3103 
3104  /* See if the expression matches the index key */
3105  if (!match_index_to_operand(expr, c, ind))
3106  continue;
3107 
3108  /*
3109  * The equality operator must be a member of the index
3110  * opfamily, else it is not asserting the right kind of
3111  * equality behavior for this index. We assume the caller
3112  * determined it is an equality operator, so we don't need to
3113  * check any more tightly than this.
3114  */
3115  if (!op_in_opfamily(opr, ind->opfamily[c]))
3116  continue;
3117 
3118  /*
3119  * XXX at some point we may need to check collations here too.
3120  * For the moment we assume all collations reduce to the same
3121  * notion of equality.
3122  */
3123 
3124  matched = true; /* column is unique */
3125  break;
3126  }
3127 
3128  if (!matched)
3129  break; /* no match; this index doesn't help us */
3130  }
3131 
3132  /* Matched all columns of this index? */
3133  if (c == ind->ncolumns)
3134  return true;
3135  }
3136 
3137  return false;
3138 }
#define NIL
Definition: pg_list.h:69
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition: lsyscache.c:63
bool predOK
Definition: relation.h:788
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3206
List * baserestrictinfo
Definition: relation.h:672
Definition: nodes.h:517
Relids left_relids
Definition: relation.h:1907
bool immediate
Definition: relation.h:790
unsigned int Oid
Definition: postgres_ext.h:31
List * mergeopfamilies
Definition: relation.h:1925
bool unique
Definition: relation.h:789
Node * get_leftop(const Expr *clause)
Definition: clauses.c:200
char * c
bool outer_is_left
Definition: relation.h:1935
int ncolumns
Definition: relation.h:763
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1880
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
List * indexlist
Definition: relation.h:649
Relids right_relids
Definition: relation.h:1908
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
Node * get_rightop(const Expr *clause)
Definition: clauses.c:217
Oid * opfamily
Definition: relation.h:768
List * indpred
Definition: relation.h:778
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ string_to_const()

static Const * string_to_const ( const char *  str,
Oid  datatype 
)
static

Definition at line 4297 of file indxpath.c.

References elog, ERROR, InvalidOid, makeConst(), NAMEDATALEN, and string_to_datum().

Referenced by prefix_quals().

4298 {
4299  Datum conval = string_to_datum(str, datatype);
4300  Oid collation;
4301  int constlen;
4302 
4303  /*
4304  * We only need to support a few datatypes here, so hard-wire properties
4305  * instead of incurring the expense of catalog lookups.
4306  */
4307  switch (datatype)
4308  {
4309  case TEXTOID:
4310  case VARCHAROID:
4311  case BPCHAROID:
4312  collation = DEFAULT_COLLATION_OID;
4313  constlen = -1;
4314  break;
4315 
4316  case NAMEOID:
4317  collation = InvalidOid;
4318  constlen = NAMEDATALEN;
4319  break;
4320 
4321  case BYTEAOID:
4322  collation = InvalidOid;
4323  constlen = -1;
4324  break;
4325 
4326  default:
4327  elog(ERROR, "unexpected datatype in string_to_const: %u",
4328  datatype);
4329  return NULL;
4330  }
4331 
4332  return makeConst(datatype, -1, collation, constlen,
4333  conval, false, false);
4334 }
unsigned int Oid
Definition: postgres_ext.h:31
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:298
#define NAMEDATALEN
#define ERROR
Definition: elog.h:43
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define elog
Definition: elog.h:219
static Datum string_to_datum(const char *str, Oid datatype)
Definition: indxpath.c:4279

◆ string_to_datum()

static Datum string_to_datum ( const char *  str,
Oid  datatype 
)
static

Definition at line 4279 of file indxpath.c.

References byteain(), CStringGetDatum, CStringGetTextDatum, DirectFunctionCall1, and namein().

Referenced by string_to_const().

4280 {
4281  /*
4282  * We cheat a little by assuming that CStringGetTextDatum() will do for
4283  * bpchar and varchar constants too...
4284  */
4285  if (datatype == NAMEOID)
4287  else if (datatype == BYTEAOID)
4289  else
4290  return CStringGetTextDatum(str);
4291 }
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
Datum byteain(PG_FUNCTION_ARGS)
Definition: varlena.c:255
#define CStringGetDatum(X)
Definition: postgres.h:563
#define CStringGetTextDatum(s)
Definition: builtins.h:95