PostgreSQL Source Code  git master
optimizer.h File Reference
#include "nodes/parsenodes.h"
Include dependency graph for optimizer.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define HAVE_PLANNERINFO_TYPEDEF   1
 
#define HAVE_INDEXOPTINFO_TYPEDEF   1
 
#define HAVE_SPECIALJOININFO_TYPEDEF   1
 
#define PVC_INCLUDE_AGGREGATES   0x0001 /* include Aggrefs in output list */
 
#define PVC_RECURSE_AGGREGATES   0x0002 /* recurse into Aggref arguments */
 
#define PVC_INCLUDE_WINDOWFUNCS   0x0004 /* include WindowFuncs in output list */
 
#define PVC_RECURSE_WINDOWFUNCS   0x0008 /* recurse into WindowFunc arguments */
 
#define PVC_INCLUDE_PLACEHOLDERS
 
#define PVC_RECURSE_PLACEHOLDERS
 

Typedefs

typedef struct PlannerInfo PlannerInfo
 
typedef struct IndexOptInfo IndexOptInfo
 
typedef struct SpecialJoinInfo SpecialJoinInfo
 

Enumerations

enum  ForceParallelMode { FORCE_PARALLEL_OFF, FORCE_PARALLEL_ON, FORCE_PARALLEL_REGRESS }
 

Functions

