PostgreSQL Source Code  git master
clauses.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_class.h"
#include "catalog/pg_language.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "executor/functions.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/optimizer.h"
#include "optimizer/plancat.h"
#include "optimizer/planmain.h"
#include "parser/analyze.h"
#include "parser/parse_agg.h"
#include "parser/parse_coerce.h"
#include "parser/parse_func.h"
#include "rewrite/rewriteManip.h"
#include "tcop/tcopprot.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for clauses.c:

Go to the source code of this file.

Data Structures

struct  eval_const_expressions_context
 
struct  substitute_actual_parameters_context
 
struct  substitute_actual_srf_parameters_context
 
struct  inline_error_callback_arg
 
struct  max_parallel_hazard_context
 

Macros

#define CCDN_CASETESTEXPR_OK   0x0001 /* CaseTestExpr okay here? */
 
#define ece_generic_processing(node)
 
#define ece_all_arguments_const(node)   (!expression_tree_walker((Node *) (node), contain_non_const_walker, NULL))
 
#define ece_evaluate_expr(node)
 

Functions

static bool contain_agg_clause_walker (Node *node, void *context)
 
static bool find_window_functions_walker (Node *node, WindowFuncLists *lists)
 
static bool contain_subplans_walker (Node *node, void *context)
 
static bool contain_mutable_functions_walker (Node *node, void *context)
 
static bool contain_volatile_functions_walker (Node *node, void *context)
 
static bool contain_volatile_functions_not_nextval_walker (Node *node, void *context)
 
static bool max_parallel_hazard_walker (Node *node, max_parallel_hazard_context *context)
 
static bool contain_nonstrict_functions_walker (Node *node, void *context)
 
static bool contain_exec_param_walker (Node *node, List *param_ids)
 
static bool contain_context_dependent_node (Node *clause)
 
static bool contain_context_dependent_node_walker (Node *node, int *flags)
 
static bool contain_leaked_vars_walker (Node *node, void *context)
 
static Relids find_nonnullable_rels_walker (Node *node, bool top_level)
 
static Listfind_nonnullable_vars_walker (Node *node, bool top_level)
 
static bool is_strict_saop (ScalarArrayOpExpr *expr, bool falseOK)
 
static Nodeeval_const_expressions_mutator (Node *node, eval_const_expressions_context *context)
 
static bool contain_non_const_walker (Node *node, void *context)
 
static bool ece_function_is_safe (Oid funcid, eval_const_expressions_context *context)
 
static Listsimplify_or_arguments (List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceTrue)
 
static Listsimplify_and_arguments (List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceFalse)
 
static Nodesimplify_boolean_equality (Oid opno, List *args)
 
static Exprsimplify_function (Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, List **args_p, bool funcvariadic, bool process_args, bool allow_non_const, eval_const_expressions_context *context)
 
static Listreorder_function_arguments (List *args, HeapTuple func_tuple)
 
static Listadd_function_defaults (List *args, HeapTuple func_tuple)
 
static Listfetch_function_defaults (HeapTuple func_tuple)
 
static void recheck_cast_function_args (List *args, Oid result_type, HeapTuple func_tuple)
 
static Exprevaluate_function (Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, List *args, bool funcvariadic, HeapTuple func_tuple, eval_const_expressions_context *context)
 
static Exprinline_function (Oid funcid, Oid result_type, Oid result_collid, Oid input_collid, List *args, bool funcvariadic, HeapTuple func_tuple, eval_const_expressions_context *context)
 
static Nodesubstitute_actual_parameters (Node *expr, int nargs, List *args, int *usecounts)
 
static Nodesubstitute_actual_parameters_mutator (Node *node, substitute_actual_parameters_context *context)
 
static void sql_inline_error_callback (void *arg)
 
static Querysubstitute_actual_srf_parameters (Query *expr, int nargs, List *args)
 
static Nodesubstitute_actual_srf_parameters_mutator (Node *node, substitute_actual_srf_parameters_context *context)
 
bool contain_agg_clause (Node *clause)
 
bool contain_window_function (Node *clause)
 
WindowFuncListsfind_window_functions (Node *clause, Index maxWinRef)
 
double expression_returns_set_rows (PlannerInfo *root, Node *clause)
 
bool contain_subplans (Node *clause)
 
bool contain_mutable_functions (Node *clause)
 
static bool contain_mutable_functions_checker (Oid func_id, void *context)
 
bool contain_volatile_functions (Node *clause)
 
static bool contain_volatile_functions_checker (Oid func_id, void *context)
 
bool contain_volatile_functions_not_nextval (Node *clause)
 
static bool contain_volatile_functions_not_nextval_checker (Oid func_id, void *context)
 
char max_parallel_hazard (Query *parse)
 
bool is_parallel_safe (PlannerInfo *root, Node *node)
 
static bool max_parallel_hazard_test (char proparallel, max_parallel_hazard_context *context)
 
static bool max_parallel_hazard_checker (Oid func_id, void *context)
 
bool contain_nonstrict_functions (Node *clause)
 
static bool contain_nonstrict_functions_checker (Oid func_id, void *context)
 
bool contain_exec_param (Node *clause, List *param_ids)
 
bool contain_leaked_vars (Node *clause)
 
static bool contain_leaked_vars_checker (Oid func_id, void *context)
 
Relids find_nonnullable_rels (Node *clause)
 
Listfind_nonnullable_vars (Node *clause)
 
Listfind_forced_null_vars (Node *node)
 
Varfind_forced_null_var (Node *node)
 
bool is_pseudo_constant_clause (Node *clause)
 
bool is_pseudo_constant_clause_relids (Node *clause, Relids relids)
 
int NumRelids (Node *clause)
 
void CommuteOpExpr (OpExpr *clause)
 
static bool rowtype_field_matches (Oid rowtypeid, int fieldnum, Oid expectedtype, int32 expectedtypmod, Oid expectedcollation)
 
Nodeeval_const_expressions (PlannerInfo *root, Node *node)
 
Nodeestimate_expression_value (PlannerInfo *root, Node *node)
 
Listexpand_function_arguments (List *args, Oid result_type, HeapTuple func_tuple)
 
Exprevaluate_expr (Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
 
Queryinline_set_returning_function (PlannerInfo *root, RangeTblEntry *rte)
 

Macro Definition Documentation

◆ CCDN_CASETESTEXPR_OK

#define CCDN_CASETESTEXPR_OK   0x0001 /* CaseTestExpr okay here? */

Definition at line 996 of file clauses.c.

Referenced by contain_context_dependent_node_walker().

◆ ece_all_arguments_const

#define ece_all_arguments_const (   node)    (!expression_tree_walker((Node *) (node), contain_non_const_walker, NULL))

Definition at line 2063 of file clauses.c.

Referenced by eval_const_expressions_mutator().

◆ ece_evaluate_expr

#define ece_evaluate_expr (   node)
Value:
((Node *) evaluate_expr((Expr *) (node), \
exprType((Node *) (node)), \
exprTypmod((Node *) (node)), \
exprCollation((Node *) (node))))
Expr * evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
Definition: clauses.c:4469
Definition: nodes.h:527
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41

Definition at line 2067 of file clauses.c.

Referenced by eval_const_expressions_mutator().

◆ ece_generic_processing

#define ece_generic_processing (   node)
Value:
(void *) context)
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2565
Definition: nodes.h:527
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2077

Definition at line 2054 of file clauses.c.

Referenced by eval_const_expressions_mutator().

Function Documentation

◆ add_function_defaults()

static List * add_function_defaults ( List args,
HeapTuple  func_tuple 
)
static

Definition at line 3840 of file clauses.c.

References elog, ERROR, fetch_function_defaults(), GETSTRUCT, list_concat_copy(), list_copy_tail(), and list_length().

Referenced by expand_function_arguments().

3841 {
3842  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
3843  int nargsprovided = list_length(args);
3844  List *defaults;
3845  int ndelete;
3846 
3847  /* Get all the default expressions from the pg_proc tuple */
3848  defaults = fetch_function_defaults(func_tuple);
3849 
3850  /* Delete any unused defaults from the list */
3851  ndelete = nargsprovided + list_length(defaults) - funcform->pronargs;
3852  if (ndelete < 0)
3853  elog(ERROR, "not enough default arguments");
3854  if (ndelete > 0)
3855  defaults = list_copy_tail(defaults, ndelete);
3856 
3857  /* And form the combined argument list, not modifying the input list */
3858  return list_concat_copy(args, defaults);
3859 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1422
#define ERROR
Definition: elog.h:43
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:552
static List * fetch_function_defaults(HeapTuple func_tuple)
Definition: clauses.c:3865
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
static int list_length(const List *l)
Definition: pg_list.h:149
#define elog(elevel,...)
Definition: elog.h:228
Definition: pg_list.h:50

◆ CommuteOpExpr()

void CommuteOpExpr ( OpExpr clause)

Definition at line 1892 of file clauses.c.

References OpExpr::args, elog, ERROR, get_commutator(), InvalidOid, is_opclause(), linitial, list_length(), lsecond, OidIsValid, OpExpr::opfuncid, and OpExpr::opno.

Referenced by get_switched_clauses().

1893 {
1894  Oid opoid;
1895  Node *temp;
1896 
1897  /* Sanity checks: caller is at fault if these fail */
1898  if (!is_opclause(clause) ||
1899  list_length(clause->args) != 2)
1900  elog(ERROR, "cannot commute non-binary-operator clause");
1901 
1902  opoid = get_commutator(clause->opno);
1903 
1904  if (!OidIsValid(opoid))
1905  elog(ERROR, "could not find commutator for operator %u",
1906  clause->opno);
1907 
1908  /*
1909  * modify the clause in-place!
1910  */
1911  clause->opno = opoid;
1912  clause->opfuncid = InvalidOid;
1913  /* opresulttype, opretset, opcollid, inputcollid need not change */
1914 
1915  temp = linitial(clause->args);
1916  linitial(clause->args) = lsecond(clause->args);
1917  lsecond(clause->args) = temp;
1918 }
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1426
Definition: nodes.h:527
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
#define lsecond(l)
Definition: pg_list.h:179
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:43
Oid opfuncid
Definition: primnodes.h:529
#define InvalidOid
Definition: postgres_ext.h:36
static int list_length(const List *l)
Definition: pg_list.h:149
#define elog(elevel,...)
Definition: elog.h:228
Oid opno
Definition: primnodes.h:528
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:66
List * args
Definition: primnodes.h:534

◆ contain_agg_clause()

bool contain_agg_clause ( Node clause)

Definition at line 169 of file clauses.c.

References contain_agg_clause_walker().

Referenced by get_eclass_for_sort_expr(), and subquery_planner().

170 {
171  return contain_agg_clause_walker(clause, NULL);
172 }
static bool contain_agg_clause_walker(Node *node, void *context)
Definition: clauses.c:175

◆ contain_agg_clause_walker()

static bool contain_agg_clause_walker ( Node node,
void *  context 
)
static

Definition at line 175 of file clauses.c.

References Assert, expression_tree_walker(), and IsA.

Referenced by contain_agg_clause().

176 {
177  if (node == NULL)
178  return false;
179  if (IsA(node, Aggref))
180  {
181  Assert(((Aggref *) node)->agglevelsup == 0);
182  return true; /* abort the tree traversal and return true */
183  }
184  if (IsA(node, GroupingFunc))
185  {
186  Assert(((GroupingFunc *) node)->agglevelsup == 0);
187  return true; /* abort the tree traversal and return true */
188  }
189  Assert(!IsA(node, SubLink));
190  return expression_tree_walker(node, contain_agg_clause_walker, context);
191 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
static bool contain_agg_clause_walker(Node *node, void *context)
Definition: clauses.c:175
#define Assert(condition)
Definition: c.h:800
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888

◆ contain_context_dependent_node()

static bool contain_context_dependent_node ( Node clause)
static

Definition at line 989 of file clauses.c.

References contain_context_dependent_node_walker().

Referenced by inline_function().

990 {
991  int flags = 0;
992 
993  return contain_context_dependent_node_walker(clause, &flags);
994 }
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:999

◆ contain_context_dependent_node_walker()

static bool contain_context_dependent_node_walker ( Node node,
int *  flags 
)
static

Definition at line 999 of file clauses.c.

References ArrayCoerceExpr::arg, CaseExpr::arg, CCDN_CASETESTEXPR_OK, ArrayCoerceExpr::elemexpr, expression_tree_walker(), and IsA.

Referenced by contain_context_dependent_node().

1000 {
1001  if (node == NULL)
1002  return false;
1003  if (IsA(node, CaseTestExpr))
1004  return !(*flags & CCDN_CASETESTEXPR_OK);
1005  else if (IsA(node, CaseExpr))
1006  {
1007  CaseExpr *caseexpr = (CaseExpr *) node;
1008 
1009  /*
1010  * If this CASE doesn't have a test expression, then it doesn't create
1011  * a context in which CaseTestExprs should appear, so just fall
1012  * through and treat it as a generic expression node.
1013  */
1014  if (caseexpr->arg)
1015  {
1016  int save_flags = *flags;
1017  bool res;
1018 
1019  /*
1020  * Note: in principle, we could distinguish the various sub-parts
1021  * of a CASE construct and set the flag bit only for some of them,
1022  * since we are only expecting CaseTestExprs to appear in the
1023  * "expr" subtree of the CaseWhen nodes. But it doesn't really
1024  * seem worth any extra code. If there are any bare CaseTestExprs
1025  * elsewhere in the CASE, something's wrong already.
1026  */
1027  *flags |= CCDN_CASETESTEXPR_OK;
1028  res = expression_tree_walker(node,
1030  (void *) flags);
1031  *flags = save_flags;
1032  return res;
1033  }
1034  }
1035  else if (IsA(node, ArrayCoerceExpr))
1036  {
1037  ArrayCoerceExpr *ac = (ArrayCoerceExpr *) node;
1038  int save_flags;
1039  bool res;
1040 
1041  /* Check the array expression */
1042  if (contain_context_dependent_node_walker((Node *) ac->arg, flags))
1043  return true;
1044 
1045  /* Check the elemexpr, which is allowed to contain CaseTestExpr */
1046  save_flags = *flags;
1047  *flags |= CCDN_CASETESTEXPR_OK;
1049  flags);
1050  *flags = save_flags;
1051  return res;
1052  }
1054  (void *) flags);
1055 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
Definition: nodes.h:527
#define CCDN_CASETESTEXPR_OK
Definition: clauses.c:996
Expr * elemexpr
Definition: primnodes.h:874
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
Expr * arg
Definition: primnodes.h:947
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:999

◆ contain_exec_param()

bool contain_exec_param ( Node clause,
List param_ids 
)

Definition at line 947 of file clauses.c.

References contain_exec_param_walker().

Referenced by test_opexpr_is_hashable().

948 {
949  return contain_exec_param_walker(clause, param_ids);
950 }
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition: clauses.c:953

◆ contain_exec_param_walker()

static bool contain_exec_param_walker ( Node node,
List param_ids 
)
static

Definition at line 953 of file clauses.c.

References expression_tree_walker(), IsA, list_member_int(), PARAM_EXEC, Param::paramid, and Param::paramkind.

Referenced by contain_exec_param().

954 {
955  if (node == NULL)
956  return false;
957  if (IsA(node, Param))
958  {
959  Param *p = (Param *) node;
960 
961  if (p->paramkind == PARAM_EXEC &&
962  list_member_int(param_ids, p->paramid))
963  return true;
964  }
965  return expression_tree_walker(node, contain_exec_param_walker, param_ids);
966 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
ParamKind paramkind
Definition: primnodes.h:262
bool list_member_int(const List *list, int datum)
Definition: list.c:654
int paramid
Definition: primnodes.h:263
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition: clauses.c:953

◆ contain_leaked_vars()

bool contain_leaked_vars ( Node clause)

Definition at line 1073 of file clauses.c.

References contain_leaked_vars_walker().

Referenced by make_restrictinfo_internal(), and qual_is_pushdown_safe().

1074 {
1075  return contain_leaked_vars_walker(clause, NULL);
1076 }
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1085

◆ contain_leaked_vars_checker()

static bool contain_leaked_vars_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 1079 of file clauses.c.

References get_func_leakproof().

Referenced by contain_leaked_vars_walker().

1080 {
1081  return !get_func_leakproof(func_id);
1082 }
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1754

◆ contain_leaked_vars_walker()

static bool contain_leaked_vars_walker ( Node node,
void *  context 
)
static

Definition at line 1085 of file clauses.c.

References MinMaxExpr::args, check_functions_in_node(), TypeCacheEntry::cmp_proc, contain_leaked_vars_checker(), contain_var_clause(), expression_tree_walker(), forthree, get_func_leakproof(), get_opcode(), RowCompareExpr::largs, lfirst, lfirst_oid, lookup_type_cache(), MinMaxExpr::minmaxtype, nodeTag, OidIsValid, RowCompareExpr::opnos, RowCompareExpr::rargs, T_ArrayCoerceExpr, T_ArrayExpr, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoerceViaIO, T_CollateExpr, T_Const, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncExpr, T_List, T_MinMaxExpr, T_NamedArgExpr, T_NextValueExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SQLValueFunction, T_SubscriptingRef, T_Var, and TYPECACHE_CMP_PROC.

Referenced by contain_leaked_vars().

1086 {
1087  if (node == NULL)
1088  return false;
1089 
1090  switch (nodeTag(node))
1091  {
1092  case T_Var:
1093  case T_Const:
1094  case T_Param:
1095  case T_ArrayExpr:
1096  case T_FieldSelect:
1097  case T_FieldStore:
1098  case T_NamedArgExpr:
1099  case T_BoolExpr:
1100  case T_RelabelType:
1101  case T_CollateExpr:
1102  case T_CaseExpr:
1103  case T_CaseTestExpr:
1104  case T_RowExpr:
1105  case T_SQLValueFunction:
1106  case T_NullTest:
1107  case T_BooleanTest:
1108  case T_NextValueExpr:
1109  case T_List:
1110 
1111  /*
1112  * We know these node types don't contain function calls; but
1113  * something further down in the node tree might.
1114  */
1115  break;
1116 
1117  case T_FuncExpr:
1118  case T_OpExpr:
1119  case T_DistinctExpr:
1120  case T_NullIfExpr:
1121  case T_ScalarArrayOpExpr:
1122  case T_CoerceViaIO:
1123  case T_ArrayCoerceExpr:
1124  case T_SubscriptingRef:
1125 
1126  /*
1127  * If node contains a leaky function call, and there's any Var
1128  * underneath it, reject.
1129  */
1131  context) &&
1132  contain_var_clause(node))
1133  return true;
1134  break;
1135 
1136  case T_RowCompareExpr:
1137  {
1138  /*
1139  * It's worth special-casing this because a leaky comparison
1140  * function only compromises one pair of row elements, which
1141  * might not contain Vars while others do.
1142  */
1143  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1144  ListCell *opid;
1145  ListCell *larg;
1146  ListCell *rarg;
1147 
1148  forthree(opid, rcexpr->opnos,
1149  larg, rcexpr->largs,
1150  rarg, rcexpr->rargs)
1151  {
1152  Oid funcid = get_opcode(lfirst_oid(opid));
1153 
1154  if (!get_func_leakproof(funcid) &&
1155  (contain_var_clause((Node *) lfirst(larg)) ||
1156  contain_var_clause((Node *) lfirst(rarg))))
1157  return true;
1158  }
1159  }
1160  break;
1161 
1162  case T_MinMaxExpr:
1163  {
1164  /*
1165  * MinMaxExpr is leakproof if the comparison function it calls
1166  * is leakproof.
1167  */
1168  MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
1169  TypeCacheEntry *typentry;
1170  bool leakproof;
1171 
1172  /* Look up the btree comparison function for the datatype */
1173  typentry = lookup_type_cache(minmaxexpr->minmaxtype,
1175  if (OidIsValid(typentry->cmp_proc))
1176  leakproof = get_func_leakproof(typentry->cmp_proc);
1177  else
1178  {
1179  /*
1180  * The executor will throw an error, but here we just
1181  * treat the missing function as leaky.
1182  */
1183  leakproof = false;
1184  }
1185 
1186  if (!leakproof &&
1187  contain_var_clause((Node *) minmaxexpr->args))
1188  return true;
1189  }
1190  break;
1191 
1192  case T_CurrentOfExpr:
1193 
1194  /*
1195  * WHERE CURRENT OF doesn't contain leaky function calls.
1196  * Moreover, it is essential that this is considered non-leaky,
1197  * since the planner must always generate a TID scan when CURRENT
1198  * OF is present -- cf. cost_tidscan.
1199  */
1200  return false;
1201 
1202  default:
1203 
1204  /*
1205  * If we don't recognize the node tag, assume it might be leaky.
1206  * This prevents an unexpected security hole if someone adds a new
1207  * node type that can call a function.
1208  */
1209  return true;
1210  }
1212  context);
1213 }
Oid minmaxtype
Definition: primnodes.h:1117
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1754
List * args
Definition: primnodes.h:1121
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:479
Definition: nodes.h:527
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
Definition: nodes.h:298
Definition: nodes.h:154
Definition: nodes.h:153
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:334
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1202
#define TYPECACHE_CMP_PROC
Definition: typcache.h:133
#define lfirst(lc)
Definition: pg_list.h:169
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
#define nodeTag(nodeptr)
Definition: nodes.h:532
static bool contain_leaked_vars_checker(Oid func_id, void *context)
Definition: clauses.c:1079
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1085
#define lfirst_oid(lc)
Definition: pg_list.h:171
Definition: nodes.h:155

