PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 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 ExplainState ExplainState
 
typedef struct PlannerInfo PlannerInfo
 
typedef struct IndexOptInfo IndexOptInfo
 
typedef struct SpecialJoinInfo SpecialJoinInfo
 
typedef struct PlannedStmt PlannedStmt
 
typedef struct ParamListInfoData * ParamListInfo
 
typedef struct HeapTupleData * HeapTuple
 

Enumerations

enum  DebugParallelMode { DEBUG_PARALLEL_OFF , DEBUG_PARALLEL_ON , DEBUG_PARALLEL_REGRESS }
 
enum  NotNullSource { NOTNULL_SOURCE_RELOPT , NOTNULL_SOURCE_HASHTABLE , NOTNULL_SOURCE_CATALOG }
 

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)
 
bool is_pseudo_constant_for_index (PlannerInfo *root, Node *expr, IndexOptInfo *index)
 
PlannedStmt * planner (Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams, ExplainState *es)
 
Expr * expression_planner (Expr *expr)
 
Expr * expression_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)
 
Node * negate_clause (Node *node)
 
Expr * canonicalize_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)
 
Node * eval_const_expressions (PlannerInfo *root, Node *node)
 
void convert_saop_to_hashed_saop (Node *node)
 
Node * estimate_expression_value (PlannerInfo *root, Node *node)
 
Expr * evaluate_expr (Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
 
bool var_is_nonnullable (PlannerInfo *root, Var *var, NotNullSource source)
 
bool expr_is_nonnullable (PlannerInfo *root, Expr *expr, NotNullSource source)
 
List * expand_function_arguments (List *args, bool include_out_arguments, Oid result_type, HeapTuple func_tuple)
 
ScalarArrayOpExpr * make_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)
 
TargetEntry * get_sortgroupref_tle (Index sortref, List *targetList)
 
TargetEntry * get_sortgroupclause_tle (SortGroupClause *sgClause, List *targetList)
 
Node * get_sortgroupclause_expr (SortGroupClause *sgClause, List *targetList)
 
List * get_sortgrouplist_exprs (List *sgClauses, List *targetList)
 
SortGroupClause * get_sortgroupref_clause (Index sortref, List *clauses)
 
SortGroupClause * get_sortgroupref_clause_noerr (Index sortref, List *clauses)
 
Bitmapset * pull_varnos (PlannerInfo *root, Node *node)
 
Bitmapset * pull_varnos_of_level (PlannerInfo *root, Node *node, int levelsup)
 
void pull_varattnos (Node *node, Index varno, Bitmapset **varattnos)
 
List * pull_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)
 
List * pull_var_clause (Node *node, int flags)
 
Node * flatten_join_alias_vars (PlannerInfo *root, Query *query, Node *node)
 
Node * flatten_join_alias_for_parser (Query *query, Node *node, int sublevels_up)
 
Node * flatten_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

◆ PVC_INCLUDE_AGGREGATES

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

Definition at line 197 of file optimizer.h.

◆ PVC_INCLUDE_PLACEHOLDERS

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

Definition at line 201 of file optimizer.h.

◆ PVC_INCLUDE_WINDOWFUNCS

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

Definition at line 199 of file optimizer.h.

◆ PVC_RECURSE_AGGREGATES

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

Definition at line 198 of file optimizer.h.

◆ PVC_RECURSE_PLACEHOLDERS

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

Definition at line 202 of file optimizer.h.

◆ PVC_RECURSE_WINDOWFUNCS

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

Definition at line 200 of file optimizer.h.

Typedef Documentation

◆ ExplainState

Definition at line 27 of file optimizer.h.

◆ HeapTuple

Definition at line 42 of file optimizer.h.

◆ IndexOptInfo

Definition at line 36 of file optimizer.h.

◆ ParamListInfo

Definition at line 41 of file optimizer.h.

◆ PlannedStmt

Definition at line 40 of file optimizer.h.

◆ PlannerInfo

Definition at line 35 of file optimizer.h.

◆ SpecialJoinInfo

Definition at line 37 of file optimizer.h.

Enumeration Type Documentation

◆ DebugParallelMode

Enumerator
DEBUG_PARALLEL_OFF 
DEBUG_PARALLEL_ON 
DEBUG_PARALLEL_REGRESS 

Definition at line 94 of file optimizer.h.

95{
DebugParallelMode
Definition optimizer.h:95
@ DEBUG_PARALLEL_REGRESS
Definition optimizer.h:98
@ DEBUG_PARALLEL_ON
Definition optimizer.h:97
@ DEBUG_PARALLEL_OFF
Definition optimizer.h:96

◆ NotNullSource

Enumerator
NOTNULL_SOURCE_RELOPT 
NOTNULL_SOURCE_HASHTABLE 
NOTNULL_SOURCE_CATALOG 

Definition at line 134 of file optimizer.h.

135{
136 NOTNULL_SOURCE_RELOPT, /* Use RelOptInfo */
137 NOTNULL_SOURCE_HASHTABLE, /* Use Global Hash Table */
138 NOTNULL_SOURCE_CATALOG, /* Use System Catalog */
NotNullSource
Definition optimizer.h:135
@ NOTNULL_SOURCE_HASHTABLE
Definition optimizer.h:137
@ NOTNULL_SOURCE_RELOPT
Definition optimizer.h:136
@ NOTNULL_SOURCE_CATALOG
Definition optimizer.h:138

Function Documentation

◆ canonicalize_qual()

Expr * canonicalize_qual ( Expr *  qual,
bool  is_check 
)
extern

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 */
310
311 return newqual;
312}
#define Assert(condition)
Definition c.h:1002
#define IsA(nodeptr, _type_)
Definition nodes.h:162
static Expr * find_duplicate_ors(Expr *qual, bool is_check)
Definition prepqual.c:406
static int fb(int x)
Definition pg_list.h:54

References Assert, fb(), 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_row_est()

double clamp_row_est ( double  nrows)
extern

Definition at line 215 of file costsize.c.

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

References fb(), and MAXIMUM_ROWCOUNT.

Referenced by adjust_limit_rows_costs(), adjust_statstuple_for_grouping(), 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(), cost_tidrangescan(), 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)
extern

Definition at line 244 of file costsize.c.

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

