PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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
 
#define PVC_INCLUDE_CONVERTROWTYPES
 

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)
 
ScalarArrayOpExprmake_SAOP_expr (Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid, Oid inputcollid, List *exprs, bool haveNonConst)
 
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)
 
bool contain_vars_returning_old_or_new (Node *node)
 
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)
 
Nodeflatten_group_exprs (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
 
PGDLLIMPORT bool enable_distinct_reordering
 

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 192 of file optimizer.h.

◆ PVC_INCLUDE_CONVERTROWTYPES

#define PVC_INCLUDE_CONVERTROWTYPES
Value:
0x0040 /* include ConvertRowtypeExprs in
* output list */

Definition at line 198 of file optimizer.h.

◆ PVC_INCLUDE_PLACEHOLDERS

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

Definition at line 196 of file optimizer.h.

◆ PVC_INCLUDE_WINDOWFUNCS

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

Definition at line 194 of file optimizer.h.

◆ PVC_RECURSE_AGGREGATES

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

Definition at line 193 of file optimizer.h.

◆ PVC_RECURSE_PLACEHOLDERS

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

Definition at line 197 of file optimizer.h.

◆ PVC_RECURSE_WINDOWFUNCS

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

Definition at line 195 of file optimizer.h.

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

◆ 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(PointerIsAligned(start, uint64))
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
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 265 of file costsize.c.

266{
267 /*
268 * Just for paranoia's sake, ensure we do something sane with negative or
269 * NaN values.
270 */
271 if (isnan(x))
272 return LONG_MAX;
273 if (x <= 0)
274 return 0;
275
276 /*
277 * If "long" is 64 bits, then LONG_MAX cannot be represented exactly as a
278 * double. Casting it to double and back may well result in overflow due
279 * to rounding, so avoid doing that. We trust that any double value that
280 * compares strictly less than "(double) LONG_MAX" will cast to a
281 * representable "long" value.
282 */
283 return (x < (double) LONG_MAX) ? (long) x : LONG_MAX;
284}
int x
Definition: isn.c:75

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 213 of file costsize.c.

214{
215 /*
216 * Avoid infinite and NaN row estimates. Costs derived from such values
217 * are going to be useless. Also force the estimate to be at least one
218 * row, to make explain output look better and to avoid possible
219 * divide-by-zero when interpolating costs. Make it an integer, too.
220 */
221 if (nrows > MAXIMUM_ROWCOUNT || isnan(nrows))
222 nrows = MAXIMUM_ROWCOUNT;
223 else if (nrows <= 1.0)
224 nrows = 1.0;
225 else
226 nrows = rint(nrows);
227
228 return nrows;
229}
#define MAXIMUM_ROWCOUNT
Definition: costsize.c:128

References MAXIMUM_ROWCOUNT.

Referenced by adjust_limit_rows_costs(), approx_tuple_count(), bernoulli_samplescangetsamplesize(), calc_joinrel_size_estimate(), compute_bitmap_pages(), compute_gather_rows(), cost_agg(), cost_append(), cost_bitmap_heap_scan(), cost_group(), cost_index(), cost_seqscan(), cost_subplan(), cost_subqueryscan(), create_bitmap_subplan(), create_memoize_path(), 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(), system_time_samplescangetsamplesize(), and table_block_relation_estimate_size().

◆ clamp_width_est()

int32 clamp_width_est ( int64  tuple_width)

Definition at line 242 of file costsize.c.

243{
244 /*
245 * Anything more than MaxAllocSize is clearly bogus, since we could not
246 * create a tuple that large.
247 */
248 if (tuple_width > MaxAllocSize)
249 return (int32) MaxAllocSize;
250
251 /*
252 * Unlike clamp_row_est, we just Assert that the value isn't negative,
253 * rather than masking such errors.
254 */
255 Assert(tuple_width >= 0);
256
257 return (int32) tuple_width;
258}
int32_t int32
Definition: c.h:498
#define MaxAllocSize
Definition: fe_memutils.h:22

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
tree ctl root
Definition: radixtree.h:1857

References clause_selectivity_ext(), and root.

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 */
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. */
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 */
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 */
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 */
893 (RowCompareExpr *) clause,
894 varRelid,
895 jointype,
896 sjinfo);
897 }
898 else if (IsA(clause, NullTest))
899 {
900 /* Use node specific selectivity calculation function */
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 */
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 */
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 */
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:2397
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:226
#define DEBUG4
Definition: elog.h:27
static bool is_andclause(const void *clause)
Definition: nodeFuncs.h:107
static bool is_orclause(const void *clause)
Definition: nodeFuncs.h:116
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:76
static bool is_funcclause(const void *clause)
Definition: nodeFuncs.h:69
static bool is_notclause(const void *clause)
Definition: nodeFuncs.h:125
static Expr * get_notclausearg(const void *notclause)
Definition: nodeFuncs.h:134
double Selectivity
Definition: nodes.h:256
@ JOIN_INNER
Definition: nodes.h:299
void * arg
Selectivity restriction_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, int varRelid)
Definition: plancat.c:1969
Selectivity join_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: plancat.c:2008
Selectivity function_selectivity(PlannerInfo *root, Oid funcid, List *args, Oid inputcollid, bool is_join, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: plancat.c:2049
static bool DatumGetBool(Datum X)
Definition: postgres.h:95
unsigned int Oid
Definition: postgres_ext.h:30
char * s1
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:414
Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1545
Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1703
Selectivity boolvarsel(PlannerInfo *root, Node *arg, int varRelid)
Definition: selfuncs.c:1517
Selectivity scalararraysel(PlannerInfo *root, ScalarArrayOpExpr *clause, bool is_join_clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:1821
Selectivity rowcomparesel(PlannerInfo *root, RowCompareExpr *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: selfuncs.c:2210
Oid funcid
Definition: primnodes.h:767
List * args
Definition: primnodes.h:785
Definition: nodes.h:135
Oid opno
Definition: primnodes.h:835
List * args
Definition: primnodes.h:853
Cardinality tuples
Definition: pathnodes.h:976
Expr * clause
Definition: pathnodes.h:2700
Definition: primnodes.h:262
int varno
Definition: primnodes.h:269
Index varlevelsup
Definition: primnodes.h:294

References arg, generate_unaccent_rules::args, FuncExpr::args, OpExpr::args, bms_is_member(), booltestsel(), boolvarsel(), RestrictInfo::clause, clause_selectivity_ext(), 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(), root, rowcomparesel(), s1, scalararraysel(), treat_as_join_clause(), RelOptInfo::tuples, and RangeQueryClause::var.

Referenced by clause_selectivity(), clause_selectivity_ext(), 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;
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 */
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:2132
bool is_pseudo_constant_clause(Node *clause)
Definition: clauses.c:2090
bool is_pseudo_constant_clause_relids(Node *clause, Relids relids)
Definition: clauses.c:2110
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:1697
void pfree(void *pointer)
Definition: mcxt.c:2147
@ RTE_RELATION
Definition: parsenodes.h:1026
#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:1957
#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:973
RTEKind rtekind
Definition: pathnodes.h:949

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(), root, 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 491 of file clauses.c.

492{
493 /* We assume here that expression_planner() won't scribble on its input */
494 expr = expression_planner(expr);
495
496 /* Now we can search for non-immutable functions */
497 return contain_mutable_functions((Node *) expr);
498}
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:371
Expr * expression_planner(Expr *expr)
Definition: planner.c:6645

References contain_mutable_functions(), and expression_planner().

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

◆ contain_var_clause()

◆ contain_vars_of_level()

bool contain_vars_of_level ( Node node,
int  levelsup 
)

◆ contain_vars_returning_old_or_new()

bool contain_vars_returning_old_or_new ( Node node)

Definition at line 511 of file var.c.

512{
514}
static bool contain_vars_returning_old_or_new_walker(Node *node, void *context)
Definition: var.c:517

References contain_vars_returning_old_or_new_walker().

Referenced by make_modifytable().

◆ contain_volatile_functions()

bool contain_volatile_functions ( Node clause)

Definition at line 539 of file clauses.c.

540{
541 return contain_volatile_functions_walker(clause, NULL);
542}
static bool contain_volatile_functions_walker(Node *node, void *context)
Definition: clauses.c:551

References contain_volatile_functions_walker().

Referenced by apply_child_basequals(), ATExecAddColumn(), check_hashjoinable(), check_mergejoinable(), check_output_expressions(), compute_semijoin_info(), contain_volatile_functions_after_planning(), convert_ANY_sublink_to_join(), convert_EXISTS_sublink_to_join(), convert_EXISTS_to_ANY(), convert_VALUES_to_ANY(), CopyFrom(), distribute_qual_to_rels(), estimate_num_groups(), ExecInitWindowAgg(), expand_indexqual_rowcompare(), find_compatible_agg(), find_simplified_clause(), get_eclass_for_sort_expr(), get_memoize_path(), group_similar_or_args(), initialize_peragg(), inline_function(), inline_set_returning_function(), is_pseudo_constant_clause(), is_pseudo_constant_clause_relids(), is_pseudo_constant_for_index(), is_safe_restriction_clause_for(), is_simple_subquery(), is_simple_values(), IsBinaryTidClause(), IsTidEqualAnyClause(), make_sort_input_target(), mark_nullable_by_grouping(), match_clause_to_ordering_op(), match_clause_to_partition_key(), match_opclause_to_indexcol(), match_orclause_to_indexcol(), match_rowcompare_to_indexcol(), match_saopclause_to_indexcol(), paraminfo_get_equal_hashops(), qual_is_pushdown_safe(), remove_unused_subquery_outputs(), SS_process_ctes(), and subquery_planner().

◆ contain_volatile_functions_after_planning()

bool contain_volatile_functions_after_planning ( Expr expr)

Definition at line 660 of file clauses.c.

661{
662 /* We assume here that expression_planner() won't scribble on its input */
663 expr = expression_planner(expr);
664
665 /* Now we can search for volatile functions */
666 return contain_volatile_functions((Node *) expr);
667}
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:539

References contain_volatile_functions(), and expression_planner().

◆ contain_volatile_functions_not_nextval()

bool contain_volatile_functions_not_nextval ( Node clause)

Definition at line 674 of file clauses.c.

675{
677}
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:687

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 2289 of file clauses.c.

2290{
2291 (void) convert_saop_to_hashed_saop_walker(node, NULL);
2292}
static bool convert_saop_to_hashed_saop_walker(Node *node, void *context)
Definition: clauses.c:2295

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 2397 of file clauses.c.

2398{
2400
2401 context.boundParams = root->glob->boundParams; /* bound Params */
2402 /* we do not need to mark the plan as depending on inlined functions */
2403 context.root = NULL;
2404 context.active_fns = NIL; /* nothing being recursively simplified */
2405 context.case_val = NULL; /* no CASE being examined */
2406 context.estimate = true; /* unsafe transformations OK */
2407 return eval_const_expressions_mutator(node, &context);
2408}
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2442
ParamListInfo boundParams
Definition: clauses.c:63

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(), NIL, eval_const_expressions_context::root, and root.

Referenced by array_unnest_support(), bernoulli_samplescangetsamplesize(), clause_selectivity_ext(), generate_series_int4_support(), generate_series_int8_support(), generate_series_numeric_support(), generate_series_timestamp_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 4976 of file clauses.c.

4978{
4979 EState *estate;
4980 ExprState *exprstate;
4981 MemoryContext oldcontext;
4982 Datum const_val;
4983 bool const_is_null;
4984 int16 resultTypLen;
4985 bool resultTypByVal;
4986
4987 /*
4988 * To use the executor, we need an EState.
4989 */
4990 estate = CreateExecutorState();
4991
4992 /* We can use the estate's working context to avoid memory leaks. */
4993 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
4994
4995 /* Make sure any opfuncids are filled in. */
4996 fix_opfuncids((Node *) expr);
4997
4998 /*
4999 * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
5000 * because it'd result in recursively invoking eval_const_expressions.)
5001 */
5002 exprstate = ExecInitExpr(expr, NULL);
5003
5004 /*
5005 * And evaluate it.
5006 *
5007 * It is OK to use a default econtext because none of the ExecEvalExpr()
5008 * code used in this situation will use econtext. That might seem
5009 * fortuitous, but it's not so unreasonable --- a constant expression does
5010 * not depend on context, by definition, n'est ce pas?
5011 */
5012 const_val = ExecEvalExprSwitchContext(exprstate,
5013 GetPerTupleExprContext(estate),
5014 &const_is_null);
5015
5016 /* Get info needed about result datatype */
5017 get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
5018
5019 /* Get back to outer memory context */
5020 MemoryContextSwitchTo(oldcontext);
5021
5022 /*
5023 * Must copy result out of sub-context used by expression eval.
5024 *
5025 * Also, if it's varlena, forcibly detoast it. This protects us against
5026 * storing TOAST pointers into plans that might outlive the referenced
5027 * data. (makeConst would handle detoasting anyway, but it's worth a few
5028 * extra lines here so that we can do the copy and detoast in one step.)
5029 */
5030 if (!const_is_null)
5031 {
5032 if (resultTypLen == -1)
5033 const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
5034 else
5035 const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
5036 }
5037
5038 /* Release all the junk we just created */
5039 FreeExecutorState(estate);
5040
5041 /*
5042 * Make the constant result node.
5043 */
5044 return (Expr *) makeConst(result_type, result_typmod, result_collation,
5045 resultTypLen,
5046 const_val, const_is_null,
5047 resultTypByVal);
5048}
int16_t int16
Definition: c.h:497
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:143
void FreeExecutorState(EState *estate)
Definition: execUtils.c:193
EState * CreateExecutorState(void)
Definition: execUtils.c:88
#define GetPerTupleExprContext(estate)
Definition: executor.h:678
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:458
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2391
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:350
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1841
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
MemoryContext es_query_cxt
Definition: execnodes.h:708

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 6645 of file planner.c.

6646{
6647 Node *result;
6648
6649 /*
6650 * Convert named-argument function calls, insert default arguments and
6651 * simplify constant subexprs
6652 */
6653 result = eval_const_expressions(NULL, (Node *) expr);
6654
6655 /* Fill in opfuncid values if missing */
6656 fix_opfuncids(result);
6657
6658 return (Expr *) result;
6659}
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2256

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(), and transformPartitionBoundValue().

◆ expression_planner_with_deps()

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

Definition at line 6672 of file planner.c.

6675{
6676 Node *result;
6677 PlannerGlobal glob;
6679
6680 /* Make up dummy planner state so we can use setrefs machinery */
6681 MemSet(&glob, 0, sizeof(glob));
6682 glob.type = T_PlannerGlobal;
6683 glob.relationOids = NIL;
6684 glob.invalItems = NIL;
6685
6686 MemSet(&root, 0, sizeof(root));
6687 root.type = T_PlannerInfo;
6688 root.glob = &glob;
6689
6690 /*
6691 * Convert named-argument function calls, insert default arguments and
6692 * simplify constant subexprs. Collect identities of inlined functions
6693 * and elided domains, too.
6694 */
6695 result = eval_const_expressions(&root, (Node *) expr);
6696
6697 /* Fill in opfuncid values if missing */
6698 fix_opfuncids(result);
6699
6700 /*
6701 * Now walk the finished expression to find anything else we ought to
6702 * record as an expression dependency.
6703 */
6704 (void) extract_query_dependencies_walker(result, &root);
6705
6706 *relationOids = glob.relationOids;
6707 *invalItems = glob.invalItems;
6708
6709 return (Expr *) result;
6710}
#define MemSet(start, val, len)
Definition: c.h:991
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:3669
List * invalItems
Definition: pathnodes.h:154
List * relationOids
Definition: pathnodes.h:151

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

Referenced by GetCachedExpression().

◆ extract_query_dependencies()

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

Definition at line 3633 of file setrefs.c.

3637{
3638 PlannerGlobal glob;
3640
3641 /* Make up dummy planner state so we can use this module's machinery */
3642 MemSet(&glob, 0, sizeof(glob));
3643 glob.type = T_PlannerGlobal;
3644 glob.relationOids = NIL;
3645 glob.invalItems = NIL;
3646 /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
3647 glob.dependsOnRole = false;
3648
3649 MemSet(&root, 0, sizeof(root));
3650 root.type = T_PlannerInfo;
3651 root.glob = &glob;
3652
3654
3655 *relationOids = glob.relationOids;
3656 *invalItems = glob.invalItems;
3657 *hasRowSecurity = glob.dependsOnRole;
3658}
bool dependsOnRole
Definition: pathnodes.h:172

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

Referenced by CompleteCachedPlan(), and RevalidateCachedQuery().

◆ flatten_group_exprs()

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

Definition at line 968 of file var.c.

969{
971
972 /*
973 * We do not expect this to be applied to the whole Query, only to
974 * expressions or LATERAL subqueries. Hence, if the top node is a Query,
975 * it's okay to immediately increment sublevels_up.
976 */
977 Assert(node != (Node *) query);
978
979 context.root = root;
980 context.query = query;
981 context.sublevels_up = 0;
982 /* flag whether grouping expressions could possibly contain SubLinks */
983 context.possible_sublink = query->hasSubLinks;
984 /* if hasSubLinks is already true, no need to work hard */
985 context.inserted_sublink = query->hasSubLinks;
986
987 return flatten_group_exprs_mutator(node, &context);
988}
PlannerInfo * root
Definition: var.c:66
static Node * flatten_group_exprs_mutator(Node *node, flatten_join_alias_vars_context *context)
Definition: var.c:991

References Assert(), flatten_group_exprs_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, root, and flatten_join_alias_vars_context::sublevels_up.

Referenced by get_query_def(), and subquery_planner().

◆ flatten_join_alias_vars()

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

Definition at line 789 of file var.c.

790{
792
793 /*
794 * We do not expect this to be applied to the whole Query, only to
795 * expressions or LATERAL subqueries. Hence, if the top node is a Query,
796 * it's okay to immediately increment sublevels_up.
797 */
798 Assert(node != (Node *) query);
799
800 context.root = root;
801 context.query = query;
802 context.sublevels_up = 0;
803 /* flag whether join aliases could possibly contain SubLinks */
804 context.possible_sublink = query->hasSubLinks;
805 /* if hasSubLinks is already true, no need to work hard */
806 context.inserted_sublink = query->hasSubLinks;
807
808 return flatten_join_alias_vars_mutator(node, &context);
809}
static Node * flatten_join_alias_vars_mutator(Node *node, flatten_join_alias_vars_context *context)
Definition: var.c:812

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, 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:2219
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 preprocess_groupclause().

◆ 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:2225

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 4512 of file indxpath.c.

4513{
4514 /* pull_varnos is cheaper than volatility check, so do that first */
4515 if (bms_is_member(index->rel->relid, pull_varnos(root, expr)))
4516 return false; /* no good, contains Var of table */
4518 return false; /* no good, volatile comparison value */
4519 return true;
4520}
Definition: type.h:96
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:114

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

◆ locate_var_of_level()

int locate_var_of_level ( Node node,
int  levelsup 
)

Definition at line 555 of file var.c.

556{
558
559 context.var_location = -1; /* in case we find nothing */
560 context.sublevels_up = levelsup;
561
564 &context,
565 0);
566
567 return context.var_location;
568}
static bool locate_var_of_level_walker(Node *node, locate_var_of_level_context *context)
Definition: var.c:571

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

◆ make_SAOP_expr()

ScalarArrayOpExpr * make_SAOP_expr ( Oid  oper,
Node leftexpr,
Oid  coltype,
Oid  arraycollid,
Oid  inputcollid,
List exprs,
bool  haveNonConst 
)

Definition at line 5453 of file clauses.c.

5455{
5456 Node *arrayNode = NULL;
5457 ScalarArrayOpExpr *saopexpr = NULL;
5458 Oid arraytype = get_array_type(coltype);
5459
5460 if (!OidIsValid(arraytype))
5461 return NULL;
5462
5463 /*
5464 * Assemble an array from the list of constants. It seems more profitable
5465 * to build a const array. But in the presence of other nodes, we don't
5466 * have a specific value here and must employ an ArrayExpr instead.
5467 */
5468 if (haveNonConst)
5469 {
5470 ArrayExpr *arrayExpr = makeNode(ArrayExpr);
5471
5472 /* array_collid will be set by parse_collate.c */
5473 arrayExpr->element_typeid = coltype;
5474 arrayExpr->array_typeid = arraytype;
5475 arrayExpr->multidims = false;
5476 arrayExpr->elements = exprs;
5477 arrayExpr->location = -1;
5478
5479 arrayNode = (Node *) arrayExpr;
5480 }
5481 else
5482 {
5483 int16 typlen;
5484 bool typbyval;
5485 char typalign;
5486 Datum *elems;
5487 bool *nulls;
5488 int i = 0;
5489 ArrayType *arrayConst;
5490 int dims[1] = {list_length(exprs)};
5491 int lbs[1] = {1};
5492
5493 get_typlenbyvalalign(coltype, &typlen, &typbyval, &typalign);
5494
5495 elems = (Datum *) palloc(sizeof(Datum) * list_length(exprs));
5496 nulls = (bool *) palloc(sizeof(bool) * list_length(exprs));
5497 foreach_node(Const, value, exprs)
5498 {
5499 elems[i] = value->constvalue;
5500 nulls[i++] = value->constisnull;
5501 }
5502
5503 arrayConst = construct_md_array(elems, nulls, 1, dims, lbs,
5504 coltype, typlen, typbyval, typalign);
5505 arrayNode = (Node *) makeConst(arraytype, -1, arraycollid,
5506 -1, PointerGetDatum(arrayConst),
5507 false, false);
5508
5509 pfree(elems);
5510 pfree(nulls);
5511 list_free(exprs);
5512 }
5513
5514 /* Build the SAOP expression node */
5515 saopexpr = makeNode(ScalarArrayOpExpr);
5516 saopexpr->opno = oper;
5517 saopexpr->opfuncid = get_opcode(oper);
5518 saopexpr->hashfuncid = InvalidOid;
5519 saopexpr->negfuncid = InvalidOid;
5520 saopexpr->useOr = true;
5521 saopexpr->inputcollid = inputcollid;
5522 saopexpr->args = list_make2(leftexpr, arrayNode);
5523 saopexpr->location = -1;
5524
5525 return saopexpr;
5526}
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3494
#define OidIsValid(objectId)
Definition: c.h:746
static struct @165 value
int i
Definition: isn.c:77
void list_free(List *list)
Definition: list.c:1546
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2411
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1425
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2927
void * palloc(Size size)
Definition: mcxt.c:1940
#define makeNode(_type_)
Definition: nodes.h:161
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:370
#define foreach_node(type, var, lst)
Definition: pg_list.h:496
#define list_make2(x1, x2)
Definition: pg_list.h:214
char typalign
Definition: pg_type.h:176
#define InvalidOid
Definition: postgres_ext.h:35
ParseLoc location
Definition: primnodes.h:1401
ParseLoc location
Definition: primnodes.h:936

References ScalarArrayOpExpr::args, construct_md_array(), foreach_node, get_array_type(), get_opcode(), get_typlenbyvalalign(), i, InvalidOid, list_free(), list_length(), list_make2, ScalarArrayOpExpr::location, ArrayExpr::location, makeConst(), makeNode, OidIsValid, oper(), ScalarArrayOpExpr::opno, palloc(), pfree(), PointerGetDatum(), typalign, ScalarArrayOpExpr::useOr, and value.

Referenced by convert_VALUES_to_ANY(), and match_orclause_to_indexcol().

◆ 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 ?
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:1673
Expr * make_orclause(List *orclauses)
Definition: makefuncs.c:743
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:408
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:727
Expr * make_notclause(Expr *notclause)
Definition: makefuncs.c:759
#define nodeTag(nodeptr)
Definition: nodes.h:139
Node * negate_clause(Node *node)
Definition: prepqual.c:73
char * c
@ IS_NOT_TRUE
Definition: primnodes.h:1981
@ IS_NOT_FALSE
Definition: primnodes.h:1981
@ IS_NOT_UNKNOWN
Definition: primnodes.h:1981
@ IS_TRUE
Definition: primnodes.h:1981
@ IS_UNKNOWN
Definition: primnodes.h:1981
@ IS_FALSE
Definition: primnodes.h:1981
@ AND_EXPR
Definition: primnodes.h:948
@ OR_EXPR
Definition: primnodes.h:948
@ NOT_EXPR
Definition: primnodes.h:948
@ IS_NOT_NULL
Definition: primnodes.h:1957
BoolExprType boolop
Definition: primnodes.h:956
List * args
Definition: primnodes.h:957
ParseLoc location
Definition: primnodes.h:1989
BoolTestType booltesttype
Definition: primnodes.h:1988
Expr * arg
Definition: primnodes.h:1987
NullTestType nulltesttype
Definition: primnodes.h:1964
ParseLoc location
Definition: primnodes.h:1967
Expr * arg
Definition: primnodes.h:1963
ParseLoc location
Definition: primnodes.h:856

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, negate_clause(), 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(), negate_clause(), and simplify_boolean_equality().

◆ plan_cluster_use_sort()

bool plan_cluster_use_sort ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 6725 of file planner.c.

6726{
6728 Query *query;
6729 PlannerGlobal *glob;
6730 RangeTblEntry *rte;
6731 RelOptInfo *rel;
6732 IndexOptInfo *indexInfo;
6733 QualCost indexExprCost;
6734 Cost comparisonCost;
6735 Path *seqScanPath;
6736 Path seqScanAndSortPath;
6737 IndexPath *indexScanPath;
6738 ListCell *lc;
6739
6740 /* We can short-circuit the cost comparison if indexscans are disabled */
6741 if (!enable_indexscan)
6742 return true; /* use sort */
6743
6744 /* Set up mostly-dummy planner state */
6745 query = makeNode(Query);
6746 query->commandType = CMD_SELECT;
6747
6748 glob = makeNode(PlannerGlobal);
6749
6751 root->parse = query;
6752 root->glob = glob;
6753 root->query_level = 1;
6754 root->planner_cxt = CurrentMemoryContext;
6755 root->wt_param_id = -1;
6756 root->join_domains = list_make1(makeNode(JoinDomain));
6757
6758 /* Build a minimal RTE for the rel */
6759 rte = makeNode(RangeTblEntry);
6760 rte->rtekind = RTE_RELATION;
6761 rte->relid = tableOid;
6762 rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
6763 rte->rellockmode = AccessShareLock;
6764 rte->lateral = false;
6765 rte->inh = false;
6766 rte->inFromCl = true;
6767 query->rtable = list_make1(rte);
6768 addRTEPermissionInfo(&query->rteperminfos, rte);
6769
6770 /* Set up RTE/RelOptInfo arrays */
6772
6773 /* Build RelOptInfo */
6774 rel = build_simple_rel(root, 1, NULL);
6775
6776 /* Locate IndexOptInfo for the target index */
6777 indexInfo = NULL;
6778 foreach(lc, rel->indexlist)
6779 {
6780 indexInfo = lfirst_node(IndexOptInfo, lc);
6781 if (indexInfo->indexoid == indexOid)
6782 break;
6783 }
6784
6785 /*
6786 * It's possible that get_relation_info did not generate an IndexOptInfo
6787 * for the desired index; this could happen if it's not yet reached its
6788 * indcheckxmin usability horizon, or if it's a system index and we're
6789 * ignoring system indexes. In such cases we should tell CLUSTER to not
6790 * trust the index contents but use seqscan-and-sort.
6791 */
6792 if (lc == NULL) /* not in the list? */
6793 return true; /* use sort */
6794
6795 /*
6796 * Rather than doing all the pushups that would be needed to use
6797 * set_baserel_size_estimates, just do a quick hack for rows and width.
6798 */
6799 rel->rows = rel->tuples;
6800 rel->reltarget->width = get_relation_data_width(tableOid, NULL);
6801
6802 root->total_table_pages = rel->pages;
6803
6804 /*
6805 * Determine eval cost of the index expressions, if any. We need to
6806 * charge twice that amount for each tuple comparison that happens during
6807 * the sort, since tuplesort.c will have to re-evaluate the index
6808 * expressions each time. (XXX that's pretty inefficient...)
6809 */
6810 cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
6811 comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
6812
6813 /* Estimate the cost of seq scan + sort */
6814 seqScanPath = create_seqscan_path(root, rel, NULL, 0);
6815 cost_sort(&seqScanAndSortPath, root, NIL,
6816 seqScanPath->disabled_nodes,
6817 seqScanPath->total_cost, rel->tuples, rel->reltarget->width,
6818 comparisonCost, maintenance_work_mem, -1.0);
6819
6820 /* Estimate the cost of index scan */
6821 indexScanPath = create_index_path(root, indexInfo,
6822 NIL, NIL, NIL, NIL,
6823 ForwardScanDirection, false,
6824 NULL, 1.0, false);
6825
6826 return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
6827}
void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, int input_disabled_nodes, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:2144
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:4741
bool enable_indexscan
Definition: costsize.c:146
int maintenance_work_mem
Definition: globals.c:134
#define AccessShareLock
Definition: lockdefs.h:36
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
double Cost
Definition: nodes.h:257
@ CMD_SELECT
Definition: nodes.h:271
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:1049
Path * create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer, int parallel_workers)
Definition: pathnode.c:983
#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:1236
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:1846
int disabled_nodes
Definition: pathnodes.h:1797
Cost total_cost
Definition: pathnodes.h:1799
Cost per_tuple
Definition: pathnodes.h:48
Cost startup
Definition: pathnodes.h:47
List * rtable
Definition: parsenodes.h:170
CmdType commandType
Definition: parsenodes.h:121
RTEKind rtekind
Definition: parsenodes.h:1061
struct PathTarget * reltarget
Definition: pathnodes.h:920
BlockNumber pages
Definition: pathnodes.h:975
List * indexlist
Definition: pathnodes.h:971
Cardinality rows
Definition: pathnodes.h:904

References AccessShareLock, addRTEPermissionInfo(), build_simple_rel(), CMD_SELECT, Query::commandType, cost_qual_eval(), cost_sort(), create_index_path(), create_seqscan_path(), CurrentMemoryContext, Path::disabled_nodes, enable_indexscan, ForwardScanDirection, get_relation_data_width(), RelOptInfo::indexlist, IndexOptInfo::indexoid, RangeTblEntry::inh, lfirst_node, list_make1, maintenance_work_mem, makeNode, NIL, RelOptInfo::pages, IndexPath::path, QualCost::per_tuple, RelOptInfo::reltarget, root, RelOptInfo::rows, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, setup_simple_rel_arrays(), QualCost::startup, Path::total_cost, RelOptInfo::tuples, and PathTarget::width.

Referenced by copy_table_data().

◆ plan_create_index_workers()

int plan_create_index_workers ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 6847 of file planner.c.

6848{
6850 Query *query;
6851 PlannerGlobal *glob;
6852 RangeTblEntry *rte;
6853 Relation heap;
6855 RelOptInfo *rel;
6856 int parallel_workers;
6857 BlockNumber heap_blocks;
6858 double reltuples;
6859 double allvisfrac;
6860
6861 /*
6862 * We don't allow performing parallel operation in standalone backend or
6863 * when parallelism is disabled.
6864 */
6866 return 0;
6867
6868 /* Set up largely-dummy planner state */
6869 query = makeNode(Query);
6870 query->commandType = CMD_SELECT;
6871
6872 glob = makeNode(PlannerGlobal);
6873
6875 root->parse = query;
6876 root->glob = glob;
6877 root->query_level = 1;
6878 root->planner_cxt = CurrentMemoryContext;
6879 root->wt_param_id = -1;
6880 root->join_domains = list_make1(makeNode(JoinDomain));
6881
6882 /*
6883 * Build a minimal RTE.
6884 *
6885 * Mark the RTE with inh = true. This is a kludge to prevent
6886 * get_relation_info() from fetching index info, which is necessary
6887 * because it does not expect that any IndexOptInfo is currently
6888 * undergoing REINDEX.
6889 */
6890 rte = makeNode(RangeTblEntry);
6891 rte->rtekind = RTE_RELATION;
6892 rte->relid = tableOid;
6893 rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
6894 rte->rellockmode = AccessShareLock;
6895 rte->lateral = false;
6896 rte->inh = true;
6897 rte->inFromCl = true;
6898 query->rtable = list_make1(rte);
6899 addRTEPermissionInfo(&query->rteperminfos, rte);
6900
6901 /* Set up RTE/RelOptInfo arrays */
6903
6904 /* Build RelOptInfo */
6905 rel = build_simple_rel(root, 1, NULL);
6906
6907 /* Rels are assumed already locked by the caller */
6908 heap = table_open(tableOid, NoLock);
6909 index = index_open(indexOid, NoLock);
6910
6911 /*
6912 * Determine if it's safe to proceed.
6913 *
6914 * Currently, parallel workers can't access the leader's temporary tables.
6915 * Furthermore, any index predicate or index expressions must be parallel
6916 * safe.
6917 */
6918 if (heap->rd_rel->relpersistence == RELPERSISTENCE_TEMP ||
6921 {
6922 parallel_workers = 0;
6923 goto done;
6924 }
6925
6926 /*
6927 * If parallel_workers storage parameter is set for the table, accept that
6928 * as the number of parallel worker processes to launch (though still cap
6929 * at max_parallel_maintenance_workers). Note that we deliberately do not
6930 * consider any other factor when parallel_workers is set. (e.g., memory
6931 * use by workers.)
6932 */
6933 if (rel->rel_parallel_workers != -1)
6934 {
6935 parallel_workers = Min(rel->rel_parallel_workers,
6937 goto done;
6938 }
6939
6940 /*
6941 * Estimate heap relation size ourselves, since rel->pages cannot be
6942 * trusted (heap RTE was marked as inheritance parent)
6943 */
6944 estimate_rel_size(heap, NULL, &heap_blocks, &reltuples, &allvisfrac);
6945
6946 /*
6947 * Determine number of workers to scan the heap relation using generic
6948 * model
6949 */
6950 parallel_workers = compute_parallel_worker(rel, heap_blocks, -1,
6952
6953 /*
6954 * Cap workers based on available maintenance_work_mem as needed.
6955 *
6956 * Note that each tuplesort participant receives an even share of the
6957 * total maintenance_work_mem budget. Aim to leave participants
6958 * (including the leader as a participant) with no less than 32MB of
6959 * memory. This leaves cases where maintenance_work_mem is set to 64MB
6960 * immediately past the threshold of being capable of launching a single
6961 * parallel worker to sort.
6962 */
6963 while (parallel_workers > 0 &&
6964 maintenance_work_mem / (parallel_workers + 1) < 32 * 1024)
6965 parallel_workers--;
6966
6967done:
6969 table_close(heap, NoLock);
6970
6971 return parallel_workers;
6972}
int compute_parallel_worker(RelOptInfo *rel, double heap_pages, double index_pages, int max_workers)
Definition: allpaths.c:4234
uint32 BlockNumber
Definition: block.h:31
#define Min(x, y)
Definition: c.h:975
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:754
int max_parallel_maintenance_workers
Definition: globals.c:135
bool IsUnderPostmaster
Definition: globals.c:121
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:1069
List * RelationGetIndexPredicate(Relation relation)
Definition: relcache.c:5193
List * RelationGetIndexExpressions(Relation relation)
Definition: relcache.c:5080
int rel_parallel_workers
Definition: pathnodes.h:983
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(), index_close(), index_open(), RangeTblEntry::inh, is_parallel_safe(), IsUnderPostmaster, list_make1, maintenance_work_mem, makeNode, max_parallel_maintenance_workers, Min, NoLock, RelationData::rd_rel, RelOptInfo::rel_parallel_workers, RelationGetIndexExpressions(), RelationGetIndexPredicate(), root, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, setup_simple_rel_arrays(), table_close(), and table_open().

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

654{
656
657 /* Assert that caller has not specified inconsistent flags */
664
665 context.varlist = NIL;
666 context.flags = flags;
667
668 pull_var_clause_walker(node, &context);
669 return context.varlist;
670}
#define PVC_RECURSE_AGGREGATES
Definition: optimizer.h:193
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:197
#define PVC_RECURSE_WINDOWFUNCS
Definition: optimizer.h:195
#define PVC_INCLUDE_WINDOWFUNCS
Definition: optimizer.h:194
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:196
#define PVC_INCLUDE_AGGREGATES
Definition: optimizer.h:192
static bool pull_var_clause_walker(Node *node, pull_var_clause_context *context)
Definition: var.c:673

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(), rebuild_eclass_attr_needed(), rebuild_joinclause_attr_needed(), rebuild_placeholder_attr_needed(), 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 114 of file var.c.

115{
116 pull_varnos_context context;
117
118 context.varnos = NULL;
119 context.root = root;
120 context.sublevels_up = 0;
121
122 /*
123 * Must be prepared to start with a Query or a bare expression tree; if
124 * it's a Query, we don't want to increment sublevels_up.
125 */
128 &context,
129 0);
130
131 return context.varnos;
132}
PlannerInfo * root
Definition: var.c:36
int sublevels_up
Definition: var.c:37
Relids varnos
Definition: var.c:35
static bool pull_varnos_walker(Node *node, pull_varnos_context *context)
Definition: var.c:161

References pull_varnos_walker(), query_or_expression_tree_walker, pull_varnos_context::root, 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(), extract_lateral_vars_from_PHVs(), find_placeholder_info(), get_eclass_for_sort_expr(), is_pseudo_constant_for_index(), IsTidEqualAnyClause(), join_is_removable(), make_outerjoininfo(), make_plain_restrictinfo(), match_rowcompare_to_indexcol(), match_saopclause_to_indexcol(), NumRelids(), pg_get_expr_worker(), process_implied_equality(), pullup_replace_vars_callback(), remove_leftjoinrel_from_query(), and subquery_planner().

◆ pull_varnos_of_level()

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

Definition at line 140 of file var.c.

141{
142 pull_varnos_context context;
143
144 context.varnos = NULL;
145 context.root = root;
146 context.sublevels_up = levelsup;
147
148 /*
149 * Must be prepared to start with a Query or a bare expression tree; if
150 * it's a Query, we don't want to increment sublevels_up.
151 */
154 &context,
155 0);
156
157 return context.varnos;
158}

References pull_varnos_walker(), query_or_expression_tree_walker, pull_varnos_context::root, 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(), jointree_contains_lateral_outer_refs(), and mark_nullable_by_grouping().

◆ pull_vars_of_level()

List * pull_vars_of_level ( Node node,
int  levelsup 
)

Definition at line 339 of file var.c.

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

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(), and extract_lateral_vars_from_PHVs().

Variable Documentation

◆ cpu_index_tuple_cost

PGDLLIMPORT double cpu_index_tuple_cost
extern

Definition at line 133 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 68 of file planner.c.

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

◆ effective_cache_size

PGDLLIMPORT int effective_cache_size
extern

Definition at line 139 of file costsize.c.

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

◆ enable_distinct_reordering

PGDLLIMPORT bool enable_distinct_reordering
extern

Definition at line 70 of file planner.c.

Referenced by get_useful_pathkeys_for_distinct().

◆ parallel_leader_participation

PGDLLIMPORT bool parallel_leader_participation
extern

Definition at line 69 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 136 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 135 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 137 of file costsize.c.

Referenced by set_cte_size_estimates().

◆ seq_page_cost