◆ contain_mutable_functions()

◆ contain_mutable_functions_checker()

static bool contain_mutable_functions_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 363 of file clauses.c.

References func_volatile().

Referenced by contain_mutable_functions_walker().

364 {
365  return (func_volatile(func_id) != PROVOLATILE_IMMUTABLE);
366 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1697

◆ contain_mutable_functions_walker()

static bool contain_mutable_functions_walker ( Node node,
void *  context 
)
static

Definition at line 369 of file clauses.c.

References check_functions_in_node(), contain_mutable_functions_checker(), expression_tree_walker(), IsA, and query_tree_walker().

Referenced by contain_mutable_functions().

370 {
371  if (node == NULL)
372  return false;
373  /* Check for mutable functions in node itself */
375  context))
376  return true;
377 
378  if (IsA(node, SQLValueFunction))
379  {
380  /* all variants of SQLValueFunction are stable */
381  return true;
382  }
383 
384  if (IsA(node, NextValueExpr))
385  {
386  /* NextValueExpr is volatile */
387  return true;
388  }
389 
390  /*
391  * It should be safe to treat MinMaxExpr as immutable, because it will
392  * depend on a non-cross-type btree comparison function, and those should
393  * always be immutable. Treating XmlExpr as immutable is more dubious,
394  * and treating CoerceToDomain as immutable is outright dangerous. But we
395  * have done so historically, and changing this would probably cause more
396  * problems than it would fix. In practice, if you have a non-immutable
397  * domain constraint you are in for pain anyhow.
398  */
399 
400  /* Recurse to check arguments */
401  if (IsA(node, Query))
402  {
403  /* Recurse into subselects */
404  return query_tree_walker((Query *) node,
406  context, 0);
407  }
409  context);
410 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2322
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
static bool contain_mutable_functions_walker(Node *node, void *context)
Definition: clauses.c:369
static bool contain_mutable_functions_checker(Oid func_id, void *context)
Definition: clauses.c:363
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888

◆ contain_non_const_walker()

static bool contain_non_const_walker ( Node node,
void *  context 
)
static

Definition at line 3297 of file clauses.c.

References expression_tree_walker(), and IsA.

3298 {
3299  if (node == NULL)
3300  return false;
3301  if (IsA(node, Const))
3302  return false;
3303  if (IsA(node, List))
3304  return expression_tree_walker(node, contain_non_const_walker, context);
3305  /* Otherwise, abort the tree traversal and return true */
3306  return true;
3307 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
Definition: pg_list.h:50
static bool contain_non_const_walker(Node *node, void *context)
Definition: clauses.c:3297

◆ contain_nonstrict_functions()

bool contain_nonstrict_functions ( Node clause)

Definition at line 806 of file clauses.c.

References contain_nonstrict_functions_walker().

Referenced by inline_function(), process_equivalence(), and pullup_replace_vars_callback().

807 {
808  return contain_nonstrict_functions_walker(clause, NULL);
809 }
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:818

◆ contain_nonstrict_functions_checker()

static bool contain_nonstrict_functions_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 812 of file clauses.c.

References func_strict().

Referenced by contain_nonstrict_functions_walker().

813 {
814  return !func_strict(func_id);
815 }
bool func_strict(Oid funcid)
Definition: lsyscache.c:1678

◆ contain_nonstrict_functions_walker()

static bool contain_nonstrict_functions_walker ( Node node,
void *  context 
)
static

Definition at line 818 of file clauses.c.

References AND_EXPR, arg, BoolExpr::boolop, check_functions_in_node(), contain_nonstrict_functions_checker(), expression_tree_walker(), IsA, and OR_EXPR.

Referenced by contain_nonstrict_functions().

819 {
820  if (node == NULL)
821  return false;
822  if (IsA(node, Aggref))
823  {
824  /* an aggregate could return non-null with null input */
825  return true;
826  }
827  if (IsA(node, GroupingFunc))
828  {
829  /*
830  * A GroupingFunc doesn't evaluate its arguments, and therefore must
831  * be treated as nonstrict.
832  */
833  return true;
834  }
835  if (IsA(node, WindowFunc))
836  {
837  /* a window function could return non-null with null input */
838  return true;
839  }
840  if (IsA(node, SubscriptingRef))
841  {
842  /*
843  * subscripting assignment is nonstrict, but subscripting itself is
844  * strict
845  */
846  if (((SubscriptingRef *) node)->refassgnexpr != NULL)
847  return true;
848 
849  /* else fall through to check args */
850  }
851  if (IsA(node, DistinctExpr))
852  {
853  /* IS DISTINCT FROM is inherently non-strict */
854  return true;
855  }
856  if (IsA(node, NullIfExpr))
857  {
858  /* NULLIF is inherently non-strict */
859  return true;
860  }
861  if (IsA(node, BoolExpr))
862  {
863  BoolExpr *expr = (BoolExpr *) node;
864 
865  switch (expr->boolop)
866  {
867  case AND_EXPR:
868  case OR_EXPR:
869  /* AND, OR are inherently non-strict */
870  return true;
871  default:
872  break;
873  }
874  }
875  if (IsA(node, SubLink))
876  {
877  /* In some cases a sublink might be strict, but in general not */
878  return true;
879  }
880  if (IsA(node, SubPlan))
881  return true;
882  if (IsA(node, AlternativeSubPlan))
883  return true;
884  if (IsA(node, FieldStore))
885  return true;
886  if (IsA(node, CoerceViaIO))
887  {
888  /*
889  * CoerceViaIO is strict regardless of whether the I/O functions are,
890  * so just go look at its argument; asking check_functions_in_node is
891  * useless expense and could deliver the wrong answer.
892  */
894  context);
895  }
896  if (IsA(node, ArrayCoerceExpr))
897  {
898  /*
899  * ArrayCoerceExpr is strict at the array level, regardless of what
900  * the per-element expression is; so we should ignore elemexpr and
901  * recurse only into the arg.
902  */
904  context);
905  }
906  if (IsA(node, CaseExpr))
907  return true;
908  if (IsA(node, ArrayExpr))
909  return true;
910  if (IsA(node, RowExpr))
911  return true;
912  if (IsA(node, RowCompareExpr))
913  return true;
914  if (IsA(node, CoalesceExpr))
915  return true;
916  if (IsA(node, MinMaxExpr))
917  return true;
918  if (IsA(node, XmlExpr))
919  return true;
920  if (IsA(node, NullTest))
921  return true;
922  if (IsA(node, BooleanTest))
923  return true;
924 
925  /* Check other function-containing nodes */
927  context))
928  return true;
929 
931  context);
932 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
Definition: nodes.h:527
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:818
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
BoolExprType boolop
Definition: primnodes.h:594
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
void * arg
static bool contain_nonstrict_functions_checker(Oid func_id, void *context)
Definition: clauses.c:812

◆ contain_subplans()

bool contain_subplans ( Node clause)

Definition at line 322 of file clauses.c.

References contain_subplans_walker().

Referenced by convert_EXISTS_to_ANY(), ExecInitValuesScan(), inline_function(), inline_set_returning_function(), qual_is_pushdown_safe(), and subquery_planner().

323 {
324  return contain_subplans_walker(clause, NULL);
325 }
static bool contain_subplans_walker(Node *node, void *context)
Definition: clauses.c:328

◆ contain_subplans_walker()

static bool contain_subplans_walker ( Node node,
void *  context 
)
static

Definition at line 328 of file clauses.c.

References expression_tree_walker(), and IsA.

Referenced by contain_subplans().