References Assert, fb(), 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 
)
extern

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 
)
extern

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,
807 }
808 else if (is_andclause(clause))
809 {
810 /* share code with clauselist_selectivity() */
812 ((BoolExpr *) clause)->args,
813 varRelid,
814 jointype,
815 sjinfo,
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,
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 /* If no support, fall back on boolvarsel */
879 if (s1 < 0)
880 s1 = boolvarsel(root, clause, varRelid);
881 }
882 else if (IsA(clause, ScalarArrayOpExpr))
883 {
884 /* Use node specific selectivity calculation function */
886 (ScalarArrayOpExpr *) clause,
887 treat_as_join_clause(root, clause, rinfo,
888 varRelid, sjinfo),
889 varRelid,
890 jointype,
891 sjinfo);
892 }
893 else if (IsA(clause, RowCompareExpr))
894 {
895 /* Use node specific selectivity calculation function */
897 (RowCompareExpr *) clause,
898 varRelid,
899 jointype,
900 sjinfo);
901 }
902 else if (IsA(clause, NullTest))
903 {
904 /* Use node specific selectivity calculation function */
906 ((NullTest *) clause)->nulltesttype,
907 (Node *) ((NullTest *) clause)->arg,
908 varRelid,
909 jointype,
910 sjinfo);
911 }
912 else if (IsA(clause, BooleanTest))
913 {
914 /* Use node specific selectivity calculation function */
916 ((BooleanTest *) clause)->booltesttype,
917 (Node *) ((BooleanTest *) clause)->arg,
918 varRelid,
919 jointype,
920 sjinfo);
921 }
922 else if (IsA(clause, CurrentOfExpr))
923 {
924 /* CURRENT OF selects at most one row of its table */
925 CurrentOfExpr *cexpr = (CurrentOfExpr *) clause;
927
928 if (crel->tuples > 0)
929 s1 = 1.0 / crel->tuples;
930 }
931 else if (IsA(clause, RelabelType))
932 {
933 /* Not sure this case is needed, but it can't hurt */
935 (Node *) ((RelabelType *) clause)->arg,
936 varRelid,
937 jointype,
938 sjinfo,
940 }
941 else if (IsA(clause, CoerceToDomain))
942 {
943 /* Not sure this case is needed, but it can't hurt */
945 (Node *) ((CoerceToDomain *) clause)->arg,
946 varRelid,
947 jointype,
948 sjinfo,
950 }
951 else
952 {
953 /*
954 * For anything else, see if we can consider it as a boolean variable.
955 * This only works if it's an immutable expression in Vars of a single
956 * relation; but there's no point in us checking that here because
957 * boolvarsel() will do it internally, and return a suitable default
958 * selectivity if not.
959 */
960 s1 = boolvarsel(root, clause, varRelid);
961 }
962
963 /* Cache the result if possible */
964 if (cacheable)
965 {
966 if (jointype == JOIN_INNER)
967 rinfo->norm_selec = s1;
968 else
969 rinfo->outer_selec = s1;
970 }
971
972#ifdef SELECTIVITY_DEBUG
973 elog(DEBUG4, "clause_selectivity: s1 %f", s1);
974#endif /* SELECTIVITY_DEBUG */
975
976 return s1;
977}
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:645
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition clauses.c:2660
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
Datum arg
Definition elog.c:1323
#define elog(elevel,...)
Definition elog.h:228
#define DEBUG4
Definition elog.h:28
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:258
@ JOIN_INNER
Definition nodes.h:301
Selectivity restriction_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, int varRelid)
Definition plancat.c:2225
Selectivity join_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition plancat.c:2264
Selectivity function_selectivity(PlannerInfo *root, Oid funcid, List *args, Oid inputcollid, bool is_join, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition plancat.c:2304
static bool DatumGetBool(Datum X)
Definition postgres.h:100
unsigned int Oid
char * s1
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition relnode.c:544
Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition selfuncs.c:1626
Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition selfuncs.c:1784
Selectivity boolvarsel(PlannerInfo *root, Node *arg, int varRelid)
Definition selfuncs.c:1587
Selectivity scalararraysel(PlannerInfo *root, ScalarArrayOpExpr *clause, bool is_join_clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition selfuncs.c:1902
Selectivity rowcomparesel(PlannerInfo *root, RowCompareExpr *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition selfuncs.c:2320
Definition nodes.h:133
Oid opno
Definition primnodes.h:835
Expr * clause
Definition pathnodes.h:2901
int varno
Definition primnodes.h:270
Index varlevelsup
Definition primnodes.h:295

References arg, bms_is_member(), booltestsel(), boolvarsel(), RestrictInfo::clause, clause_selectivity_ext(), clauselist_selectivity_ext(), clauselist_selectivity_or(), CurrentOfExpr::cvarno, DatumGetBool(), DEBUG4, elog, estimate_expression_value(), fb(), find_base_rel(), function_selectivity(), get_notclausearg(), is_andclause(), is_funcclause(), is_notclause(), is_opclause(), is_orclause(), IsA, JOIN_INNER, join_selectivity(), nulltestsel(), restriction_selectivity(), root, rowcomparesel(), s1, scalararraysel(), treat_as_join_clause(), 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 
)
extern

Definition at line 117 of file clausesel.c.

123{
124 Selectivity s1 = 1.0;
125 RelOptInfo *rel;
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,
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 */
180 continue;
181
182 /* Compute the selectivity of this clause in isolation */
183 s2 = clause_selectivity_ext(root, clause, varRelid, jointype, sjinfo,
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 {
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:2391
bool is_pseudo_constant_clause(Node *clause)
Definition clauses.c:2349
bool is_pseudo_constant_clause_relids(Node *clause, Relids relids)
Definition clauses.c:2369
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:1871
void pfree(void *pointer)
Definition mcxt.c:1619
@ RTE_RELATION
#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:1980
#define DEFAULT_RANGE_INEQ_SEL
Definition selfuncs.h:40
#define DEFAULT_INEQ_SEL
Definition selfuncs.h:37
List * args
Definition primnodes.h:853
Selectivity hibound
Definition clausesel.c:38
List * statlist
Definition pathnodes.h:1093
RTEKind rtekind
Definition pathnodes.h:1073

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

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)
extern

Definition at line 519 of file clauses.c.

520{
521 /* We assume here that expression_planner() won't scribble on its input */
522 expr = expression_planner(expr);
523
524 /* Now we can search for non-immutable functions */
525 return contain_mutable_functions((Node *) expr);
526}
bool contain_mutable_functions(Node *clause)
Definition clauses.c:399
Expr * expression_planner(Expr *expr)
Definition planner.c:7010

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 
)
extern

◆ contain_vars_returning_old_or_new()

bool contain_vars_returning_old_or_new ( Node *  node)
extern

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

Referenced by make_modifytable().

◆ contain_volatile_functions()

bool contain_volatile_functions ( Node *  clause)
extern

Definition at line 567 of file clauses.c.

568{
570}
static bool contain_volatile_functions_walker(Node *node, void *context)
Definition clauses.c:579

References contain_volatile_functions_walker(), and fb().

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(), create_agg_clause_infos(), distribute_qual_to_rels(), DomainHasConstraints(), 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(), init_notnull_info(), initialize_peragg(), inline_function(), inline_function_in_from(), 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)
extern

Definition at line 688 of file clauses.c.

689{
690 /* We assume here that expression_planner() won't scribble on its input */
691 expr = expression_planner(expr);
692
693 /* Now we can search for volatile functions */
694 return contain_volatile_functions((Node *) expr);
695}
bool contain_volatile_functions(Node *clause)
Definition clauses.c:567

References contain_volatile_functions(), and expression_planner().

◆ contain_volatile_functions_not_nextval()

bool contain_volatile_functions_not_nextval ( Node *  clause)
extern

Definition at line 702 of file clauses.c.

703{
705}
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition clauses.c:715

References contain_volatile_functions_not_nextval_walker(), and fb().

Referenced by BeginCopyFrom().

◆ convert_saop_to_hashed_saop()

void convert_saop_to_hashed_saop ( Node *  node)
extern

Definition at line 2549 of file clauses.c.

2550{
2552}
static bool convert_saop_to_hashed_saop_walker(Node *node, void *context)
Definition clauses.c:2555

References convert_saop_to_hashed_saop_walker(), and fb().

Referenced by preprocess_expression().

◆ count_nonjunk_tlist_entries()

int count_nonjunk_tlist_entries ( List *  tlist)
extern

Definition at line 195 of file tlist.c.

196{
197 int len = 0;
198 ListCell *l;
199
200 foreach(l, tlist)
201 {
203
204 if (!tle->resjunk)
205 len++;
206 }
207 return len;
208}
const void size_t len

References fb(), 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 
)
extern

Definition at line 2660 of file clauses.c.

2661{
2663
2664 context.boundParams = root->glob->boundParams; /* bound Params */
2665 /* we do not need to mark the plan as depending on inlined functions */
2666 context.root = NULL;
2667 context.active_fns = NIL; /* nothing being recursively simplified */
2668 context.case_val = NULL; /* no CASE being examined */
2669 context.estimate = true; /* unsafe transformations OK */
2670 return eval_const_expressions_mutator(node, &context);
2671}
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition clauses.c:2705

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(), fb(), 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()

Node * eval_const_expressions ( PlannerInfo *  root,
Node *  node 
)
extern

Definition at line 2516 of file clauses.c.

2517{
2519
2520 if (root)
2521 context.boundParams = root->glob->boundParams; /* bound Params */
2522 else
2523 context.boundParams = NULL;
2524 context.root = root; /* for inlined-function dependencies */
2525 context.active_fns = NIL; /* nothing being recursively simplified */
2526 context.case_val = NULL; /* no CASE being examined */
2527 context.estimate = false; /* safe transformations only */
2528 return eval_const_expressions_mutator(node, &context);
2529}

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

Referenced by apply_child_basequals(), ATExecAttachPartition(), ConstraintImpliedByRelConstraint(), convert_EXISTS_to_ANY(), convert_VALUES_to_ANY(), DoCopy(), expand_insert_targetlist(), expression_planner(), expression_planner_with_deps(), extended_statistics_update(), fetch_statentries_for_relation(), get_proposed_default_constraint(), get_relation_constraints(), get_relation_info(), get_relation_statistics(), infer_arbiter_indexes(), preprocess_expression(), preprocess_function_rtes(), process_implied_equality(), RelationBuildPartitionKey(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), simplify_EXISTS_query(), and SplitPartitionMoveRows().

◆ evaluate_expr()

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

Definition at line 5743 of file clauses.c.

5745{
5746 EState *estate;
5747 ExprState *exprstate;
5748 MemoryContext oldcontext;
5750 bool const_is_null;
5752 bool resultTypByVal;
5753
5754 /*
5755 * To use the executor, we need an EState.
5756 */
5757 estate = CreateExecutorState();
5758
5759 /* We can use the estate's working context to avoid memory leaks. */
5760 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
5761
5762 /* Make sure any opfuncids are filled in. */
5763 fix_opfuncids((Node *) expr);
5764
5765 /*
5766 * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
5767 * because it'd result in recursively invoking eval_const_expressions.)
5768 */
5769 exprstate = ExecInitExpr(expr, NULL);
5770
5771 /*
5772 * And evaluate it.
5773 *
5774 * It is OK to use a default econtext because none of the ExecEvalExpr()
5775 * code used in this situation will use econtext. That might seem
5776 * fortuitous, but it's not so unreasonable --- a constant expression does
5777 * not depend on context, by definition, n'est ce pas?
5778 */
5780 GetPerTupleExprContext(estate),
5781 &const_is_null);
5782
5783 /* Get info needed about result datatype */
5785
5786 /* Get back to outer memory context */
5787 MemoryContextSwitchTo(oldcontext);
5788
5789 /*
5790 * Must copy result out of sub-context used by expression eval.
5791 *
5792 * Also, if it's varlena, forcibly detoast it. This protects us against
5793 * storing TOAST pointers into plans that might outlive the referenced
5794 * data. (makeConst would handle detoasting anyway, but it's worth a few
5795 * extra lines here so that we can do the copy and detoast in one step.)
5796 */
5797 if (!const_is_null)
5798 {
5799 if (resultTypLen == -1)
5801 else
5803 }
5804
5805 /* Release all the junk we just created */
5806 FreeExecutorState(estate);
5807
5808 /*
5809 * Make the constant result node.
5810 */
5811 return (Expr *) makeConst(result_type, result_typmod, result_collation,
5815}
int16_t int16
Definition c.h:678
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:197
EState * CreateExecutorState(void)
Definition execUtils.c:90
#define GetPerTupleExprContext(estate)
Definition executor.h:665
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:444
#define PG_DETOAST_DATUM_COPY(datum)
Definition fmgr.h:242
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition lsyscache.c:2565
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:1859
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
uint64_t Datum
Definition postgres.h:70
#define PointerGetDatum(X)
Definition postgres.h:354
MemoryContext es_query_cxt
Definition execnodes.h:747

References CreateExecutorState(), datumCopy(), EState::es_query_cxt, ExecEvalExprSwitchContext(), ExecInitExpr(), fb(), 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,
HeapTuple  func_tuple 
)
extern