Selectivity clause_selectivity (PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
Selectivity clauselist_selectivity_simple (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, Bitmapset *estimatedclauses)
 
Selectivity clauselist_selectivity (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
double clamp_row_est (double nrows)
 
bool is_pseudo_constant_for_index (Node *expr, IndexOptInfo *index)
 
struct PlannedStmtplanner (Query *parse, int cursorOptions, struct ParamListInfoData *boundParams)
 
Exprexpression_planner (Expr *expr)
 
Exprexpression_planner_with_deps (Expr *expr, List **relationOids, List **invalItems)
 
bool plan_cluster_use_sort (Oid tableOid, Oid indexOid)
 
int plan_create_index_workers (Oid tableOid, Oid indexOid)
 
void extract_query_dependencies (Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
 
Nodenegate_clause (Node *node)
 
Exprcanonicalize_qual (Expr *qual, bool is_check)
 
bool contain_mutable_functions (Node *clause)
 
bool contain_volatile_functions (Node *clause)
 
bool contain_volatile_functions_not_nextval (Node *clause)
 
Nodeeval_const_expressions (PlannerInfo *root, Node *node)
 
Nodeestimate_expression_value (PlannerInfo *root, Node *node)
 
Exprevaluate_expr (Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
 
Listexpand_function_arguments (List *args, Oid result_type, struct HeapTupleData *func_tuple)
 
bool predicate_implied_by (List *predicate_list, List *clause_list, bool weak)
 
bool predicate_refuted_by (List *predicate_list, List *clause_list, bool weak)
 
int count_nonjunk_tlist_entries (List *tlist)
 
TargetEntryget_sortgroupref_tle (Index sortref, List *targetList)
 
TargetEntryget_sortgroupclause_tle (SortGroupClause *sgClause, List *targetList)
 
Nodeget_sortgroupclause_expr (SortGroupClause *sgClause, List *targetList)
 
Listget_sortgrouplist_exprs (List *sgClauses, List *targetList)
 
SortGroupClauseget_sortgroupref_clause (Index sortref, List *clauses)
 
SortGroupClauseget_sortgroupref_clause_noerr (Index sortref, List *clauses)
 
Bitmapsetpull_varnos (Node *node)
 
Bitmapsetpull_varnos_of_level (Node *node, int levelsup)
 
void pull_varattnos (Node *node, Index varno, Bitmapset **varattnos)
 
Listpull_vars_of_level (Node *node, int levelsup)
 
bool contain_var_clause (Node *node)
 
bool contain_vars_of_level (Node *node, int levelsup)
 
int locate_var_of_level (Node *node, int levelsup)
 
Listpull_var_clause (Node *node, int flags)
 
Nodeflatten_join_alias_vars (Query *query, Node *node)
 

Variables

PGDLLIMPORT double seq_page_cost
 
PGDLLIMPORT double random_page_cost
 
PGDLLIMPORT double cpu_tuple_cost
 
PGDLLIMPORT double cpu_index_tuple_cost
 
PGDLLIMPORT double cpu_operator_cost
 
PGDLLIMPORT double parallel_tuple_cost
 
PGDLLIMPORT double parallel_setup_cost
 
PGDLLIMPORT int effective_cache_size
 
int force_parallel_mode
 
bool parallel_leader_participation
 

Macro Definition Documentation

◆ HAVE_INDEXOPTINFO_TYPEDEF

#define HAVE_INDEXOPTINFO_TYPEDEF   1

Definition at line 41 of file optimizer.h.

◆ HAVE_PLANNERINFO_TYPEDEF

#define HAVE_PLANNERINFO_TYPEDEF   1

Definition at line 35 of file optimizer.h.

◆ HAVE_SPECIALJOININFO_TYPEDEF

#define HAVE_SPECIALJOININFO_TYPEDEF   1

Definition at line 45 of file optimizer.h.

◆ PVC_INCLUDE_AGGREGATES

#define PVC_INCLUDE_AGGREGATES   0x0001 /* include Aggrefs in output list */

◆ PVC_INCLUDE_PLACEHOLDERS

◆ PVC_INCLUDE_WINDOWFUNCS

#define PVC_INCLUDE_WINDOWFUNCS   0x0004 /* include WindowFuncs in output list */

◆ PVC_RECURSE_AGGREGATES

◆ PVC_RECURSE_PLACEHOLDERS

#define PVC_RECURSE_PLACEHOLDERS
Value:
0x0020 /* recurse into PlaceHolderVar
* arguments */

Definition at line 176 of file optimizer.h.

Referenced by build_tlist_to_deparse(), estimate_num_groups(), pull_var_clause(), and pull_var_clause_walker().

◆ PVC_RECURSE_WINDOWFUNCS

Typedef Documentation

◆ IndexOptInfo

typedef struct IndexOptInfo IndexOptInfo

Definition at line 40 of file optimizer.h.

◆ PlannerInfo

typedef struct PlannerInfo PlannerInfo

Definition at line 34 of file optimizer.h.

◆ SpecialJoinInfo

Definition at line 44 of file optimizer.h.

Enumeration Type Documentation

◆ ForceParallelMode

Enumerator
FORCE_PARALLEL_OFF 
FORCE_PARALLEL_ON 
FORCE_PARALLEL_REGRESS 

Definition at line 94 of file optimizer.h.

Function Documentation

◆ canonicalize_qual()

Expr* canonicalize_qual ( Expr qual,
bool  is_check 
)

Definition at line 292 of file prepqual.c.

References Assert, find_duplicate_ors(), and IsA.

Referenced by ConstraintImpliedByRelConstraint(), convert_EXISTS_to_ANY(), DoCopy(), get_proposed_default_constraint(), get_relation_constraints(), preprocess_expression(), and RelationGetIndexPredicate().

293 {
294  Expr *newqual;
295 
296  /* Quick exit for empty qual */
297  if (qual == NULL)
298  return NULL;
299 
300  /* This should not be invoked on quals in implicit-AND format */
301  Assert(!IsA(qual, List));
302 
303  /*
304  * Pull up redundant subclauses in OR-of-AND trees. We do this only
305  * within the top-level AND/OR structure; there's no point in looking
306  * deeper. Also remove any NULL constants in the top-level structure.
307  */
308  newqual = find_duplicate_ors(qual, is_check);
309 
310  return newqual;
311 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
static Expr * find_duplicate_ors(Expr *qual, bool is_check)
Definition: prepqual.c:405
#define Assert(condition)
Definition: c.h:733
Definition: pg_list.h:50

◆ clamp_row_est()

double clamp_row_est ( double  nrows)

Definition at line 187 of file costsize.c.

References rint().

Referenced by adjust_limit_rows_costs(), approx_tuple_count(), bernoulli_samplescangetsamplesize(), calc_joinrel_size_estimate(), compute_bitmap_pages(), cost_agg(), cost_append(), cost_bitmap_heap_scan(), cost_group(), cost_index(), cost_seqscan(), cost_subplan(), create_bitmap_subplan(), estimate_hash_bucket_stats(), estimate_num_groups(), estimate_path_cost_size(), estimate_size(), expression_returns_set_rows(), final_cost_hashjoin(), final_cost_mergejoin(), final_cost_nestloop(), get_parameterized_baserel_size(), get_variable_numdistinct(), initial_cost_mergejoin(), set_baserel_size_estimates(), set_foreign_size(), system_rows_samplescangetsamplesize(), system_samplescangetsamplesize(), and system_time_samplescangetsamplesize().

188 {
189  /*
190  * Force estimate to be at least one row, to make explain output look
191  * better and to avoid possible divide-by-zero when interpolating costs.
192  * Make it an integer, too.
193  */
194  if (nrows <= 1.0)
195  nrows = 1.0;
196  else
197  nrows = rint(nrows);
198 
199  return nrows;
200 }
double rint(double x)
Definition: rint.c:21

◆ clause_selectivity()

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

Definition at line 600 of file clausesel.c.

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

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

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

◆ clauselist_selectivity()

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

Definition at line 69 of file clausesel.c.

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

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

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

◆ clauselist_selectivity_simple()

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

Definition at line 150 of file clausesel.c.

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

Referenced by clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

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

◆ contain_mutable_functions()

◆ contain_var_clause()

bool contain_var_clause ( Node node)

◆ contain_vars_of_level()

bool contain_vars_of_level ( Node node,
int  levelsup 
)

Definition at line 369 of file var.c.

References contain_vars_of_level_walker(), and query_or_expression_tree_walker().

Referenced by apply_child_basequals(), checkExprIsVarFree(), convert_ANY_sublink_to_join(), convert_EXISTS_sublink_to_join(), convert_EXISTS_to_ANY(), pull_up_simple_values(), pullup_replace_vars_callback(), transformAExprIn(), transformInsertStmt(), transformRangeFunction(), transformRangeTableFunc(), transformSetOperationTree(), and transformValuesClause().

370 {
371  int sublevels_up = levelsup;
372 
375  (void *) &sublevels_up,
376  0);
377 }
bool query_or_expression_tree_walker(Node *node, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:3347
static bool contain_vars_of_level_walker(Node *node, int *sublevels_up)
Definition: var.c:380

◆ contain_volatile_functions()

◆ contain_volatile_functions_not_nextval()

bool contain_volatile_functions_not_nextval ( Node clause)

Definition at line 774 of file clauses.c.

References contain_volatile_functions_not_nextval_walker().

Referenced by BeginCopyFrom().

775 {
777 }
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:787

◆ count_nonjunk_tlist_entries()

int count_nonjunk_tlist_entries ( List tlist)

Definition at line 208 of file tlist.c.

References lfirst, and TargetEntry::resjunk.

Referenced by get_update_query_targetlist_def(), transformMultiAssignRef(), and transformSubLink().

209 {
210  int len = 0;
211  ListCell *l;
212 
213  foreach(l, tlist)
214  {
215  TargetEntry *tle = (TargetEntry *) lfirst(l);
216 
217  if (!tle->resjunk)
218  len++;
219  }
220  return len;
221 }
bool resjunk
Definition: primnodes.h:1400
#define lfirst(lc)
Definition: pg_list.h:190

◆ estimate_expression_value()

Node* estimate_expression_value ( PlannerInfo root,
Node node 
)

Definition at line 2286 of file clauses.c.

References eval_const_expressions_context::active_fns, eval_const_expressions_context::boundParams, PlannerGlobal::boundParams, eval_const_expressions_context::case_val, eval_const_expressions_context::estimate, eval_const_expressions_mutator(), PlannerInfo::glob, NIL, and eval_const_expressions_context::root.

Referenced by array_unnest_support(), bernoulli_samplescangetsamplesize(), clause_selectivity(), generate_series_int4_support(), generate_series_int8_support(), get_restriction_variable(), gincost_opexpr(), gincost_scalararrayopexpr(), preprocess_limit(), scalararraysel(), system_rows_samplescangetsamplesize(), system_samplescangetsamplesize(), and system_time_samplescangetsamplesize().

2287 {
2289 
2290  context.boundParams = root->glob->boundParams; /* bound Params */
2291  /* we do not need to mark the plan as depending on inlined functions */
2292  context.root = NULL;
2293  context.active_fns = NIL; /* nothing being recursively simplified */
2294  context.case_val = NULL; /* no CASE being examined */
2295  context.estimate = true; /* unsafe transformations OK */
2296  return eval_const_expressions_mutator(node, &context);
2297 }
#define NIL
Definition: pg_list.h:65
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2331
ParamListInfo boundParams
Definition: clauses.c:66
PlannerGlobal * glob
Definition: pathnodes.h:179
ParamListInfo boundParams
Definition: pathnodes.h:109

◆ eval_const_expressions()

Node* eval_const_expressions ( PlannerInfo root,
Node node 
)

Definition at line 2253 of file clauses.c.

References eval_const_expressions_context::active_fns, eval_const_expressions_context::boundParams, PlannerGlobal::boundParams, eval_const_expressions_context::case_val, eval_const_expressions_context::estimate, eval_const_expressions_mutator(), PlannerInfo::glob, NIL, and eval_const_expressions_context::root.

Referenced by apply_child_basequals(), ATExecAttachPartition(), ConstraintImpliedByRelConstraint(), convert_EXISTS_to_ANY(), DoCopy(), expression_planner(), expression_planner_with_deps(), get_proposed_default_constraint(), get_relation_constraints(), preprocess_expression(), preprocess_function_rtes(), process_implied_equality(), RelationBuildPartitionKey(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), and simplify_EXISTS_query().

2254 {
2256 
2257  if (root)
2258  context.boundParams = root->glob->boundParams; /* bound Params */
2259  else
2260  context.boundParams = NULL;
2261  context.root = root; /* for inlined-function dependencies */
2262  context.active_fns = NIL; /* nothing being recursively simplified */
2263  context.case_val = NULL; /* no CASE being examined */
2264  context.estimate = false; /* safe transformations only */
2265  return eval_const_expressions_mutator(node, &context);
2266 }
#define NIL
Definition: pg_list.h:65
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2331
ParamListInfo boundParams
Definition: clauses.c:66
PlannerGlobal * glob
Definition: pathnodes.h:179
ParamListInfo boundParams
Definition: pathnodes.h:109

◆ evaluate_expr()

Expr* evaluate_expr ( Expr expr,
Oid  result_type,
int32  result_typmod,
Oid  result_collation 
)

Definition at line 4778 of file clauses.c.

References CreateExecutorState(), datumCopy(), EState::es_query_cxt, ExecEvalExprSwitchContext(), ExecInitExpr(), fix_opfuncids(), FreeExecutorState(), get_typlenbyval(), GetPerTupleExprContext, makeConst(), MemoryContextSwitchTo(), PG_DETOAST_DATUM_COPY, and PointerGetDatum.

Referenced by eval_const_expressions_mutator(), evaluate_function(), and transformPartitionBoundValue().

4780 {
4781  EState *estate;
4782  ExprState *exprstate;
4783  MemoryContext oldcontext;
4784  Datum const_val;
4785  bool const_is_null;
4786  int16 resultTypLen;
4787  bool resultTypByVal;
4788 
4789  /*
4790  * To use the executor, we need an EState.
4791  */
4792  estate = CreateExecutorState();
4793 
4794  /* We can use the estate's working context to avoid memory leaks. */
4795  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
4796 
4797  /* Make sure any opfuncids are filled in. */
4798  fix_opfuncids((Node *) expr);
4799 
4800  /*
4801  * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
4802  * because it'd result in recursively invoking eval_const_expressions.)
4803  */
4804  exprstate = ExecInitExpr(expr, NULL);
4805 
4806  /*
4807  * And evaluate it.
4808  *
4809  * It is OK to use a default econtext because none of the ExecEvalExpr()
4810  * code used in this situation will use econtext. That might seem
4811  * fortuitous, but it's not so unreasonable --- a constant expression does
4812  * not depend on context, by definition, n'est ce pas?
4813  */
4814  const_val = ExecEvalExprSwitchContext(exprstate,
4815  GetPerTupleExprContext(estate),
4816  &const_is_null);
4817 
4818  /* Get info needed about result datatype */
4819  get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
4820 
4821  /* Get back to outer memory context */
4822  MemoryContextSwitchTo(oldcontext);
4823 
4824  /*
4825  * Must copy result out of sub-context used by expression eval.
4826  *
4827  * Also, if it's varlena, forcibly detoast it. This protects us against
4828  * storing TOAST pointers into plans that might outlive the referenced
4829  * data. (makeConst would handle detoasting anyway, but it's worth a few
4830  * extra lines here so that we can do the copy and detoast in one step.)
4831  */
4832  if (!const_is_null)
4833  {
4834  if (resultTypLen == -1)
4835  const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
4836  else
4837  const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
4838  }
4839 
4840  /* Release all the junk we just created */
4841  FreeExecutorState(estate);
4842 
4843  /*
4844  * Make the constant result node.
4845  */
4846  return (Expr *) makeConst(result_type, result_typmod, result_collation,
4847  resultTypLen,
4848  const_val, const_is_null,
4849  resultTypByVal);
4850 }
signed short int16
Definition: c.h:346
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:300
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:237
#define PointerGetDatum(X)
Definition: postgres.h:556
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1587
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:525
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:297
void FreeExecutorState(EState *estate)
Definition: execUtils.c:190
#define GetPerTupleExprContext(estate)
Definition: executor.h:501
MemoryContext es_query_cxt
Definition: execnodes.h:550
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:130
EState * CreateExecutorState(void)
Definition: execUtils.c:88
uintptr_t Datum
Definition: postgres.h:367
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2029
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:121

◆ expand_function_arguments()

List* expand_function_arguments ( List args,
Oid  result_type,
struct HeapTupleData func_tuple 
)

◆ expression_planner()

Expr* expression_planner ( Expr expr)

Definition at line 6045 of file planner.c.

References eval_const_expressions(), and fix_opfuncids().

Referenced by ATExecAddColumn(), ATPrepAlterColumnType(), BeginCopyFrom(), CheckMutability(), ComputePartitionAttrs(), ExecPrepareCheck(), ExecPrepareExpr(), ExecPrepareQual(), load_domaintype_info(), set_baserel_partition_constraint(), slot_fill_defaults(), StoreAttrDefault(), and transformPartitionBoundValue().

6046 {
6047  Node *result;
6048 
6049  /*
6050  * Convert named-argument function calls, insert default arguments and
6051  * simplify constant subexprs
6052  */
6053  result = eval_const_expressions(NULL, (Node *) expr);
6054 
6055  /* Fill in opfuncid values if missing */
6056  fix_opfuncids(result);
6057 
6058  return (Expr *) result;
6059 }
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1587
Definition: nodes.h:525
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2253

◆ expression_planner_with_deps()

Expr* expression_planner_with_deps ( Expr expr,
List **  relationOids,
List **  invalItems 
)

Definition at line 6072 of file planner.c.

References eval_const_expressions(), extract_query_dependencies_walker(), fix_opfuncids(), PlannerInfo::glob, PlannerGlobal::invalItems, MemSet, NIL, PlannerGlobal::relationOids, T_PlannerGlobal, T_PlannerInfo, PlannerGlobal::type, and PlannerInfo::type.

Referenced by GetCachedExpression().

6075 {
6076  Node *result;
6077  PlannerGlobal glob;
6078  PlannerInfo root;
6079 
6080  /* Make up dummy planner state so we can use setrefs machinery */
6081  MemSet(&glob, 0, sizeof(glob));
6082  glob.type = T_PlannerGlobal;
6083  glob.relationOids = NIL;
6084  glob.invalItems = NIL;
6085 
6086  MemSet(&root, 0, sizeof(root));
6087  root.type = T_PlannerInfo;
6088  root.glob = &glob;
6089 
6090  /*
6091  * Convert named-argument function calls, insert default arguments and
6092  * simplify constant subexprs. Collect identities of inlined functions
6093  * and elided domains, too.
6094  */
6095  result = eval_const_expressions(&root, (Node *) expr);
6096 
6097  /* Fill in opfuncid values if missing */
6098  fix_opfuncids(result);
6099 
6100  /*
6101  * Now walk the finished expression to find anything else we ought to
6102  * record as an expression dependency.
6103  */
6104  (void) extract_query_dependencies_walker(result, &root);
6105 
6106  *relationOids = glob.relationOids;
6107  *invalItems = glob.invalItems;
6108 
6109  return (Expr *) result;
6110 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1587
Definition: nodes.h:525
#define MemSet(start, val, len)
Definition: c.h:956
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2253
PlannerGlobal * glob
Definition: pathnodes.h:179
List * invalItems
Definition: pathnodes.h:127
NodeTag type
Definition: pathnodes.h:175
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:2794
NodeTag type
Definition: pathnodes.h:107
List * relationOids
Definition: pathnodes.h:125

◆ extract_query_dependencies()

void extract_query_dependencies ( Node query,
List **  relationOids,
List **  invalItems,
bool hasRowSecurity 
)

Definition at line 2758 of file setrefs.c.

References PlannerGlobal::dependsOnRole, extract_query_dependencies_walker(), PlannerInfo::glob, PlannerGlobal::invalItems, MemSet, NIL, PlannerGlobal::relationOids, T_PlannerGlobal, T_PlannerInfo, PlannerGlobal::type, and PlannerInfo::type.

Referenced by CompleteCachedPlan(), and RevalidateCachedQuery().

2762 {
2763  PlannerGlobal glob;
2764  PlannerInfo root;
2765 
2766  /* Make up dummy planner state so we can use this module's machinery */
2767  MemSet(&glob, 0, sizeof(glob));
2768  glob.type = T_PlannerGlobal;
2769  glob.relationOids = NIL;
2770  glob.invalItems = NIL;
2771  /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
2772  glob.dependsOnRole = false;
2773 
2774  MemSet(&root, 0, sizeof(root));
2775  root.type = T_PlannerInfo;
2776  root.glob = &glob;
2777 
2778  (void) extract_query_dependencies_walker(query, &root);
2779 
2780  *relationOids = glob.relationOids;
2781  *invalItems = glob.invalItems;
2782  *hasRowSecurity = glob.dependsOnRole;
2783 }
#define NIL
Definition: pg_list.h:65
#define MemSet(start, val, len)
Definition: c.h:956
bool dependsOnRole
Definition: pathnodes.h:139
PlannerGlobal * glob
Definition: pathnodes.h:179
List * invalItems
Definition: pathnodes.h:127
NodeTag type
Definition: pathnodes.h:175
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:2794
NodeTag type
Definition: pathnodes.h:107
List * relationOids
Definition: pathnodes.h:125

◆ flatten_join_alias_vars()

Node* flatten_join_alias_vars ( Query query,
Node node 
)

Definition at line 670 of file var.c.

References flatten_join_alias_vars_mutator(), Query::hasSubLinks, flatten_join_alias_vars_context::inserted_sublink, flatten_join_alias_vars_context::possible_sublink, flatten_join_alias_vars_context::query, and flatten_join_alias_vars_context::sublevels_up.

Referenced by finalize_grouping_exprs_walker(), parseCheckAggregates(), preprocess_expression(), pull_up_simple_subquery(), and subquery_planner().

671 {
673 
674  context.query = query;
675  context.sublevels_up = 0;
676  /* flag whether join aliases could possibly contain SubLinks */
677  context.possible_sublink = query->hasSubLinks;
678  /* if hasSubLinks is already true, no need to work hard */
679  context.inserted_sublink = query->hasSubLinks;
680 
681  return flatten_join_alias_vars_mutator(node, &context);
682 }
bool hasSubLinks
Definition: parsenodes.h:128
static Node * flatten_join_alias_vars_mutator(Node *node, flatten_join_alias_vars_context *context)
Definition: var.c:685

◆ get_sortgroupclause_expr()

Node* get_sortgroupclause_expr ( SortGroupClause sgClause,
List targetList 
)

Definition at line 401 of file tlist.c.

References TargetEntry::expr, and get_sortgroupclause_tle().

Referenced by get_sortgrouplist_exprs(), make_pathkeys_for_sortclauses(), transformAggregateCall(), and transformWindowDefinitions().

402 {
403  TargetEntry *tle = get_sortgroupclause_tle(sgClause, targetList);
404 
405  return (Node *) tle->expr;
406 }
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:389
Definition: nodes.h:525
Expr * expr
Definition: primnodes.h:1393

◆ get_sortgroupclause_tle()

◆ get_sortgrouplist_exprs()

List* get_sortgrouplist_exprs ( List sgClauses,
List targetList 
)

Definition at line 414 of file tlist.c.

References get_sortgroupclause_expr(), lappend(), lfirst, and NIL.

Referenced by create_distinct_paths(), estimate_path_cost_size(), get_number_of_groups(), and group_by_has_partkey().

415 {
416  List *result = NIL;
417  ListCell *l;
418 
419  foreach(l, sgClauses)
420  {
421  SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
422  Node *sortexpr;
423 
424  sortexpr = get_sortgroupclause_expr(sortcl, targetList);
425  result = lappend(result, sortexpr);
426  }
427  return result;
428 }
#define NIL
Definition: pg_list.h:65
Node * get_sortgroupclause_expr(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:401
Definition: nodes.h:525
List * lappend(List *list, void *datum)
Definition: list.c:322
#define lfirst(lc)
Definition: pg_list.h:190
Definition: pg_list.h:50

◆ get_sortgroupref_clause()

SortGroupClause* get_sortgroupref_clause ( Index  sortref,
List clauses 
)

Definition at line 444 of file tlist.c.

References elog, ERROR, lfirst, and SortGroupClause::tleSortGroupRef.

Referenced by preprocess_groupclause().

445 {
446  ListCell *l;
447 
448  foreach(l, clauses)
449  {
451 
452  if (cl->tleSortGroupRef == sortref)
453  return cl;
454  }
455 
456  elog(ERROR, "ORDER/GROUP BY expression not found in list");
457  return NULL; /* keep compiler quiet */
458 }
Index tleSortGroupRef
Definition: parsenodes.h:1234
#define ERROR
Definition: elog.h:43
#define lfirst(lc)
Definition: pg_list.h:190
#define elog(elevel,...)
Definition: elog.h:228

◆ get_sortgroupref_clause_noerr()

SortGroupClause* get_sortgroupref_clause_noerr ( Index  sortref,
List clauses 
)

Definition at line 465 of file tlist.c.

References lfirst, and SortGroupClause::tleSortGroupRef.

Referenced by find_em_expr_for_input_target(), foreign_grouping_ok(), make_group_input_target(), and make_partial_grouping_target().

466 {
467  ListCell *l;
468 
469  foreach(l, clauses)
470  {
472 
473  if (cl->tleSortGroupRef == sortref)
474  return cl;
475  }
476 
477  return NULL;
478 }
Index tleSortGroupRef
Definition: parsenodes.h:1234
#define lfirst(lc)
Definition: pg_list.h:190

◆ get_sortgroupref_tle()

TargetEntry* get_sortgroupref_tle ( Index  sortref,
List targetList 
)

Definition at line 367 of file tlist.c.

References elog, ERROR, lfirst, and TargetEntry::ressortgroupref.

Referenced by convert_subquery_pathkeys(), deparseSortGroupClause(), foreign_expr_walker(), get_rule_sortgroupclause(), get_sortgroupclause_tle(), make_unique_from_pathkeys(), prepare_sort_from_pathkeys(), and transformDistinctOnClause().

368 {
369  ListCell *l;
370 
371  foreach(l, targetList)
372  {
373  TargetEntry *tle = (TargetEntry *) lfirst(l);
374 
375  if (tle->ressortgroupref == sortref)
376  return tle;
377  }
378 
379  elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
380  return NULL; /* keep compiler quiet */
381 }
#define ERROR
Definition: elog.h:43
#define lfirst(lc)
Definition: pg_list.h:190
#define elog(elevel,...)
Definition: elog.h:228
Index ressortgroupref
Definition: primnodes.h:1396

◆ is_pseudo_constant_for_index()

bool is_pseudo_constant_for_index ( Node expr,
IndexOptInfo index 
)

Definition at line 3891 of file indxpath.c.

References bms_is_member(), contain_volatile_functions(), pull_varnos(), IndexOptInfo::rel, and RelOptInfo::relid.

3892 {
3893  /* pull_varnos is cheaper than volatility check, so do that first */
3894  if (bms_is_member(index->rel->relid, pull_varnos(expr)))
3895  return false; /* no good, contains Var of table */
3896  if (contain_volatile_functions(expr))
3897  return false; /* no good, volatile comparison value */
3898  return true;
3899 }
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:724
RelOptInfo * rel
Definition: pathnodes.h:791
Relids pull_varnos(Node *node)
Definition: var.c:95
Index relid
Definition: pathnodes.h:669
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427

◆ locate_var_of_level()

int locate_var_of_level ( Node node,
int  levelsup 
)

Definition at line 437 of file var.c.

References locate_var_of_level_walker(), query_or_expression_tree_walker(), locate_var_of_level_context::sublevels_up, and locate_var_of_level_context::var_location.

Referenced by check_agg_arguments(), checkExprIsVarFree(), and transformSetOperationTree().

438 {
440 
441  context.var_location = -1; /* in case we find nothing */
442  context.sublevels_up = levelsup;
443 
446  (void *) &context,
447  0);
448 
449  return context.var_location;
450 }
bool query_or_expression_tree_walker(Node *node, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:3347
static bool locate_var_of_level_walker(Node *node, locate_var_of_level_context *context)
Definition: var.c:453

◆ negate_clause()

Node* negate_clause ( Node node)

Definition at line 74 of file prepqual.c.

References AND_EXPR, NullTest::arg, BooleanTest::arg, NullTest::argisrow, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, Const::constisnull, Const::constvalue, DatumGetBool, elog, ERROR, get_negator(), OpExpr::inputcollid, ScalarArrayOpExpr::inputcollid, InvalidOid, IS_FALSE, IS_NOT_FALSE, IS_NOT_NULL, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_NULL, IS_TRUE, IS_UNKNOWN, lappend(), lfirst, linitial, OpExpr::location, ScalarArrayOpExpr::location, NullTest::location, BooleanTest::location, make_andclause(), make_notclause(), make_orclause(), makeBoolConst(), makeNode, negate_clause(), NIL, nodeTag, NOT_EXPR, NullTest::nulltesttype, OpExpr::opcollid, OpExpr::opfuncid, ScalarArrayOpExpr::opfuncid, OpExpr::opno, ScalarArrayOpExpr::opno, OpExpr::opresulttype, OpExpr::opretset, OR_EXPR, T_BooleanTest, T_BoolExpr, T_Const, T_NullTest, T_OpExpr, T_ScalarArrayOpExpr, and ScalarArrayOpExpr::useOr.

Referenced by eval_const_expressions_mutator(), match_boolean_partition_clause(), negate_clause(), and simplify_boolean_equality().

75 {
76  if (node == NULL) /* should not happen */
77  elog(ERROR, "can't negate an empty subexpression");
78  switch (nodeTag(node))
79  {
80  case T_Const:
81  {
82  Const *c = (Const *) node;
83 
84  /* NOT NULL is still NULL */
85  if (c->constisnull)
86  return makeBoolConst(false, true);
87  /* otherwise pretty easy */
88  return makeBoolConst(!DatumGetBool(c->constvalue), false);
89  }
90  break;
91  case T_OpExpr:
92  {
93  /*
94  * Negate operator if possible: (NOT (< A B)) => (>= A B)
95  */
96  OpExpr *opexpr = (OpExpr *) node;
97  Oid negator = get_negator(opexpr->opno);
98 
99  if (negator)
100  {
101  OpExpr *newopexpr = makeNode(OpExpr);
102 
103  newopexpr->opno = negator;
104  newopexpr->opfuncid = InvalidOid;
105  newopexpr->opresulttype = opexpr->opresulttype;
106  newopexpr->opretset = opexpr->opretset;
107  newopexpr->opcollid = opexpr->opcollid;
108  newopexpr->inputcollid = opexpr->inputcollid;
109  newopexpr->args = opexpr->args;
110  newopexpr->location = opexpr->location;
111  return (Node *) newopexpr;
112  }
113  }
114  break;
115  case T_ScalarArrayOpExpr:
116  {
117  /*
118  * Negate a ScalarArrayOpExpr if its operator has a negator;
119  * for example x = ANY (list) becomes x <> ALL (list)
120  */
121  ScalarArrayOpExpr *saopexpr = (ScalarArrayOpExpr *) node;
122  Oid negator = get_negator(saopexpr->opno);
123 
124  if (negator)
125  {
127 
128  newopexpr->opno = negator;
129  newopexpr->opfuncid = InvalidOid;
130  newopexpr->useOr = !saopexpr->useOr;
131  newopexpr->inputcollid = saopexpr->inputcollid;
132  newopexpr->args = saopexpr->args;
133  newopexpr->location = saopexpr->location;
134  return (Node *) newopexpr;
135  }
136  }
137  break;
138  case T_BoolExpr:
139  {
140  BoolExpr *expr = (BoolExpr *) node;
141 
142  switch (expr->boolop)
143  {
144  /*--------------------
145  * Apply DeMorgan's Laws:
146  * (NOT (AND A B)) => (OR (NOT A) (NOT B))
147  * (NOT (OR A B)) => (AND (NOT A) (NOT B))
148  * i.e., swap AND for OR and negate each subclause.
149  *
150  * If the input is already AND/OR flat and has no NOT
151  * directly above AND or OR, this transformation preserves
152  * those properties. For example, if no direct child of
153  * the given AND clause is an AND or a NOT-above-OR, then
154  * the recursive calls of negate_clause() can't return any
155  * OR clauses. So we needn't call pull_ors() before
156  * building a new OR clause. Similarly for the OR case.
157  *--------------------
158  */
159  case AND_EXPR:
160  {
161  List *nargs = NIL;
162  ListCell *lc;
163 
164  foreach(lc, expr->args)
165  {
166  nargs = lappend(nargs,
167  negate_clause(lfirst(lc)));
168  }
169  return (Node *) make_orclause(nargs);
170  }
171  break;
172  case OR_EXPR:
173  {
174  List *nargs = NIL;
175  ListCell *lc;
176 
177  foreach(lc, expr->args)
178  {
179  nargs = lappend(nargs,
180  negate_clause(lfirst(lc)));
181  }
182  return (Node *) make_andclause(nargs);
183  }
184  break;
185  case NOT_EXPR:
186 
187  /*
188  * NOT underneath NOT: they cancel. We assume the
189  * input is already simplified, so no need to recurse.
190  */
191  return (Node *) linitial(expr->args);
192  default:
193  elog(ERROR, "unrecognized boolop: %d",
194  (int) expr->boolop);
195  break;
196  }
197  }
198  break;
199  case T_NullTest:
200  {
201  NullTest *expr = (NullTest *) node;
202 
203  /*
204  * In the rowtype case, the two flavors of NullTest are *not*
205  * logical inverses, so we can't simplify. But it does work
206  * for scalar datatypes.
207  */
208  if (!expr->argisrow)
209  {
210  NullTest *newexpr = makeNode(NullTest);
211 
212  newexpr->arg = expr->arg;
213  newexpr->nulltesttype = (expr->nulltesttype == IS_NULL ?
214  IS_NOT_NULL : IS_NULL);
215  newexpr->argisrow = expr->argisrow;
216  newexpr->location = expr->location;
217  return (Node *) newexpr;
218  }
219  }
220  break;
221  case T_BooleanTest:
222  {
223  BooleanTest *expr = (BooleanTest *) node;
224  BooleanTest *newexpr = makeNode(BooleanTest);
225 
226  newexpr->arg = expr->arg;
227  switch (expr->booltesttype)
228  {
229  case IS_TRUE:
230  newexpr->booltesttype = IS_NOT_TRUE;
231  break;
232  case IS_NOT_TRUE:
233  newexpr->booltesttype = IS_TRUE;
234  break;
235  case IS_FALSE:
236  newexpr->booltesttype = IS_NOT_FALSE;
237  break;
238  case IS_NOT_FALSE:
239  newexpr->booltesttype = IS_FALSE;
240  break;
241  case IS_UNKNOWN:
242  newexpr->booltesttype = IS_NOT_UNKNOWN;
243  break;
244  case IS_NOT_UNKNOWN:
245  newexpr->booltesttype = IS_UNKNOWN;
246  break;
247  default:
248  elog(ERROR, "unrecognized booltesttype: %d",
249  (int) expr->booltesttype);
250  break;
251  }
252  newexpr->location = expr->location;
253  return (Node *) newexpr;
254  }
255  break;
256  default:
257  /* else fall through */
258  break;
259  }
260 
261  /*
262  * Otherwise we don't know how to simplify this, so just tack on an
263  * explicit NOT node.
264  */
265  return (Node *) make_notclause((Expr *) node);
266 }
Datum constvalue
Definition: primnodes.h:200
#define NIL
Definition: pg_list.h:65
Expr * make_notclause(Expr *notclause)
Definition: makefuncs.c:665
Node * negate_clause(Node *node)
Definition: prepqual.c:74
Definition: nodes.h:525
unsigned int Oid
Definition: postgres_ext.h:31
Expr * make_orclause(List *orclauses)
Definition: makefuncs.c:649
Oid opresulttype
Definition: primnodes.h:504
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:568
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:355
Expr * arg
Definition: primnodes.h:1205
char * c
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:633
int location
Definition: primnodes.h:509
Expr * arg
Definition: primnodes.h:1228
#define DatumGetBool(X)
Definition: postgres.h:393
Oid opcollid
Definition: primnodes.h:506
Definition: nodes.h:152
List * lappend(List *list, void *datum)
Definition: list.c:322
BoolTestType booltesttype
Definition: primnodes.h:1229
Oid opfuncid
Definition: primnodes.h:503
NullTestType nulltesttype
Definition: primnodes.h:1206
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:573
#define lfirst(lc)
Definition: pg_list.h:190
int location
Definition: primnodes.h:1208
Oid inputcollid
Definition: primnodes.h:507
List * args
Definition: primnodes.h:569
#define nodeTag(nodeptr)
Definition: nodes.h:530
#define elog(elevel,...)
Definition: elog.h:228
bool argisrow
Definition: primnodes.h:1207
Oid opno
Definition: primnodes.h:502
Oid get_negator(Oid opno)
Definition: lsyscache.c:1335
List * args
Definition: primnodes.h:508
Definition: pg_list.h:50
bool constisnull
Definition: primnodes.h:201
bool opretset
Definition: primnodes.h:505

◆ plan_cluster_use_sort()

bool plan_cluster_use_sort ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 6125 of file planner.c.

References AccessShareLock, build_simple_rel(), CMD_SELECT, Query::commandType, cost_qual_eval(), cost_sort(), create_index_path(), create_seqscan_path(), CurrentMemoryContext, enable_indexscan, ForwardScanDirection, get_relation_data_width(), PlannerInfo::glob, RelOptInfo::indexlist, IndexOptInfo::indexoid, IndexOptInfo::indexprs, RangeTblEntry::inFromCl, RangeTblEntry::inh, RangeTblEntry::lateral, lfirst_node, list_make1, maintenance_work_mem, makeNode, NIL, RelOptInfo::pages, PlannerInfo::parse, IndexPath::path, QualCost::per_tuple, PlannerInfo::planner_cxt, PlannerInfo::query_level, RangeTblEntry::relid, RangeTblEntry::relkind, RangeTblEntry::rellockmode, RelOptInfo::reltarget, RelOptInfo::rows, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, setup_simple_rel_arrays(), QualCost::startup, Path::total_cost, PlannerInfo::total_table_pages, RelOptInfo::tuples, PathTarget::width, and PlannerInfo::wt_param_id.

Referenced by copy_table_data().

6126 {
6127  PlannerInfo *root;
6128  Query *query;
6129  PlannerGlobal *glob;
6130  RangeTblEntry *rte;
6131  RelOptInfo *rel;
6132  IndexOptInfo *indexInfo;
6133  QualCost indexExprCost;
6134  Cost comparisonCost;
6135  Path *seqScanPath;
6136  Path seqScanAndSortPath;
6137  IndexPath *indexScanPath;
6138  ListCell *lc;
6139 
6140  /* We can short-circuit the cost comparison if indexscans are disabled */
6141  if (!enable_indexscan)
6142  return true; /* use sort */
6143 
6144  /* Set up mostly-dummy planner state */
6145  query = makeNode(Query);
6146  query->commandType = CMD_SELECT;
6147 
6148  glob = makeNode(PlannerGlobal);
6149 
6150  root = makeNode(PlannerInfo);
6151  root->parse = query;
6152  root->glob = glob;
6153  root->query_level = 1;
6155  root->wt_param_id = -1;
6156 
6157  /* Build a minimal RTE for the rel */
6158  rte = makeNode(RangeTblEntry);
6159  rte->rtekind = RTE_RELATION;
6160  rte->relid = tableOid;
6161  rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
6163  rte->lateral = false;
6164  rte->inh = false;
6165  rte->inFromCl = true;
6166  query->rtable = list_make1(rte);
6167 
6168  /* Set up RTE/RelOptInfo arrays */
6170 
6171  /* Build RelOptInfo */
6172  rel = build_simple_rel(root, 1, NULL);
6173 
6174  /* Locate IndexOptInfo for the target index */
6175  indexInfo = NULL;
6176  foreach(lc, rel->indexlist)
6177  {
6178  indexInfo = lfirst_node(IndexOptInfo, lc);
6179  if (indexInfo->indexoid == indexOid)
6180  break;
6181  }
6182 
6183  /*
6184  * It's possible that get_relation_info did not generate an IndexOptInfo
6185  * for the desired index; this could happen if it's not yet reached its
6186  * indcheckxmin usability horizon, or if it's a system index and we're
6187  * ignoring system indexes. In such cases we should tell CLUSTER to not
6188  * trust the index contents but use seqscan-and-sort.
6189  */
6190  if (lc == NULL) /* not in the list? */
6191  return true; /* use sort */
6192 
6193  /*
6194  * Rather than doing all the pushups that would be needed to use
6195  * set_baserel_size_estimates, just do a quick hack for rows and width.
6196  */
6197  rel->rows = rel->tuples;
6198  rel->reltarget->width = get_relation_data_width(tableOid, NULL);
6199 
6200  root->total_table_pages = rel->pages;
6201 
6202  /*
6203  * Determine eval cost of the index expressions, if any. We need to
6204  * charge twice that amount for each tuple comparison that happens during
6205  * the sort, since tuplesort.c will have to re-evaluate the index
6206  * expressions each time. (XXX that's pretty inefficient...)
6207  */
6208  cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
6209  comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
6210 
6211  /* Estimate the cost of seq scan + sort */
6212  seqScanPath = create_seqscan_path(root, rel, NULL, 0);
6213  cost_sort(&seqScanAndSortPath, root, NIL,
6214  seqScanPath->total_cost, rel->tuples, rel->reltarget->width,
6215  comparisonCost, maintenance_work_mem, -1.0);
6216 
6217  /* Estimate the cost of index scan */
6218  indexScanPath = create_index_path(root, indexInfo,
6219  NIL, NIL, NIL, NIL,
6220  ForwardScanDirection, false,
6221  NULL, 1.0, false);
6222 
6223  return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
6224 }
#define NIL
Definition: pg_list.h:65
Query * parse
Definition: pathnodes.h:177
Path path
Definition: pathnodes.h:1176
double tuples
Definition: pathnodes.h:681
#define AccessShareLock
Definition: lockdefs.h:36
Cost startup
Definition: pathnodes.h:45
#define list_make1(x1)
Definition: pg_list.h:227
Cost per_tuple
Definition: pathnodes.h:46
int wt_param_id
Definition: pathnodes.h:351
List * rtable
Definition: parsenodes.h:137
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:3819
#define lfirst_node(type, lc)
Definition: pg_list.h:193
IndexPath * create_index_path(PlannerInfo *root, IndexOptInfo *index, List *indexclauses, List *indexorderbys, List *indexorderbycols, List *pathkeys, ScanDirection indexscandir, bool indexonly, Relids required_outer, double loop_count, bool partial_path)
Definition: pathnode.c:997
PlannerGlobal * glob
Definition: pathnodes.h:179
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:185
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
double total_table_pages
Definition: pathnodes.h:331
int32 get_relation_data_width(Oid relid, int32 *attr_widths)
Definition: plancat.c:1129
void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:1693
List * indexlist
Definition: pathnodes.h:678
double rows
Definition: pathnodes.h:644
int maintenance_work_mem
Definition: globals.c:122
Cost total_cost
Definition: pathnodes.h:1126
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:573
BlockNumber pages
Definition: pathnodes.h:680
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:74
Index query_level
Definition: pathnodes.h:181
RTEKind rtekind
Definition: parsenodes.h:974
MemoryContext planner_cxt
Definition: pathnodes.h:329
struct PathTarget * reltarget
Definition: pathnodes.h:652
bool enable_indexscan
Definition: costsize.c:125
Path * create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer, int parallel_workers)
Definition: pathnode.c:929
double Cost
Definition: nodes.h:659
List * indexprs
Definition: pathnodes.h:813

◆ plan_create_index_workers()

int plan_create_index_workers ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 6243 of file planner.c.

References AccessShareLock, build_simple_rel(), CMD_SELECT, Query::commandType, compute_parallel_worker(), CurrentMemoryContext, estimate_rel_size(), PlannerInfo::glob, index_close(), index_open(), RangeTblEntry::inFromCl, RangeTblEntry::inh, is_parallel_safe(), RangeTblEntry::lateral, list_make1, maintenance_work_mem, makeNode, max_parallel_maintenance_workers, Min, NoLock, PlannerInfo::parse, PlannerInfo::planner_cxt, PlannerInfo::query_level, RelationData::rd_rel, RelOptInfo::rel_parallel_workers, RelationGetIndexExpressions(), RelationGetIndexPredicate(), RangeTblEntry::relid, RangeTblEntry::relkind, RangeTblEntry::rellockmode, reltuples, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, setup_simple_rel_arrays(), table_close(), table_open(), and PlannerInfo::wt_param_id.

Referenced by index_build().

6244 {
6245  PlannerInfo *root;
6246  Query *query;
6247  PlannerGlobal *glob;
6248  RangeTblEntry *rte;
6249  Relation heap;
6250  Relation index;
6251  RelOptInfo *rel;
6252  int parallel_workers;
6253  BlockNumber heap_blocks;
6254  double reltuples;
6255  double allvisfrac;
6256 
6257  /* Return immediately when parallelism disabled */
6259  return 0;
6260 
6261  /* Set up largely-dummy planner state */
6262  query = makeNode(Query);
6263  query->commandType = CMD_SELECT;
6264 
6265  glob = makeNode(PlannerGlobal);
6266 
6267  root = makeNode(PlannerInfo);
6268  root->parse = query;
6269  root->glob = glob;
6270  root->query_level = 1;
6272  root->wt_param_id = -1;
6273 
6274  /*
6275  * Build a minimal RTE.
6276  *
6277  * Mark the RTE with inh = true. This is a kludge to prevent
6278  * get_relation_info() from fetching index info, which is necessary
6279  * because it does not expect that any IndexOptInfo is currently
6280  * undergoing REINDEX.
6281  */
6282  rte = makeNode(RangeTblEntry);
6283  rte->rtekind = RTE_RELATION;
6284  rte->relid = tableOid;
6285  rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
6287  rte->lateral = false;
6288  rte->inh = true;
6289  rte->inFromCl = true;
6290  query->rtable = list_make1(rte);
6291 
6292  /* Set up RTE/RelOptInfo arrays */
6294 
6295  /* Build RelOptInfo */
6296  rel = build_simple_rel(root, 1, NULL);
6297 
6298  /* Rels are assumed already locked by the caller */
6299  heap = table_open(tableOid, NoLock);
6300  index = index_open(indexOid, NoLock);
6301 
6302  /*
6303  * Determine if it's safe to proceed.
6304  *
6305  * Currently, parallel workers can't access the leader's temporary tables.
6306  * Furthermore, any index predicate or index expressions must be parallel
6307  * safe.
6308  */
6309  if (heap->rd_rel->relpersistence == RELPERSISTENCE_TEMP ||
6310  !is_parallel_safe(root, (Node *) RelationGetIndexExpressions(index)) ||
6311  !is_parallel_safe(root, (Node *) RelationGetIndexPredicate(index)))
6312  {
6313  parallel_workers = 0;
6314  goto done;
6315  }
6316 
6317  /*
6318  * If parallel_workers storage parameter is set for the table, accept that
6319  * as the number of parallel worker processes to launch (though still cap
6320  * at max_parallel_maintenance_workers). Note that we deliberately do not
6321  * consider any other factor when parallel_workers is set. (e.g., memory
6322  * use by workers.)
6323  */
6324  if (rel->rel_parallel_workers != -1)
6325  {
6326  parallel_workers = Min(rel->rel_parallel_workers,
6328  goto done;
6329  }
6330 
6331  /*
6332  * Estimate heap relation size ourselves, since rel->pages cannot be
6333  * trusted (heap RTE was marked as inheritance parent)
6334  */
6335  estimate_rel_size(heap, NULL, &heap_blocks, &reltuples, &allvisfrac);
6336 
6337  /*
6338  * Determine number of workers to scan the heap relation using generic
6339  * model
6340  */
6341  parallel_workers = compute_parallel_worker(rel, heap_blocks, -1,
6343 
6344  /*
6345  * Cap workers based on available maintenance_work_mem as needed.
6346  *
6347  * Note that each tuplesort participant receives an even share of the
6348  * total maintenance_work_mem budget. Aim to leave participants
6349  * (including the leader as a participant) with no less than 32MB of
6350  * memory. This leaves cases where maintenance_work_mem is set to 64MB
6351  * immediately past the threshold of being capable of launching a single
6352  * parallel worker to sort.
6353  */
6354  while (parallel_workers > 0 &&
6355  maintenance_work_mem / (parallel_workers + 1) < 32768L)
6356  parallel_workers--;
6357 
6358 done:
6359  index_close(index, NoLock);
6360  table_close(heap, NoLock);
6361 
6362  return parallel_workers;
6363 }
Query * parse
Definition: pathnodes.h:177
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
int compute_parallel_worker(RelOptInfo *rel, double heap_pages, double index_pages, int max_workers)
Definition: allpaths.c:3575
#define Min(x, y)
Definition: c.h:905
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:525
uint32 BlockNumber
Definition: block.h:31
Form_pg_class rd_rel
Definition: rel.h:83
List * RelationGetIndexPredicate(Relation relation)
Definition: relcache.c:4643
Definition: type.h:89
#define list_make1(x1)
Definition: pg_list.h:227
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:854
int wt_param_id
Definition: pathnodes.h:351
List * rtable
Definition: parsenodes.h:137
#define NoLock
Definition: lockdefs.h:34
List * RelationGetIndexExpressions(Relation relation)
Definition: relcache.c:4581
PlannerGlobal * glob
Definition: pathnodes.h:179
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:185
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void estimate_rel_size(Relation rel, int32 *attr_widths, BlockNumber *pages, double *tuples, double *allvisfrac)
Definition: plancat.c:946
int rel_parallel_workers
Definition: pathnodes.h:687
int max_parallel_maintenance_workers
Definition: globals.c:123
int maintenance_work_mem
Definition: globals.c:122
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:573
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:74
Index query_level
Definition: pathnodes.h:181
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:152
RTEKind rtekind
Definition: parsenodes.h:974
MemoryContext planner_cxt
Definition: pathnodes.h:329
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:126
float4 reltuples
Definition: pg_class.h:63

◆ planner()

struct PlannedStmt* planner ( Query parse,
int  cursorOptions,
struct ParamListInfoData boundParams 
)

◆ predicate_implied_by()

bool predicate_implied_by ( List predicate_list,
List clause_list,
bool  weak 
)

Definition at line 151 of file predtest.c.

References linitial, list_length(), NIL, and predicate_implied_by_recurse().

Referenced by add_predicate_to_index_quals(), build_paths_for_OR(), check_index_predicates(), choose_bitmap_and(), ConstraintImpliedByRelConstraint(), create_bitmap_scan_plan(), create_bitmap_subplan(), create_indexscan_plan(), infer_arbiter_indexes(), and test_predtest().

153 {
154  Node *p,
155  *c;
156 
157  if (predicate_list == NIL)
158  return true; /* no predicate: implication is vacuous */
159  if (clause_list == NIL)
160  return false; /* no restriction: implication must fail */
161 
162  /*
163  * If either input is a single-element list, replace it with its lone
164  * member; this avoids one useless level of AND-recursion. We only need
165  * to worry about this at top level, since eval_const_expressions should
166  * have gotten rid of any trivial ANDs or ORs below that.
167  */
168  if (list_length(predicate_list) == 1)
169  p = (Node *) linitial(predicate_list);
170  else
171  p = (Node *) predicate_list;
172  if (list_length(clause_list) == 1)
173  c = (Node *) linitial(clause_list);
174  else
175  c = (Node *) clause_list;
176 
177  /* And away we go ... */
178  return predicate_implied_by_recurse(c, p, weak);
179 }
#define NIL
Definition: pg_list.h:65
Definition: nodes.h:525
#define linitial(l)
Definition: pg_list.h:195
char * c
static int list_length(const List *l)
Definition: pg_list.h:169
static bool predicate_implied_by_recurse(Node *clause, Node *predicate, bool weak)
Definition: predtest.c:289

◆ predicate_refuted_by()

bool predicate_refuted_by ( List predicate_list,
List clause_list,
bool  weak 
)

Definition at line 221 of file predtest.c.

References linitial, list_length(), NIL, and predicate_refuted_by_recurse().

Referenced by gen_partprune_steps_internal(), relation_excluded_by_constraints(), and test_predtest().

223 {
224  Node *p,
225  *c;
226 
227  if (predicate_list == NIL)
228  return false; /* no predicate: no refutation is possible */
229  if (clause_list == NIL)
230  return false; /* no restriction: refutation must fail */
231 
232  /*
233  * If either input is a single-element list, replace it with its lone
234  * member; this avoids one useless level of AND-recursion. We only need
235  * to worry about this at top level, since eval_const_expressions should
236  * have gotten rid of any trivial ANDs or ORs below that.
237  */
238  if (list_length(predicate_list) == 1)
239  p = (Node *) linitial(predicate_list);
240  else
241  p = (Node *) predicate_list;
242  if (list_length(clause_list) == 1)
243  c = (Node *) linitial(clause_list);
244  else
245  c = (Node *) clause_list;
246 
247  /* And away we go ... */
248  return predicate_refuted_by_recurse(c, p, weak);
249 }
#define NIL
Definition: pg_list.h:65
Definition: nodes.h:525
#define linitial(l)
Definition: pg_list.h:195
char * c
static bool predicate_refuted_by_recurse(Node *clause, Node *predicate, bool weak)
Definition: predtest.c:530
static int list_length(const List *l)
Definition: pg_list.h:169

◆ pull_var_clause()

List* pull_var_clause ( Node node,
int  flags 
)

Definition at line 535 of file var.c.

References Assert, pull_var_clause_context::flags, NIL, pull_var_clause_walker(), PVC_INCLUDE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS, PVC_INCLUDE_WINDOWFUNCS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_PLACEHOLDERS, PVC_RECURSE_WINDOWFUNCS, and pull_var_clause_context::varlist.

Referenced by AddRelationNewConstraints(), build_base_rel_tlists(), build_remote_returning(), build_tlist_to_deparse(), CreateTrigger(), distribute_qual_to_rels(), estimate_num_groups(), find_placeholders_in_expr(), fix_placeholder_input_needed_levels(), foreign_grouping_ok(), generate_base_implied_equalities_no_const(), make_group_input_target(), make_partial_grouping_target(), make_sort_input_target(), make_window_input_target(), prepare_sort_from_pathkeys(), preprocess_targetlist(), qual_is_pushdown_safe(), and StoreRelCheck().

536 {
537  pull_var_clause_context context;
538 
539  /* Assert that caller has not specified inconsistent flags */
546 
547  context.varlist = NIL;
548  context.flags = flags;
549 
550  pull_var_clause_walker(node, &context);
551  return context.varlist;
552 }
#define NIL
Definition: pg_list.h:65
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:176
#define PVC_INCLUDE_AGGREGATES
Definition: optimizer.h:170
#define PVC_INCLUDE_WINDOWFUNCS
Definition: optimizer.h:172
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:174
#define Assert(condition)
Definition: c.h:733
static bool pull_var_clause_walker(Node *node, pull_var_clause_context *context)
Definition: var.c:555
#define PVC_RECURSE_WINDOWFUNCS
Definition: optimizer.h:173
#define PVC_RECURSE_AGGREGATES
Definition: optimizer.h:171

◆ pull_varattnos()

void pull_varattnos ( Node node,
Index  varno,
Bitmapset **  varattnos 
)

Definition at line 219 of file var.c.

References pull_varattnos_walker(), pull_varattnos_context::varattnos, and pull_varattnos_context::varno.

Referenced by check_index_only(), check_selective_binary_conversion(), ComputePartitionAttrs(), create_foreignscan_plan(), DefineIndex(), deparseReturningList(), has_partition_attrs(), postgresGetForeignRelSize(), RelationGetIndexAttrBitmap(), remove_unused_subquery_outputs(), and transformUpdateTargetList().

220 {
221  pull_varattnos_context context;
222 
223  context.varattnos = *varattnos;
224  context.varno = varno;
225 
226  (void) pull_varattnos_walker(node, &context);
227 
228  *varattnos = context.varattnos;
229 }
Bitmapset * varattnos
Definition: var.c:39
static bool pull_varattnos_walker(Node *node, pull_varattnos_context *context)
Definition: var.c:232

◆ pull_varnos()

Bitmapset* pull_varnos ( Node node)

Definition at line 95 of file var.c.

References pull_varnos_walker(), query_or_expression_tree_walker(), pull_varnos_context::sublevels_up, and pull_varnos_context::varnos.

Referenced by compute_semijoin_info(), convert_ANY_sublink_to_join(), convert_EXISTS_sublink_to_join(), distribute_qual_to_rels(), examine_variable(), expand_indexqual_rowcompare(), find_placeholder_info(), get_eclass_for_sort_expr(), is_pseudo_constant_for_index(), IsTidEqualAnyClause(), join_is_removable(), make_outerjoininfo(), make_restrictinfo_internal(), match_rowcompare_to_indexcol(), match_saopclause_to_indexcol(), NumRelids(), pullup_replace_vars_callback(), and reduce_outer_joins_pass2().

96 {
97  pull_varnos_context context;
98 
99  context.varnos = NULL;
100  context.sublevels_up = 0;
101 
102  /*
103  * Must be prepared to start with a Query or a bare expression tree; if
104  * it's a Query, we don't want to increment sublevels_up.
105  */
108  (void *) &context,
109  0);
110 
111  return context.varnos;
112 }
static bool pull_varnos_walker(Node *node, pull_varnos_context *context)
Definition: var.c:140
int sublevels_up
Definition: var.c:34
Relids varnos
Definition: var.c:33
bool query_or_expression_tree_walker(Node *node, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:3347

◆ pull_varnos_of_level()

Bitmapset* pull_varnos_of_level ( Node node,
int  levelsup 
)

Definition at line 120 of file var.c.

References pull_varnos_walker(), query_or_expression_tree_walker(), pull_varnos_context::sublevels_up, and pull_varnos_context::varnos.

Referenced by is_simple_subquery(), and jointree_contains_lateral_outer_refs().

121 {
122  pull_varnos_context context;
123 
124  context.varnos = NULL;
125  context.sublevels_up = levelsup;
126 
127  /*
128  * Must be prepared to start with a Query or a bare expression tree; if
129  * it's a Query, we don't want to increment sublevels_up.
130  */
133  (void *) &context,
134  0);
135 
136  return context.varnos;
137 }
static bool pull_varnos_walker(Node *node, pull_varnos_context *context)
Definition: var.c:140
int sublevels_up
Definition: var.c:34
Relids varnos
Definition: var.c:33
bool query_or_expression_tree_walker(Node *node, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:3347

◆ pull_vars_of_level()

List* pull_vars_of_level ( Node node,
int  levelsup 
)

Definition at line 263 of file var.c.

References NIL, pull_vars_walker(), query_or_expression_tree_walker(), pull_vars_context::sublevels_up, and pull_vars_context::vars.

Referenced by extract_lateral_references().

264 {
265  pull_vars_context context;
266 
267  context.vars = NIL;
268  context.sublevels_up = levelsup;
269 
270  /*
271  * Must be prepared to start with a Query or a bare expression tree; if
272  * it's a Query, we don't want to increment sublevels_up.
273  */
276  (void *) &context,
277  0);
278 
279  return context.vars;
280 }
int sublevels_up
Definition: var.c:46
#define NIL
Definition: pg_list.h:65
static bool pull_vars_walker(Node *node, pull_vars_context *context)
Definition: var.c:283
List * vars
Definition: var.c:45
bool query_or_expression_tree_walker(Node *node, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:3347

Variable Documentation

◆ cpu_index_tuple_cost

PGDLLIMPORT double cpu_index_tuple_cost

Definition at line 113 of file costsize.c.

Referenced by genericcostestimate(), and gincostestimate().

◆ cpu_operator_cost

◆ cpu_tuple_cost

◆ effective_cache_size

PGDLLIMPORT int effective_cache_size

Definition at line 118 of file costsize.c.

Referenced by gistBuildCallback(), gistInitBuffering(), and index_pages_fetched().

◆ force_parallel_mode

int force_parallel_mode

Definition at line 70 of file planner.c.

Referenced by HandleParallelMessage(), query_planner(), and standard_planner().

◆ parallel_leader_participation

bool parallel_leader_participation

Definition at line 71 of file planner.c.

Referenced by ExecGather(), ExecGatherMerge(), ExecInitGather(), and get_parallel_divisor().

◆ parallel_setup_cost

PGDLLIMPORT double parallel_setup_cost

Definition at line 116 of file costsize.c.

Referenced by cost_gather(), cost_gather_merge(), and standard_planner().

◆ parallel_tuple_cost

PGDLLIMPORT double parallel_tuple_cost

Definition at line 115 of file costsize.c.

Referenced by cost_gather(), cost_gather_merge(), and standard_planner().

◆ random_page_cost

PGDLLIMPORT double random_page_cost

Definition at line 111 of file costsize.c.

Referenced by cost_sort(), get_tablespace_page_costs(), and tablespace_reloptions().

◆ seq_page_cost