329 {
330  if (node == NULL)
331  return false;
332  if (IsA(node, SubPlan) ||
333  IsA(node, AlternativeSubPlan) ||
334  IsA(node, SubLink))
335  return true; /* abort the tree traversal and return true */
336  return expression_tree_walker(node, contain_subplans_walker, context);
337 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
static bool contain_subplans_walker(Node *node, void *context)
Definition: clauses.c:328

◆ contain_volatile_functions()

◆ contain_volatile_functions_checker()

static bool contain_volatile_functions_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 442 of file clauses.c.

References func_volatile().

Referenced by contain_volatile_functions_walker().

443 {
444  return (func_volatile(func_id) == PROVOLATILE_VOLATILE);
445 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1697

◆ contain_volatile_functions_not_nextval()

bool contain_volatile_functions_not_nextval ( Node clause)

Definition at line 486 of file clauses.c.

References contain_volatile_functions_not_nextval_walker().

Referenced by BeginCopyFrom().

487 {
489 }
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:499

◆ contain_volatile_functions_not_nextval_checker()

static bool contain_volatile_functions_not_nextval_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 492 of file clauses.c.

References func_volatile().

Referenced by contain_volatile_functions_not_nextval_walker().

493 {
494  return (func_id != F_NEXTVAL &&
495  func_volatile(func_id) == PROVOLATILE_VOLATILE);
496 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1697

◆ contain_volatile_functions_not_nextval_walker()

static bool contain_volatile_functions_not_nextval_walker ( Node node,
void *  context 
)
static

Definition at line 499 of file clauses.c.

References check_functions_in_node(), contain_volatile_functions_not_nextval_checker(), expression_tree_walker(), IsA, and query_tree_walker().

Referenced by contain_volatile_functions_not_nextval().

500 {
501  if (node == NULL)
502  return false;
503  /* Check for volatile functions in node itself */
504  if (check_functions_in_node(node,
506  context))
507  return true;
508 
509  /*
510  * See notes in contain_mutable_functions_walker about why we treat
511  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
512  * SQLValueFunction is stable. Hence, none of them are of interest here.
513  * Also, since we're intentionally ignoring nextval(), presumably we
514  * should ignore NextValueExpr.
515  */
516 
517  /* Recurse to check arguments */
518  if (IsA(node, Query))
519  {
520  /* Recurse into subselects */
521  return query_tree_walker((Query *) node,
523  context, 0);
524  }
525  return expression_tree_walker(node,
527  context);
528 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2322
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:499
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
static bool contain_volatile_functions_not_nextval_checker(Oid func_id, void *context)
Definition: clauses.c:492

◆ contain_volatile_functions_walker()

static bool contain_volatile_functions_walker ( Node node,
void *  context 
)
static

Definition at line 448 of file clauses.c.

References check_functions_in_node(), contain_volatile_functions_checker(), expression_tree_walker(), IsA, and query_tree_walker().

Referenced by contain_volatile_functions().

449 {
450  if (node == NULL)
451  return false;
452  /* Check for volatile functions in node itself */
454  context))
455  return true;
456 
457  if (IsA(node, NextValueExpr))
458  {
459  /* NextValueExpr is volatile */
460  return true;
461  }
462 
463  /*
464  * See notes in contain_mutable_functions_walker about why we treat
465  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
466  * SQLValueFunction is stable. Hence, none of them are of interest here.
467  */
468 
469  /* Recurse to check arguments */
470  if (IsA(node, Query))
471  {
472  /* Recurse into subselects */
473  return query_tree_walker((Query *) node,
475  context, 0);
476  }
478  context);
479 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2322
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
static bool contain_volatile_functions_walker(Node *node, void *context)
Definition: clauses.c:448
static bool contain_volatile_functions_checker(Oid func_id, void *context)
Definition: clauses.c:442
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888

◆ contain_window_function()

bool contain_window_function ( Node clause)

Definition at line 206 of file clauses.c.

References contain_windowfuncs().

Referenced by get_eclass_for_sort_expr(), and qual_is_pushdown_safe().

207 {
208  return contain_windowfuncs(clause);
209 }
bool contain_windowfuncs(Node *node)
Definition: rewriteManip.c:197

◆ ece_function_is_safe()

static bool ece_function_is_safe ( Oid  funcid,
eval_const_expressions_context context 
)
static

Definition at line 3313 of file clauses.c.

References eval_const_expressions_context::estimate, and func_volatile().

Referenced by eval_const_expressions_mutator().

3314 {
3315  char provolatile = func_volatile(funcid);
3316 
3317  /*
3318  * Ordinarily we are only allowed to simplify immutable functions. But for
3319  * purposes of estimation, we consider it okay to simplify functions that
3320  * are merely stable; the risk that the result might change from planning
3321  * time to execution time is worth taking in preference to not being able
3322  * to estimate the value at all.
3323  */
3324  if (provolatile == PROVOLATILE_IMMUTABLE)
3325  return true;
3326  if (context->estimate && provolatile == PROVOLATILE_STABLE)
3327  return true;
3328  return false;
3329 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1697

◆ estimate_expression_value()

Node* estimate_expression_value ( PlannerInfo root,
Node node 
)

Definition at line 2032 of file clauses.c.

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

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

2033 {
2035 
2036  context.boundParams = root->glob->boundParams; /* bound Params */
2037  /* we do not need to mark the plan as depending on inlined functions */
2038  context.root = NULL;
2039  context.active_fns = NIL; /* nothing being recursively simplified */
2040  context.case_val = NULL; /* no CASE being examined */
2041  context.estimate = true; /* unsafe transformations OK */
2042  return eval_const_expressions_mutator(node, &context);
2043 }
#define NIL
Definition: pg_list.h:65
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2077
ParamListInfo boundParams
Definition: clauses.c:58
PlannerGlobal * glob
Definition: pathnodes.h:175
ParamListInfo boundParams
Definition: pathnodes.h:105

◆ eval_const_expressions()

Node* eval_const_expressions ( PlannerInfo root,
Node node 
)

Definition at line 1999 of file clauses.c.

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

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

2000 {
2002 
2003  if (root)
2004  context.boundParams = root->glob->boundParams; /* bound Params */
2005  else
2006  context.boundParams = NULL;
2007  context.root = root; /* for inlined-function dependencies */
2008  context.active_fns = NIL; /* nothing being recursively simplified */
2009  context.case_val = NULL; /* no CASE being examined */
2010  context.estimate = false; /* safe transformations only */
2011  return eval_const_expressions_mutator(node, &context);
2012 }
#define NIL
Definition: pg_list.h:65
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2077
ParamListInfo boundParams
Definition: clauses.c:58
PlannerGlobal * glob
Definition: pathnodes.h:175
ParamListInfo boundParams
Definition: pathnodes.h:105

◆ eval_const_expressions_mutator()

static Node * eval_const_expressions_mutator ( Node node,
eval_const_expressions_context context 
)
static

Definition at line 2077 of file clauses.c.

References WindowFunc::aggfilter, AND_EXPR, applyRelabelType(), arg, FieldSelect::arg, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, CaseExpr::arg, NullTest::arg, BooleanTest::arg, CoerceToDomain::arg, NullTest::argisrow, generate_unaccent_rules::args, WindowFunc::args, FuncExpr::args, OpExpr::args, BoolExpr::args, CaseExpr::args, RowExpr::args, CoalesceExpr::args, Assert, BoolGetDatum, BoolExpr::boolop, BooleanTest::booltesttype, eval_const_expressions_context::boundParams, eval_const_expressions_context::case_val, CaseExpr::casecollid, CaseExpr::casetype, castNode, CoalesceExpr::coalescecollid, CoalesceExpr::coalescetype, COERCE_IMPLICIT_CAST, CoerceViaIO::coerceformat, CoerceToDomain::coercionformat, CollateExpr::collOid, Const::constisnull, Const::consttype, Const::constvalue, contain_mutable_functions(), ConvertRowtypeExpr::convertformat, copyObject, datumCopy(), DatumGetBool, CaseExpr::defresult, DomainHasConstraints(), ece_all_arguments_const, ece_evaluate_expr, ece_function_is_safe(), ece_generic_processing, ArrayCoerceExpr::elemexpr, elog, ERROR, eval_const_expressions_context::estimate, evaluate_expr(), expand_function_arguments(), CaseWhen::expr, exprCollation(), expression_tree_mutator(), exprType(), exprTypmod(), FieldSelect::fieldnum, FuncExpr::funccollid, FuncExpr::funcformat, FuncExpr::funcid, FuncExpr::funcresulttype, FuncExpr::funcretset, FuncExpr::funcvariadic, get_typlenbyval(), getTypeInputInfo(), getTypeOutputInfo(), HeapTupleIsValid, WindowFunc::inputcollid, FuncExpr::inputcollid, OpExpr::inputcollid, Int32GetDatum, InvalidAttrNumber, InvalidOid, IS_FALSE, IS_NOT_FALSE, IS_NOT_NULL, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_NULL, IS_TRUE, IS_UNKNOWN, IsA, ParamExternData::isnull, lappend(), lfirst, lfirst_node, linitial, list_length(), list_make1, list_make3, list_nth(), WindowFunc::location, FuncExpr::location, OpExpr::location, RelabelType::location, CoerceViaIO::location, ConvertRowtypeExpr::location, CollateExpr::location, CaseExpr::location, CaseWhen::location, CoalesceExpr::location, NullTest::location, BooleanTest::location, CoerceToDomain::location, make_andclause(), make_orclause(), makeBoolConst(), makeConst(), makeNode, makeNullConst(), makeVar(), negate_clause(), NIL, nodeTag, NOT_EXPR, NullTest::nulltesttype, ParamListInfoData::numParams, ObjectIdGetDatum, OidIsValid, OpExpr::opcollid, OpExpr::opfuncid, ScalarArrayOpExpr::opfuncid, OpExpr::opno, OpExpr::opresulttype, OpExpr::opretset, OR_EXPR, PARAM_EXTERN, PARAM_FLAG_CONST, Param::paramcollid, ParamListInfoData::paramFetch, Param::paramid, Param::paramkind, ParamListInfoData::params, Param::paramtype, Param::paramtypmod, ParamExternData::pflags, PlaceHolderVar::phexpr, PROCOID, ParamExternData::ptype, record_plan_type_dependency(), RelabelType::relabelformat, ReleaseSysCache(), CaseWhen::result, FieldSelect::resultcollid, RelabelType::resultcollid, CoerceViaIO::resultcollid, CoerceToDomain::resultcollid, FieldSelect::resulttype, RelabelType::resulttype, CoerceViaIO::resulttype, ConvertRowtypeExpr::resulttype, CoerceToDomain::resulttype, FieldSelect::resulttypmod, RelabelType::resulttypmod, CoerceToDomain::resulttypmod, eval_const_expressions_context::root, RowExpr::row_typeid, rowtype_field_matches(), SearchSysCache1(), set_opfuncid(), set_sa_opfuncid(), simplify_and_arguments(), simplify_boolean_equality(), simplify_function(), simplify_or_arguments(), T_AlternativeSubPlan, T_ArrayCoerceExpr, T_ArrayExpr, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceViaIO, T_CollateExpr, T_ConvertRowtypeExpr, T_DistinctExpr, T_FieldSelect, T_FuncExpr, T_MinMaxExpr, T_NullTest, T_OpExpr, T_Param, T_PlaceHolderVar, T_RelabelType, T_RowExpr, T_ScalarArrayOpExpr, T_SQLValueFunction, T_SubPlan, T_SubscriptingRef, T_WindowFunc, Expr::type, ParamExternData::value, WindowFunc::winagg, WindowFunc::wincollid, WindowFunc::winfnoid, WindowFunc::winref, WindowFunc::winstar, and WindowFunc::wintype.

Referenced by estimate_expression_value(), eval_const_expressions(), inline_function(), simplify_and_arguments(), simplify_function(), and simplify_or_arguments().

2079 {
2080  if (node == NULL)
2081  return NULL;
2082  switch (nodeTag(node))
2083  {
2084  case T_Param:
2085  {
2086  Param *param = (Param *) node;
2087  ParamListInfo paramLI = context->boundParams;
2088 
2089  /* Look to see if we've been given a value for this Param */
2090  if (param->paramkind == PARAM_EXTERN &&
2091  paramLI != NULL &&
2092  param->paramid > 0 &&
2093  param->paramid <= paramLI->numParams)
2094  {
2095  ParamExternData *prm;
2096  ParamExternData prmdata;
2097 
2098  /*
2099  * Give hook a chance in case parameter is dynamic. Tell
2100  * it that this fetch is speculative, so it should avoid
2101  * erroring out if parameter is unavailable.
2102  */
2103  if (paramLI->paramFetch != NULL)
2104  prm = paramLI->paramFetch(paramLI, param->paramid,
2105  true, &prmdata);
2106  else
2107  prm = &paramLI->params[param->paramid - 1];
2108 
2109  /*
2110  * We don't just check OidIsValid, but insist that the
2111  * fetched type match the Param, just in case the hook did
2112  * something unexpected. No need to throw an error here
2113  * though; leave that for runtime.
2114  */
2115  if (OidIsValid(prm->ptype) &&
2116  prm->ptype == param->paramtype)
2117  {
2118  /* OK to substitute parameter value? */
2119  if (context->estimate ||
2120  (prm->pflags & PARAM_FLAG_CONST))
2121  {
2122  /*
2123  * Return a Const representing the param value.
2124  * Must copy pass-by-ref datatypes, since the
2125  * Param might be in a memory context
2126  * shorter-lived than our output plan should be.
2127  */
2128  int16 typLen;
2129  bool typByVal;
2130  Datum pval;
2131 
2132  get_typlenbyval(param->paramtype,
2133  &typLen, &typByVal);
2134  if (prm->isnull || typByVal)
2135  pval = prm->value;
2136  else
2137  pval = datumCopy(prm->value, typByVal, typLen);
2138  return (Node *) makeConst(param->paramtype,
2139  param->paramtypmod,
2140  param->paramcollid,
2141  (int) typLen,
2142  pval,
2143  prm->isnull,
2144  typByVal);
2145  }
2146  }
2147  }
2148 
2149  /*
2150  * Not replaceable, so just copy the Param (no need to
2151  * recurse)
2152  */
2153  return (Node *) copyObject(param);
2154  }
2155  case T_WindowFunc:
2156  {
2157  WindowFunc *expr = (WindowFunc *) node;
2158  Oid funcid = expr->winfnoid;
2159  List *args;
2160  Expr *aggfilter;
2161  HeapTuple func_tuple;
2162  WindowFunc *newexpr;
2163 
2164  /*
2165  * We can't really simplify a WindowFunc node, but we mustn't
2166  * just fall through to the default processing, because we
2167  * have to apply expand_function_arguments to its argument
2168  * list. That takes care of inserting default arguments and
2169  * expanding named-argument notation.
2170  */
2171  func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2172  if (!HeapTupleIsValid(func_tuple))
2173  elog(ERROR, "cache lookup failed for function %u", funcid);
2174 
2175  args = expand_function_arguments(expr->args, expr->wintype,
2176  func_tuple);
2177 
2178  ReleaseSysCache(func_tuple);
2179 
2180  /* Now, recursively simplify the args (which are a List) */
2181  args = (List *)
2184  (void *) context);
2185  /* ... and the filter expression, which isn't */
2186  aggfilter = (Expr *)
2188  context);
2189 
2190  /* And build the replacement WindowFunc node */
2191  newexpr = makeNode(WindowFunc);
2192  newexpr->winfnoid = expr->winfnoid;
2193  newexpr->wintype = expr->wintype;
2194  newexpr->wincollid = expr->wincollid;
2195  newexpr->inputcollid = expr->inputcollid;
2196  newexpr->args = args;
2197  newexpr->aggfilter = aggfilter;
2198  newexpr->winref = expr->winref;
2199  newexpr->winstar = expr->winstar;
2200  newexpr->winagg = expr->winagg;
2201  newexpr->location = expr->location;
2202 
2203  return (Node *) newexpr;
2204  }
2205  case T_FuncExpr:
2206  {
2207  FuncExpr *expr = (FuncExpr *) node;
2208  List *args = expr->args;
2209  Expr *simple;
2210  FuncExpr *newexpr;
2211 
2212  /*
2213  * Code for op/func reduction is pretty bulky, so split it out
2214  * as a separate function. Note: exprTypmod normally returns
2215  * -1 for a FuncExpr, but not when the node is recognizably a
2216  * length coercion; we want to preserve the typmod in the
2217  * eventual Const if so.
2218  */
2219  simple = simplify_function(expr->funcid,
2220  expr->funcresulttype,
2221  exprTypmod(node),
2222  expr->funccollid,
2223  expr->inputcollid,
2224  &args,
2225  expr->funcvariadic,
2226  true,
2227  true,
2228  context);
2229  if (simple) /* successfully simplified it */
2230  return (Node *) simple;
2231 
2232  /*
2233  * The expression cannot be simplified any further, so build
2234  * and return a replacement FuncExpr node using the
2235  * possibly-simplified arguments. Note that we have also
2236  * converted the argument list to positional notation.
2237  */
2238  newexpr = makeNode(FuncExpr);
2239  newexpr->funcid = expr->funcid;
2240  newexpr->funcresulttype = expr->funcresulttype;
2241  newexpr->funcretset = expr->funcretset;
2242  newexpr->funcvariadic = expr->funcvariadic;
2243  newexpr->funcformat = expr->funcformat;
2244  newexpr->funccollid = expr->funccollid;
2245  newexpr->inputcollid = expr->inputcollid;
2246  newexpr->args = args;
2247  newexpr->location = expr->location;
2248  return (Node *) newexpr;
2249  }
2250  case T_OpExpr:
2251  {
2252  OpExpr *expr = (OpExpr *) node;
2253  List *args = expr->args;
2254  Expr *simple;
2255  OpExpr *newexpr;
2256 
2257  /*
2258  * Need to get OID of underlying function. Okay to scribble
2259  * on input to this extent.
2260  */
2261  set_opfuncid(expr);
2262 
2263  /*
2264  * Code for op/func reduction is pretty bulky, so split it out
2265  * as a separate function.
2266  */
2267  simple = simplify_function(expr->opfuncid,
2268  expr->opresulttype, -1,
2269  expr->opcollid,
2270  expr->inputcollid,
2271  &args,
2272  false,
2273  true,
2274  true,
2275  context);
2276  if (simple) /* successfully simplified it */
2277  return (Node *) simple;
2278 
2279  /*
2280  * If the operator is boolean equality or inequality, we know
2281  * how to simplify cases involving one constant and one
2282  * non-constant argument.
2283  */
2284  if (expr->opno == BooleanEqualOperator ||
2285  expr->opno == BooleanNotEqualOperator)
2286  {
2287  simple = (Expr *) simplify_boolean_equality(expr->opno,
2288  args);
2289  if (simple) /* successfully simplified it */
2290  return (Node *) simple;
2291  }
2292 
2293  /*
2294  * The expression cannot be simplified any further, so build
2295  * and return a replacement OpExpr node using the
2296  * possibly-simplified arguments.
2297  */
2298  newexpr = makeNode(OpExpr);
2299  newexpr->opno = expr->opno;
2300  newexpr->opfuncid = expr->opfuncid;
2301  newexpr->opresulttype = expr->opresulttype;
2302  newexpr->opretset = expr->opretset;
2303  newexpr->opcollid = expr->opcollid;
2304  newexpr->inputcollid = expr->inputcollid;
2305  newexpr->args = args;
2306  newexpr->location = expr->location;
2307  return (Node *) newexpr;
2308  }
2309  case T_DistinctExpr:
2310  {
2311  DistinctExpr *expr = (DistinctExpr *) node;
2312  List *args;
2313  ListCell *arg;
2314  bool has_null_input = false;
2315  bool all_null_input = true;
2316  bool has_nonconst_input = false;
2317  Expr *simple;
2318  DistinctExpr *newexpr;
2319 
2320  /*
2321  * Reduce constants in the DistinctExpr's arguments. We know
2322  * args is either NIL or a List node, so we can call
2323  * expression_tree_mutator directly rather than recursing to
2324  * self.
2325  */
2326  args = (List *) expression_tree_mutator((Node *) expr->args,
2328  (void *) context);
2329 
2330  /*
2331  * We must do our own check for NULLs because DistinctExpr has
2332  * different results for NULL input than the underlying
2333  * operator does.
2334  */
2335  foreach(arg, args)
2336  {
2337  if (IsA(lfirst(arg), Const))
2338  {
2339  has_null_input |= ((Const *) lfirst(arg))->constisnull;
2340  all_null_input &= ((Const *) lfirst(arg))->constisnull;
2341  }
2342  else
2343  has_nonconst_input = true;
2344  }
2345 
2346  /* all constants? then can optimize this out */
2347  if (!has_nonconst_input)
2348  {
2349  /* all nulls? then not distinct */
2350  if (all_null_input)
2351  return makeBoolConst(false, false);
2352 
2353  /* one null? then distinct */
2354  if (has_null_input)
2355  return makeBoolConst(true, false);
2356 
2357  /* otherwise try to evaluate the '=' operator */
2358  /* (NOT okay to try to inline it, though!) */
2359 
2360  /*
2361  * Need to get OID of underlying function. Okay to
2362  * scribble on input to this extent.
2363  */
2364  set_opfuncid((OpExpr *) expr); /* rely on struct
2365  * equivalence */
2366 
2367  /*
2368  * Code for op/func reduction is pretty bulky, so split it
2369  * out as a separate function.
2370  */
2371  simple = simplify_function(expr->opfuncid,
2372  expr->opresulttype, -1,
2373  expr->opcollid,
2374  expr->inputcollid,
2375  &args,
2376  false,
2377  false,
2378  false,
2379  context);
2380  if (simple) /* successfully simplified it */
2381  {
2382  /*
2383  * Since the underlying operator is "=", must negate
2384  * its result
2385  */
2386  Const *csimple = castNode(Const, simple);
2387 
2388  csimple->constvalue =
2389  BoolGetDatum(!DatumGetBool(csimple->constvalue));
2390  return (Node *) csimple;
2391  }
2392  }
2393 
2394  /*
2395  * The expression cannot be simplified any further, so build
2396  * and return a replacement DistinctExpr node using the
2397  * possibly-simplified arguments.
2398  */
2399  newexpr = makeNode(DistinctExpr);
2400  newexpr->opno = expr->opno;
2401  newexpr->opfuncid = expr->opfuncid;
2402  newexpr->opresulttype = expr->opresulttype;
2403  newexpr->opretset = expr->opretset;
2404  newexpr->opcollid = expr->opcollid;
2405  newexpr->inputcollid = expr->inputcollid;
2406  newexpr->args = args;
2407  newexpr->location = expr->location;
2408  return (Node *) newexpr;
2409  }
2410  case T_ScalarArrayOpExpr:
2411  {
2412  ScalarArrayOpExpr *saop;
2413 
2414  /* Copy the node and const-simplify its arguments */
2415  saop = (ScalarArrayOpExpr *) ece_generic_processing(node);
2416 
2417  /* Make sure we know underlying function */
2418  set_sa_opfuncid(saop);
2419 
2420  /*
2421  * If all arguments are Consts, and it's a safe function, we
2422  * can fold to a constant
2423  */
2424  if (ece_all_arguments_const(saop) &&
2425  ece_function_is_safe(saop->opfuncid, context))
2426  return ece_evaluate_expr(saop);
2427  return (Node *) saop;
2428  }
2429  case T_BoolExpr:
2430  {
2431  BoolExpr *expr = (BoolExpr *) node;
2432 
2433  switch (expr->boolop)
2434  {
2435  case OR_EXPR:
2436  {
2437  List *newargs;
2438  bool haveNull = false;
2439  bool forceTrue = false;
2440 
2441  newargs = simplify_or_arguments(expr->args,
2442  context,
2443  &haveNull,
2444  &forceTrue);
2445  if (forceTrue)
2446  return makeBoolConst(true, false);
2447  if (haveNull)
2448  newargs = lappend(newargs,
2449  makeBoolConst(false, true));
2450  /* If all the inputs are FALSE, result is FALSE */
2451  if (newargs == NIL)
2452  return makeBoolConst(false, false);
2453 
2454  /*
2455  * If only one nonconst-or-NULL input, it's the
2456  * result
2457  */
2458  if (list_length(newargs) == 1)
2459  return (Node *) linitial(newargs);
2460  /* Else we still need an OR node */
2461  return (Node *) make_orclause(newargs);
2462  }
2463  case AND_EXPR:
2464  {
2465  List *newargs;
2466  bool haveNull = false;
2467  bool forceFalse = false;
2468 
2469  newargs = simplify_and_arguments(expr->args,
2470  context,
2471  &haveNull,
2472  &forceFalse);
2473  if (forceFalse)
2474  return makeBoolConst(false, false);
2475  if (haveNull)
2476  newargs = lappend(newargs,
2477  makeBoolConst(false, true));
2478  /* If all the inputs are TRUE, result is TRUE */
2479  if (newargs == NIL)
2480  return makeBoolConst(true, false);
2481 
2482  /*
2483  * If only one nonconst-or-NULL input, it's the
2484  * result
2485  */
2486  if (list_length(newargs) == 1)
2487  return (Node *) linitial(newargs);
2488  /* Else we still need an AND node */
2489  return (Node *) make_andclause(newargs);
2490  }
2491  case NOT_EXPR:
2492  {
2493  Node *arg;
2494 
2495  Assert(list_length(expr->args) == 1);
2497  context);
2498 
2499  /*
2500  * Use negate_clause() to see if we can simplify
2501  * away the NOT.
2502  */
2503  return negate_clause(arg);
2504  }
2505  default:
2506  elog(ERROR, "unrecognized boolop: %d",
2507  (int) expr->boolop);
2508  break;
2509  }
2510  break;
2511  }
2512  case T_SubPlan:
2513  case T_AlternativeSubPlan:
2514 
2515  /*
2516  * Return a SubPlan unchanged --- too late to do anything with it.
2517  *
2518  * XXX should we ereport() here instead? Probably this routine
2519  * should never be invoked after SubPlan creation.
2520  */
2521  return node;
2522  case T_RelabelType:
2523  {
2524  RelabelType *relabel = (RelabelType *) node;
2525  Node *arg;
2526 
2527  /* Simplify the input ... */
2528  arg = eval_const_expressions_mutator((Node *) relabel->arg,
2529  context);
2530  /* ... and attach a new RelabelType node, if needed */
2531  return applyRelabelType(arg,
2532  relabel->resulttype,
2533  relabel->resulttypmod,
2534  relabel->resultcollid,
2535  relabel->relabelformat,
2536  relabel->location,
2537  true);
2538  }
2539  case T_CoerceViaIO:
2540  {
2541  CoerceViaIO *expr = (CoerceViaIO *) node;
2542  List *args;
2543  Oid outfunc;
2544  bool outtypisvarlena;
2545  Oid infunc;
2546  Oid intypioparam;
2547  Expr *simple;
2548  CoerceViaIO *newexpr;
2549 
2550  /* Make a List so we can use simplify_function */
2551  args = list_make1(expr->arg);
2552 
2553  /*
2554  * CoerceViaIO represents calling the source type's output
2555  * function then the result type's input function. So, try to
2556  * simplify it as though it were a stack of two such function
2557  * calls. First we need to know what the functions are.
2558  *
2559  * Note that the coercion functions are assumed not to care
2560  * about input collation, so we just pass InvalidOid for that.
2561  */
2562  getTypeOutputInfo(exprType((Node *) expr->arg),
2563  &outfunc, &outtypisvarlena);
2565  &infunc, &intypioparam);
2566 
2567  simple = simplify_function(outfunc,
2568  CSTRINGOID, -1,
2569  InvalidOid,
2570  InvalidOid,
2571  &args,
2572  false,
2573  true,
2574  true,
2575  context);
2576  if (simple) /* successfully simplified output fn */
2577  {
2578  /*
2579  * Input functions may want 1 to 3 arguments. We always
2580  * supply all three, trusting that nothing downstream will
2581  * complain.
2582  */
2583  args = list_make3(simple,
2584  makeConst(OIDOID,
2585  -1,
2586  InvalidOid,
2587  sizeof(Oid),
2588  ObjectIdGetDatum(intypioparam),
2589  false,
2590  true),
2591  makeConst(INT4OID,
2592  -1,
2593  InvalidOid,
2594  sizeof(int32),
2595  Int32GetDatum(-1),
2596  false,
2597  true));
2598 
2599  simple = simplify_function(infunc,
2600  expr->resulttype, -1,
2601  expr->resultcollid,
2602  InvalidOid,
2603  &args,
2604  false,
2605  false,
2606  true,
2607  context);
2608  if (simple) /* successfully simplified input fn */
2609  return (Node *) simple;
2610  }
2611 
2612  /*
2613  * The expression cannot be simplified any further, so build
2614  * and return a replacement CoerceViaIO node using the
2615  * possibly-simplified argument.
2616  */
2617  newexpr = makeNode(CoerceViaIO);
2618  newexpr->arg = (Expr *) linitial(args);
2619  newexpr->resulttype = expr->resulttype;
2620  newexpr->resultcollid = expr->resultcollid;
2621  newexpr->coerceformat = expr->coerceformat;
2622  newexpr->location = expr->location;
2623  return (Node *) newexpr;
2624  }
2625  case T_ArrayCoerceExpr:
2626  {
2628  Node *save_case_val;
2629 
2630  /*
2631  * Copy the node and const-simplify its arguments. We can't
2632  * use ece_generic_processing() here because we need to mess
2633  * with case_val only while processing the elemexpr.
2634  */
2635  memcpy(ac, node, sizeof(ArrayCoerceExpr));
2636  ac->arg = (Expr *)
2638  context);
2639 
2640  /*
2641  * Set up for the CaseTestExpr node contained in the elemexpr.
2642  * We must prevent it from absorbing any outer CASE value.
2643  */
2644  save_case_val = context->case_val;
2645  context->case_val = NULL;
2646 
2647  ac->elemexpr = (Expr *)
2649  context);
2650 
2651  context->case_val = save_case_val;
2652 
2653  /*
2654  * If constant argument and the per-element expression is
2655  * immutable, we can simplify the whole thing to a constant.
2656  * Exception: although contain_mutable_functions considers
2657  * CoerceToDomain immutable for historical reasons, let's not
2658  * do so here; this ensures coercion to an array-over-domain
2659  * does not apply the domain's constraints until runtime.
2660  */
2661  if (ac->arg && IsA(ac->arg, Const) &&
2662  ac->elemexpr && !IsA(ac->elemexpr, CoerceToDomain) &&
2664  return ece_evaluate_expr(ac);
2665 
2666  return (Node *) ac;
2667  }
2668  case T_CollateExpr:
2669  {
2670  /*
2671  * We replace CollateExpr with RelabelType, so as to improve
2672  * uniformity of expression representation and thus simplify
2673  * comparison of expressions. Hence this looks very nearly
2674  * the same as the RelabelType case, and we can apply the same
2675  * optimizations to avoid unnecessary RelabelTypes.
2676  */
2677  CollateExpr *collate = (CollateExpr *) node;
2678  Node *arg;
2679 
2680  /* Simplify the input ... */
2681  arg = eval_const_expressions_mutator((Node *) collate->arg,
2682  context);
2683  /* ... and attach a new RelabelType node, if needed */
2684  return applyRelabelType(arg,
2685  exprType(arg),
2686  exprTypmod(arg),
2687  collate->collOid,
2689  collate->location,
2690  true);
2691  }
2692  case T_CaseExpr:
2693  {
2694  /*----------
2695  * CASE expressions can be simplified if there are constant
2696  * condition clauses:
2697  * FALSE (or NULL): drop the alternative
2698  * TRUE: drop all remaining alternatives
2699  * If the first non-FALSE alternative is a constant TRUE,
2700  * we can simplify the entire CASE to that alternative's
2701  * expression. If there are no non-FALSE alternatives,
2702  * we simplify the entire CASE to the default result (ELSE).
2703  *
2704  * If we have a simple-form CASE with constant test
2705  * expression, we substitute the constant value for contained
2706  * CaseTestExpr placeholder nodes, so that we have the
2707  * opportunity to reduce constant test conditions. For
2708  * example this allows
2709  * CASE 0 WHEN 0 THEN 1 ELSE 1/0 END
2710  * to reduce to 1 rather than drawing a divide-by-0 error.
2711  * Note that when the test expression is constant, we don't
2712  * have to include it in the resulting CASE; for example
2713  * CASE 0 WHEN x THEN y ELSE z END
2714  * is transformed by the parser to
2715  * CASE 0 WHEN CaseTestExpr = x THEN y ELSE z END
2716  * which we can simplify to
2717  * CASE WHEN 0 = x THEN y ELSE z END
2718  * It is not necessary for the executor to evaluate the "arg"
2719  * expression when executing the CASE, since any contained
2720  * CaseTestExprs that might have referred to it will have been
2721  * replaced by the constant.
2722  *----------
2723  */
2724  CaseExpr *caseexpr = (CaseExpr *) node;
2725  CaseExpr *newcase;
2726  Node *save_case_val;
2727  Node *newarg;
2728  List *newargs;
2729  bool const_true_cond;
2730  Node *defresult = NULL;
2731  ListCell *arg;
2732 
2733  /* Simplify the test expression, if any */
2734  newarg = eval_const_expressions_mutator((Node *) caseexpr->arg,
2735  context);
2736 
2737  /* Set up for contained CaseTestExpr nodes */
2738  save_case_val = context->case_val;
2739  if (newarg && IsA(newarg, Const))
2740  {
2741  context->case_val = newarg;
2742  newarg = NULL; /* not needed anymore, see above */
2743  }
2744  else
2745  context->case_val = NULL;
2746 
2747  /* Simplify the WHEN clauses */
2748  newargs = NIL;
2749  const_true_cond = false;
2750  foreach(arg, caseexpr->args)
2751  {
2752  CaseWhen *oldcasewhen = lfirst_node(CaseWhen, arg);
2753  Node *casecond;
2754  Node *caseresult;
2755 
2756  /* Simplify this alternative's test condition */
2757  casecond = eval_const_expressions_mutator((Node *) oldcasewhen->expr,
2758  context);
2759 
2760  /*
2761  * If the test condition is constant FALSE (or NULL), then
2762  * drop this WHEN clause completely, without processing
2763  * the result.
2764  */
2765  if (casecond && IsA(casecond, Const))
2766  {
2767  Const *const_input = (Const *) casecond;
2768 
2769  if (const_input->constisnull ||
2770  !DatumGetBool(const_input->constvalue))
2771  continue; /* drop alternative with FALSE cond */
2772  /* Else it's constant TRUE */
2773  const_true_cond = true;
2774  }
2775 
2776  /* Simplify this alternative's result value */
2777  caseresult = eval_const_expressions_mutator((Node *) oldcasewhen->result,
2778  context);
2779 
2780  /* If non-constant test condition, emit a new WHEN node */
2781  if (!const_true_cond)
2782  {
2783  CaseWhen *newcasewhen = makeNode(CaseWhen);
2784 
2785  newcasewhen->expr = (Expr *) casecond;
2786  newcasewhen->result = (Expr *) caseresult;
2787  newcasewhen->location = oldcasewhen->location;
2788  newargs = lappend(newargs, newcasewhen);
2789  continue;
2790  }
2791 
2792  /*
2793  * Found a TRUE condition, so none of the remaining
2794  * alternatives can be reached. We treat the result as
2795  * the default result.
2796  */
2797  defresult = caseresult;
2798  break;
2799  }
2800 
2801  /* Simplify the default result, unless we replaced it above */
2802  if (!const_true_cond)
2803  defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult,
2804  context);
2805 
2806  context->case_val = save_case_val;
2807 
2808  /*
2809  * If no non-FALSE alternatives, CASE reduces to the default
2810  * result
2811  */
2812  if (newargs == NIL)
2813  return defresult;
2814  /* Otherwise we need a new CASE node */
2815  newcase = makeNode(CaseExpr);
2816  newcase->casetype = caseexpr->casetype;
2817  newcase->casecollid = caseexpr->casecollid;
2818  newcase->arg = (Expr *) newarg;
2819  newcase->args = newargs;
2820  newcase->defresult = (Expr *) defresult;
2821  newcase->location = caseexpr->location;
2822  return (Node *) newcase;
2823  }
2824  case T_CaseTestExpr:
2825  {
2826  /*
2827  * If we know a constant test value for the current CASE
2828  * construct, substitute it for the placeholder. Else just
2829  * return the placeholder as-is.
2830  */
2831  if (context->case_val)
2832  return copyObject(context->case_val);
2833  else
2834  return copyObject(node);
2835  }
2836  case T_SubscriptingRef:
2837  case T_ArrayExpr:
2838  case T_RowExpr:
2839  case T_MinMaxExpr:
2840  {
2841  /*
2842  * Generic handling for node types whose own processing is
2843  * known to be immutable, and for which we need no smarts
2844  * beyond "simplify if all inputs are constants".
2845  *
2846  * Treating MinMaxExpr this way amounts to assuming that the
2847  * btree comparison function it calls is immutable; see the
2848  * reasoning in contain_mutable_functions_walker.
2849  */
2850 
2851  /* Copy the node and const-simplify its arguments */
2852  node = ece_generic_processing(node);
2853  /* If all arguments are Consts, we can fold to a constant */
2854  if (ece_all_arguments_const(node))
2855  return ece_evaluate_expr(node);
2856  return node;
2857  }
2858  case T_CoalesceExpr:
2859  {
2860  CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
2861  CoalesceExpr *newcoalesce;
2862  List *newargs;
2863  ListCell *arg;
2864 
2865  newargs = NIL;
2866  foreach(arg, coalesceexpr->args)
2867  {
2868  Node *e;
2869 
2871  context);
2872 
2873  /*
2874  * We can remove null constants from the list. For a
2875  * non-null constant, if it has not been preceded by any
2876  * other non-null-constant expressions then it is the
2877  * result. Otherwise, it's the next argument, but we can
2878  * drop following arguments since they will never be
2879  * reached.
2880  */
2881  if (IsA(e, Const))
2882  {
2883  if (((Const *) e)->constisnull)
2884  continue; /* drop null constant */
2885  if (newargs == NIL)
2886  return e; /* first expr */
2887  newargs = lappend(newargs, e);
2888  break;
2889  }
2890  newargs = lappend(newargs, e);
2891  }
2892 
2893  /*
2894  * If all the arguments were constant null, the result is just
2895  * null
2896  */
2897  if (newargs == NIL)
2898  return (Node *) makeNullConst(coalesceexpr->coalescetype,
2899  -1,
2900  coalesceexpr->coalescecollid);
2901 
2902  newcoalesce = makeNode(CoalesceExpr);
2903  newcoalesce->coalescetype = coalesceexpr->coalescetype;
2904  newcoalesce->coalescecollid = coalesceexpr->coalescecollid;
2905  newcoalesce->args = newargs;
2906  newcoalesce->location = coalesceexpr->location;
2907  return (Node *) newcoalesce;
2908  }
2909  case T_SQLValueFunction:
2910  {
2911  /*
2912  * All variants of SQLValueFunction are stable, so if we are
2913  * estimating the expression's value, we should evaluate the
2914  * current function value. Otherwise just copy.
2915  */
2916  SQLValueFunction *svf = (SQLValueFunction *) node;
2917 
2918  if (context->estimate)
2919  return (Node *) evaluate_expr((Expr *) svf,
2920  svf->type,
2921  svf->typmod,
2922  InvalidOid);
2923  else
2924  return copyObject((Node *) svf);
2925  }
2926  case T_FieldSelect:
2927  {
2928  /*
2929  * We can optimize field selection from a whole-row Var into a
2930  * simple Var. (This case won't be generated directly by the
2931  * parser, because ParseComplexProjection short-circuits it.
2932  * But it can arise while simplifying functions.) Also, we
2933  * can optimize field selection from a RowExpr construct, or
2934  * of course from a constant.
2935  *
2936  * However, replacing a whole-row Var in this way has a
2937  * pitfall: if we've already built the rel targetlist for the
2938  * source relation, then the whole-row Var is scheduled to be
2939  * produced by the relation scan, but the simple Var probably
2940  * isn't, which will lead to a failure in setrefs.c. This is
2941  * not a problem when handling simple single-level queries, in
2942  * which expression simplification always happens first. It
2943  * is a risk for lateral references from subqueries, though.
2944  * To avoid such failures, don't optimize uplevel references.
2945  *
2946  * We must also check that the declared type of the field is
2947  * still the same as when the FieldSelect was created --- this
2948  * can change if someone did ALTER COLUMN TYPE on the rowtype.
2949  * If it isn't, we skip the optimization; the case will
2950  * probably fail at runtime, but that's not our problem here.
2951  */
2952  FieldSelect *fselect = (FieldSelect *) node;
2953  FieldSelect *newfselect;
2954  Node *arg;
2955 
2956  arg = eval_const_expressions_mutator((Node *) fselect->arg,
2957  context);
2958  if (arg && IsA(arg, Var) &&
2959  ((Var *) arg)->varattno == InvalidAttrNumber &&
2960  ((Var *) arg)->varlevelsup == 0)
2961  {
2962  if (rowtype_field_matches(((Var *) arg)->vartype,
2963  fselect->fieldnum,
2964  fselect->resulttype,
2965  fselect->resulttypmod,
2966  fselect->resultcollid))
2967  return (Node *) makeVar(((Var *) arg)->varno,
2968  fselect->fieldnum,
2969  fselect->resulttype,
2970  fselect->resulttypmod,
2971  fselect->resultcollid,
2972  ((Var *) arg)->varlevelsup);
2973  }
2974  if (arg && IsA(arg, RowExpr))
2975  {
2976  RowExpr *rowexpr = (RowExpr *) arg;
2977 
2978  if (fselect->fieldnum > 0 &&
2979  fselect->fieldnum <= list_length(rowexpr->args))
2980  {
2981  Node *fld = (Node *) list_nth(rowexpr->args,
2982  fselect->fieldnum - 1);
2983 
2984  if (rowtype_field_matches(rowexpr->row_typeid,
2985  fselect->fieldnum,
2986  fselect->resulttype,
2987  fselect->resulttypmod,
2988  fselect->resultcollid) &&
2989  fselect->resulttype == exprType(fld) &&
2990  fselect->resulttypmod == exprTypmod(fld) &&
2991  fselect->resultcollid == exprCollation(fld))
2992  return fld;
2993  }
2994  }
2995  newfselect = makeNode(FieldSelect);
2996  newfselect->arg = (Expr *) arg;
2997  newfselect->fieldnum = fselect->fieldnum;
2998  newfselect->resulttype = fselect->resulttype;
2999  newfselect->resulttypmod = fselect->resulttypmod;
3000  newfselect->resultcollid = fselect->resultcollid;
3001  if (arg && IsA(arg, Const))
3002  {
3003  Const *con = (Const *) arg;
3004 
3006  newfselect->fieldnum,
3007  newfselect->resulttype,
3008  newfselect->resulttypmod,
3009  newfselect->resultcollid))
3010  return ece_evaluate_expr(newfselect);
3011  }
3012  return (Node *) newfselect;
3013  }
3014  case T_NullTest:
3015  {
3016  NullTest *ntest = (NullTest *) node;
3017  NullTest *newntest;
3018  Node *arg;
3019 
3020  arg = eval_const_expressions_mutator((Node *) ntest->arg,
3021  context);
3022  if (ntest->argisrow && arg && IsA(arg, RowExpr))
3023  {
3024  /*
3025  * We break ROW(...) IS [NOT] NULL into separate tests on
3026  * its component fields. This form is usually more
3027  * efficient to evaluate, as well as being more amenable
3028  * to optimization.
3029  */
3030  RowExpr *rarg = (RowExpr *) arg;
3031  List *newargs = NIL;
3032  ListCell *l;
3033 
3034  foreach(l, rarg->args)
3035  {
3036  Node *relem = (Node *) lfirst(l);
3037 
3038  /*
3039  * A constant field refutes the whole NullTest if it's
3040  * of the wrong nullness; else we can discard it.
3041  */
3042  if (relem && IsA(relem, Const))
3043  {
3044  Const *carg = (Const *) relem;
3045 
3046  if (carg->constisnull ?
3047  (ntest->nulltesttype == IS_NOT_NULL) :
3048  (ntest->nulltesttype == IS_NULL))
3049  return makeBoolConst(false, false);
3050  continue;
3051  }
3052 
3053  /*
3054  * Else, make a scalar (argisrow == false) NullTest
3055  * for this field. Scalar semantics are required
3056  * because IS [NOT] NULL doesn't recurse; see comments
3057  * in ExecEvalRowNullInt().
3058  */
3059  newntest = makeNode(NullTest);
3060  newntest->arg = (Expr *) relem;
3061  newntest->nulltesttype = ntest->nulltesttype;
3062  newntest->argisrow = false;
3063  newntest->location = ntest->location;
3064  newargs = lappend(newargs, newntest);
3065  }
3066  /* If all the inputs were constants, result is TRUE */
3067  if (newargs == NIL)
3068  return makeBoolConst(true, false);
3069  /* If only one nonconst input, it's the result */
3070  if (list_length(newargs) == 1)
3071  return (Node *) linitial(newargs);
3072  /* Else we need an AND node */
3073  return (Node *) make_andclause(newargs);
3074  }
3075  if (!ntest->argisrow && arg && IsA(arg, Const))
3076  {
3077  Const *carg = (Const *) arg;
3078  bool result;
3079 
3080  switch (ntest->nulltesttype)
3081  {
3082  case IS_NULL:
3083  result = carg->constisnull;
3084  break;
3085  case IS_NOT_NULL:
3086  result = !carg->constisnull;
3087  break;
3088  default:
3089  elog(ERROR, "unrecognized nulltesttype: %d",
3090  (int) ntest->nulltesttype);
3091  result = false; /* keep compiler quiet */
3092  break;
3093  }
3094 
3095  return makeBoolConst(result, false);
3096  }
3097 
3098  newntest = makeNode(NullTest);
3099  newntest->arg = (Expr *) arg;
3100  newntest->nulltesttype = ntest->nulltesttype;
3101  newntest->argisrow = ntest->argisrow;
3102  newntest->location = ntest->location;
3103  return (Node *) newntest;
3104  }
3105  case T_BooleanTest:
3106  {
3107  /*
3108  * This case could be folded into the generic handling used
3109  * for SubscriptingRef etc. But because the simplification
3110  * logic is so trivial, applying evaluate_expr() to perform it
3111  * would be a heavy overhead. BooleanTest is probably common
3112  * enough to justify keeping this bespoke implementation.
3113  */
3114  BooleanTest *btest = (BooleanTest *) node;
3115  BooleanTest *newbtest;
3116  Node *arg;
3117 
3118  arg = eval_const_expressions_mutator((Node *) btest->arg,
3119  context);
3120  if (arg && IsA(arg, Const))
3121  {
3122  Const *carg = (Const *) arg;
3123  bool result;
3124 
3125  switch (btest->booltesttype)
3126  {
3127  case IS_TRUE:
3128  result = (!carg->constisnull &&
3129  DatumGetBool(carg->constvalue));
3130  break;
3131  case IS_NOT_TRUE:
3132  result = (carg->constisnull ||
3133  !DatumGetBool(carg->constvalue));
3134  break;
3135  case IS_FALSE:
3136  result = (!carg->constisnull &&
3137  !DatumGetBool(carg->constvalue));
3138  break;
3139  case IS_NOT_FALSE:
3140  result = (carg->constisnull ||
3141  DatumGetBool(carg->constvalue));
3142  break;
3143  case IS_UNKNOWN:
3144  result = carg->constisnull;
3145  break;
3146  case IS_NOT_UNKNOWN:
3147  result = !carg->constisnull;
3148  break;
3149  default:
3150  elog(ERROR, "unrecognized booltesttype: %d",
3151  (int) btest->booltesttype);
3152  result = false; /* keep compiler quiet */
3153  break;
3154  }
3155 
3156  return makeBoolConst(result, false);
3157  }
3158 
3159  newbtest = makeNode(BooleanTest);
3160  newbtest->arg = (Expr *) arg;
3161  newbtest->booltesttype = btest->booltesttype;
3162  newbtest->location = btest->location;
3163  return (Node *) newbtest;
3164  }
3165  case T_CoerceToDomain:
3166  {
3167  /*
3168  * If the domain currently has no constraints, we replace the
3169  * CoerceToDomain node with a simple RelabelType, which is
3170  * both far faster to execute and more amenable to later
3171  * optimization. We must then mark the plan as needing to be
3172  * rebuilt if the domain's constraints change.
3173  *
3174  * Also, in estimation mode, always replace CoerceToDomain
3175  * nodes, effectively assuming that the coercion will succeed.
3176  */
3177  CoerceToDomain *cdomain = (CoerceToDomain *) node;
3178  CoerceToDomain *newcdomain;
3179  Node *arg;
3180 
3181  arg = eval_const_expressions_mutator((Node *) cdomain->arg,
3182  context);
3183  if (context->estimate ||
3184  !DomainHasConstraints(cdomain->resulttype))
3185  {
3186  /* Record dependency, if this isn't estimation mode */
3187  if (context->root && !context->estimate)
3188  record_plan_type_dependency(context->root,
3189  cdomain->resulttype);
3190 
3191  /* Generate RelabelType to substitute for CoerceToDomain */
3192  return applyRelabelType(arg,
3193  cdomain->resulttype,
3194  cdomain->resulttypmod,
3195  cdomain->resultcollid,
3196  cdomain->coercionformat,
3197  cdomain->location,
3198  true);
3199  }
3200 
3201  newcdomain = makeNode(CoerceToDomain);
3202  newcdomain->arg = (Expr *) arg;
3203  newcdomain->resulttype = cdomain->resulttype;
3204  newcdomain->resulttypmod = cdomain->resulttypmod;
3205  newcdomain->resultcollid = cdomain->resultcollid;
3206  newcdomain->coercionformat = cdomain->coercionformat;
3207  newcdomain->location = cdomain->location;
3208  return (Node *) newcdomain;
3209  }
3210  case T_PlaceHolderVar:
3211 
3212  /*
3213  * In estimation mode, just strip the PlaceHolderVar node
3214  * altogether; this amounts to estimating that the contained value
3215  * won't be forced to null by an outer join. In regular mode we
3216  * just use the default behavior (ie, simplify the expression but
3217  * leave the PlaceHolderVar node intact).
3218  */
3219  if (context->estimate)
3220  {
3221  PlaceHolderVar *phv = (PlaceHolderVar *) node;
3222 
3223  return eval_const_expressions_mutator((Node *) phv->phexpr,
3224  context);
3225  }
3226  break;
3227  case T_ConvertRowtypeExpr:
3228  {
3230  Node *arg;
3231  ConvertRowtypeExpr *newcre;
3232 
3233  arg = eval_const_expressions_mutator((Node *) cre->arg,
3234  context);
3235 
3236  newcre = makeNode(ConvertRowtypeExpr);
3237  newcre->resulttype = cre->resulttype;
3238  newcre->convertformat = cre->convertformat;
3239  newcre->location = cre->location;
3240 
3241  /*
3242  * In case of a nested ConvertRowtypeExpr, we can convert the
3243  * leaf row directly to the topmost row format without any
3244  * intermediate conversions. (This works because
3245  * ConvertRowtypeExpr is used only for child->parent
3246  * conversion in inheritance trees, which works by exact match
3247  * of column name, and a column absent in an intermediate
3248  * result can't be present in the final result.)
3249  *
3250  * No need to check more than one level deep, because the
3251  * above recursion will have flattened anything else.
3252  */
3253  if (arg != NULL && IsA(arg, ConvertRowtypeExpr))
3254  {
3255  ConvertRowtypeExpr *argcre = (ConvertRowtypeExpr *) arg;
3256 
3257  arg = (Node *) argcre->arg;
3258 
3259  /*
3260  * Make sure an outer implicit conversion can't hide an
3261  * inner explicit one.
3262  */
3263  if (newcre->convertformat == COERCE_IMPLICIT_CAST)
3264  newcre->convertformat = argcre->convertformat;
3265  }
3266 
3267  newcre->arg = (Expr *) arg;
3268 
3269  if (arg != NULL && IsA(arg, Const))
3270  return ece_evaluate_expr((Node *) newcre);
3271  return (Node *) newcre;
3272  }
3273  default:
3274  break;
3275  }
3276 
3277  /*
3278  * For any node type not handled above, copy the node unchanged but
3279  * const-simplify its subexpressions. This is the correct thing for node
3280  * types whose behavior might change between planning and execution, such
3281  * as CurrentOfExpr. It's also a safe default for new node types not
3282  * known to this routine.
3283  */
3284  return ece_generic_processing(node);
3285 }
Datum constvalue
Definition: primnodes.h:214
#define list_make3(x1, x2, x3)
Definition: pg_list.h:210
Expr * evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
Definition: clauses.c:4469
signed short int16
Definition: c.h:416
Oid funcresulttype
Definition: primnodes.h:482
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:125
#define NIL
Definition: pg_list.h:65
Datum value
Definition: params.h:92
#define ece_generic_processing(node)
Definition: clauses.c:2054
List * args
Definition: primnodes.h:1037
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
static Expr * simplify_function(Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, List **args_p, bool funcvariadic, bool process_args, bool allow_non_const, eval_const_expressions_context *context)
Definition: clauses.c:3620
Node * negate_clause(Node *node)
Definition: prepqual.c:74
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2565
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2789
List * expand_function_arguments(List *args, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:3727
List * args
Definition: primnodes.h:385
List * args
Definition: primnodes.h:489
Oid wincollid
Definition: primnodes.h:383
int32 resulttypmod
Definition: primnodes.h:1276
Oid resulttype
Definition: primnodes.h:779
#define castNode(_type_, nodeptr)
Definition: nodes.h:596
Node * applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat, int rlocation, bool overwrite_ok)
Definition: nodeFuncs.c:591
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:275
Oid funccollid
Definition: primnodes.h:487
Oid resulttype
Definition: primnodes.h:850
Oid casecollid
Definition: primnodes.h:946
Expr * arg
Definition: primnodes.h:829
ParamKind paramkind
Definition: primnodes.h:262
Definition: nodes.h:527
CoercionForm coercionformat
Definition: primnodes.h:1278
Expr * arg
Definition: primnodes.h:777
bool funcretset
Definition: primnodes.h:483
Oid casetype
Definition: primnodes.h:945
unsigned int Oid
Definition: postgres_ext.h:31
Expr * make_orclause(List *orclauses)
Definition: makefuncs.c:652
Index winref
Definition: primnodes.h:387
Definition: primnodes.h:181
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:299
#define OidIsValid(objectId)
Definition: c.h:706
#define ece_all_arguments_const(node)
Definition: clauses.c:2063
int location
Definition: primnodes.h:961
signed int int32
Definition: c.h:417
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:337
bool DomainHasConstraints(Oid type_id)
Definition: typcache.c:1346
#define list_make1(x1)
Definition: pg_list.h:206
Oid consttype
Definition: primnodes.h:210
CoercionForm funcformat
Definition: primnodes.h:486
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2077
Oid opresulttype
Definition: primnodes.h:530
ParamFetchHook paramFetch
Definition: params.h:112
ParamListInfo boundParams
Definition: clauses.c:58
#define linitial(l)
Definition: pg_list.h:174
Oid funcid
Definition: primnodes.h:481
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static bool rowtype_field_matches(Oid rowtypeid, int fieldnum, Oid expectedtype, int32 expectedtypmod, Oid expectedcollation)
Definition: clauses.c:1931
Oid paramcollid
Definition: primnodes.h:266
static void * list_nth(const List *list, int n)
Definition: pg_list.h:266
List * args
Definition: primnodes.h:1101
BoolExprType boolop
Definition: primnodes.h:594
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:357
Expr * arg
Definition: primnodes.h:1234
Oid resultcollid
Definition: primnodes.h:782
#define lfirst_node(type, lc)
Definition: pg_list.h:172
struct Const Const
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:636
int location
Definition: primnodes.h:535
Expr * arg
Definition: primnodes.h:1257
#define DatumGetBool(X)
Definition: postgres.h:393
Oid winfnoid
Definition: primnodes.h:381
Expr * arg
Definition: primnodes.h:849
Expr * elemexpr
Definition: primnodes.h:874
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2756
Oid opcollid
Definition: primnodes.h:532
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
List * lappend(List *list, void *datum)
Definition: list.c:321
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
List * args
Definition: primnodes.h:948
BoolTestType booltesttype
Definition: primnodes.h:1258
uintptr_t Datum
Definition: postgres.h:367
CoercionForm convertformat
Definition: primnodes.h:901
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
Oid resultcollid
Definition: primnodes.h:852
Oid opfuncid
Definition: primnodes.h:529
Oid resulttype
Definition: primnodes.h:830
NullTestType nulltesttype
Definition: primnodes.h:1235
#define BoolGetDatum(X)
Definition: postgres.h:402
Oid resultcollid
Definition: primnodes.h:832
#define InvalidOid
Definition: postgres_ext.h:36
int32 paramtypmod
Definition: primnodes.h:265
#define makeNode(_type_)
Definition: nodes.h:575
static Node * simplify_boolean_equality(Oid opno, List *args)
Definition: clauses.c:3551
int location
Definition: primnodes.h:854
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int location
Definition: primnodes.h:390
Oid inputcollid
Definition: primnodes.h:488
#define Assert(condition)
Definition: c.h:800
#define lfirst(lc)
Definition: pg_list.h:169
Expr * aggfilter
Definition: primnodes.h:386
int paramid
Definition: primnodes.h:263
uint16 pflags
Definition: params.h:94
int location
Definition: primnodes.h:1237
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static List * simplify_and_arguments(List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceFalse)
Definition: clauses.c:3457
Oid row_typeid
Definition: primnodes.h:1038
static int list_length(const List *l)
Definition: pg_list.h:149
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:768
Expr * arg
Definition: primnodes.h:915
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2144
int location
Definition: primnodes.h:950
Oid inputcollid
Definition: primnodes.h:533
static bool ece_function_is_safe(Oid funcid, eval_const_expressions_context *context)
Definition: clauses.c:3313
Oid inputcollid
Definition: primnodes.h:384
List * args
Definition: primnodes.h:595
#define InvalidAttrNumber
Definition: attnum.h:23
#define nodeTag(nodeptr)
Definition: nodes.h:532
Oid wintype
Definition: primnodes.h:382
CoercionForm coerceformat
Definition: primnodes.h:853
static List * simplify_or_arguments(List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceTrue)
Definition: clauses.c:3351
#define Int32GetDatum(X)
Definition: postgres.h:479
e
Definition: preproc-init.c:82
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1667
bool winagg
Definition: primnodes.h:389
#define elog(elevel,...)
Definition: elog.h:228
Oid coalescetype
Definition: primnodes.h:1099
void * arg
NodeTag type
Definition: primnodes.h:138
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:357
bool argisrow
Definition: primnodes.h:1236
int32 resulttypmod
Definition: primnodes.h:831
Expr * arg
Definition: primnodes.h:947
int location
Definition: primnodes.h:490
Oid opno
Definition: primnodes.h:528
Expr * result
Definition: primnodes.h:960
#define copyObject(obj)
Definition: nodes.h:643
List * args
Definition: primnodes.h:534
CoercionForm relabelformat
Definition: primnodes.h:833
Expr * defresult
Definition: primnodes.h:949
Expr * expr
Definition: primnodes.h:959
int location
Definition: primnodes.h:917
Definition: pg_list.h:50
bool isnull
Definition: params.h:93
void set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
Definition: nodeFuncs.c:1678
Oid paramtype
Definition: primnodes.h:264
int location
Definition: primnodes.h:834
bool constisnull
Definition: primnodes.h:215
Oid coalescecollid
Definition: primnodes.h:1100
bool funcvariadic
Definition: primnodes.h:484
#define PARAM_FLAG_CONST
Definition: params.h:88
bool opretset
Definition: primnodes.h:531
int32 resulttypmod
Definition: primnodes.h:781
bool winstar
Definition: primnodes.h:388
void record_plan_type_dependency(PlannerInfo *root, Oid typid)
Definition: setrefs.c:2929
Definition: nodes.h:155
AttrNumber fieldnum
Definition: primnodes.h:778
#define ece_evaluate_expr(node)
Definition: clauses.c:2067