Definition at line 4946 of file clauses.c.

4948{
4950 Oid *proargtypes = funcform->proargtypes.values;
4951 int pronargs = funcform->pronargs;
4952 bool has_named_args = false;
4953 ListCell *lc;
4954
4955 /*
4956 * If we are asked to match to OUT arguments, then use the proallargtypes
4957 * array (which includes those); otherwise use proargtypes (which
4958 * doesn't). Of course, if proallargtypes is null, we always use
4959 * proargtypes. (Fetching proallargtypes is annoyingly expensive
4960 * considering that we may have nothing to do here, but fortunately the
4961 * common case is include_out_arguments == false.)
4962 */
4964 {
4966 bool isNull;
4967
4970 &isNull);
4971 if (!isNull)
4972 {
4974
4975 pronargs = ARR_DIMS(arr)[0];
4976 if (ARR_NDIM(arr) != 1 ||
4977 pronargs < 0 ||
4978 ARR_HASNULL(arr) ||
4979 ARR_ELEMTYPE(arr) != OIDOID)
4980 elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
4981 Assert(pronargs >= funcform->pronargs);
4982 proargtypes = (Oid *) ARR_DATA_PTR(arr);
4983 }
4984 }
4985
4986 /* Do we have any named arguments? */
4987 foreach(lc, args)
4988 {
4989 Node *arg = (Node *) lfirst(lc);
4990
4991 if (IsA(arg, NamedArgExpr))
4992 {
4993 has_named_args = true;
4994 break;
4995 }
4996 }
4997
4998 /* If so, we must apply reorder_function_arguments */
4999 if (has_named_args)
5000 {
5002 /* Recheck argument types and add casts if needed */
5003 recheck_cast_function_args(args, result_type,
5005 func_tuple);
5006 }
5007 else if (list_length(args) < pronargs)
5008 {
5009 /* No named args, but we seem to be short some defaults */
5011 /* Recheck argument types and add casts if needed */
5012 recheck_cast_function_args(args, result_type,
5014 func_tuple);
5015 }
5016
5017 return args;
5018}
#define ARR_NDIM(a)
Definition array.h:290
#define ARR_DATA_PTR(a)
Definition array.h:322
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_DIMS(a)
Definition array.h:294
#define ARR_HASNULL(a)
Definition array.h:291
static List * add_function_defaults(List *args, int pronargs, HeapTuple func_tuple)
Definition clauses.c:5097
static List * reorder_function_arguments(List *args, int pronargs, HeapTuple func_tuple)
Definition clauses.c:5027
static void recheck_cast_function_args(List *args, Oid result_type, Oid *proargtypes, int pronargs, HeapTuple func_tuple)
Definition clauses.c:5151
#define ERROR
Definition elog.h:40
static void * GETSTRUCT(const HeapTupleData *tuple)
int16 pronargs
Definition pg_proc.h:83
END_CATALOG_STRUCT typedef FormData_pg_proc * Form_pg_proc
Definition pg_proc.h:140
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596

