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  DebugParallelMode { DEBUG_PARALLEL_OFF , DEBUG_PARALLEL_ON , DEBUG_PARALLEL_REGRESS }
 

Functions

Selectivity clause_selectivity (PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
Selectivity clause_selectivity_ext (PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, bool use_extended_stats)
 
Selectivity clauselist_selectivity (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
 
Selectivity clauselist_selectivity_ext (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, bool use_extended_stats)
 
double clamp_row_est (double nrows)
 
int32 clamp_width_est (int64 tuple_width)
 
long clamp_cardinality_to_long (Cardinality x)
 
bool is_pseudo_constant_for_index (PlannerInfo *root, Node *expr, IndexOptInfo *index)
 
struct PlannedStmtplanner (Query *parse, const char *query_string, 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_mutable_functions_after_planning (Expr *expr)
 
bool contain_volatile_functions (Node *clause)
 
bool contain_volatile_functions_after_planning (Expr *expr)
 
bool contain_volatile_functions_not_nextval (Node *clause)
 
Nodeeval_const_expressions (PlannerInfo *root, Node *node)
 
void convert_saop_to_hashed_saop (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, bool include_out_arguments, 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 (PlannerInfo *root, Node *node)
 
Bitmapsetpull_varnos_of_level (PlannerInfo *root, 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 (PlannerInfo *root, 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 double recursive_worktable_factor
 
PGDLLIMPORT int effective_cache_size
 
PGDLLIMPORT int debug_parallel_query
 
PGDLLIMPORT 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 */

Definition at line 186 of file optimizer.h.

◆ PVC_INCLUDE_PLACEHOLDERS

#define PVC_INCLUDE_PLACEHOLDERS
Value:
0x0010 /* include PlaceHolderVars in
* output list */

Definition at line 190 of file optimizer.h.

◆ PVC_INCLUDE_WINDOWFUNCS

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

Definition at line 188 of file optimizer.h.

◆ PVC_RECURSE_AGGREGATES

#define PVC_RECURSE_AGGREGATES   0x0002 /* recurse into Aggref arguments */

Definition at line 187 of file optimizer.h.

◆ PVC_RECURSE_PLACEHOLDERS

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

Definition at line 191 of file optimizer.h.

◆ PVC_RECURSE_WINDOWFUNCS

#define PVC_RECURSE_WINDOWFUNCS   0x0008 /* recurse into WindowFunc arguments */

Definition at line 189 of file optimizer.h.

Typedef Documentation

◆ IndexOptInfo

typedef struct IndexOptInfo IndexOptInfo

Definition at line 1 of file optimizer.h.

◆ PlannerInfo

typedef struct PlannerInfo PlannerInfo

Definition at line 1 of file optimizer.h.

◆ SpecialJoinInfo

Definition at line 1 of file optimizer.h.

Enumeration Type Documentation

◆ DebugParallelMode

Enumerator
DEBUG_PARALLEL_OFF 
DEBUG_PARALLEL_ON 
DEBUG_PARALLEL_REGRESS 

Definition at line 104 of file optimizer.h.

105 {
DebugParallelMode
Definition: optimizer.h:105
@ DEBUG_PARALLEL_REGRESS
Definition: optimizer.h:108
@ DEBUG_PARALLEL_ON
Definition: optimizer.h:107
@ DEBUG_PARALLEL_OFF
Definition: optimizer.h:106

Function Documentation

◆ canonicalize_qual()

Expr* canonicalize_qual ( Expr qual,
bool  is_check 
)

Definition at line 293 of file prepqual.c.

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

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

◆ clamp_cardinality_to_long()

long clamp_cardinality_to_long ( Cardinality  x)

Definition at line 254 of file costsize.c.

255 {
256  /*
257  * Just for paranoia's sake, ensure we do something sane with negative or
258  * NaN values.
259  */
260  if (isnan(x))
261  return LONG_MAX;
262  if (x <= 0)
263  return 0;
264 
265  /*
266  * If "long" is 64 bits, then LONG_MAX cannot be represented exactly as a
267  * double. Casting it to double and back may well result in overflow due
268  * to rounding, so avoid doing that. We trust that any double value that
269  * compares strictly less than "(double) LONG_MAX" will cast to a
270  * representable "long" value.
271  */
272  return (x < (double) LONG_MAX) ? (long) x : LONG_MAX;
273 }
int x
Definition: isn.c:71

References x.

Referenced by buildSubPlanHash(), create_recursiveunion_plan(), create_setop_plan(), and make_agg().

◆ clamp_row_est()

double clamp_row_est ( double  nrows)

Definition at line 202 of file costsize.c.

203 {
204  /*
205  * Avoid infinite and NaN row estimates. Costs derived from such values
206  * are going to be useless. Also force the estimate to be at least one
207  * row, to make explain output look better and to avoid possible
208  * divide-by-zero when interpolating costs. Make it an integer, too.
209  */
210  if (nrows > MAXIMUM_ROWCOUNT || isnan(nrows))
211  nrows = MAXIMUM_ROWCOUNT;
212  else if (nrows <= 1.0)
213  nrows = 1.0;
214  else
215  nrows = rint(nrows);
216 
217  return nrows;
218 }
#define MAXIMUM_ROWCOUNT
Definition: costsize.c:117

References MAXIMUM_ROWCOUNT.

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(), cost_subqueryscan(), create_bitmap_subplan(), estimate_array_length(), 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(), get_windowclause_startup_tuples(), initial_cost_mergejoin(), set_baserel_size_estimates(), set_cte_size_estimates(), set_foreign_size(), system_rows_samplescangetsamplesize(), system_samplescangetsamplesize(), and system_time_samplescangetsamplesize().

◆ clamp_width_est()

int32 clamp_width_est ( int64  tuple_width)

Definition at line 231 of file costsize.c.

232 {
233  /*
234  * Anything more than MaxAllocSize is clearly bogus, since we could not
235  * create a tuple that large.
236  */
237  if (tuple_width > MaxAllocSize)
238  return (int32) MaxAllocSize;
239 
240  /*
241  * Unlike clamp_row_est, we just Assert that the value isn't negative,
242  * rather than masking such errors.
243  */
244  Assert(tuple_width >= 0);
245 
246  return (int32) tuple_width;
247 }
signed int int32
Definition: c.h:481
#define MaxAllocSize
Definition: memutils.h:40

References Assert(), and MaxAllocSize.

Referenced by add_placeholders_to_joinrel(), build_joinrel_tlist(), create_one_window_path(), get_rel_data_width(), set_pathtarget_cost_width(), and set_rel_width().

◆ clause_selectivity()

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

Definition at line 667 of file clausesel.c.

672 {
673  return clause_selectivity_ext(root, clause, varRelid,
674  jointype, sjinfo, true);
675 }
Selectivity clause_selectivity_ext(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, bool use_extended_stats)
Definition: clausesel.c:684

References clause_selectivity_ext().

Referenced by approx_tuple_count(), booltestsel(), consider_new_or_clause(), and get_foreign_key_join_selectivity().

◆ clause_selectivity_ext()

Selectivity clause_selectivity_ext ( PlannerInfo root,
Node clause,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo,
bool  use_extended_stats 
)

Definition at line 684 of file clausesel.c.

690 {
691  Selectivity s1 = 0.5; /* default for any unhandled clause type */
692  RestrictInfo *rinfo = NULL;
693  bool cacheable = false;
694 
695  if (clause == NULL) /* can this still happen? */
696  return s1;
697 
698  if (IsA(clause, RestrictInfo))
699  {
700  rinfo = (RestrictInfo *) clause;
701 
702  /*
703  * If the clause is marked pseudoconstant, then it will be used as a
704  * gating qual and should not affect selectivity estimates; hence
705  * return 1.0. The only exception is that a constant FALSE may be
706  * taken as having selectivity 0.0, since it will surely mean no rows
707  * out of the plan. This case is simple enough that we need not
708  * bother caching the result.
709  */
710  if (rinfo->pseudoconstant)
711  {
712  if (!IsA(rinfo->clause, Const))
713  return (Selectivity) 1.0;
714  }
715 
716  /*
717  * If possible, cache the result of the selectivity calculation for
718  * the clause. We can cache if varRelid is zero or the clause
719  * contains only vars of that relid --- otherwise varRelid will affect
720  * the result, so mustn't cache. Outer join quals might be examined
721  * with either their join's actual jointype or JOIN_INNER, so we need
722  * two cache variables to remember both cases. Note: we assume the
723  * result won't change if we are switching the input relations or
724  * considering a unique-ified case, so we only need one cache variable
725  * for all non-JOIN_INNER cases.
726  */
727  if (varRelid == 0 ||
728  rinfo->num_base_rels == 0 ||
729  (rinfo->num_base_rels == 1 &&
730  bms_is_member(varRelid, rinfo->clause_relids)))
731  {
732  /* Cacheable --- do we already have the result? */
733  if (jointype == JOIN_INNER)
734  {
735  if (rinfo->norm_selec >= 0)
736  return rinfo->norm_selec;
737  }
738  else
739  {
740  if (rinfo->outer_selec >= 0)
741  return rinfo->outer_selec;
742  }
743  cacheable = true;
744  }
745 
746  /*
747  * Proceed with examination of contained clause. If the clause is an
748  * OR-clause, we want to look at the variant with sub-RestrictInfos,
749  * so that per-subclause selectivities can be cached.
750  */
751  if (rinfo->orclause)
752  clause = (Node *) rinfo->orclause;
753  else
754  clause = (Node *) rinfo->clause;
755  }
756 
757  if (IsA(clause, Var))
758  {
759  Var *var = (Var *) clause;
760 
761  /*
762  * We probably shouldn't ever see an uplevel Var here, but if we do,
763  * return the default selectivity...
764  */
765  if (var->varlevelsup == 0 &&
766  (varRelid == 0 || varRelid == (int) var->varno))
767  {
768  /* Use the restriction selectivity function for a bool Var */
769  s1 = boolvarsel(root, (Node *) var, varRelid);
770  }
771  }
772  else if (IsA(clause, Const))
773  {
774  /* bool constant is pretty easy... */
775  Const *con = (Const *) clause;
776 
777  s1 = con->constisnull ? 0.0 :
778  DatumGetBool(con->constvalue) ? 1.0 : 0.0;
779  }
780  else if (IsA(clause, Param))
781  {
782  /* see if we can replace the Param */
783  Node *subst = estimate_expression_value(root, clause);
784 
785  if (IsA(subst, Const))
786  {
787  /* bool constant is pretty easy... */
788  Const *con = (Const *) subst;
789 
790  s1 = con->constisnull ? 0.0 :
791  DatumGetBool(con->constvalue) ? 1.0 : 0.0;
792  }
793  else
794  {
795  /* XXX any way to do better than default? */
796  }
797  }
798  else if (is_notclause(clause))
799  {
800  /* inverse of the selectivity of the underlying clause */
801  s1 = 1.0 - clause_selectivity_ext(root,
802  (Node *) get_notclausearg((Expr *) clause),
803  varRelid,
804  jointype,
805  sjinfo,
806  use_extended_stats);
807  }
808  else if (is_andclause(clause))
809  {
810  /* share code with clauselist_selectivity() */
812  ((BoolExpr *) clause)->args,
813  varRelid,
814  jointype,
815  sjinfo,
816  use_extended_stats);
817  }
818  else if (is_orclause(clause))
819  {
820  /*
821  * Almost the same thing as clauselist_selectivity, but with the
822  * clauses connected by OR.
823  */
825  ((BoolExpr *) clause)->args,
826  varRelid,
827  jointype,
828  sjinfo,
829  use_extended_stats);
830  }
831  else if (is_opclause(clause) || IsA(clause, DistinctExpr))
832  {
833  OpExpr *opclause = (OpExpr *) clause;
834  Oid opno = opclause->opno;
835 
836  if (treat_as_join_clause(root, clause, rinfo, varRelid, sjinfo))
837  {
838  /* Estimate selectivity for a join clause. */
839  s1 = join_selectivity(root, opno,
840  opclause->args,
841  opclause->inputcollid,
842  jointype,
843  sjinfo);
844  }
845  else
846  {
847  /* Estimate selectivity for a restriction clause. */
848  s1 = restriction_selectivity(root, opno,
849  opclause->args,
850  opclause->inputcollid,
851  varRelid);
852  }
853 
854  /*
855  * DistinctExpr has the same representation as OpExpr, but the
856  * contained operator is "=" not "<>", so we must negate the result.
857  * This estimation method doesn't give the right behavior for nulls,
858  * but it's better than doing nothing.
859  */
860  if (IsA(clause, DistinctExpr))
861  s1 = 1.0 - s1;
862  }
863  else if (is_funcclause(clause))
864  {
865  FuncExpr *funcclause = (FuncExpr *) clause;
866 
867  /* Try to get an estimate from the support function, if any */
868  s1 = function_selectivity(root,
869  funcclause->funcid,
870  funcclause->args,
871  funcclause->inputcollid,
872  treat_as_join_clause(root, clause, rinfo,
873  varRelid, sjinfo),
874  varRelid,
875  jointype,
876  sjinfo);
877  }
878  else if (IsA(clause, ScalarArrayOpExpr))
879  {
880  /* Use node specific selectivity calculation function */
881  s1 = scalararraysel(root,
882  (ScalarArrayOpExpr *) clause,
883  treat_as_join_clause(root, clause, rinfo,
884  varRelid, sjinfo),
885  varRelid,
886  jointype,
887  sjinfo);
888  }
889  else if (IsA(clause, RowCompareExpr))
890  {
891  /* Use node specific selectivity calculation function */
892  s1 = rowcomparesel(root,
893  (RowCompareExpr *) clause,
894  varRelid,
895  jointype,
896  sjinfo);
897  }
898  else if (IsA(clause, NullTest))
899  {
900  /* Use node specific selectivity calculation function */
901  s1 = nulltestsel(root,
902  ((NullTest *) clause)->nulltesttype,
903  (Node *) ((NullTest *) clause)->arg,
904  varRelid,
905  jointype,
906  sjinfo);
907  }
908  else if (IsA(clause, BooleanTest))
909  {
910  /* Use node specific selectivity calculation function */
911  s1 = booltestsel(root,
912  ((BooleanTest *) clause)->booltesttype,
913  (Node *) ((BooleanTest *) clause)->arg,
914  varRelid,
915  jointype,
916  sjinfo);
917  }
918  else if (IsA(clause, CurrentOfExpr))
919  {
920  /* CURRENT OF selects at most one row of its table */
921  CurrentOfExpr *cexpr = (CurrentOfExpr *) clause;
922  RelOptInfo *crel = find_base_rel(root, cexpr->cvarno);
923 
924  if (crel->tuples > 0)
925  s1 = 1.0 / crel->tuples;
926  }
927  else if (IsA(clause, RelabelType))
928  {
929  /* Not sure this case is needed, but it can't hurt */
930  s1 = clause_selectivity_ext(root,
931  (Node *) ((RelabelType *) clause)->arg,
932  varRelid,
933  jointype,
934  sjinfo,
935  use_extended_stats);
936  }
937  else if (IsA(clause, CoerceToDomain))
938  {
939  /* Not sure this case is needed, but it can't hurt */
940  s1 = clause_selectivity_ext(root,
941  (Node *) ((CoerceToDomain *) clause)->arg,
942  varRelid,
943  jointype,
944  sjinfo,
945  use_extended_stats);
946  }
947  else
948  {
949  /*
950  * For anything else, see if we can consider it as a boolean variable.
951  * This only works if it's an immutable expression in Vars of a single
952  * relation; but there's no point in us checking that here because
953  * boolvarsel() will do it internally, and return a suitable default
954  * selectivity if not.
955  */
956  s1 = boolvarsel(root, clause, varRelid);
957  }
958 
959  /* Cache the result if possible */
960  if (cacheable)
961  {
962  if (jointype == JOIN_INNER)
963  rinfo->norm_selec = s1;
964  else
965  rinfo->outer_selec = s1;
966  }
967 
968 #ifdef SELECTIVITY_DEBUG
969  elog(DEBUG4, "clause_selectivity: s1 %f", s1);
970 #endif /* SELECTIVITY_DEBUG */
971 
972  return s1;
973 }
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2375
Selectivity clauselist_selectivity_ext(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, bool use_extended_stats)
Definition: clausesel.c:117
static bool treat_as_join_clause(PlannerInfo *root, Node *clause, RestrictInfo *rinfo, int varRelid, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:586
static Selectivity clauselist_selectivity_or(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, bool use_extended_stats)
Definition: clausesel.c:359
#define elog(elevel,...)
Definition: elog.h:224
#define DEBUG4
Definition: elog.h:27
static bool is_andclause(const void *clause)
Definition: nodeFuncs.h:105
static Expr * get_notclausearg(const void *notclause)
Definition: nodeFuncs.h:132
static bool is_orclause(const void *clause)
Definition: nodeFuncs.h:114
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:74
static bool is_funcclause(const void *clause)
Definition: nodeFuncs.h:67
static bool is_notclause(const void *clause)
Definition: nodeFuncs.h:123
double Selectivity
Definition: nodes.h:240
@ JOIN_INNER
Definition: nodes.h:283
void * arg
Selectivity restriction_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, int varRelid)
Definition: plancat.c:1919
Selectivity join_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: plancat.c:1958
Selectivity function_selectivity(PlannerInfo *root, Oid funcid, List *args, Oid inputcollid, bool is_join, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: plancat.c:1999
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
unsigned int Oid
Definition: postgres_ext.h:31
char * s1
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:407
Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1540
Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1698
Selectivity boolvarsel(PlannerInfo *root, Node *arg, int varRelid)
Definition: selfuncs.c:1512
Selectivity scalararraysel(PlannerInfo *root, ScalarArrayOpExpr *clause, bool is_join_clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1816
Selectivity rowcomparesel(PlannerInfo *root, RowCompareExpr *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:2202
Oid funcid
Definition: primnodes.h:706
List * args
Definition: primnodes.h:724
Definition: nodes.h:129
Oid opno
Definition: primnodes.h:774
List * args
Definition: primnodes.h:792
Cardinality tuples
Definition: pathnodes.h:930
Expr * clause
Definition: pathnodes.h:2541
Definition: primnodes.h:234
int varno
Definition: primnodes.h:241
Index varlevelsup
Definition: primnodes.h:266

References arg, generate_unaccent_rules::args, FuncExpr::args, OpExpr::args, bms_is_member(), booltestsel(), boolvarsel(), RestrictInfo::clause, clauselist_selectivity_ext(), clauselist_selectivity_or(), CurrentOfExpr::cvarno, DatumGetBool(), DEBUG4, elog, estimate_expression_value(), find_base_rel(), FuncExpr::funcid, function_selectivity(), get_notclausearg(), is_andclause(), is_funcclause(), is_notclause(), is_opclause(), is_orclause(), IsA, JOIN_INNER, join_selectivity(), nulltestsel(), OpExpr::opno, restriction_selectivity(), rowcomparesel(), s1, scalararraysel(), treat_as_join_clause(), RelOptInfo::tuples, and RangeQueryClause::var.

Referenced by clause_selectivity(), clauselist_selectivity_ext(), clauselist_selectivity_or(), and statext_mcv_clauselist_selectivity().

◆ clauselist_selectivity()

◆ clauselist_selectivity_ext()

Selectivity clauselist_selectivity_ext ( PlannerInfo root,
List clauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo,
bool  use_extended_stats 
)

Definition at line 117 of file clausesel.c.

123 {
124  Selectivity s1 = 1.0;
125  RelOptInfo *rel;
126  Bitmapset *estimatedclauses = NULL;
127  RangeQueryClause *rqlist = NULL;
128  ListCell *l;
129  int listidx;
130 
131  /*
132  * If there's exactly one clause, just go directly to
133  * clause_selectivity_ext(). None of what we might do below is relevant.
134  */
135  if (list_length(clauses) == 1)
136  return clause_selectivity_ext(root, (Node *) linitial(clauses),
137  varRelid, jointype, sjinfo,
138  use_extended_stats);
139 
140  /*
141  * Determine if these clauses reference a single relation. If so, and if
142  * it has extended statistics, try to apply those.
143  */
144  rel = find_single_rel_for_clauses(root, clauses);
145  if (use_extended_stats && rel && rel->rtekind == RTE_RELATION && rel->statlist != NIL)
146  {
147  /*
148  * Estimate as many clauses as possible using extended statistics.
149  *
150  * 'estimatedclauses' is populated with the 0-based list position
151  * index of clauses estimated here, and that should be ignored below.
152  */
153  s1 = statext_clauselist_selectivity(root, clauses, varRelid,
154  jointype, sjinfo, rel,
155  &estimatedclauses, false);
156  }
157 
158  /*
159  * Apply normal selectivity estimates for remaining clauses. We'll be
160  * careful to skip any clauses which were already estimated above.
161  *
162  * Anything that doesn't look like a potential rangequery clause gets
163  * multiplied into s1 and forgotten. Anything that does gets inserted into
164  * an rqlist entry.
165  */
166  listidx = -1;
167  foreach(l, clauses)
168  {
169  Node *clause = (Node *) lfirst(l);
170  RestrictInfo *rinfo;
171  Selectivity s2;
172 
173  listidx++;
174 
175  /*
176  * Skip this clause if it's already been estimated by some other
177  * statistics above.
178  */
179  if (bms_is_member(listidx, estimatedclauses))
180  continue;
181 
182  /* Compute the selectivity of this clause in isolation */
183  s2 = clause_selectivity_ext(root, clause, varRelid, jointype, sjinfo,
184  use_extended_stats);
185 
186  /*
187  * Check for being passed a RestrictInfo.
188  *
189  * If it's a pseudoconstant RestrictInfo, then s2 is either 1.0 or
190  * 0.0; just use that rather than looking for range pairs.
191  */
192  if (IsA(clause, RestrictInfo))
193  {
194  rinfo = (RestrictInfo *) clause;
195  if (rinfo->pseudoconstant)
196  {
197  s1 = s1 * s2;
198  continue;
199  }
200  clause = (Node *) rinfo->clause;
201  }
202  else
203  rinfo = NULL;
204 
205  /*
206  * See if it looks like a restriction clause with a pseudoconstant on
207  * one side. (Anything more complicated than that might not behave in
208  * the simple way we are expecting.) Most of the tests here can be
209  * done more efficiently with rinfo than without.
210  */
211  if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
212  {
213  OpExpr *expr = (OpExpr *) clause;
214  bool varonleft = true;
215  bool ok;
216 
217  if (rinfo)
218  {
219  ok = (rinfo->num_base_rels == 1) &&
221  rinfo->right_relids) ||
222  (varonleft = false,
224  rinfo->left_relids)));
225  }
226  else
227  {
228  ok = (NumRelids(root, clause) == 1) &&
230  (varonleft = false,
232  }
233 
234  if (ok)
235  {
236  /*
237  * If it's not a "<"/"<="/">"/">=" operator, just merge the
238  * selectivity in generically. But if it's the right oprrest,
239  * add the clause to rqlist for later processing.
240  */
241  switch (get_oprrest(expr->opno))
242  {
243  case F_SCALARLTSEL:
244  case F_SCALARLESEL:
245  addRangeClause(&rqlist, clause,
246  varonleft, true, s2);
247  break;
248  case F_SCALARGTSEL:
249  case F_SCALARGESEL:
250  addRangeClause(&rqlist, clause,
251  varonleft, false, s2);
252  break;
253  default:
254  /* Just merge the selectivity in generically */
255  s1 = s1 * s2;
256  break;
257  }
258  continue; /* drop to loop bottom */
259  }
260  }
261 
262  /* Not the right form, so treat it generically. */
263  s1 = s1 * s2;
264  }
265 
266  /*
267  * Now scan the rangequery pair list.
268  */
269  while (rqlist != NULL)
270  {
271  RangeQueryClause *rqnext;
272 
273  if (rqlist->have_lobound && rqlist->have_hibound)
274  {
275  /* Successfully matched a pair of range clauses */
276  Selectivity s2;
277 
278  /*
279  * Exact equality to the default value probably means the
280  * selectivity function punted. This is not airtight but should
281  * be good enough.
282  */
283  if (rqlist->hibound == DEFAULT_INEQ_SEL ||
284  rqlist->lobound == DEFAULT_INEQ_SEL)
285  {
287  }
288  else
289  {
290  s2 = rqlist->hibound + rqlist->lobound - 1.0;
291 
292  /* Adjust for double-exclusion of NULLs */
293  s2 += nulltestsel(root, IS_NULL, rqlist->var,
294  varRelid, jointype, sjinfo);
295 
296  /*
297  * A zero or slightly negative s2 should be converted into a
298  * small positive value; we probably are dealing with a very
299  * tight range and got a bogus result due to roundoff errors.
300  * However, if s2 is very negative, then we probably have
301  * default selectivity estimates on one or both sides of the
302  * range that we failed to recognize above for some reason.
303  */
304  if (s2 <= 0.0)
305  {
306  if (s2 < -0.01)
307  {
308  /*
309  * No data available --- use a default estimate that
310  * is small, but not real small.
311  */
313  }
314  else
315  {
316  /*
317  * It's just roundoff error; use a small positive
318  * value
319  */
320  s2 = 1.0e-10;
321  }
322  }
323  }
324  /* Merge in the selectivity of the pair of clauses */
325  s1 *= s2;
326  }
327  else
328  {
329  /* Only found one of a pair, merge it in generically */
330  if (rqlist->have_lobound)
331  s1 *= rqlist->lobound;
332  else
333  s1 *= rqlist->hibound;
334  }
335  /* release storage and advance */
336  rqnext = rqlist->next;
337  pfree(rqlist);
338  rqlist = rqnext;
339  }
340 
341  return s1;
342 }
int NumRelids(PlannerInfo *root, Node *clause)
Definition: clauses.c:2110
bool is_pseudo_constant_clause(Node *clause)
Definition: clauses.c:2068
bool is_pseudo_constant_clause_relids(Node *clause, Relids relids)
Definition: clauses.c:2088
static void addRangeClause(RangeQueryClause **rqlist, Node *clause, bool varonleft, bool isLTsel, Selectivity s2)
Definition: clausesel.c:427
static RelOptInfo * find_single_rel_for_clauses(PlannerInfo *root, List *clauses)
Definition: clausesel.c:523
Selectivity statext_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses, bool is_or)
RegProcedure get_oprrest(Oid opno)
Definition: lsyscache.c:1535
void pfree(void *pointer)
Definition: mcxt.c:1508
@ RTE_RELATION
Definition: parsenodes.h:1011
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
char * s2
@ IS_NULL
Definition: primnodes.h:1715
#define DEFAULT_RANGE_INEQ_SEL
Definition: selfuncs.h:40
#define DEFAULT_INEQ_SEL
Definition: selfuncs.h:37
Selectivity hibound
Definition: clausesel.c:38
Selectivity lobound
Definition: clausesel.c:37
struct RangeQueryClause * next
Definition: clausesel.c:33
List * statlist
Definition: pathnodes.h:927
RTEKind rtekind
Definition: pathnodes.h:907

References addRangeClause(), generate_unaccent_rules::args, OpExpr::args, bms_is_member(), RestrictInfo::clause, clause_selectivity_ext(), DEFAULT_INEQ_SEL, DEFAULT_RANGE_INEQ_SEL, find_single_rel_for_clauses(), get_oprrest(), RangeQueryClause::have_hibound, RangeQueryClause::have_lobound, RangeQueryClause::hibound, IS_NULL, is_opclause(), is_pseudo_constant_clause(), is_pseudo_constant_clause_relids(), IsA, lfirst, linitial, list_length(), RangeQueryClause::lobound, lsecond, RangeQueryClause::next, NIL, nulltestsel(), NumRelids(), OpExpr::opno, pfree(), RTE_RELATION, RelOptInfo::rtekind, s1, s2, statext_clauselist_selectivity(), RelOptInfo::statlist, and RangeQueryClause::var.

Referenced by clause_selectivity_ext(), clauselist_apply_dependencies(), clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

◆ contain_mutable_functions()

◆ contain_mutable_functions_after_planning()

bool contain_mutable_functions_after_planning ( Expr expr)

Definition at line 470 of file clauses.c.

471 {
472  /* We assume here that expression_planner() won't scribble on its input */
473  expr = expression_planner(expr);
474 
475  /* Now we can search for non-immutable functions */
476  return contain_mutable_functions((Node *) expr);
477 }
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:369
Expr * expression_planner(Expr *expr)
Definition: planner.c:6400

References contain_mutable_functions(), and expression_planner().

Referenced by CheckPredicate(), ComputeIndexAttrs(), and cookDefault().

◆ 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 441 of file var.c.

442 {
443  int sublevels_up = levelsup;
444 
447  (void *) &sublevels_up,
448  0);
449 }
#define query_or_expression_tree_walker(n, w, c, f)
Definition: nodeFuncs.h:169
static bool contain_vars_of_level_walker(Node *node, int *sublevels_up)
Definition: var.c:452

References contain_vars_of_level_walker(), and query_or_expression_tree_walker.

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

◆ contain_volatile_functions()

◆ contain_volatile_functions_after_planning()

bool contain_volatile_functions_after_planning ( Expr expr)

Definition at line 639 of file clauses.c.

640 {
641  /* We assume here that expression_planner() won't scribble on its input */
642  expr = expression_planner(expr);
643 
644  /* Now we can search for volatile functions */
645  return contain_volatile_functions((Node *) expr);
646 }
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:518

References contain_volatile_functions(), and expression_planner().

Referenced by AddRelationNewConstraints().

◆ contain_volatile_functions_not_nextval()

bool contain_volatile_functions_not_nextval ( Node clause)

Definition at line 653 of file clauses.c.

654 {
656 }
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:666

References contain_volatile_functions_not_nextval_walker().

Referenced by BeginCopyFrom().

◆ convert_saop_to_hashed_saop()

void convert_saop_to_hashed_saop ( Node node)

Definition at line 2267 of file clauses.c.

2268 {
2269  (void) convert_saop_to_hashed_saop_walker(node, NULL);
2270 }
static bool convert_saop_to_hashed_saop_walker(Node *node, void *context)
Definition: clauses.c:2273

References convert_saop_to_hashed_saop_walker().

Referenced by preprocess_expression().

◆ count_nonjunk_tlist_entries()

int count_nonjunk_tlist_entries ( List tlist)

Definition at line 186 of file tlist.c.

187 {
188  int len = 0;
189  ListCell *l;
190 
191  foreach(l, tlist)
192  {
193  TargetEntry *tle = (TargetEntry *) lfirst(l);
194 
195  if (!tle->resjunk)
196  len++;
197  }
198  return len;
199 }
const void size_t len

References len, and lfirst.

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

◆ estimate_expression_value()

Node* estimate_expression_value ( PlannerInfo root,
Node node 
)

Definition at line 2375 of file clauses.c.

2376 {
2378 
2379  context.boundParams = root->glob->boundParams; /* bound Params */
2380  /* we do not need to mark the plan as depending on inlined functions */
2381  context.root = NULL;
2382  context.active_fns = NIL; /* nothing being recursively simplified */
2383  context.case_val = NULL; /* no CASE being examined */
2384  context.estimate = true; /* unsafe transformations OK */
2385  return eval_const_expressions_mutator(node, &context);
2386 }
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2420
PlannerGlobal * glob
Definition: pathnodes.h:202
ParamListInfo boundParams
Definition: clauses.c:60

References eval_const_expressions_context::active_fns, eval_const_expressions_context::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_ext(), 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().

◆ eval_const_expressions()

◆ evaluate_expr()

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

Definition at line 4941 of file clauses.c.

4943 {
4944  EState *estate;
4945  ExprState *exprstate;
4946  MemoryContext oldcontext;
4947  Datum const_val;
4948  bool const_is_null;
4949  int16 resultTypLen;
4950  bool resultTypByVal;
4951 
4952  /*
4953  * To use the executor, we need an EState.
4954  */
4955  estate = CreateExecutorState();
4956 
4957  /* We can use the estate's working context to avoid memory leaks. */
4958  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
4959 
4960  /* Make sure any opfuncids are filled in. */
4961  fix_opfuncids((Node *) expr);
4962 
4963  /*
4964  * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
4965  * because it'd result in recursively invoking eval_const_expressions.)
4966  */
4967  exprstate = ExecInitExpr(expr, NULL);
4968 
4969  /*
4970  * And evaluate it.
4971  *
4972  * It is OK to use a default econtext because none of the ExecEvalExpr()
4973  * code used in this situation will use econtext. That might seem
4974  * fortuitous, but it's not so unreasonable --- a constant expression does
4975  * not depend on context, by definition, n'est ce pas?
4976  */
4977  const_val = ExecEvalExprSwitchContext(exprstate,
4978  GetPerTupleExprContext(estate),
4979  &const_is_null);
4980 
4981  /* Get info needed about result datatype */
4982  get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
4983 
4984  /* Get back to outer memory context */
4985  MemoryContextSwitchTo(oldcontext);
4986 
4987  /*
4988  * Must copy result out of sub-context used by expression eval.
4989  *
4990  * Also, if it's varlena, forcibly detoast it. This protects us against
4991  * storing TOAST pointers into plans that might outlive the referenced
4992  * data. (makeConst would handle detoasting anyway, but it's worth a few
4993  * extra lines here so that we can do the copy and detoast in one step.)
4994  */
4995  if (!const_is_null)
4996  {
4997  if (resultTypLen == -1)
4998  const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
4999  else
5000  const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
5001  }
5002 
5003  /* Release all the junk we just created */
5004  FreeExecutorState(estate);
5005 
5006  /*
5007  * Make the constant result node.
5008  */
5009  return (Expr *) makeConst(result_type, result_typmod, result_collation,
5010  resultTypLen,
5011  const_val, const_is_null,
5012  resultTypByVal);
5013 }
signed short int16
Definition: c.h:480
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:127
EState * CreateExecutorState(void)
Definition: execUtils.c:88
void FreeExecutorState(EState *estate)
Definition: execUtils.c:189
#define GetPerTupleExprContext(estate)
Definition: executor.h:550
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:348
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2207
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:301
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1759
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
MemoryContext es_query_cxt
Definition: execnodes.h:665

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

◆ expand_function_arguments()

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

◆ expression_planner()

Expr* expression_planner ( Expr expr)

Definition at line 6400 of file planner.c.

6401 {
6402  Node *result;
6403 
6404  /*
6405  * Convert named-argument function calls, insert default arguments and
6406  * simplify constant subexprs
6407  */
6408  result = eval_const_expressions(NULL, (Node *) expr);
6409 
6410  /* Fill in opfuncid values if missing */
6411  fix_opfuncids(result);
6412 
6413  return (Expr *) result;
6414 }
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2234

References eval_const_expressions(), and fix_opfuncids().

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

◆ expression_planner_with_deps()

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

Definition at line 6427 of file planner.c.

6430 {
6431  Node *result;
6432  PlannerGlobal glob;
6433  PlannerInfo root;
6434 
6435  /* Make up dummy planner state so we can use setrefs machinery */
6436  MemSet(&glob, 0, sizeof(glob));
6437  glob.type = T_PlannerGlobal;
6438  glob.relationOids = NIL;
6439  glob.invalItems = NIL;
6440 
6441  MemSet(&root, 0, sizeof(root));
6442  root.type = T_PlannerInfo;
6443  root.glob = &glob;
6444 
6445  /*
6446  * Convert named-argument function calls, insert default arguments and
6447  * simplify constant subexprs. Collect identities of inlined functions
6448  * and elided domains, too.
6449  */
6450  result = eval_const_expressions(&root, (Node *) expr);
6451 
6452  /* Fill in opfuncid values if missing */
6453  fix_opfuncids(result);
6454 
6455  /*
6456  * Now walk the finished expression to find anything else we ought to
6457  * record as an expression dependency.
6458  */
6459  (void) extract_query_dependencies_walker(result, &root);
6460 
6461  *relationOids = glob.relationOids;
6462  *invalItems = glob.invalItems;
6463 
6464  return (Expr *) result;
6465 }
#define MemSet(start, val, len)
Definition: c.h:1007
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:3561
List * invalItems
Definition: pathnodes.h:132
List * relationOids
Definition: pathnodes.h:129

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

Referenced by GetCachedExpression().

◆ extract_query_dependencies()

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

Definition at line 3525 of file setrefs.c.

3529 {
3530  PlannerGlobal glob;
3531  PlannerInfo root;
3532 
3533  /* Make up dummy planner state so we can use this module's machinery */
3534  MemSet(&glob, 0, sizeof(glob));
3535  glob.type = T_PlannerGlobal;
3536  glob.relationOids = NIL;
3537  glob.invalItems = NIL;
3538  /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
3539  glob.dependsOnRole = false;
3540 
3541  MemSet(&root, 0, sizeof(root));
3542  root.type = T_PlannerInfo;
3543  root.glob = &glob;
3544 
3545  (void) extract_query_dependencies_walker(query, &root);
3546 
3547  *relationOids = glob.relationOids;
3548  *invalItems = glob.invalItems;
3549  *hasRowSecurity = glob.dependsOnRole;
3550 }
bool dependsOnRole
Definition: pathnodes.h:150

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

Referenced by CompleteCachedPlan(), and RevalidateCachedQuery().

◆ flatten_join_alias_vars()

Node* flatten_join_alias_vars ( PlannerInfo root,
Query query,
Node node 
)

Definition at line 744 of file var.c.

745 {
747 
748  /*
749  * We do not expect this to be applied to the whole Query, only to
750  * expressions or LATERAL subqueries. Hence, if the top node is a Query,
751  * it's okay to immediately increment sublevels_up.
752  */
753  Assert(node != (Node *) query);
754 
755  context.root = root;
756  context.query = query;
757  context.sublevels_up = 0;
758  /* flag whether join aliases could possibly contain SubLinks */
759  context.possible_sublink = query->hasSubLinks;
760  /* if hasSubLinks is already true, no need to work hard */
761  context.inserted_sublink = query->hasSubLinks;
762 
763  return flatten_join_alias_vars_mutator(node, &context);
764 }
PlannerInfo * root
Definition: var.c:65
static Node * flatten_join_alias_vars_mutator(Node *node, flatten_join_alias_vars_context *context)
Definition: var.c:767

References Assert(), flatten_join_alias_vars_mutator(), flatten_join_alias_vars_context::inserted_sublink, flatten_join_alias_vars_context::possible_sublink, flatten_join_alias_vars_context::query, flatten_join_alias_vars_context::root, and flatten_join_alias_vars_context::sublevels_up.

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

◆ get_sortgroupclause_expr()

Node* get_sortgroupclause_expr ( SortGroupClause sgClause,
List targetList 
)

Definition at line 379 of file tlist.c.

380 {
381  TargetEntry *tle = get_sortgroupclause_tle(sgClause, targetList);
382 
383  return (Node *) tle->expr;
384 }
Expr * expr
Definition: primnodes.h:1943
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:367

References TargetEntry::expr, and get_sortgroupclause_tle().

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

◆ get_sortgroupclause_tle()

◆ get_sortgrouplist_exprs()

List* get_sortgrouplist_exprs ( List sgClauses,
List targetList 
)

Definition at line 392 of file tlist.c.

393 {
394  List *result = NIL;
395  ListCell *l;
396 
397  foreach(l, sgClauses)
398  {
399  SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
400  Node *sortexpr;
401 
402  sortexpr = get_sortgroupclause_expr(sortcl, targetList);
403  result = lappend(result, sortexpr);
404  }
405  return result;
406 }
List * lappend(List *list, void *datum)
Definition: list.c:339
Node * get_sortgroupclause_expr(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:379

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

Referenced by create_final_distinct_paths(), create_partial_distinct_paths(), estimate_path_cost_size(), get_number_of_groups(), get_windowclause_startup_tuples(), and group_by_has_partkey().

◆ get_sortgroupref_clause()

SortGroupClause* get_sortgroupref_clause ( Index  sortref,
List clauses 
)

Definition at line 422 of file tlist.c.

423 {
424  ListCell *l;
425 
426  foreach(l, clauses)
427  {
429 
430  if (cl->tleSortGroupRef == sortref)
431  return cl;
432  }
433 
434  elog(ERROR, "ORDER/GROUP BY expression not found in list");
435  return NULL; /* keep compiler quiet */
436 }
#define ERROR
Definition: elog.h:39

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

Referenced by groupclause_apply_groupingset().

◆ get_sortgroupref_clause_noerr()

SortGroupClause* get_sortgroupref_clause_noerr ( Index  sortref,
List clauses 
)

Definition at line 443 of file tlist.c.

444 {
445  ListCell *l;
446 
447  foreach(l, clauses)
448  {
450 
451  if (cl->tleSortGroupRef == sortref)
452  return cl;
453  }
454 
455  return NULL;
456 }

References lfirst, and SortGroupClause::tleSortGroupRef.

Referenced by find_em_for_rel_target(), foreign_grouping_ok(), group_keys_reorder_by_pathkeys(), make_group_input_target(), and make_partial_grouping_target().

◆ get_sortgroupref_tle()

TargetEntry* get_sortgroupref_tle ( Index  sortref,
List targetList 
)

Definition at line 345 of file tlist.c.

346 {
347  ListCell *l;
348 
349  foreach(l, targetList)
350  {
351  TargetEntry *tle = (TargetEntry *) lfirst(l);
352 
353  if (tle->ressortgroupref == sortref)
354  return tle;
355  }
356 
357  elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
358  return NULL; /* keep compiler quiet */
359 }
Index ressortgroupref
Definition: primnodes.h:1949

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

◆ is_pseudo_constant_for_index()

bool is_pseudo_constant_for_index ( PlannerInfo root,
Node expr,
IndexOptInfo index 
)

Definition at line 3844 of file indxpath.c.

3845 {
3846  /* pull_varnos is cheaper than volatility check, so do that first */
3847  if (bms_is_member(index->rel->relid, pull_varnos(root, expr)))
3848  return false; /* no good, contains Var of table */
3849  if (contain_volatile_functions(expr))
3850  return false; /* no good, volatile comparison value */
3851  return true;
3852 }
Definition: type.h:95
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:108

References bms_is_member(), contain_volatile_functions(), and pull_varnos().

◆ locate_var_of_level()

int locate_var_of_level ( Node node,
int  levelsup 
)

Definition at line 509 of file var.c.

510 {
512 
513  context.var_location = -1; /* in case we find nothing */
514  context.sublevels_up = levelsup;
515 
518  (void *) &context,
519  0);
520 
521  return context.var_location;
522 }
static bool locate_var_of_level_walker(Node *node, locate_var_of_level_context *context)
Definition: var.c:525

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

◆ negate_clause()

Node* negate_clause ( Node node)

Definition at line 73 of file prepqual.c.

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

References AND_EXPR, NullTest::arg, BooleanTest::arg, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, DatumGetBool(), elog, ERROR, get_negator(), 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, NIL, nodeTag, NOT_EXPR, NullTest::nulltesttype, OpExpr::opno, ScalarArrayOpExpr::opno, OR_EXPR, and ScalarArrayOpExpr::useOr.

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

◆ plan_cluster_use_sort()

bool plan_cluster_use_sort ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 6480 of file planner.c.

6481 {
6482  PlannerInfo *root;
6483  Query *query;
6484  PlannerGlobal *glob;
6485  RangeTblEntry *rte;
6486  RelOptInfo *rel;
6487  IndexOptInfo *indexInfo;
6488  QualCost indexExprCost;
6489  Cost comparisonCost;
6490  Path *seqScanPath;
6491  Path seqScanAndSortPath;
6492  IndexPath *indexScanPath;
6493  ListCell *lc;
6494 
6495  /* We can short-circuit the cost comparison if indexscans are disabled */
6496  if (!enable_indexscan)
6497  return true; /* use sort */
6498 
6499  /* Set up mostly-dummy planner state */
6500  query = makeNode(Query);
6501  query->commandType = CMD_SELECT;
6502 
6503  glob = makeNode(PlannerGlobal);
6504 
6505  root = makeNode(PlannerInfo);
6506  root->parse = query;
6507  root->glob = glob;
6508  root->query_level = 1;
6509  root->planner_cxt = CurrentMemoryContext;
6510  root->wt_param_id = -1;
6512 
6513  /* Build a minimal RTE for the rel */
6514  rte = makeNode(RangeTblEntry);
6515  rte->rtekind = RTE_RELATION;
6516  rte->relid = tableOid;
6517  rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
6519  rte->lateral = false;
6520  rte->inh = false;
6521  rte->inFromCl = true;
6522  query->rtable = list_make1(rte);
6523  addRTEPermissionInfo(&query->rteperminfos, rte);
6524 
6525  /* Set up RTE/RelOptInfo arrays */
6527 
6528  /* Build RelOptInfo */
6529  rel = build_simple_rel(root, 1, NULL);
6530 
6531  /* Locate IndexOptInfo for the target index */
6532  indexInfo = NULL;
6533  foreach(lc, rel->indexlist)
6534  {
6535  indexInfo = lfirst_node(IndexOptInfo, lc);
6536  if (indexInfo->indexoid == indexOid)
6537  break;
6538  }
6539 
6540  /*
6541  * It's possible that get_relation_info did not generate an IndexOptInfo
6542  * for the desired index; this could happen if it's not yet reached its
6543  * indcheckxmin usability horizon, or if it's a system index and we're
6544  * ignoring system indexes. In such cases we should tell CLUSTER to not
6545  * trust the index contents but use seqscan-and-sort.
6546  */
6547  if (lc == NULL) /* not in the list? */
6548  return true; /* use sort */
6549 
6550  /*
6551  * Rather than doing all the pushups that would be needed to use
6552  * set_baserel_size_estimates, just do a quick hack for rows and width.
6553  */
6554  rel->rows = rel->tuples;
6555  rel->reltarget->width = get_relation_data_width(tableOid, NULL);
6556 
6557  root->total_table_pages = rel->pages;
6558 
6559  /*
6560  * Determine eval cost of the index expressions, if any. We need to
6561  * charge twice that amount for each tuple comparison that happens during
6562  * the sort, since tuplesort.c will have to re-evaluate the index
6563  * expressions each time. (XXX that's pretty inefficient...)
6564  */
6565  cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
6566  comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
6567 
6568  /* Estimate the cost of seq scan + sort */
6569  seqScanPath = create_seqscan_path(root, rel, NULL, 0);
6570  cost_sort(&seqScanAndSortPath, root, NIL,
6571  seqScanPath->total_cost, rel->tuples, rel->reltarget->width,
6572  comparisonCost, maintenance_work_mem, -1.0);
6573 
6574  /* Estimate the cost of index scan */
6575  indexScanPath = create_index_path(root, indexInfo,
6576  NIL, NIL, NIL, NIL,
6577  ForwardScanDirection, false,
6578  NULL, 1.0, false);
6579 
6580  return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
6581 }
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:4640
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:2124
bool enable_indexscan
Definition: costsize.c:135
int maintenance_work_mem
Definition: globals.c:130
#define AccessShareLock
Definition: lockdefs.h:36
MemoryContext CurrentMemoryContext
Definition: mcxt.c:131
double Cost
Definition: nodes.h:241
@ CMD_SELECT
Definition: nodes.h:255
RTEPermissionInfo * addRTEPermissionInfo(List **rteperminfos, RangeTblEntry *rte)
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:991
Path * create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer, int parallel_workers)
Definition: pathnode.c:925
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define list_make1(x1)
Definition: pg_list.h:212
int32 get_relation_data_width(Oid relid, int32 *attr_widths)
Definition: plancat.c:1197
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:94
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:192
@ ForwardScanDirection
Definition: sdir.h:28
Path path
Definition: pathnodes.h:1689
Cost total_cost
Definition: pathnodes.h:1642
Index query_level
Definition: pathnodes.h:205
List * join_domains
Definition: pathnodes.h:308
int wt_param_id
Definition: pathnodes.h:521
Cardinality total_table_pages
Definition: pathnodes.h:475
Query * parse
Definition: pathnodes.h:199
Cost per_tuple
Definition: pathnodes.h:48
Cost startup
Definition: pathnodes.h:47
List * rtable
Definition: parsenodes.h:168
CmdType commandType
Definition: parsenodes.h:121
RTEKind rtekind
Definition: parsenodes.h:1030
struct PathTarget * reltarget
Definition: pathnodes.h:878
BlockNumber pages
Definition: pathnodes.h:929
List * indexlist
Definition: pathnodes.h:925
Cardinality rows
Definition: pathnodes.h:862

References AccessShareLock, addRTEPermissionInfo(), 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, RangeTblEntry::inFromCl, RangeTblEntry::inh, PlannerInfo::join_domains, RangeTblEntry::lateral, lfirst_node, list_make1, maintenance_work_mem, makeNode, NIL, RelOptInfo::pages, PlannerInfo::parse, IndexPath::path, QualCost::per_tuple, 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().

◆ plan_create_index_workers()

int plan_create_index_workers ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 6600 of file planner.c.

6601 {
6602  PlannerInfo *root;
6603  Query *query;
6604  PlannerGlobal *glob;
6605  RangeTblEntry *rte;
6606  Relation heap;
6607  Relation index;
6608  RelOptInfo *rel;
6609  int parallel_workers;
6610  BlockNumber heap_blocks;
6611  double reltuples;
6612  double allvisfrac;
6613 
6614  /*
6615  * We don't allow performing parallel operation in standalone backend or
6616  * when parallelism is disabled.
6617  */
6619  return 0;
6620 
6621  /* Set up largely-dummy planner state */
6622  query = makeNode(Query);
6623  query->commandType = CMD_SELECT;
6624 
6625  glob = makeNode(PlannerGlobal);
6626 
6627  root = makeNode(PlannerInfo);
6628  root->parse = query;
6629  root->glob = glob;
6630  root->query_level = 1;
6631  root->planner_cxt = CurrentMemoryContext;
6632  root->wt_param_id = -1;
6634 
6635  /*
6636  * Build a minimal RTE.
6637  *
6638  * Mark the RTE with inh = true. This is a kludge to prevent
6639  * get_relation_info() from fetching index info, which is necessary
6640  * because it does not expect that any IndexOptInfo is currently
6641  * undergoing REINDEX.
6642  */
6643  rte = makeNode(RangeTblEntry);
6644  rte->rtekind = RTE_RELATION;
6645  rte->relid = tableOid;
6646  rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
6648  rte->lateral = false;
6649  rte->inh = true;
6650  rte->inFromCl = true;
6651  query->rtable = list_make1(rte);
6652  addRTEPermissionInfo(&query->rteperminfos, rte);
6653 
6654  /* Set up RTE/RelOptInfo arrays */
6656 
6657  /* Build RelOptInfo */
6658  rel = build_simple_rel(root, 1, NULL);
6659 
6660  /* Rels are assumed already locked by the caller */
6661  heap = table_open(tableOid, NoLock);
6662  index = index_open(indexOid, NoLock);
6663 
6664  /*
6665  * Determine if it's safe to proceed.
6666  *
6667  * Currently, parallel workers can't access the leader's temporary tables.
6668  * Furthermore, any index predicate or index expressions must be parallel
6669  * safe.
6670  */
6671  if (heap->rd_rel->relpersistence == RELPERSISTENCE_TEMP ||
6674  {
6675  parallel_workers = 0;
6676  goto done;
6677  }
6678 
6679  /*
6680  * If parallel_workers storage parameter is set for the table, accept that
6681  * as the number of parallel worker processes to launch (though still cap
6682  * at max_parallel_maintenance_workers). Note that we deliberately do not
6683  * consider any other factor when parallel_workers is set. (e.g., memory
6684  * use by workers.)
6685  */
6686  if (rel->rel_parallel_workers != -1)
6687  {
6688  parallel_workers = Min(rel->rel_parallel_workers,
6690  goto done;
6691  }
6692 
6693  /*
6694  * Estimate heap relation size ourselves, since rel->pages cannot be
6695  * trusted (heap RTE was marked as inheritance parent)
6696  */
6697  estimate_rel_size(heap, NULL, &heap_blocks, &reltuples, &allvisfrac);
6698 
6699  /*
6700  * Determine number of workers to scan the heap relation using generic
6701  * model
6702  */
6703  parallel_workers = compute_parallel_worker(rel, heap_blocks, -1,
6705 
6706  /*
6707  * Cap workers based on available maintenance_work_mem as needed.
6708  *
6709  * Note that each tuplesort participant receives an even share of the
6710  * total maintenance_work_mem budget. Aim to leave participants
6711  * (including the leader as a participant) with no less than 32MB of
6712  * memory. This leaves cases where maintenance_work_mem is set to 64MB
6713  * immediately past the threshold of being capable of launching a single
6714  * parallel worker to sort.
6715  */
6716  while (parallel_workers > 0 &&
6717  maintenance_work_mem / (parallel_workers + 1) < 32768L)
6718  parallel_workers--;
6719 
6720 done:
6722  table_close(heap, NoLock);
6723 
6724  return parallel_workers;
6725 }
int compute_parallel_worker(RelOptInfo *rel, double heap_pages, double index_pages, int max_workers)
Definition: allpaths.c:4210
uint32 BlockNumber
Definition: block.h:31
#define Min(x, y)
Definition: c.h:991
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:733
int max_parallel_maintenance_workers
Definition: globals.c:131
bool IsUnderPostmaster
Definition: globals.c:117
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:133
#define NoLock
Definition: lockdefs.h:34
void estimate_rel_size(Relation rel, int32 *attr_widths, BlockNumber *pages, double *tuples, double *allvisfrac)
Definition: plancat.c:1030
List * RelationGetIndexPredicate(Relation relation)
Definition: relcache.c:5127
List * RelationGetIndexExpressions(Relation relation)
Definition: relcache.c:5014
int rel_parallel_workers
Definition: pathnodes.h:937
Form_pg_class rd_rel
Definition: rel.h:111
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References AccessShareLock, addRTEPermissionInfo(), 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(), IsUnderPostmaster, PlannerInfo::join_domains, RangeTblEntry::lateral, list_make1, maintenance_work_mem, makeNode, max_parallel_maintenance_workers, Min, NoLock, PlannerInfo::parse, PlannerInfo::query_level, RelationData::rd_rel, RelOptInfo::rel_parallel_workers, RelationGetIndexExpressions(), RelationGetIndexPredicate(), RangeTblEntry::relid, RangeTblEntry::relkind, RangeTblEntry::rellockmode, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, setup_simple_rel_arrays(), table_close(), table_open(), and PlannerInfo::wt_param_id.

Referenced by index_build().

◆ planner()

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

◆ predicate_implied_by()

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

Definition at line 152 of file predtest.c.

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

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

◆ predicate_refuted_by()

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

Definition at line 222 of file predtest.c.

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

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

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

◆ pull_var_clause()

List* pull_var_clause ( Node node,
int  flags 
)

Definition at line 607 of file var.c.

608 {
609  pull_var_clause_context context;
610 
611  /* Assert that caller has not specified inconsistent flags */
618 
619  context.varlist = NIL;
620  context.flags = flags;
621 
622  pull_var_clause_walker(node, &context);
623  return context.varlist;
624 }
#define PVC_RECURSE_AGGREGATES
Definition: optimizer.h:187
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:191
#define PVC_RECURSE_WINDOWFUNCS
Definition: optimizer.h:189
#define PVC_INCLUDE_WINDOWFUNCS
Definition: optimizer.h:188
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:190
#define PVC_INCLUDE_AGGREGATES
Definition: optimizer.h:186
static bool pull_var_clause_walker(Node *node, pull_var_clause_context *context)
Definition: var.c:627

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 add_paths_with_pathkeys_for_rel(), AddRelationNewConstraints(), build_base_rel_tlists(), build_remote_returning(), build_tlist_to_deparse(), CreateTriggerFiringOn(), distribute_qual_to_rels(), estimate_num_groups(), find_computable_ec_member(), 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(), preprocess_targetlist(), process_implied_equality(), qual_is_pushdown_safe(), semijoin_target_ok(), and StoreRelCheck().

◆ pull_varattnos()

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

◆ pull_varnos()

Bitmapset* pull_varnos ( PlannerInfo root,
Node node 
)

Definition at line 108 of file var.c.

109 {
110  pull_varnos_context context;
111 
112  context.varnos = NULL;
113  context.root = root;
114  context.sublevels_up = 0;
115 
116  /*
117  * Must be prepared to start with a Query or a bare expression tree; if
118  * it's a Query, we don't want to increment sublevels_up.
119  */
122  (void *) &context,
123  0);
124 
125  return context.varnos;
126 }
PlannerInfo * root
Definition: var.c:35
int sublevels_up
Definition: var.c:36
Relids varnos
Definition: var.c:34
static bool pull_varnos_walker(Node *node, pull_varnos_context *context)
Definition: var.c:155

References pull_varnos_walker(), query_or_expression_tree_walker, pull_varnos_context::root, 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(), cost_incremental_sort(), 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(), pg_get_expr_worker(), process_implied_equality(), and remove_leftjoinrel_from_query().

◆ pull_varnos_of_level()

Bitmapset* pull_varnos_of_level ( PlannerInfo root,
Node node,
int  levelsup 
)

Definition at line 134 of file var.c.

135 {
136  pull_varnos_context context;
137 
138  context.varnos = NULL;
139  context.root = root;
140  context.sublevels_up = levelsup;
141 
142  /*
143  * Must be prepared to start with a Query or a bare expression tree; if
144  * it's a Query, we don't want to increment sublevels_up.
145  */
148  (void *) &context,
149  0);
150 
151  return context.varnos;
152 }

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

Referenced by add_nullingrels_if_needed(), convert_ANY_sublink_to_join(), is_simple_subquery(), and jointree_contains_lateral_outer_refs().

◆ pull_vars_of_level()

List* pull_vars_of_level ( Node node,
int  levelsup 
)

Definition at line 335 of file var.c.

336 {
337  pull_vars_context context;
338 
339  context.vars = NIL;
340  context.sublevels_up = levelsup;
341 
342  /*
343  * Must be prepared to start with a Query or a bare expression tree; if
344  * it's a Query, we don't want to increment sublevels_up.
345  */
348  (void *) &context,
349  0);
350 
351  return context.vars;
352 }
int sublevels_up
Definition: var.c:48
List * vars
Definition: var.c:47
static bool pull_vars_walker(Node *node, pull_vars_context *context)
Definition: var.c:355

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

Variable Documentation

◆ cpu_index_tuple_cost

PGDLLIMPORT double cpu_index_tuple_cost
extern

Definition at line 122 of file costsize.c.

Referenced by genericcostestimate(), and gincostestimate().

◆ cpu_operator_cost

◆ cpu_tuple_cost

◆ debug_parallel_query

PGDLLIMPORT int debug_parallel_query
extern

Definition at line 66 of file planner.c.

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

◆ effective_cache_size

PGDLLIMPORT int effective_cache_size
extern

Definition at line 128 of file costsize.c.

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

◆ parallel_leader_participation

PGDLLIMPORT bool parallel_leader_participation
extern

Definition at line 67 of file planner.c.

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

◆ parallel_setup_cost

PGDLLIMPORT double parallel_setup_cost
extern

Definition at line 125 of file costsize.c.

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

◆ parallel_tuple_cost

PGDLLIMPORT double parallel_tuple_cost
extern

Definition at line 124 of file costsize.c.

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

◆ random_page_cost

PGDLLIMPORT double random_page_cost
extern

◆ recursive_worktable_factor

PGDLLIMPORT double recursive_worktable_factor
extern

Definition at line 126 of file costsize.c.

Referenced by set_cte_size_estimates().

◆ seq_page_cost