◆ evaluate_expr()

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

Definition at line 4469 of file clauses.c.

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

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

4471 {
4472  EState *estate;
4473  ExprState *exprstate;
4474  MemoryContext oldcontext;
4475  Datum const_val;
4476  bool const_is_null;
4477  int16 resultTypLen;
4478  bool resultTypByVal;
4479 
4480  /*
4481  * To use the executor, we need an EState.
4482  */
4483  estate = CreateExecutorState();
4484 
4485  /* We can use the estate's working context to avoid memory leaks. */
4486  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
4487 
4488  /* Make sure any opfuncids are filled in. */
4489  fix_opfuncids((Node *) expr);
4490 
4491  /*
4492  * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
4493  * because it'd result in recursively invoking eval_const_expressions.)
4494  */
4495  exprstate = ExecInitExpr(expr, NULL);
4496 
4497  /*
4498  * And evaluate it.
4499  *
4500  * It is OK to use a default econtext because none of the ExecEvalExpr()
4501  * code used in this situation will use econtext. That might seem
4502  * fortuitous, but it's not so unreasonable --- a constant expression does
4503  * not depend on context, by definition, n'est ce pas?
4504  */
4505  const_val = ExecEvalExprSwitchContext(exprstate,
4506  GetPerTupleExprContext(estate),
4507  &const_is_null);
4508 
4509  /* Get info needed about result datatype */
4510  get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
4511 
4512  /* Get back to outer memory context */
4513  MemoryContextSwitchTo(oldcontext);
4514 
4515  /*
4516  * Must copy result out of sub-context used by expression eval.
4517  *
4518  * Also, if it's varlena, forcibly detoast it. This protects us against
4519  * storing TOAST pointers into plans that might outlive the referenced
4520  * data. (makeConst would handle detoasting anyway, but it's worth a few
4521  * extra lines here so that we can do the copy and detoast in one step.)
4522  */
4523  if (!const_is_null)
4524  {
4525  if (resultTypLen == -1)
4526  const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
4527  else
4528  const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
4529  }
4530 
4531  /* Release all the junk we just created */
4532  FreeExecutorState(estate);
4533 
4534  /*
4535  * Make the constant result node.
4536  */
4537  return (Expr *) makeConst(result_type, result_typmod, result_collation,
4538  resultTypLen,
4539  const_val, const_is_null,
4540  resultTypByVal);
4541 }
signed short int16
Definition: c.h:416
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:307
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
#define PointerGetDatum(X)
Definition: postgres.h:556
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1636
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:527
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:299
void FreeExecutorState(EState *estate)
Definition: execUtils.c:185
#define GetPerTupleExprContext(estate)
Definition: executor.h:509
MemoryContext es_query_cxt
Definition: execnodes.h:559
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
EState * CreateExecutorState(void)
Definition: execUtils.c:89
uintptr_t Datum
Definition: postgres.h:367
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2144
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:122