References add_function_defaults(), arg, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, Assert, DatumGetArrayTypeP, elog, ERROR, fb(), Form_pg_proc, GETSTRUCT(), IsA, lfirst, list_length(), pronargs, recheck_cast_function_args(), reorder_function_arguments(), and SysCacheGetAttr().

Referenced by eval_const_expressions_mutator(), simplify_function(), and transformCallStmt().

◆ expr_is_nonnullable()

bool expr_is_nonnullable ( PlannerInfo *  root,
Expr *  expr,
NotNullSource  source 
)
extern

Definition at line 4804 of file clauses.c.

4805{
4806 /* since this function recurses, it could be driven to stack overflow */
4808
4809 switch (nodeTag(expr))
4810 {
4811 case T_Var:
4812 {
4813 if (root)
4814 return var_is_nonnullable(root, (Var *) expr, source);
4815 }
4816 break;
4817 case T_Const:
4818 return !((Const *) expr)->constisnull;
4819 case T_CoalesceExpr:
4820 {
4821 /*
4822 * A CoalesceExpr returns NULL if and only if all its
4823 * arguments are NULL. Therefore, we can determine that a
4824 * CoalesceExpr cannot be NULL if at least one of its
4825 * arguments can be proven non-nullable.
4826 */
4828
4830 {
4832 return true;
4833 }
4834 }
4835 break;
4836 case T_MinMaxExpr:
4837 {
4838 /*
4839 * Like CoalesceExpr, a MinMaxExpr returns NULL only if all
4840 * its arguments evaluate to NULL.
4841 */
4842 MinMaxExpr *minmaxexpr = (MinMaxExpr *) expr;
4843
4845 {
4847 return true;
4848 }
4849 }
4850 break;
4851 case T_CaseExpr:
4852 {
4853 /*
4854 * A CASE expression is non-nullable if all branch results are
4855 * non-nullable. We must also verify that the default result
4856 * (ELSE) exists and is non-nullable.
4857 */
4858 CaseExpr *caseexpr = (CaseExpr *) expr;
4859
4860 /* The default result must be present and non-nullable */
4861 if (caseexpr->defresult == NULL ||
4862 !expr_is_nonnullable(root, caseexpr->defresult, source))
4863 return false;
4864
4865 /* All branch results must be non-nullable */
4867 {
4868 if (!expr_is_nonnullable(root, casewhen->result, source))
4869 return false;
4870 }
4871
4872 return true;
4873 }
4874 break;
4875 case T_ArrayExpr:
4876 {
4877 /*
4878 * An ARRAY[] expression always returns a valid Array object,
4879 * even if it is empty (ARRAY[]) or contains NULLs
4880 * (ARRAY[NULL]). It never evaluates to a SQL NULL.
4881 */
4882 return true;
4883 }
4884 case T_NullTest:
4885 {
4886 /*
4887 * An IS NULL / IS NOT NULL expression always returns a
4888 * boolean value. It never returns SQL NULL.
4889 */
4890 return true;
4891 }
4892 case T_BooleanTest:
4893 {
4894 /*
4895 * A BooleanTest expression always evaluates to a boolean
4896 * value. It never returns SQL NULL.
4897 */
4898 return true;
4899 }
4900 case T_DistinctExpr:
4901 {
4902 /*
4903 * IS DISTINCT FROM never returns NULL, effectively acting as
4904 * though NULL were a normal data value.
4905 */
4906 return true;
4907 }
4908 case T_RelabelType:
4909 {
4910 /*
4911 * RelabelType does not change the nullability of the data.
4912 * The result is non-nullable if and only if the argument is
4913 * non-nullable.
4914 */
4915 return expr_is_nonnullable(root, ((RelabelType *) expr)->arg,
4916 source);
4917 }
4918 default:
4919 break;
4920 }
4921
4922 return false;
4923}
bool expr_is_nonnullable(PlannerInfo *root, Expr *expr, NotNullSource source)
Definition clauses.c:4804
bool var_is_nonnullable(PlannerInfo *root, Var *var, NotNullSource source)
Definition clauses.c:4660
#define nodeTag(nodeptr)
Definition nodes.h:137
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
static rewind_source * source
Definition pg_rewind.c:89
void check_stack_depth(void)
Definition stack_depth.c:96

References arg, check_stack_depth(), expr_is_nonnullable(), fb(), foreach_ptr, nodeTag, root, source, and var_is_nonnullable().

Referenced by eval_const_expressions_mutator(), expr_is_nonnullable(), int8inc_support(), query_outputs_are_not_nullable(), restriction_is_always_false(), restriction_is_always_true(), and sublink_testexpr_is_not_nullable().

◆ expression_planner()

Expr * expression_planner ( Expr *  expr)
extern

Definition at line 7010 of file planner.c.

7011{
7012 Node *result;
7013
7014 /*
7015 * Convert named-argument function calls, insert default arguments and
7016 * simplify constant subexprs
7017 */
7019
7020 /* Fill in opfuncid values if missing */
7022
7023 return (Expr *) result;
7024}
uint32 result
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition clauses.c:2516

References eval_const_expressions(), fb(), fix_opfuncids(), and result.

Referenced by ATExecAddColumn(), ATExecSetExpression(), ATPrepAlterColumnType(), BeginCopyFrom(), ComputePartitionAttrs(), contain_mutable_functions_after_planning(), contain_volatile_functions_after_planning(), createTableConstraints(), 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 
)
extern

Definition at line 7037 of file planner.c.

7040{
7041 Node *result;
7042 PlannerGlobal glob;
7044
7045 /* Make up dummy planner state so we can use setrefs machinery */
7046 MemSet(&glob, 0, sizeof(glob));
7047 glob.type = T_PlannerGlobal;
7048 glob.relationOids = NIL;
7049 glob.invalItems = NIL;
7050
7051 MemSet(&root, 0, sizeof(root));
7052 root.type = T_PlannerInfo;
7053 root.glob = &glob;
7054
7055 /*
7056 * Convert named-argument function calls, insert default arguments and
7057 * simplify constant subexprs. Collect identities of inlined functions
7058 * and elided domains, too.
7059 */
7060 result = eval_const_expressions(&root, (Node *) expr);
7061
7062 /* Fill in opfuncid values if missing */
7064
7065 /*
7066 * Now walk the finished expression to find anything else we ought to
7067 * record as an expression dependency.
7068 */
7070
7071 *relationOids = glob.relationOids;
7072 *invalItems = glob.invalItems;
7073
7074 return (Expr *) result;
7075}
#define MemSet(start, val, len)
Definition c.h:1147
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition setrefs.c:3716
List * invalItems
Definition pathnodes.h:230
List * relationOids
Definition pathnodes.h:227

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

Referenced by GetCachedExpression().

◆ extract_query_dependencies()

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

Definition at line 3680 of file setrefs.c.

3684{
3685 PlannerGlobal glob;
3687
3688 /* Make up dummy planner state so we can use this module's machinery */
3689 MemSet(&glob, 0, sizeof(glob));
3690 glob.type = T_PlannerGlobal;
3691 glob.relationOids = NIL;
3692 glob.invalItems = NIL;
3693 /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
3694 glob.dependsOnRole = false;
3695
3696 MemSet(&root, 0, sizeof(root));
3697 root.type = T_PlannerInfo;
3698 root.glob = &glob;
3699
3701
3702 *relationOids = glob.relationOids;
3703 *invalItems = glob.invalItems;
3704 *hasRowSecurity = glob.dependsOnRole;
3705}
bool dependsOnRole
Definition pathnodes.h:251

References PlannerGlobal::dependsOnRole, extract_query_dependencies_walker(), fb(), 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 
)
extern

Definition at line 999 of file var.c.

1000{
1002
1003 /*
1004 * We do not expect this to be applied to the whole Query, only to
1005 * expressions or LATERAL subqueries. Hence, if the top node is a Query,
1006 * it's okay to immediately increment sublevels_up.
1007 */
1008 Assert(node != (Node *) query);
1009
1010 context.root = root;
1011 context.query = query;
1012 context.sublevels_up = 0;
1013 /* flag whether grouping expressions could possibly contain SubLinks */
1014 context.possible_sublink = query->hasSubLinks;
1015 /* if hasSubLinks is already true, no need to work hard */
1016 context.inserted_sublink = query->hasSubLinks;
1017
1018 return flatten_group_exprs_mutator(node, &context);
1019}
static Node * flatten_group_exprs_mutator(Node *node, flatten_join_alias_vars_context *context)
Definition var.c:1022

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 check_output_expressions(), get_query_def(), query_outputs_are_not_nullable(), and subquery_planner().

◆ flatten_join_alias_for_parser()

Node * flatten_join_alias_for_parser ( Query *  query,
Node *  node,
int  sublevels_up 
)
extern

Definition at line 819 of file var.c.

820{
822
823 /*
824 * We do not expect this to be applied to the whole Query, only to
825 * expressions or LATERAL subqueries. Hence, if the top node is a Query,
826 * it's okay to immediately increment sublevels_up.
827 */
828 Assert(node != (Node *) query);
829
830 context.root = NULL;
831 context.query = query;
832 context.sublevels_up = sublevels_up;
833 /* flag whether join aliases could possibly contain SubLinks */
834 context.possible_sublink = query->hasSubLinks;
835 /* if hasSubLinks is already true, no need to work hard */
836 context.inserted_sublink = query->hasSubLinks;
837
838 return flatten_join_alias_vars_mutator(node, &context);
839}
static Node * flatten_join_alias_vars_mutator(Node *node, flatten_join_alias_vars_context *context)
Definition var.c:842

References Assert, fb(), 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(), and parseCheckAggregates().

◆ flatten_join_alias_vars()

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

Definition at line 781 of file var.c.

782{
784
785 /*
786 * We do not expect this to be applied to the whole Query, only to
787 * expressions or LATERAL subqueries. Hence, if the top node is a Query,
788 * it's okay to immediately increment sublevels_up.
789 */
790 Assert(node != (Node *) query);
791
792 context.root = root;
793 context.query = query;
794 context.sublevels_up = 0;
795 /* flag whether join aliases could possibly contain SubLinks */
796 context.possible_sublink = query->hasSubLinks;
797 /* if hasSubLinks is already true, no need to work hard */
798 context.inserted_sublink = query->hasSubLinks;
799
800 return flatten_join_alias_vars_mutator(node, &context);
801}

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 preprocess_expression(), pull_up_simple_subquery(), query_outputs_are_not_nullable(), sublink_testexpr_is_not_nullable(), and subquery_planner().

◆ get_sortgroupclause_expr()

Node * get_sortgroupclause_expr ( SortGroupClause *  sgClause,
List *  targetList 
)
extern

Definition at line 388 of file tlist.c.

389{
391
392 return (Node *) tle->expr;
393}
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition tlist.c:376

References fb(), 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 
)
extern

Definition at line 401 of file tlist.c.

402{
403 List *result = NIL;
404 ListCell *l;
405
406 foreach(l, sgClauses)
407 {
409 Node *sortexpr;
410
413 }
414 return result;
415}
List * lappend(List *list, void *datum)
Definition list.c:339
Node * get_sortgroupclause_expr(SortGroupClause *sgClause, List *targetList)
Definition tlist.c:388

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

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 
)
extern

Definition at line 431 of file tlist.c.

432{
433 ListCell *l;
434
435 foreach(l, clauses)
436 {
438
439 if (cl->tleSortGroupRef == sortref)
440 return cl;
441 }
442
443 elog(ERROR, "ORDER/GROUP BY expression not found in list");
444 return NULL; /* keep compiler quiet */
445}

References elog, ERROR, fb(), and lfirst.

Referenced by init_grouping_targets(), and preprocess_groupclause().

◆ get_sortgroupref_clause_noerr()

SortGroupClause * get_sortgroupref_clause_noerr ( Index  sortref,
List *  clauses 
)
extern

Definition at line 452 of file tlist.c.

453{
454 ListCell *l;
455
456 foreach(l, clauses)
457 {
459
460 if (cl->tleSortGroupRef == sortref)
461 return cl;
462 }
463
464 return NULL;
465}

References fb(), and lfirst.

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 
)
extern

Definition at line 354 of file tlist.c.

355{
356 ListCell *l;
357
358 foreach(l, targetList)
359 {
361
362 if (tle->ressortgroupref == sortref)
363 return tle;
364 }
365
366 elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
367 return NULL; /* keep compiler quiet */
368}

References elog, ERROR, fb(), and lfirst.

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 
)
extern

Definition at line 4453 of file indxpath.c.

4454{
4455 /* pull_varnos is cheaper than volatility check, so do that first */
4456 if (bms_is_member(index->rel->relid, pull_varnos(root, expr)))
4457 return false; /* no good, contains Var of table */
4459 return false; /* no good, volatile comparison value */
4460 return true;
4461}
Definition type.h:97
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 
)
extern

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 fb(), 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 
)
extern

Definition at line 6543 of file clauses.c.

6545{
6546 Node *arrayNode = NULL;
6548 Oid arraytype = get_array_type(coltype);
6549
6550 if (!OidIsValid(arraytype))
6551 return NULL;
6552
6553 /*
6554 * Assemble an array from the list of constants. It seems more profitable
6555 * to build a const array. But in the presence of other nodes, we don't
6556 * have a specific value here and must employ an ArrayExpr instead.
6557 */
6558 if (haveNonConst)
6559 {
6561
6562 /* array_collid will be set by parse_collate.c */
6563 arrayExpr->element_typeid = coltype;
6564 arrayExpr->array_typeid = arraytype;
6565 arrayExpr->multidims = false;
6566 arrayExpr->elements = exprs;
6567 arrayExpr->location = -1;
6568
6569 arrayNode = (Node *) arrayExpr;
6570 }
6571 else
6572 {
6573 int16 typlen;
6574 bool typbyval;
6575 char typalign;
6576 Datum *elems;
6577 bool *nulls;
6578 int i = 0;
6580 int dims[1] = {list_length(exprs)};
6581 int lbs[1] = {1};
6582
6583 get_typlenbyvalalign(coltype, &typlen, &typbyval, &typalign);
6584
6585 elems = palloc_array(Datum, list_length(exprs));
6586 nulls = palloc_array(bool, list_length(exprs));
6587 foreach_node(Const, value, exprs)
6588 {
6589 elems[i] = value->constvalue;
6590 nulls[i++] = value->constisnull;
6591 }
6592
6593 arrayConst = construct_md_array(elems, nulls, 1, dims, lbs,
6594 coltype, typlen, typbyval, typalign);
6597 false, false);
6598
6599 pfree(elems);
6600 pfree(nulls);
6601 list_free(exprs);
6602 }
6603
6604 /* Build the SAOP expression node */
6606 saopexpr->opno = oper;
6607 saopexpr->opfuncid = get_opcode(oper);
6608 saopexpr->hashfuncid = InvalidOid;
6609 saopexpr->negfuncid = InvalidOid;
6610 saopexpr->useOr = true;
6611 saopexpr->inputcollid = inputcollid;
6613 saopexpr->location = -1;
6614
6615 return saopexpr;
6616}
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
#define OidIsValid(objectId)
Definition c.h:917
#define palloc_array(type, count)
Definition fe_memutils.h:91
static struct @175 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:2585
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1585
Oid get_array_type(Oid typid)
Definition lsyscache.c:3103
#define makeNode(_type_)
Definition nodes.h:159
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition parse_oper.c:376
#define foreach_node(type, var, lst)
Definition pg_list.h:528
#define list_make2(x1, x2)
Definition pg_list.h:246
char typalign
Definition pg_type.h:178
#define InvalidOid

References construct_md_array(), fb(), foreach_node, get_array_type(), get_opcode(), get_typlenbyvalalign(), i, InvalidOid, list_free(), list_length(), list_make2, makeConst(), makeNode, OidIsValid, oper(), palloc_array, pfree(), PointerGetDatum, typalign, and value.

Referenced by convert_VALUES_to_ANY(), and match_orclause_to_indexcol().

◆ negate_clause()

Node * negate_clause ( Node *  node)
extern

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 {
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;
115 {
116 /*
117 * Negate a ScalarArrayOpExpr if its operator has a negator;
118 * for example x = ANY (list) becomes x <> ALL (list)
119 */
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,
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,
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 {
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;
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:1847
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
Node * negate_clause(Node *node)
Definition prepqual.c:73
char * c
@ IS_NOT_TRUE
Definition primnodes.h:2004
@ IS_NOT_FALSE
Definition primnodes.h:2004
@ IS_NOT_UNKNOWN
Definition primnodes.h:2004
@ IS_TRUE
Definition primnodes.h:2004
@ IS_UNKNOWN
Definition primnodes.h:2004
@ IS_FALSE
Definition primnodes.h:2004
@ AND_EXPR
Definition primnodes.h:945
@ OR_EXPR
Definition primnodes.h:945
@ NOT_EXPR
Definition primnodes.h:945
@ IS_NOT_NULL
Definition primnodes.h:1980
BoolExprType boolop
Definition primnodes.h:953
List * args
Definition primnodes.h:954
ParseLoc location
Definition primnodes.h:2012
BoolTestType booltesttype
Definition primnodes.h:2011
NullTestType nulltesttype
Definition primnodes.h:1987
ParseLoc location
Definition primnodes.h:1990
Expr * arg
Definition primnodes.h:1986
ParseLoc location
Definition primnodes.h:856

References AND_EXPR, NullTest::arg, BooleanTest::arg, OpExpr::args, BoolExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, DatumGetBool(), elog, ERROR, fb(), 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, NullTest::location, BooleanTest::location, make_andclause(), make_notclause(), make_orclause(), makeBoolConst(), makeNode, negate_clause(), NIL, nodeTag, NOT_EXPR, NullTest::nulltesttype, OpExpr::opno, and OR_EXPR.

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 
)
extern

Definition at line 7090 of file planner.c.

7091{
7093 Query *query;
7094 PlannerGlobal *glob;
7096 RelOptInfo *rel;
7097 IndexOptInfo *indexInfo;
7103 ListCell *lc;
7104
7105 /* We can short-circuit the cost comparison if indexscans are disabled */
7106 if (!enable_indexscan)
7107 return true; /* use sort */
7108
7109 /* Set up mostly-dummy planner state */
7110 query = makeNode(Query);
7111 query->commandType = CMD_SELECT;
7112
7113 glob = makeNode(PlannerGlobal);
7114
7116 root->parse = query;
7117 root->glob = glob;
7118 root->query_level = 1;
7119 root->planner_cxt = CurrentMemoryContext;
7120 root->wt_param_id = -1;
7121 root->join_domains = list_make1(makeNode(JoinDomain));
7122
7123 /* Build a minimal RTE for the rel */
7125 rte->rtekind = RTE_RELATION;
7126 rte->relid = tableOid;
7127 rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
7128 rte->rellockmode = AccessShareLock;
7129 rte->lateral = false;
7130 rte->inh = false;
7131 rte->inFromCl = true;
7132 query->rtable = list_make1(rte);
7133 addRTEPermissionInfo(&query->rteperminfos, rte);
7134
7135 /* Set up RTE/RelOptInfo arrays */
7137
7138 /* Build RelOptInfo */
7139 rel = build_simple_rel(root, 1, NULL);
7140
7141 /* Locate IndexOptInfo for the target index */
7142 indexInfo = NULL;
7143 foreach(lc, rel->indexlist)
7144 {
7145 indexInfo = lfirst_node(IndexOptInfo, lc);
7146 if (indexInfo->indexoid == indexOid)
7147 break;
7148 }
7149
7150 /*
7151 * It's possible that get_relation_info did not generate an IndexOptInfo
7152 * for the desired index; this could happen if it's not yet reached its
7153 * indcheckxmin usability horizon, or if it's a system index and we're
7154 * ignoring system indexes. In such cases we should tell CLUSTER to not
7155 * trust the index contents but use seqscan-and-sort.
7156 */
7157 if (lc == NULL) /* not in the list? */
7158 return true; /* use sort */
7159
7160 /*
7161 * Rather than doing all the pushups that would be needed to use
7162 * set_baserel_size_estimates, just do a quick hack for rows and width.
7163 */
7164 rel->rows = rel->tuples;
7165 rel->reltarget->width = get_relation_data_width(tableOid, NULL);
7166
7167 root->total_table_pages = rel->pages;
7168
7169 /*
7170 * Determine eval cost of the index expressions, if any. We need to
7171 * charge twice that amount for each tuple comparison that happens during
7172 * the sort, since tuplesort.c will have to re-evaluate the index
7173 * expressions each time. (XXX that's pretty inefficient...)
7174 */
7175 cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
7176 comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
7177
7178 /* Estimate the cost of seq scan + sort */
7181 seqScanPath->disabled_nodes,
7182 seqScanPath->total_cost, rel->tuples, rel->reltarget->width,
7184
7185 /* Estimate the cost of index scan */
7187 NIL, NIL, NIL, NIL,
7188 ForwardScanDirection, false,
7189 NULL, 1.0, false);
7190
7191 return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
7192}
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:2202
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition costsize.c:4923
bool enable_indexscan
Definition costsize.c:147
int maintenance_work_mem
Definition globals.c:135
#define AccessShareLock
Definition lockdefs.h:36
MemoryContext CurrentMemoryContext
Definition mcxt.c:161
double Cost
Definition nodes.h:259
@ CMD_SELECT
Definition nodes.h:273
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:1092
Path * create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer, int parallel_workers)
Definition pathnode.c:1026
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define list_make1(x1)
Definition pg_list.h:244
int32 get_relation_data_width(Oid relid, int32 *attr_widths)
Definition plancat.c:1472
void setup_simple_rel_arrays(PlannerInfo *root)
Definition relnode.c:114
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition relnode.c:212
@ ForwardScanDirection
Definition sdir.h:28
List * rtable
Definition parsenodes.h:180
CmdType commandType
Definition parsenodes.h:124
struct PathTarget * reltarget
Definition pathnodes.h:1045
Cardinality tuples
Definition pathnodes.h:1096
BlockNumber pages
Definition pathnodes.h:1095
List * indexlist
Definition pathnodes.h:1091
Cardinality rows
Definition pathnodes.h:1027