◆ evaluate_function()

static Expr * evaluate_function ( Oid  funcid,
Oid  result_type,
int32  result_typmod,
Oid  result_collid,
Oid  input_collid,
List args,
bool  funcvariadic,
HeapTuple  func_tuple,
eval_const_expressions_context context 
)
static

Definition at line 3944 of file clauses.c.

References arg, generate_unaccent_rules::args, FuncExpr::args, COERCE_EXPLICIT_CALL, eval_const_expressions_context::estimate, evaluate_expr(), FuncExpr::funccollid, FuncExpr::funcformat, FuncExpr::funcid, FuncExpr::funcresulttype, FuncExpr::funcretset, FuncExpr::funcvariadic, GETSTRUCT, FuncExpr::inputcollid, IsA, lfirst, FuncExpr::location, makeNode, and makeNullConst().

Referenced by simplify_function().

3949 {
3950  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
3951  bool has_nonconst_input = false;
3952  bool has_null_input = false;
3953  ListCell *arg;
3954  FuncExpr *newexpr;
3955 
3956  /*
3957  * Can't simplify if it returns a set.
3958  */
3959  if (funcform->proretset)
3960  return NULL;
3961 
3962  /*
3963  * Can't simplify if it returns RECORD. The immediate problem is that it
3964  * will be needing an expected tupdesc which we can't supply here.
3965  *
3966  * In the case where it has OUT parameters, it could get by without an
3967  * expected tupdesc, but we still have issues: get_expr_result_type()
3968  * doesn't know how to extract type info from a RECORD constant, and in
3969  * the case of a NULL function result there doesn't seem to be any clean
3970  * way to fix that. In view of the likelihood of there being still other
3971  * gotchas, seems best to leave the function call unreduced.
3972  */
3973  if (funcform->prorettype == RECORDOID)
3974  return NULL;
3975 
3976  /*
3977  * Check for constant inputs and especially constant-NULL inputs.
3978  */
3979  foreach(arg, args)
3980  {
3981  if (IsA(lfirst(arg), Const))
3982  has_null_input |= ((Const *) lfirst(arg))->constisnull;
3983  else
3984  has_nonconst_input = true;
3985  }
3986 
3987  /*
3988  * If the function is strict and has a constant-NULL input, it will never
3989  * be called at all, so we can replace the call by a NULL constant, even
3990  * if there are other inputs that aren't constant, and even if the
3991  * function is not otherwise immutable.
3992  */
3993  if (funcform->proisstrict && has_null_input)
3994  return (Expr *) makeNullConst(result_type, result_typmod,
3995  result_collid);
3996 
3997  /*
3998  * Otherwise, can simplify only if all inputs are constants. (For a
3999  * non-strict function, constant NULL inputs are treated the same as
4000  * constant non-NULL inputs.)
4001  */
4002  if (has_nonconst_input)
4003  return NULL;
4004 
4005  /*
4006  * Ordinarily we are only allowed to simplify immutable functions. But for
4007  * purposes of estimation, we consider it okay to simplify functions that
4008  * are merely stable; the risk that the result might change from planning
4009  * time to execution time is worth taking in preference to not being able
4010  * to estimate the value at all.
4011  */
4012  if (funcform->provolatile == PROVOLATILE_IMMUTABLE)
4013  /* okay */ ;
4014  else if (context->estimate && funcform->provolatile == PROVOLATILE_STABLE)
4015  /* okay */ ;
4016  else
4017  return NULL;
4018 
4019  /*
4020  * OK, looks like we can simplify this operator/function.
4021  *
4022  * Build a new FuncExpr node containing the already-simplified arguments.
4023  */
4024  newexpr = makeNode(FuncExpr);
4025  newexpr->funcid = funcid;
4026  newexpr->funcresulttype = result_type;
4027  newexpr->funcretset = false;
4028  newexpr->funcvariadic = funcvariadic;
4029  newexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
4030  newexpr->funccollid = result_collid; /* doesn't matter */
4031  newexpr->inputcollid = input_collid;
4032  newexpr->args = args;
4033  newexpr->location = -1;
4034 
4035  return evaluate_expr((Expr *) newexpr, result_type, result_typmod,
4036  result_collid);
4037 }
Expr * evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
Definition: clauses.c:4469
Oid funcresulttype
Definition: primnodes.h:482
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
List * args
Definition: primnodes.h:489
Oid funccollid
Definition: primnodes.h:487
bool funcretset
Definition: primnodes.h:483
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:337
CoercionForm funcformat
Definition: primnodes.h:486
Oid funcid
Definition: primnodes.h:481
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define makeNode(_type_)
Definition: nodes.h:575
Oid inputcollid
Definition: primnodes.h:488
#define lfirst(lc)
Definition: pg_list.h:169
void * arg
int location
Definition: primnodes.h:490
bool funcvariadic
Definition: primnodes.h:484