References AccessShareLock, addRTEPermissionInfo(), build_simple_rel(), CMD_SELECT, Query::commandType, cost_qual_eval(), cost_sort(), create_index_path(), create_seqscan_path(), CurrentMemoryContext, enable_indexscan, fb(), ForwardScanDirection, get_relation_data_width(), RelOptInfo::indexlist, IndexOptInfo::indexoid, lfirst_node, list_make1, maintenance_work_mem, makeNode, NIL, RelOptInfo::pages, RelOptInfo::reltarget, root, RelOptInfo::rows, Query::rtable, RTE_RELATION, setup_simple_rel_arrays(), RelOptInfo::tuples, and PathTarget::width.

Referenced by copy_table_data().

◆ plan_create_index_workers()

int plan_create_index_workers ( Oid  tableOid,
Oid  indexOid 
)
extern

Definition at line 7212 of file planner.c.

7213{
7215 Query *query;
7216 PlannerGlobal *glob;
7218 Relation heap;
7220 RelOptInfo *rel;
7221 int parallel_workers;
7223 double reltuples;
7224 double allvisfrac;
7225
7226 /*
7227 * We don't allow performing parallel operation in standalone backend or
7228 * when parallelism is disabled.
7229 */
7231 return 0;
7232
7233 /* Set up largely-dummy planner state */
7234 query = makeNode(Query);
7235 query->commandType = CMD_SELECT;
7236
7237 glob = makeNode(PlannerGlobal);
7238
7240 root->parse = query;
7241 root->glob = glob;
7242 root->query_level = 1;
7243 root->planner_cxt = CurrentMemoryContext;
7244 root->wt_param_id = -1;
7245 root->join_domains = list_make1(makeNode(JoinDomain));
7246
7247 /*
7248 * Build a minimal RTE.
7249 *
7250 * Mark the RTE with inh = true. This is a kludge to prevent
7251 * get_relation_info() from fetching index info, which is necessary
7252 * because it does not expect that any IndexOptInfo is currently
7253 * undergoing REINDEX.
7254 */
7256 rte->rtekind = RTE_RELATION;
7257 rte->relid = tableOid;
7258 rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
7259 rte->rellockmode = AccessShareLock;
7260 rte->lateral = false;
7261 rte->inh = true;
7262 rte->inFromCl = true;
7263 query->rtable = list_make1(rte);
7264 addRTEPermissionInfo(&query->rteperminfos, rte);
7265
7266 /* Set up RTE/RelOptInfo arrays */
7268
7269 /* Build RelOptInfo */
7270 rel = build_simple_rel(root, 1, NULL);
7271
7272 /* Rels are assumed already locked by the caller */
7273 heap = table_open(tableOid, NoLock);
7274 index = index_open(indexOid, NoLock);
7275
7276 /*
7277 * Determine if it's safe to proceed.
7278 *
7279 * Currently, parallel workers can't access the leader's temporary tables.
7280 * Furthermore, any index predicate or index expressions must be parallel
7281 * safe.
7282 */
7283 if (heap->rd_rel->relpersistence == RELPERSISTENCE_TEMP ||
7286 {
7287 parallel_workers = 0;
7288 goto done;
7289 }
7290
7291 /*
7292 * If parallel_workers storage parameter is set for the table, accept that
7293 * as the number of parallel worker processes to launch (though still cap
7294 * at max_parallel_maintenance_workers). Note that we deliberately do not
7295 * consider any other factor when parallel_workers is set. (e.g., memory
7296 * use by workers.)
7297 */
7298 if (rel->rel_parallel_workers != -1)
7299 {
7300 parallel_workers = Min(rel->rel_parallel_workers,
7302 goto done;
7303 }
7304
7305 /*
7306 * Estimate heap relation size ourselves, since rel->pages cannot be
7307 * trusted (heap RTE was marked as inheritance parent)
7308 */
7309 estimate_rel_size(heap, NULL, &heap_blocks, &reltuples, &allvisfrac);
7310
7311 /*
7312 * Determine number of workers to scan the heap relation using generic
7313 * model
7314 */
7315 parallel_workers = compute_parallel_worker(rel, heap_blocks, -1,
7317
7318 /*
7319 * Cap workers based on available maintenance_work_mem as needed.
7320 *
7321 * Note that each tuplesort participant receives an even share of the
7322 * total maintenance_work_mem budget. Aim to leave participants
7323 * (including the leader as a participant) with no less than 32MB of
7324 * memory. This leaves cases where maintenance_work_mem is set to 64MB
7325 * immediately past the threshold of being capable of launching a single
7326 * parallel worker to sort.
7327 */
7328 while (parallel_workers > 0 &&
7329 maintenance_work_mem / (parallel_workers + 1) < 32 * 1024)
7330 parallel_workers--;
7331
7332done:
7334 table_close(heap, NoLock);
7335
7336 return parallel_workers;
7337}
int compute_parallel_worker(RelOptInfo *rel, double heap_pages, double index_pages, int max_workers)
Definition allpaths.c:4973
uint32 BlockNumber
Definition block.h:31
#define Min(x, y)
Definition c.h:1131
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition clauses.c:782
int max_parallel_maintenance_workers
Definition globals.c:136
bool IsUnderPostmaster
Definition globals.c:122
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:178
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:134
#define NoLock
Definition lockdefs.h:34
void estimate_rel_size(Relation rel, int32 *attr_widths, BlockNumber *pages, double *tuples, double *allvisfrac)
Definition plancat.c:1305
List * RelationGetIndexPredicate(Relation relation)
Definition relcache.c:5222
List * RelationGetIndexExpressions(Relation relation)
Definition relcache.c:5109
int rel_parallel_workers
Definition pathnodes.h:1103
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(), fb(), index_close(), index_open(), 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, setup_simple_rel_arrays(), table_close(), and table_open().

Referenced by index_build().

◆ planner()

PlannedStmt * planner ( Query *  parse,
const char *  query_string,
int  cursorOptions,
ParamListInfo  boundParams,
ExplainState *  es 
)
extern

Definition at line 328 of file planner.c.

330{
332
333 if (planner_hook)
334 result = (*planner_hook) (parse, query_string, cursorOptions,
335 boundParams, es);
336 else
337 result = standard_planner(parse, query_string, cursorOptions,
338 boundParams, es);
339
340 pgstat_report_plan_id(result->planId, false);
341
342 return result;
343}
void pgstat_report_plan_id(int64 plan_id, bool force)
void parse(int)
Definition parse.c:49
planner_hook_type planner_hook
Definition planner.c:74
PlannedStmt * standard_planner(Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams, ExplainState *es)
Definition planner.c:346

References parse(), pgstat_report_plan_id(), planner_hook, result, and standard_planner().

Referenced by pg_plan_query(), and test_plan_advice_advisor().

◆ predicate_implied_by()

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

Definition at line 154 of file predtest.c.

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

References fb(), 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 
)
extern

Definition at line 224 of file predtest.c.

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

References fb(), 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 
)
extern

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:198
#define PVC_RECURSE_PLACEHOLDERS
Definition optimizer.h:202
#define PVC_RECURSE_WINDOWFUNCS
Definition optimizer.h:200
#define PVC_INCLUDE_WINDOWFUNCS
Definition optimizer.h:199
#define PVC_INCLUDE_PLACEHOLDERS
Definition optimizer.h:201
#define PVC_INCLUDE_AGGREGATES
Definition optimizer.h:197
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(), create_agg_clause_infos(), 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(), is_var_in_aggref_only(), 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()

◆ pull_varnos()

Bitmapset * pull_varnos ( PlannerInfo *  root,
Node *  node 
)
extern

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
Relids varnos
Definition var.c:35
static bool pull_varnos_walker(Node *node, pull_varnos_context *context)
Definition var.c:161

References fb(), 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(), create_agg_clause_infos(), 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 
)
extern

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 fb(), 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 
)
extern

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

◆ var_is_nonnullable()

bool var_is_nonnullable ( PlannerInfo *  root,
Var *  var,
NotNullSource  source 
)
extern

Definition at line 4660 of file clauses.c.

4661{
4662 Assert(IsA(var, Var));
4663
4664 /* skip upper-level Vars */
4665 if (var->varlevelsup != 0)
4666 return false;
4667
4668 /* could the Var be nulled by any outer joins or grouping sets? */
4669 if (!bms_is_empty(var->varnullingrels))
4670 return false;
4671
4672 /*
4673 * If the Var has a non-default returning type, it could be NULL
4674 * regardless of any NOT NULL constraint. For example, OLD.col is NULL
4675 * for INSERT, and NEW.col is NULL for DELETE.
4676 */
4678 return false;
4679
4680 /* system columns cannot be NULL */
4681 if (var->varattno < 0)
4682 return true;
4683
4684 /* we don't trust whole-row Vars */
4685 if (var->varattno == 0)
4686 return false;
4687
4688 /* Check if the Var is defined as NOT NULL. */
4689 switch (source)
4690 {
4692 {
4693 /*
4694 * We retrieve the column NOT NULL constraint information from
4695 * the corresponding RelOptInfo.
4696 */
4697 RelOptInfo *rel;
4698 Bitmapset *notnullattnums;
4699
4700 rel = find_base_rel(root, var->varno);
4701 notnullattnums = rel->notnullattnums;
4702
4703 return bms_is_member(var->varattno, notnullattnums);
4704 }
4706 {
4707 /*
4708 * We retrieve the column NOT NULL constraint information from
4709 * the hash table.
4710 */
4712 Bitmapset *notnullattnums;
4713
4714 rte = planner_rt_fetch(var->varno, root);
4715
4716 /* We can only reason about ordinary relations */
4717 if (rte->rtekind != RTE_RELATION)
4718 return false;
4719
4720 /*
4721 * We must skip inheritance parent tables, as some child
4722 * tables may have a NOT NULL constraint for a column while
4723 * others may not. This cannot happen with partitioned
4724 * tables, though.
4725 */
4726 if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
4727 return false;
4728
4729 notnullattnums = find_relation_notnullatts(root, rte->relid);
4730
4731 return bms_is_member(var->varattno, notnullattnums);
4732 }
4734 {
4735 /*
4736 * We check the attnullability field in the tuple descriptor.
4737 * This is necessary rather than checking the attnotnull field
4738 * from the attribute relation, because attnotnull is also set
4739 * for invalid (NOT VALID) NOT NULL constraints, which do not
4740 * guarantee the absence of NULLs.
4741 */
4743 Relation rel;
4744 CompactAttribute *attr;
4745 bool result;
4746
4747 rte = planner_rt_fetch(var->varno, root);
4748
4749 /* We can only reason about ordinary relations */
4750 if (rte->rtekind != RTE_RELATION)
4751 return false;
4752
4753 /*
4754 * We must skip inheritance parent tables, as some child
4755 * tables may have a NOT NULL constraint for a column while
4756 * others may not. This cannot happen with partitioned
4757 * tables, though.
4758 *
4759 * Note that we need to check if the relation actually has any
4760 * children, as we might not have done that yet.
4761 */
4762 if (rte->inh && has_subclass(rte->relid) &&
4763 rte->relkind != RELKIND_PARTITIONED_TABLE)
4764 return false;
4765
4766 /* We need not lock the relation since it was already locked */
4767 rel = table_open(rte->relid, NoLock);
4769 var->varattno - 1);
4771 table_close(rel, NoLock);
4772
4773 return result;
4774 }
4775 default:
4776 elog(ERROR, "unrecognized NotNullSource: %d",
4777 (int) source);
4778 break;
4779 }
4780
4781 return false;
4782}
#define bms_is_empty(a)
Definition bitmapset.h:119
#define planner_rt_fetch(rti, root)
Definition pathnodes.h:704
bool has_subclass(Oid relationId)
Bitmapset * find_relation_notnullatts(PlannerInfo *root, Oid relid)
Definition plancat.c:763
@ VAR_RETURNING_DEFAULT
Definition primnodes.h:257
#define RelationGetDescr(relation)
Definition rel.h:542
char attnullability
Definition tupdesc.h:80
Bitmapset * notnullattnums
Definition pathnodes.h:1083
AttrNumber varattno
Definition primnodes.h:275
VarReturningType varreturningtype
Definition primnodes.h:298
#define ATTNULLABLE_VALID
Definition tupdesc.h:86
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:195

References Assert, CompactAttribute::attnullability, ATTNULLABLE_VALID, bms_is_empty, bms_is_member(), elog, ERROR, fb(), find_base_rel(), find_relation_notnullatts(), has_subclass(), IsA, NoLock, NOTNULL_SOURCE_CATALOG, NOTNULL_SOURCE_HASHTABLE, NOTNULL_SOURCE_RELOPT, RelOptInfo::notnullattnums, planner_rt_fetch, RelationGetDescr, result, root, RTE_RELATION, source, table_close(), table_open(), TupleDescCompactAttr(), VAR_RETURNING_DEFAULT, Var::varattno, Var::varlevelsup, Var::varno, and Var::varreturningtype.

Referenced by expr_is_nonnullable().

Variable Documentation

◆ cpu_index_tuple_cost

PGDLLIMPORT double cpu_index_tuple_cost
extern

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

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

◆ effective_cache_size

PGDLLIMPORT int effective_cache_size
extern

Definition at line 140 of file costsize.c.

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

◆ enable_distinct_reordering

PGDLLIMPORT bool enable_distinct_reordering
extern

Definition at line 71 of file planner.c.

Referenced by get_useful_pathkeys_for_distinct().

◆ parallel_leader_participation

PGDLLIMPORT bool parallel_leader_participation
extern

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

Referenced by set_cte_size_estimates().

◆ seq_page_cost