◆ expand_function_arguments()

List* expand_function_arguments ( List args,
Oid  result_type,
HeapTuple  func_tuple 
)

Definition at line 3727 of file clauses.c.

References add_function_defaults(), arg, generate_unaccent_rules::args, GETSTRUCT, IsA, lfirst, list_length(), recheck_cast_function_args(), and reorder_function_arguments().

Referenced by eval_const_expressions_mutator(), exec_stmt_call(), ExecuteCallStmt(), and simplify_function().

3728 {
3729  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
3730  bool has_named_args = false;
3731  ListCell *lc;
3732 
3733  /* Do we have any named arguments? */
3734  foreach(lc, args)
3735  {
3736  Node *arg = (Node *) lfirst(lc);
3737 
3738  if (IsA(arg, NamedArgExpr))
3739  {
3740  has_named_args = true;
3741  break;
3742  }
3743  }
3744 
3745  /* If so, we must apply reorder_function_arguments */
3746  if (has_named_args)
3747  {
3748  args = reorder_function_arguments(args, func_tuple);
3749  /* Recheck argument types and add casts if needed */
3750  recheck_cast_function_args(args, result_type, func_tuple);
3751  }
3752  else if (list_length(args) < funcform->pronargs)
3753  {
3754  /* No named args, but we seem to be short some defaults */
3755  args = add_function_defaults(args, func_tuple);
3756  /* Recheck argument types and add casts if needed */
3757  recheck_cast_function_args(args, result_type, func_tuple);
3758  }
3759 
3760  return args;
3761 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Definition: nodes.h:527
static void recheck_cast_function_args(List *args, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:3900
static List * add_function_defaults(List *args, HeapTuple func_tuple)
Definition: clauses.c:3840
static List * reorder_function_arguments(List *args, HeapTuple func_tuple)
Definition: clauses.c:3770
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
void * arg

◆ expression_returns_set_rows()

double expression_returns_set_rows ( PlannerInfo root,
Node clause 
)

Definition at line 281 of file clauses.c.

References clamp_row_est(), FuncExpr::funcid, FuncExpr::funcretset, get_function_rows(), IsA, OpExpr::opfuncid, OpExpr::opretset, and set_opfuncid().

Referenced by create_set_projection_path(), estimate_num_groups(), and set_function_size_estimates().

282 {
283  if (clause == NULL)
284  return 1.0;
285  if (IsA(clause, FuncExpr))
286  {
287  FuncExpr *expr = (FuncExpr *) clause;
288 
289  if (expr->funcretset)
290  return clamp_row_est(get_function_rows(root, expr->funcid, clause));
291  }
292  if (IsA(clause, OpExpr))
293  {
294  OpExpr *expr = (OpExpr *) clause;
295 
296  if (expr->opretset)
297  {
298  set_opfuncid(expr);
299  return clamp_row_est(get_function_rows(root, expr->opfuncid, clause));
300  }
301  }
302  return 1.0;
303 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
bool funcretset
Definition: primnodes.h:483
Oid funcid
Definition: primnodes.h:481
Oid opfuncid
Definition: primnodes.h:529
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1667
double clamp_row_est(double nrows)
Definition: costsize.c:196
bool opretset
Definition: primnodes.h:531
double get_function_rows(PlannerInfo *root, Oid funcid, Node *node)
Definition: plancat.c:1979

◆ fetch_function_defaults()

static List * fetch_function_defaults ( HeapTuple  func_tuple)
static

Definition at line 3865 of file clauses.c.

References castNode, elog, ERROR, pfree(), PROCOID, generate_unaccent_rules::str, stringToNode(), SysCacheGetAttr(), and TextDatumGetCString.

Referenced by add_function_defaults(), and reorder_function_arguments().

3866 {
3867  List *defaults;
3868  Datum proargdefaults;
3869  bool isnull;
3870  char *str;
3871 
3872  /* The error cases here shouldn't happen, but check anyway */
3873  proargdefaults = SysCacheGetAttr(PROCOID, func_tuple,
3874  Anum_pg_proc_proargdefaults,
3875  &isnull);
3876  if (isnull)
3877  elog(ERROR, "not enough default arguments");
3878  str = TextDatumGetCString(proargdefaults);
3879  defaults = castNode(List, stringToNode(str));
3880  pfree(str);
3881  return defaults;
3882 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:596
void * stringToNode(const char *str)
Definition: read.c:89
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:43
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1376
#define elog(elevel,...)
Definition: elog.h:228
Definition: pg_list.h:50

◆ find_forced_null_var()

Var* find_forced_null_var ( Node node)

Definition at line 1724 of file clauses.c.

References NullTest::arg, BooleanTest::arg, NullTest::argisrow, BooleanTest::booltesttype, IS_NULL, IS_UNKNOWN, IsA, NullTest::nulltesttype, and Var::varlevelsup.

Referenced by check_redundant_nullability_qual(), and find_forced_null_vars().

1725 {
1726  if (node == NULL)
1727  return NULL;
1728  if (IsA(node, NullTest))
1729  {
1730  /* check for var IS NULL */
1731  NullTest *expr = (NullTest *) node;
1732 
1733  if (expr->nulltesttype == IS_NULL && !expr->argisrow)
1734  {
1735  Var *var = (Var *) expr->arg;
1736 
1737  if (var && IsA(var, Var) &&
1738  var->varlevelsup == 0)
1739  return var;
1740  }
1741  }
1742  else if (IsA(node, BooleanTest))
1743  {
1744  /* var IS UNKNOWN is equivalent to var IS NULL */
1745  BooleanTest *expr = (BooleanTest *) node;
1746 
1747  if (expr->booltesttype == IS_UNKNOWN)
1748  {
1749  Var *var = (Var *) expr->arg;
1750 
1751  if (var && IsA(var, Var) &&
1752  var->varlevelsup == 0)
1753  return var;
1754  }
1755  }
1756  return NULL;
1757 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
Index varlevelsup
Definition: primnodes.h:191
Definition: primnodes.h:181
Expr * arg
Definition: primnodes.h:1234
Expr * arg
Definition: primnodes.h:1257
BoolTestType booltesttype
Definition: primnodes.h:1258
NullTestType nulltesttype
Definition: primnodes.h:1235
bool argisrow
Definition: primnodes.h:1236

◆ find_forced_null_vars()

List* find_forced_null_vars ( Node node)

Definition at line 1665 of file clauses.c.

References AND_EXPR, BoolExpr::args, BoolExpr::boolop, find_forced_null_var(), find_forced_null_vars(), IsA, lfirst, list_concat(), list_make1, and NIL.

Referenced by find_forced_null_vars(), and reduce_outer_joins_pass2().

1666 {
1667  List *result = NIL;
1668  Var *var;
1669  ListCell *l;
1670 
1671  if (node == NULL)
1672  return NIL;
1673  /* Check single-clause cases using subroutine */
1674  var = find_forced_null_var(node);
1675  if (var)
1676  {
1677  result = list_make1(var);
1678  }
1679  /* Otherwise, handle AND-conditions */
1680  else if (IsA(node, List))
1681  {
1682  /*
1683  * At top level, we are examining an implicit-AND list: if any of the
1684  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1685  */
1686  foreach(l, (List *) node)
1687  {
1688  result = list_concat(result,
1690  }
1691  }
1692  else if (IsA(node, BoolExpr))
1693  {
1694  BoolExpr *expr = (BoolExpr *) node;
1695 
1696  /*
1697  * We don't bother considering the OR case, because it's fairly
1698  * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
1699  * the NOT case isn't worth expending code on.
1700  */
1701  if (expr->boolop == AND_EXPR)
1702  {
1703  /* At top level we can just recurse (to the List case) */
1704  result = find_forced_null_vars((Node *) expr->args);
1705  }
1706  }
1707  return result;
1708 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
Definition: nodes.h:527
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
Definition: primnodes.h:181
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1665
#define list_make1(x1)
Definition: pg_list.h:206
BoolExprType boolop
Definition: primnodes.h:594
#define lfirst(lc)
Definition: pg_list.h:169
List * args
Definition: primnodes.h:595
Definition: pg_list.h:50
Var * find_forced_null_var(Node *node)
Definition: clauses.c:1724

◆ find_nonnullable_rels()

Relids find_nonnullable_rels ( Node clause)

Definition at line 1247 of file clauses.c.

References find_nonnullable_rels_walker().

Referenced by make_outerjoininfo(), and reduce_outer_joins_pass2().

1248 {
1249  return find_nonnullable_rels_walker(clause, true);
1250 }
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1253

◆ find_nonnullable_rels_walker()

static Relids find_nonnullable_rels_walker ( Node node,
bool  top_level 
)
static

Definition at line 1253 of file clauses.c.

References AND_EXPR, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, NullTest::arg, BooleanTest::arg, NullTest::argisrow, FuncExpr::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, bms_add_members(), bms_int_members(), bms_is_empty(), bms_join(), bms_make_singleton(), bms_membership(), BMS_SINGLETON, BoolExpr::boolop, BooleanTest::booltesttype, elog, ERROR, func_strict(), FuncExpr::funcid, IS_FALSE, IS_NOT_NULL, IS_NOT_UNKNOWN, is_strict_saop(), IS_TRUE, IsA, lfirst, NOT_EXPR, NullTest::nulltesttype, OpExpr::opfuncid, OR_EXPR, PlaceHolderVar::phexpr, PlaceHolderVar::phlevelsup, PlaceHolderVar::phrels, set_opfuncid(), Var::varlevelsup, and Var::varno.

Referenced by find_nonnullable_rels().

1254 {
1255  Relids result = NULL;
1256  ListCell *l;
1257 
1258  if (node == NULL)
1259  return NULL;
1260  if (IsA(node, Var))
1261  {
1262  Var *var = (Var *) node;
1263 
1264  if (var->varlevelsup == 0)
1265  result = bms_make_singleton(var->varno);
1266  }
1267  else if (IsA(node, List))
1268  {
1269  /*
1270  * At top level, we are examining an implicit-AND list: if any of the
1271  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1272  * not at top level, we are examining the arguments of a strict
1273  * function: if any of them produce NULL then the result of the
1274  * function must be NULL. So in both cases, the set of nonnullable
1275  * rels is the union of those found in the arms, and we pass down the
1276  * top_level flag unmodified.
1277  */
1278  foreach(l, (List *) node)
1279  {
1280  result = bms_join(result,
1282  top_level));
1283  }
1284  }
1285  else if (IsA(node, FuncExpr))
1286  {
1287  FuncExpr *expr = (FuncExpr *) node;
1288 
1289  if (func_strict(expr->funcid))
1290  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1291  }
1292  else if (IsA(node, OpExpr))
1293  {
1294  OpExpr *expr = (OpExpr *) node;
1295 
1296  set_opfuncid(expr);
1297  if (func_strict(expr->opfuncid))
1298  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1299  }
1300  else if (IsA(node, ScalarArrayOpExpr))
1301  {
1302  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1303 
1304  if (is_strict_saop(expr, true))
1305  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1306  }
1307  else if (IsA(node, BoolExpr))
1308  {
1309  BoolExpr *expr = (BoolExpr *) node;
1310 
1311  switch (expr->boolop)
1312  {
1313  case AND_EXPR:
1314  /* At top level we can just recurse (to the List case) */
1315  if (top_level)
1316  {
1317  result = find_nonnullable_rels_walker((Node *) expr->args,
1318  top_level);
1319  break;
1320  }
1321 
1322  /*
1323  * Below top level, even if one arm produces NULL, the result
1324  * could be FALSE (hence not NULL). However, if *all* the
1325  * arms produce NULL then the result is NULL, so we can take
1326  * the intersection of the sets of nonnullable rels, just as
1327  * for OR. Fall through to share code.
1328  */
1329  /* FALL THRU */
1330  case OR_EXPR:
1331 
1332  /*
1333  * OR is strict if all of its arms are, so we can take the
1334  * intersection of the sets of nonnullable rels for each arm.
1335  * This works for both values of top_level.
1336  */
1337  foreach(l, expr->args)
1338  {
1339  Relids subresult;
1340 
1341  subresult = find_nonnullable_rels_walker(lfirst(l),
1342  top_level);
1343  if (result == NULL) /* first subresult? */
1344  result = subresult;
1345  else
1346  result = bms_int_members(result, subresult);
1347 
1348  /*
1349  * If the intersection is empty, we can stop looking. This
1350  * also justifies the test for first-subresult above.
1351  */
1352  if (bms_is_empty(result))
1353  break;
1354  }
1355  break;
1356  case NOT_EXPR:
1357  /* NOT will return null if its arg is null */
1358  result = find_nonnullable_rels_walker((Node *) expr->args,
1359  false);
1360  break;
1361  default:
1362  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1363  break;
1364  }
1365  }
1366  else if (IsA(node, RelabelType))
1367  {
1368  RelabelType *expr = (RelabelType *) node;
1369 
1370  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1371  }
1372  else if (IsA(node, CoerceViaIO))
1373  {
1374  /* not clear this is useful, but it can't hurt */
1375  CoerceViaIO *expr = (CoerceViaIO *) node;
1376 
1377  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1378  }
1379  else if (IsA(node, ArrayCoerceExpr))
1380  {
1381  /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1382  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1383 
1384  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1385  }
1386  else if (IsA(node, ConvertRowtypeExpr))
1387  {
1388  /* not clear this is useful, but it can't hurt */
1389  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1390 
1391  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1392  }
1393  else if (IsA(node, CollateExpr))
1394  {
1395  CollateExpr *expr = (CollateExpr *) node;
1396 
1397  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1398  }
1399  else if (IsA(node, NullTest))
1400  {
1401  /* IS NOT NULL can be considered strict, but only at top level */
1402  NullTest *expr = (NullTest *) node;
1403 
1404  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1405  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1406  }
1407  else if (IsA(node, BooleanTest))
1408  {
1409  /* Boolean tests that reject NULL are strict at top level */
1410  BooleanTest *expr = (BooleanTest *) node;
1411 
1412  if (top_level &&
1413  (expr->booltesttype == IS_TRUE ||
1414  expr->booltesttype == IS_FALSE ||
1415  expr->booltesttype == IS_NOT_UNKNOWN))
1416  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1417  }
1418  else if (IsA(node, PlaceHolderVar))
1419  {
1420  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1421 
1422  /*
1423  * If the contained expression forces any rels non-nullable, so does
1424  * the PHV.
1425  */
1426  result = find_nonnullable_rels_walker((Node *) phv->phexpr, top_level);
1427 
1428  /*
1429  * If the PHV's syntactic scope is exactly one rel, it will be forced
1430  * to be evaluated at that rel, and so it will behave like a Var of
1431  * that rel: if the rel's entire output goes to null, so will the PHV.
1432  * (If the syntactic scope is a join, we know that the PHV will go to
1433  * null if the whole join does; but that is AND semantics while we
1434  * need OR semantics for find_nonnullable_rels' result, so we can't do
1435  * anything with the knowledge.)
1436  */
1437  if (phv->phlevelsup == 0 &&
1439  result = bms_add_members(result, phv->phrels);
1440  }
1441  return result;
1442 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
Index varlevelsup
Definition: primnodes.h:191
List * args
Definition: primnodes.h:489
Expr * arg
Definition: primnodes.h:829
Definition: nodes.h:527
Definition: primnodes.h:181
Oid funcid
Definition: primnodes.h:481
#define ERROR
Definition: elog.h:43
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:949
BoolExprType boolop
Definition: primnodes.h:594
Expr * arg
Definition: primnodes.h:1234
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
Expr * arg
Definition: primnodes.h:1257
Expr * arg
Definition: primnodes.h:849
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
Index varno
Definition: primnodes.h:184
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:672
BoolTestType booltesttype
Definition: primnodes.h:1258
Oid opfuncid
Definition: primnodes.h:529
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1253
NullTestType nulltesttype
Definition: primnodes.h:1235
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition: clauses.c:1773
#define lfirst(lc)
Definition: pg_list.h:169
Expr * arg
Definition: primnodes.h:915
List * args
Definition: primnodes.h:595
bool func_strict(Oid funcid)
Definition: lsyscache.c:1678
Index phlevelsup
Definition: pathnodes.h:2116
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1667
#define elog(elevel,...)
Definition: elog.h:228
bool argisrow
Definition: primnodes.h:1236
List * args
Definition: primnodes.h:534
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:902
Definition: pg_list.h:50
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:793

◆ find_nonnullable_vars()

List* find_nonnullable_vars ( Node clause)

Definition at line 1472 of file clauses.c.

References find_nonnullable_vars_walker().

Referenced by reduce_outer_joins_pass2().

1473 {
1474  return find_nonnullable_vars_walker(clause, true);
1475 }
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1478

◆ find_nonnullable_vars_walker()

static List * find_nonnullable_vars_walker ( Node node,
bool  top_level 
)
static

Definition at line 1478 of file clauses.c.

References AND_EXPR, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, NullTest::arg, BooleanTest::arg, NullTest::argisrow, FuncExpr::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, elog, ERROR, func_strict(), FuncExpr::funcid, IS_FALSE, IS_NOT_NULL, IS_NOT_UNKNOWN, is_strict_saop(), IS_TRUE, IsA, lfirst, list_concat(), list_intersection(), list_make1, NIL, NOT_EXPR, NullTest::nulltesttype, OpExpr::opfuncid, OR_EXPR, PlaceHolderVar::phexpr, set_opfuncid(), and Var::varlevelsup.

Referenced by find_nonnullable_vars().

1479 {
1480  List *result = NIL;
1481  ListCell *l;
1482 
1483  if (node == NULL)
1484  return NIL;
1485  if (IsA(node, Var))
1486  {
1487  Var *var = (Var *) node;
1488 
1489  if (var->varlevelsup == 0)
1490  result = list_make1(var);
1491  }
1492  else if (IsA(node, List))
1493  {
1494  /*
1495  * At top level, we are examining an implicit-AND list: if any of the
1496  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1497  * not at top level, we are examining the arguments of a strict
1498  * function: if any of them produce NULL then the result of the
1499  * function must be NULL. So in both cases, the set of nonnullable
1500  * vars is the union of those found in the arms, and we pass down the
1501  * top_level flag unmodified.
1502  */
1503  foreach(l, (List *) node)
1504  {
1505  result = list_concat(result,
1507  top_level));
1508  }
1509  }
1510  else if (IsA(node, FuncExpr))
1511  {
1512  FuncExpr *expr = (FuncExpr *) node;
1513 
1514  if (func_strict(expr->funcid))
1515  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1516  }
1517  else if (IsA(node, OpExpr))
1518  {
1519  OpExpr *expr = (OpExpr *) node;
1520 
1521  set_opfuncid(expr);
1522  if (func_strict(expr->opfuncid))
1523  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1524  }
1525  else if (IsA(node, ScalarArrayOpExpr))
1526  {
1527  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1528 
1529  if (is_strict_saop(expr, true))
1530  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1531  }
1532  else if (IsA(node, BoolExpr))
1533  {
1534  BoolExpr *expr = (BoolExpr *) node;
1535 
1536  switch (expr->boolop)
1537  {
1538  case AND_EXPR:
1539  /* At top level we can just recurse (to the List case) */
1540  if (top_level)
1541  {
1542  result = find_nonnullable_vars_walker((Node *) expr->args,
1543  top_level);
1544  break;
1545  }
1546 
1547  /*
1548  * Below top level, even if one arm produces NULL, the result
1549  * could be FALSE (hence not NULL). However, if *all* the
1550  * arms produce NULL then the result is NULL, so we can take
1551  * the intersection of the sets of nonnullable vars, just as
1552  * for OR. Fall through to share code.
1553  */
1554  /* FALL THRU */
1555  case OR_EXPR:
1556 
1557  /*
1558  * OR is strict if all of its arms are, so we can take the
1559  * intersection of the sets of nonnullable vars for each arm.
1560  * This works for both values of top_level.
1561  */
1562  foreach(l, expr->args)
1563  {
1564  List *subresult;
1565 
1566  subresult = find_nonnullable_vars_walker(lfirst(l),
1567  top_level);
1568  if (result == NIL) /* first subresult? */
1569  result = subresult;
1570  else
1571  result = list_intersection(result, subresult);
1572 
1573  /*
1574  * If the intersection is empty, we can stop looking. This
1575  * also justifies the test for first-subresult above.
1576  */
1577  if (result == NIL)
1578  break;
1579  }
1580  break;
1581  case NOT_EXPR:
1582  /* NOT will return null if its arg is null */
1583  result = find_nonnullable_vars_walker((Node *) expr->args,
1584  false);
1585  break;
1586  default:
1587  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1588  break;
1589  }
1590  }
1591  else if (IsA(node, RelabelType))
1592  {
1593  RelabelType *expr = (RelabelType *) node;
1594 
1595  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1596  }
1597  else if (IsA(node, CoerceViaIO))
1598  {
1599  /* not clear this is useful, but it can't hurt */
1600  CoerceViaIO *expr = (CoerceViaIO *) node;
1601 
1602  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1603  }
1604  else if (IsA(node, ArrayCoerceExpr))
1605  {
1606  /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1607  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1608 
1609  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1610  }
1611  else if (IsA(node, ConvertRowtypeExpr))
1612  {
1613  /* not clear this is useful, but it can't hurt */
1614  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1615 
1616  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1617  }
1618  else if (IsA(node, CollateExpr))
1619  {
1620  CollateExpr *expr = (CollateExpr *) node;
1621 
1622  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1623  }
1624  else if (IsA(node, NullTest))
1625  {
1626  /* IS NOT NULL can be considered strict, but only at top level */
1627  NullTest *expr = (NullTest *) node;
1628 
1629  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1630  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1631  }
1632  else if (IsA(node, BooleanTest))
1633  {
1634  /* Boolean tests that reject NULL are strict at top level */
1635  BooleanTest *expr = (BooleanTest *) node;
1636 
1637  if (top_level &&
1638  (expr->booltesttype == IS_TRUE ||
1639  expr->booltesttype == IS_FALSE ||
1640  expr->booltesttype == IS_NOT_UNKNOWN))
1641  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1642  }
1643  else if (IsA(node, PlaceHolderVar))
1644  {
1645  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1646 
1647  result = find_nonnullable_vars_walker((Node *) phv->phexpr, top_level);
1648  }
1649  return result;
1650 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
Index varlevelsup
Definition: primnodes.h:191
List * args
Definition: primnodes.h:489
Expr * arg
Definition: primnodes.h:829
Definition: nodes.h:527
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
Definition: primnodes.h:181
#define list_make1(x1)
Definition: pg_list.h:206
Oid funcid
Definition: primnodes.h:481
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:594
Expr * arg
Definition: primnodes.h:1234
Expr * arg
Definition: primnodes.h:1257
List * list_intersection(const List *list1, const List *list2)
Definition: list.c:1018
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1478
Expr * arg
Definition: primnodes.h:849
BoolTestType booltesttype
Definition: primnodes.h:1258
Oid opfuncid
Definition: primnodes.h:529
NullTestType nulltesttype
Definition: primnodes.h:1235
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition: clauses.c:1773
#define lfirst(lc)
Definition: pg_list.h:169
Expr * arg
Definition: primnodes.h:915
List * args
Definition: primnodes.h:595
bool func_strict(Oid funcid)
Definition: lsyscache.c:1678
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1667
#define elog(elevel,...)
Definition: elog.h:228
bool argisrow
Definition: primnodes.h:1236
List * args
Definition: primnodes.h:534
Definition: pg_list.h:50

◆ find_window_functions()

WindowFuncLists* find_window_functions ( Node clause,
Index  maxWinRef 
)

Definition at line 219 of file clauses.c.

References find_window_functions_walker(), WindowFuncLists::maxWinRef, WindowFuncLists::numWindowFuncs, palloc(), palloc0(), and WindowFuncLists::windowFuncs.

Referenced by grouping_planner().

220 {
221  WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
222 
223  lists->numWindowFuncs = 0;
224  lists->maxWinRef = maxWinRef;
225  lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
226  (void) find_window_functions_walker(clause, lists);
227  return lists;
228 }
Index maxWinRef
Definition: clauses.h:22
int numWindowFuncs
Definition: clauses.h:21
void * palloc0(Size size)
Definition: mcxt.c:981
void * palloc(Size size)
Definition: mcxt.c:950
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:231
Definition: pg_list.h:50
List ** windowFuncs
Definition: clauses.h:23

◆ find_window_functions_walker()

static bool find_window_functions_walker ( Node node,
WindowFuncLists lists 
)
static

Definition at line 231 of file clauses.c.

References Assert, elog, ERROR, expression_tree_walker(), IsA, lappend(), list_member(), WindowFuncLists::maxWinRef, WindowFuncLists::numWindowFuncs, WindowFuncLists::windowFuncs, and WindowFunc::winref.

Referenced by find_window_functions().

232 {
233  if (node == NULL)
234  return false;
235  if (IsA(node, WindowFunc))
236  {
237  WindowFunc *wfunc = (WindowFunc *) node;
238 
239  /* winref is unsigned, so one-sided test is OK */
240  if (wfunc->winref > lists->maxWinRef)
241  elog(ERROR, "WindowFunc contains out-of-range winref %u",
242  wfunc->winref);
243  /* eliminate duplicates, so that we avoid repeated computation */
244  if (!list_member(lists->windowFuncs[wfunc->winref], wfunc))
245  {
246  lists->windowFuncs[wfunc->winref] =
247  lappend(lists->windowFuncs[wfunc->winref], wfunc);
248  lists->numWindowFuncs++;
249  }
250 
251  /*
252  * We assume that the parser checked that there are no window
253  * functions in the arguments or filter clause. Hence, we need not
254  * recurse into them. (If either the parser or the planner screws up
255  * on this point, the executor will still catch it; see ExecInitExpr.)
256  */
257  return false;
258  }
259  Assert(!IsA(node, SubLink));
261  (void *) lists);
262 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
Index maxWinRef
Definition: clauses.h:22
int numWindowFuncs
Definition: clauses.h:21
Index winref
Definition: primnodes.h:387
#define ERROR
Definition: elog.h:43
bool list_member(const List *list, const void *datum)
Definition: list.c:613
List * lappend(List *list, void *datum)
Definition: list.c:321
#define Assert(condition)
Definition: c.h:800
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
#define elog(elevel,...)
Definition: elog.h:228
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:231
List ** windowFuncs
Definition: clauses.h:23

◆ inline_function()

static Expr * inline_function ( Oid  funcid,
Oid  result_type,
Oid  result_collid,
Oid  input_collid,
List args,
bool  funcvariadic,
HeapTuple  func_tuple,
eval_const_expressions_context context 
)
static

Definition at line 4071 of file clauses.c.

References ACL_EXECUTE, ACLCHECK_OK, eval_const_expressions_context::active_fns, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, arg, ErrorContextCallback::arg, CollateExpr::arg, generate_unaccent_rules::args, FuncExpr::args, ErrorContextCallback::callback, check_sql_fn_retval(), CMD_SELECT, COERCE_EXPLICIT_CALL, CollateExpr::collOid, Query::commandType, contain_context_dependent_node(), contain_mutable_functions(), contain_nonstrict_functions(), contain_subplans(), contain_volatile_functions(), copyObject, cost_qual_eval(), cpu_operator_cost, Query::cteList, CurrentMemoryContext, Query::distinctClause, elog, ERROR, error_context_stack, eval_const_expressions_mutator(), exprCollation(), exprType(), FmgrHookIsNeeded, free_parsestate(), FromExpr::fromlist, FuncExpr::funccollid, FuncExpr::funcformat, FuncExpr::funcid, FuncExpr::funcresulttype, FuncExpr::funcretset, FuncExpr::funcvariadic, get_expr_result_type(), GETSTRUCT, GetUserId(), Query::groupClause, Query::groupingSets, Query::hasAggs, Query::hasSubLinks, Query::hasTargetSRFs, Query::hasWindowFuncs, Query::havingQual, heap_attisnull(), i, FuncExpr::inputcollid, IsA, Query::jointree, lappend_oid(), lfirst, Query::limitCount, Query::limitOffset, linitial, list_delete_last(), list_length(), list_make1, list_member_oid(), FuncExpr::location, CollateExpr::location, make_parsestate(), makeNode, MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, OidIsValid, ParseState::p_sourcetext, palloc0(), QualCost::per_tuple, pg_parse_query(), pg_proc_aclcheck(), prepare_sql_fn_parse_info(), ErrorContextCallback::previous, PROCOID, inline_error_callback_arg::proname, inline_error_callback_arg::prosrc, FromExpr::quals, querytree(), record_plan_function_dependency(), eval_const_expressions_context::root, Query::rtable, Query::setOperations, Query::sortClause, sql_fn_parser_setup(), sql_inline_error_callback(), QualCost::startup, substitute_actual_parameters(), SysCacheGetAttr(), Query::targetList, TextDatumGetCString, transformTopLevelStmt(), and Query::windowClause.

Referenced by simplify_function().

4076 {
4077  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4078  char *src;
4079  Datum tmp;
4080  bool isNull;
4081  MemoryContext oldcxt;
4082  MemoryContext mycxt;
4083  inline_error_callback_arg callback_arg;
4084  ErrorContextCallback sqlerrcontext;
4085  FuncExpr *fexpr;
4087  TupleDesc rettupdesc;
4088  ParseState *pstate;
4089  List *raw_parsetree_list;
4090  List *querytree_list;
4091  Query *querytree;
4092  Node *newexpr;
4093  int *usecounts;
4094  ListCell *arg;
4095  int i;
4096 
4097  /*
4098  * Forget it if the function is not SQL-language or has other showstopper
4099  * properties. (The prokind and nargs checks are just paranoia.)
4100  */
4101  if (funcform->prolang != SQLlanguageId ||
4102  funcform->prokind != PROKIND_FUNCTION ||
4103  funcform->prosecdef ||
4104  funcform->proretset ||
4105  funcform->prorettype == RECORDOID ||
4106  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL) ||
4107  funcform->pronargs != list_length(args))
4108  return NULL;
4109 
4110  /* Check for recursive function, and give up trying to expand if so */
4111  if (list_member_oid(context->active_fns, funcid))
4112  return NULL;
4113 
4114  /* Check permission to call function (fail later, if not) */
4116  return NULL;
4117 
4118  /* Check whether a plugin wants to hook function entry/exit */
4119  if (FmgrHookIsNeeded(funcid))
4120  return NULL;
4121 
4122  /*
4123  * Make a temporary memory context, so that we don't leak all the stuff
4124  * that parsing might create.
4125  */
4127  "inline_function",
4129  oldcxt = MemoryContextSwitchTo(mycxt);
4130 
4131  /* Fetch the function body */
4132  tmp = SysCacheGetAttr(PROCOID,
4133  func_tuple,
4134  Anum_pg_proc_prosrc,
4135  &isNull);
4136  if (isNull)
4137  elog(ERROR, "null prosrc for function %u", funcid);
4138  src = TextDatumGetCString(tmp);
4139 
4140  /*
4141  * Setup error traceback support for ereport(). This is so that we can
4142  * finger the function that bad information came from.
4143  */
4144  callback_arg.proname = NameStr(funcform->proname);
4145  callback_arg.prosrc = src;
4146 
4147  sqlerrcontext.callback = sql_inline_error_callback;
4148  sqlerrcontext.arg = (void *) &callback_arg;
4149  sqlerrcontext.previous = error_context_stack;
4150  error_context_stack = &sqlerrcontext;
4151 
4152  /*
4153  * Set up to handle parameters while parsing the function body. We need a
4154  * dummy FuncExpr node containing the already-simplified arguments to pass
4155  * to prepare_sql_fn_parse_info. (In some cases we don't really need
4156  * that, but for simplicity we always build it.)
4157  */
4158  fexpr = makeNode(FuncExpr);
4159  fexpr->funcid = funcid;
4160  fexpr->funcresulttype = result_type;
4161  fexpr->funcretset = false;
4162  fexpr->funcvariadic = funcvariadic;
4163  fexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
4164  fexpr->funccollid = result_collid; /* doesn't matter */
4165  fexpr->inputcollid = input_collid;
4166  fexpr->args = args;
4167  fexpr->location = -1;
4168 
4169  pinfo = prepare_sql_fn_parse_info(func_tuple,
4170  (Node *) fexpr,
4171  input_collid);
4172 
4173  /* fexpr also provides a convenient way to resolve a composite result */
4174  (void) get_expr_result_type((Node *) fexpr,
4175  NULL,
4176  &rettupdesc);
4177 
4178  /*
4179  * We just do parsing and parse analysis, not rewriting, because rewriting
4180  * will not affect table-free-SELECT-only queries, which is all that we
4181  * care about. Also, we can punt as soon as we detect more than one
4182  * command in the function body.
4183  */
4184  raw_parsetree_list = pg_parse_query(src);
4185  if (list_length(raw_parsetree_list) != 1)
4186  goto fail;
4187 
4188  pstate = make_parsestate(NULL);
4189  pstate->p_sourcetext = src;
4190  sql_fn_parser_setup(pstate, pinfo);
4191 
4192  querytree = transformTopLevelStmt(pstate, linitial(raw_parsetree_list));
4193 
4194  free_parsestate(pstate);
4195 
4196  /*
4197  * The single command must be a simple "SELECT expression".
4198  *
4199  * Note: if you change the tests involved in this, see also plpgsql's
4200  * exec_simple_check_plan(). That generally needs to have the same idea
4201  * of what's a "simple expression", so that inlining a function that
4202  * previously wasn't inlined won't change plpgsql's conclusion.
4203  */
4204  if (!IsA(querytree, Query) ||
4205  querytree->commandType != CMD_SELECT ||
4206  querytree->hasAggs ||
4207  querytree->hasWindowFuncs ||
4208  querytree->hasTargetSRFs ||
4209  querytree->hasSubLinks ||
4210  querytree->cteList ||
4211  querytree->rtable ||
4212  querytree->jointree->fromlist ||
4213  querytree->jointree->quals ||
4214  querytree->groupClause ||
4215  querytree->groupingSets ||
4216  querytree->havingQual ||
4217  querytree->windowClause ||
4218  querytree->distinctClause ||
4219  querytree->sortClause ||
4220  querytree->limitOffset ||
4221  querytree->limitCount ||
4222  querytree->setOperations ||
4223  list_length(querytree->targetList) != 1)
4224  goto fail;
4225 
4226  /*
4227  * Make sure the function (still) returns what it's declared to. This
4228  * will raise an error if wrong, but that's okay since the function would
4229  * fail at runtime anyway. Note that check_sql_fn_retval will also insert
4230  * a coercion if needed to make the tlist expression match the declared
4231  * type of the function.
4232  *
4233  * Note: we do not try this until we have verified that no rewriting was
4234  * needed; that's probably not important, but let's be careful.
4235  */
4236  querytree_list = list_make1(querytree);
4237  if (check_sql_fn_retval(list_make1(querytree_list),
4238  result_type, rettupdesc,
4239  false, NULL))
4240  goto fail; /* reject whole-tuple-result cases */
4241 
4242  /*
4243  * Given the tests above, check_sql_fn_retval shouldn't have decided to
4244  * inject a projection step, but let's just make sure.
4245  */
4246  if (querytree != linitial(querytree_list))
4247  goto fail;
4248 
4249  /* Now we can grab the tlist expression */
4250  newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr;
4251 
4252  /*
4253  * If the SQL function returns VOID, we can only inline it if it is a
4254  * SELECT of an expression returning VOID (ie, it's just a redirection to
4255  * another VOID-returning function). In all non-VOID-returning cases,
4256  * check_sql_fn_retval should ensure that newexpr returns the function's
4257  * declared result type, so this test shouldn't fail otherwise; but we may
4258  * as well cope gracefully if it does.
4259  */
4260  if (exprType(newexpr) != result_type)
4261  goto fail;
4262 
4263  /*
4264  * Additional validity checks on the expression. It mustn't be more
4265  * volatile than the surrounding function (this is to avoid breaking hacks
4266  * that involve pretending a function is immutable when it really ain't).
4267  * If the surrounding function is declared strict, then the expression
4268  * must contain only strict constructs and must use all of the function
4269  * parameters (this is overkill, but an exact analysis is hard).
4270  */
4271  if (funcform->provolatile == PROVOLATILE_IMMUTABLE &&
4272  contain_mutable_functions(newexpr))
4273  goto fail;
4274  else if (funcform->provolatile == PROVOLATILE_STABLE &&
4275  contain_volatile_functions(newexpr))
4276  goto fail;
4277 
4278  if (funcform->proisstrict &&
4279  contain_nonstrict_functions(newexpr))
4280  goto fail;
4281 
4282  /*
4283  * If any parameter expression contains a context-dependent node, we can't
4284  * inline, for fear of putting such a node into the wrong context.
4285  */
4286  if (contain_context_dependent_node((Node *) args))
4287  goto fail;
4288 
4289  /*
4290  * We may be able to do it; there are still checks on parameter usage to
4291  * make, but those are most easily done in combination with the actual
4292  * substitution of the inputs. So start building expression with inputs
4293  * substituted.
4294  */
4295  usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
4296  newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
4297  args, usecounts);
4298 
4299  /* Now check for parameter usage */
4300  i = 0;
4301  foreach(arg, args)
4302  {
4303  Node *param = lfirst(arg);
4304 
4305  if (usecounts[i] == 0)
4306  {
4307  /* Param not used at all: uncool if func is strict */
4308  if (funcform->proisstrict)
4309  goto fail;
4310  }
4311  else if (usecounts[i] != 1)
4312  {
4313  /* Param used multiple times: uncool if expensive or volatile */
4314  QualCost eval_cost;
4315 
4316  /*
4317  * We define "expensive" as "contains any subplan or more than 10
4318  * operators". Note that the subplan search has to be done
4319  * explicitly, since cost_qual_eval() will barf on unplanned
4320  * subselects.
4321  */
4322  if (contain_subplans(param))
4323  goto fail;
4324  cost_qual_eval(&eval_cost, list_make1(param), NULL);
4325  if (eval_cost.startup + eval_cost.per_tuple >
4326  10 * cpu_operator_cost)
4327  goto fail;
4328 
4329  /*
4330  * Check volatility last since this is more expensive than the
4331  * above tests
4332  */
4333  if (contain_volatile_functions(param))
4334  goto fail;
4335  }
4336  i++;
4337  }
4338 
4339  /*
4340  * Whew --- we can make the substitution. Copy the modified expression
4341  * out of the temporary memory context, and clean up.
4342  */
4343  MemoryContextSwitchTo(oldcxt);
4344 
4345  newexpr = copyObject(newexpr);
4346 
4347  MemoryContextDelete(mycxt);
4348 
4349  /*
4350  * If the result is of a collatable type, force the result to expose the
4351  * correct collation. In most cases this does not matter, but it's
4352  * possible that the function result is used directly as a sort key or in
4353  * other places where we expect exprCollation() to tell the truth.
4354  */
4355  if (OidIsValid(result_collid))
4356  {
4357  Oid exprcoll = exprCollation(newexpr);
4358 
4359  if (OidIsValid(exprcoll) && exprcoll != result_collid)
4360  {
4361  CollateExpr *newnode = makeNode(CollateExpr);
4362 
4363  newnode->arg = (Expr *) newexpr;
4364  newnode->collOid = result_collid;
4365  newnode->location = -1;
4366 
4367  newexpr = (Node *) newnode;
4368  }
4369  }
4370 
4371  /*
4372  * Since there is now no trace of the function in the plan tree, we must
4373  * explicitly record the plan's dependency on the function.
4374  */
4375  if (context->root)
4376  record_plan_function_dependency(context->root, funcid);
4377 
4378  /*
4379  * Recursively try to simplify the modified expression. Here we must add
4380  * the current function to the context list of active functions.
4381  */
4382  context->active_fns = lappend_oid(context->active_fns, funcid);
4383  newexpr = eval_const_expressions_mutator(newexpr, context);
4384  context->active_fns = list_delete_last(context->active_fns);
4385 
4386  error_context_stack = sqlerrcontext.previous;
4387 
4388  return (Expr *) newexpr;
4389 
4390  /* Here if func is not inlinable: release temp memory and return NULL */
4391 fail:
4392  MemoryContextSwitchTo(oldcxt);
4393  MemoryContextDelete(mycxt);
4394  error_context_stack = sqlerrcontext.previous;
4395 
4396  return NULL;
4397 }
Node * limitOffset
Definition: parsenodes.h:160
Oid funcresulttype
Definition: primnodes.h:482
bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, bool insertDroppedCols, List **resultTargetList)
Definition: functions.c:1601
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
#define AllocSetContextCreate
Definition: memutils.h:170
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
List * sortClause
Definition: parsenodes.h:158
List * args
Definition: primnodes.h:489
FromExpr * jointree
Definition: parsenodes.h:138
Oid GetUserId(void)
Definition: miscinit.c:476
Oid funccollid
Definition: primnodes.h:487
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition: functions.c:280
bool hasAggs
Definition: parsenodes.h:125
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * groupingSets
Definition: parsenodes.h:150
Definition: nodes.h:527
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
bool funcretset
Definition: primnodes.h:483
List * fromlist
Definition: primnodes.h:1525
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:436
unsigned int Oid
Definition: postgres_ext.h:31
void(* callback)(void *arg)
Definition: elog.h:243
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:221
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
struct ErrorContextCallback * previous
Definition: elog.h:242
#define OidIsValid(objectId)
Definition: c.h:706
#define FmgrHookIsNeeded(fn_oid)
Definition: fmgr.h:774
Node * quals
Definition: primnodes.h:1526
Cost startup
Definition: pathnodes.h:45
List * windowClause
Definition: parsenodes.h:154
List * targetList
Definition: parsenodes.h:140
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:43
ErrorContextCallback * error_context_stack
Definition: elog.c:92
#define list_make1(x1)
Definition: pg_list.h:206
bool contain_subplans(Node *clause)
Definition: clauses.c:322
CoercionForm funcformat
Definition: primnodes.h:486
Cost per_tuple
Definition: pathnodes.h:46
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2077
#define linitial(l)
Definition: pg_list.h:174
List * rtable
Definition: parsenodes.h:137
List * distinctClause
Definition: parsenodes.h:156
Oid funcid
Definition: primnodes.h:481
#define ERROR
Definition: elog.h:43
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:4066
List * pg_parse_query(const char *query_string)
Definition: postgres.c:628
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
Node * limitCount
Definition: parsenodes.h:161
List * list_delete_last(List *list)
Definition: list.c:877
double cpu_operator_cost
Definition: costsize.c:122
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
const char * p_sourcetext
Definition: parse_node.h:179
static Node * substitute_actual_parameters(Node *expr, int nargs, List *args, int *usecounts)
Definition: clauses.c:4403
static void sql_inline_error_callback(void *arg)
Definition: clauses.c:4445
#define TextDatumGetCString(d)
Definition: builtins.h:87
void * palloc0(Size size)
Definition: mcxt.c:981
uintptr_t Datum
Definition: postgres.h:367
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1376
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2889
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
CmdType commandType
Definition: parsenodes.h:112
bool hasTargetSRFs
Definition: parsenodes.h:127
#define makeNode(_type_)
Definition: nodes.h:575
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:674
Oid inputcollid
Definition: primnodes.h:488
#define lfirst(lc)
Definition: pg_list.h:169
bool hasWindowFuncs
Definition: parsenodes.h:126
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:191
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static int list_length(const List *l)
Definition: pg_list.h:149
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:768
Expr * arg
Definition: primnodes.h:915
Datum querytree(PG_FUNCTION_ARGS)
Definition: _int_bool.c:664
static bool contain_context_dependent_node(Node *clause)
Definition: clauses.c:989
List * cteList
Definition: parsenodes.h:135
Node * setOperations
Definition: parsenodes.h:166
List * groupClause
Definition: parsenodes.h:148
bool hasSubLinks
Definition: parsenodes.h:128
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:228
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4587
int i
#define NameStr(name)
Definition: c.h:677
void * arg
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:357
int location
Definition: primnodes.h:490
bool contain_nonstrict_functions(Node *clause)
Definition: clauses.c:806
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
Definition: functions.c:190
#define copyObject(obj)
Definition: nodes.h:643
Node * havingQual
Definition: parsenodes.h:152
int location
Definition: primnodes.h:917
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:76
Definition: pg_list.h:50
bool funcvariadic
Definition: primnodes.h:484

◆ inline_set_returning_function()

Query* inline_set_returning_function ( PlannerInfo root,
RangeTblEntry rte 
)

Definition at line 4561 of file clauses.c.

References ACL_EXECUTE, ACLCHECK_OK, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, FuncExpr::args, Assert, BuildDescFromLists(), ErrorContextCallback::callback, check_sql_fn_retval(), check_stack_depth(), CMD_SELECT, Query::commandType, contain_subplans(), contain_volatile_functions(), copyObject, CurrentMemoryContext, elog, ERROR, error_context_stack, FmgrHookIsNeeded, RangeTblFunction::funccolcollations, RangeTblFunction::funccolnames, RangeTblFunction::funccoltypes, RangeTblFunction::funccoltypmods, RangeTblFunction::funcexpr, FuncExpr::funcid, RangeTblEntry::funcordinality, FuncExpr::funcretset, RangeTblEntry::functions, get_expr_result_type(), GETSTRUCT, GetUserId(), heap_attisnull(), HeapTupleIsValid, IsA, linitial, linitial_node, list_length(), list_make1, MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, ObjectIdGetDatum, pg_analyze_and_rewrite_params(), pg_parse_query(), pg_proc_aclcheck(), prepare_sql_fn_parse_info(), ErrorContextCallback::previous, PROCOID, inline_error_callback_arg::proname, inline_error_callback_arg::prosrc, querytree(), record_plan_function_dependency(), ReleaseSysCache(), RTE_FUNCTION, RangeTblEntry::rtekind, SearchSysCache1(), sql_fn_parser_setup(), sql_inline_error_callback(), substitute_actual_srf_parameters(), SysCacheGetAttr(), TextDatumGetCString, TYPEFUNC_COMPOSITE, TYPEFUNC_COMPOSITE_DOMAIN, and TYPEFUNC_RECORD.

Referenced by preprocess_function_rtes().

4562 {
4563  RangeTblFunction *rtfunc;
4564  FuncExpr *fexpr;
4565  Oid func_oid;
4566  HeapTuple func_tuple;
4567  Form_pg_proc funcform;
4568  char *src;
4569  Datum tmp;
4570  bool isNull;
4571  MemoryContext oldcxt;
4572  MemoryContext mycxt;
4573  inline_error_callback_arg callback_arg;
4574  ErrorContextCallback sqlerrcontext;
4576  TypeFuncClass functypclass;
4577  TupleDesc rettupdesc;
4578  List *raw_parsetree_list;
4579  List *querytree_list;
4580  Query *querytree;
4581 
4582  Assert(rte->rtekind == RTE_FUNCTION);
4583 
4584  /*
4585  * It doesn't make a lot of sense for a SQL SRF to refer to itself in its
4586  * own FROM clause, since that must cause infinite recursion at runtime.
4587  * It will cause this code to recurse too, so check for stack overflow.
4588  * (There's no need to do more.)
4589  */
4591 
4592  /* Fail if the RTE has ORDINALITY - we don't implement that here. */
4593  if (rte->funcordinality)
4594  return NULL;
4595 
4596  /* Fail if RTE isn't a single, simple FuncExpr */
4597  if (list_length(rte->functions) != 1)
4598  return NULL;
4599  rtfunc = (RangeTblFunction *) linitial(rte->functions);
4600 
4601  if (!IsA(rtfunc->funcexpr, FuncExpr))
4602  return NULL;
4603  fexpr = (FuncExpr *) rtfunc->funcexpr;
4604 
4605  func_oid = fexpr->funcid;
4606 
4607  /*
4608  * The function must be declared to return a set, else inlining would
4609  * change the results if the contained SELECT didn't return exactly one
4610  * row.
4611  */
4612  if (!fexpr->funcretset)
4613  return NULL;
4614 
4615  /*
4616  * Refuse to inline if the arguments contain any volatile functions or
4617  * sub-selects. Volatile functions are rejected because inlining may
4618  * result in the arguments being evaluated multiple times, risking a
4619  * change in behavior. Sub-selects are rejected partly for implementation
4620  * reasons (pushing them down another level might change their behavior)
4621  * and partly because they're likely to be expensive and so multiple
4622  * evaluation would be bad.
4623  */
4624  if (contain_volatile_functions((Node *) fexpr->args) ||
4625  contain_subplans((Node *) fexpr->args))
4626  return NULL;
4627 
4628  /* Check permission to call function (fail later, if not) */
4629  if (pg_proc_aclcheck(func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
4630  return NULL;
4631 
4632  /* Check whether a plugin wants to hook function entry/exit */
4633  if (FmgrHookIsNeeded(func_oid))
4634  return NULL;
4635 
4636  /*
4637  * OK, let's take a look at the function's pg_proc entry.
4638  */
4639  func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid));
4640  if (!HeapTupleIsValid(func_tuple))
4641  elog(ERROR, "cache lookup failed for function %u", func_oid);
4642  funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4643 
4644  /*
4645  * Forget it if the function is not SQL-language or has other showstopper
4646  * properties. In particular it mustn't be declared STRICT, since we
4647  * couldn't enforce that. It also mustn't be VOLATILE, because that is
4648  * supposed to cause it to be executed with its own snapshot, rather than
4649  * sharing the snapshot of the calling query. We also disallow returning
4650  * SETOF VOID, because inlining would result in exposing the actual result
4651  * of the function's last SELECT, which should not happen in that case.
4652  * (Rechecking prokind, proretset, and pronargs is just paranoia.)
4653  */
4654  if (funcform->prolang != SQLlanguageId ||
4655  funcform->prokind != PROKIND_FUNCTION ||
4656  funcform->proisstrict ||
4657  funcform->provolatile == PROVOLATILE_VOLATILE ||
4658  funcform->prorettype == VOIDOID ||
4659  funcform->prosecdef ||
4660  !funcform->proretset ||
4661  list_length(fexpr->args) != funcform->pronargs ||
4662  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL))
4663  {
4664  ReleaseSysCache(func_tuple);
4665  return NULL;
4666  }
4667 
4668  /*
4669  * Make a temporary memory context, so that we don't leak all the stuff
4670  * that parsing might create.
4671  */
4673  "inline_set_returning_function",
4675  oldcxt = MemoryContextSwitchTo(mycxt);
4676 
4677  /* Fetch the function body */
4678  tmp = SysCacheGetAttr(PROCOID,
4679  func_tuple,
4680  Anum_pg_proc_prosrc,
4681  &isNull);
4682  if (isNull)
4683  elog(ERROR, "null prosrc for function %u", func_oid);
4684  src = TextDatumGetCString(tmp);
4685 
4686  /*
4687  * Setup error traceback support for ereport(). This is so that we can
4688  * finger the function that bad information came from.
4689  */
4690  callback_arg.proname = NameStr(funcform->proname);
4691  callback_arg.prosrc = src;
4692 
4693  sqlerrcontext.callback = sql_inline_error_callback;
4694  sqlerrcontext.arg = (void *) &callback_arg;
4695  sqlerrcontext.previous = error_context_stack;
4696  error_context_stack = &sqlerrcontext;
4697 
4698  /*
4699  * Set up to handle parameters while parsing the function body. We can
4700  * use the FuncExpr just created as the input for
4701  * prepare_sql_fn_parse_info.
4702  */
4703  pinfo = prepare_sql_fn_parse_info(func_tuple,
4704  (Node *) fexpr,
4705  fexpr->inputcollid);
4706 
4707  /*
4708  * Also resolve the actual function result tupdesc, if composite. If the
4709  * function is just declared to return RECORD, dig the info out of the AS
4710  * clause.
4711  */
4712  functypclass = get_expr_result_type((Node *) fexpr, NULL, &rettupdesc);
4713  if (functypclass == TYPEFUNC_RECORD)
4714  rettupdesc = BuildDescFromLists(rtfunc->funccolnames,
4715  rtfunc->funccoltypes,
4716  rtfunc->funccoltypmods,
4717  rtfunc->funccolcollations);
4718 
4719  /*
4720  * Parse, analyze, and rewrite (unlike inline_function(), we can't skip
4721  * rewriting here). We can fail as soon as we find more than one query,
4722  * though.
4723  */
4724  raw_parsetree_list = pg_parse_query(src);
4725  if (list_length(raw_parsetree_list) != 1)
4726  goto fail;
4727 
4728  querytree_list = pg_analyze_and_rewrite_params(linitial(raw_parsetree_list),
4729  src,
4731  pinfo, NULL);
4732  if (list_length(querytree_list) != 1)
4733  goto fail;
4734  querytree = linitial(querytree_list);
4735 
4736  /*
4737  * The single command must be a plain SELECT.
4738  */
4739  if (!IsA(querytree, Query) ||
4740  querytree->commandType != CMD_SELECT)
4741  goto fail;
4742 
4743  /*
4744  * Make sure the function (still) returns what it's declared to. This
4745  * will raise an error if wrong, but that's okay since the function would
4746  * fail at runtime anyway. Note that check_sql_fn_retval will also insert
4747  * coercions if needed to make the tlist expression(s) match the declared
4748  * type of the function. We also ask it to insert dummy NULL columns for
4749  * any dropped columns in rettupdesc, so that the elements of the modified
4750  * tlist match up to the attribute numbers.
4751  *
4752  * If the function returns a composite type, don't inline unless the check
4753  * shows it's returning a whole tuple result; otherwise what it's
4754  * returning is a single composite column which is not what we need.
4755  */
4756  if (!check_sql_fn_retval(list_make1(querytree_list),
4757  fexpr->funcresulttype, rettupdesc,
4758  true, NULL) &&
4759  (functypclass == TYPEFUNC_COMPOSITE ||
4760  functypclass == TYPEFUNC_COMPOSITE_DOMAIN ||
4761  functypclass == TYPEFUNC_RECORD))
4762  goto fail; /* reject not-whole-tuple-result cases */
4763 
4764  /*
4765  * check_sql_fn_retval might've inserted a projection step, but that's
4766  * fine; just make sure we use the upper Query.
4767  */
4768  querytree = linitial_node(Query, querytree_list);
4769 
4770  /*
4771  * Looks good --- substitute parameters into the query.
4772  */
4773  querytree = substitute_actual_srf_parameters(querytree,
4774  funcform->pronargs,
4775  fexpr->args);
4776 
4777  /*
4778  * Copy the modified query out of the temporary memory context, and clean
4779  * up.
4780  */
4781  MemoryContextSwitchTo(oldcxt);
4782 
4783  querytree = copyObject(querytree);
4784 
4785  MemoryContextDelete(mycxt);
4786  error_context_stack = sqlerrcontext.previous;
4787  ReleaseSysCache(func_tuple);
4788 
4789  /*
4790  * We don't have to fix collations here because the upper query is already
4791  * parsed, ie, the collations in the RTE are what count.
4792  */
4793 
4794  /*
4795  * Since there is now no trace of the function in the plan tree, we must
4796  * explicitly record the plan's dependency on the function.
4797  */
4798  record_plan_function_dependency(root, func_oid);
4799 
4800  return querytree;
4801 
4802  /* Here if func is not inlinable: release temp memory and return NULL */
4803 fail:
4804  MemoryContextSwitchTo(oldcxt);
4805  MemoryContextDelete(mycxt);
4806  error_context_stack = sqlerrcontext.previous;
4807  ReleaseSysCache(func_tuple);
4808 
4809  return NULL;
4810 }
Oid funcresulttype
Definition: primnodes.h:482
bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, bool insertDroppedCols, List **resultTargetList)
Definition: functions.c:1601
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
#define AllocSetContextCreate
Definition: memutils.h:170
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
TupleDesc BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
Definition: tupdesc.c:892
List * args
Definition: primnodes.h:489
Oid GetUserId(void)
Definition: miscinit.c:476
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition: functions.c:280
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:527
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
bool funcretset
Definition: primnodes.h:483
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:436
bool funcordinality
Definition: parsenodes.h:1070
unsigned int Oid
Definition: postgres_ext.h:31
#define linitial_node(type, l)
Definition: pg_list.h:177
void(* callback)(void *arg)
Definition: elog.h:243
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:221
struct ErrorContextCallback * previous
Definition: elog.h:242
#define FmgrHookIsNeeded(fn_oid)
Definition: fmgr.h:774
ErrorContextCallback * error_context_stack
Definition: elog.c:92
#define list_make1(x1)
Definition: pg_list.h:206
bool contain_subplans(Node *clause)
Definition: clauses.c:322
#define linitial(l)
Definition: pg_list.h:174
Oid funcid
Definition: primnodes.h:481
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
List * pg_parse_query(const char *query_string)
Definition: postgres.c:628
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
Definition: params.h:108
void check_stack_depth(void)
Definition: postgres.c:3317
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
TypeFuncClass
Definition: funcapi.h:146
static void sql_inline_error_callback(void *arg)
Definition: clauses.c:4445
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1376
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2889
static Query * substitute_actual_srf_parameters(Query *expr, int nargs, List *args)
Definition: clauses.c:4819
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
List * funccoltypmods
Definition: parsenodes.h:1159
CmdType commandType
Definition: parsenodes.h:112
List * funccolcollations
Definition: parsenodes.h:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:800
List * functions
Definition: parsenodes.h:1069
static int list_length(const List *l)
Definition: pg_list.h:149
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:713
Datum querytree(PG_FUNCTION_ARGS)
Definition: _int_bool.c:664
RTEKind rtekind
Definition: parsenodes.h:982
#define ACL_EXECUTE
Definition: