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/subscripting.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/rewriteHandler.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 MIN_ARRAY_SIZE_FOR_HASHED_SAOP   9
 
#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 bool convert_saop_to_hashed_saop_walker (Node *node, void *context)
 
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, int pronargs, HeapTuple func_tuple)
 
static Listadd_function_defaults (List *args, int pronargs, HeapTuple func_tuple)
 
static Listfetch_function_defaults (HeapTuple func_tuple)
 
static void recheck_cast_function_args (List *args, Oid result_type, Oid *proargtypes, int pronargs, 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)
 
static bool pull_paramids_walker (Node *node, Bitmapset **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 (PlannerInfo *root, 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)
 
void convert_saop_to_hashed_saop (Node *node)
 
Nodeestimate_expression_value (PlannerInfo *root, Node *node)
 
Listexpand_function_arguments (List *args, bool include_out_arguments, 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)
 
Bitmapsetpull_paramids (Expr *expr)
 

Macro Definition Documentation

◆ CCDN_CASETESTEXPR_OK

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

Definition at line 1073 of file clauses.c.

◆ ece_all_arguments_const

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

Definition at line 2266 of file clauses.c.

◆ 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:4786
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
Definition: nodes.h:539

Definition at line 2270 of file clauses.c.

◆ ece_generic_processing

#define ece_generic_processing (   node)
Value:
(void *) context)
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2280
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2618

Definition at line 2257 of file clauses.c.

◆ MIN_ARRAY_SIZE_FOR_HASHED_SAOP

#define MIN_ARRAY_SIZE_FOR_HASHED_SAOP   9

Definition at line 2110 of file clauses.c.

Function Documentation

◆ add_function_defaults()

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

Definition at line 4129 of file clauses.c.

4130 {
4131  int nargsprovided = list_length(args);
4132  List *defaults;
4133  int ndelete;
4134 
4135  /* Get all the default expressions from the pg_proc tuple */
4136  defaults = fetch_function_defaults(func_tuple);
4137 
4138  /* Delete any unused defaults from the list */
4139  ndelete = nargsprovided + list_length(defaults) - pronargs;
4140  if (ndelete < 0)
4141  elog(ERROR, "not enough default arguments");
4142  if (ndelete > 0)
4143  defaults = list_delete_first_n(defaults, ndelete);
4144 
4145  /* And form the combined argument list, not modifying the input list */
4146  return list_concat_copy(args, defaults);
4147 }
static List * fetch_function_defaults(HeapTuple func_tuple)
Definition: clauses.c:4153
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
List * list_delete_first_n(List *list, int n)
Definition: list.c:942
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:577
static int list_length(const List *l)
Definition: pg_list.h:149
int16 pronargs
Definition: pg_proc.h:81
Definition: pg_list.h:51

References generate_unaccent_rules::args, elog, ERROR, fetch_function_defaults(), list_concat_copy(), list_delete_first_n(), list_length(), and pronargs.

Referenced by expand_function_arguments().

◆ CommuteOpExpr()

void CommuteOpExpr ( OpExpr clause)

Definition at line 1988 of file clauses.c.

1989 {
1990  Oid opoid;
1991  Node *temp;
1992 
1993  /* Sanity checks: caller is at fault if these fail */
1994  if (!is_opclause(clause) ||
1995  list_length(clause->args) != 2)
1996  elog(ERROR, "cannot commute non-binary-operator clause");
1997 
1998  opoid = get_commutator(clause->opno);
1999 
2000  if (!OidIsValid(opoid))
2001  elog(ERROR, "could not find commutator for operator %u",
2002  clause->opno);
2003 
2004  /*
2005  * modify the clause in-place!
2006  */
2007  clause->opno = opoid;
2008  clause->opfuncid = InvalidOid;
2009  /* opresulttype, opretset, opcollid, inputcollid need not change */
2010 
2011  temp = linitial(clause->args);
2012  linitial(clause->args) = lsecond(clause->args);
2013  lsecond(clause->args) = temp;
2014 }
#define OidIsValid(objectId)
Definition: c.h:710
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1480
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:64
#define linitial(l)
Definition: pg_list.h:174
#define lsecond(l)
Definition: pg_list.h:179
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
Oid opno
Definition: primnodes.h:542
List * args
Definition: primnodes.h:548
Oid opfuncid
Definition: primnodes.h:543

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

◆ contain_agg_clause()

bool contain_agg_clause ( Node clause)

Definition at line 176 of file clauses.c.

177 {
178  return contain_agg_clause_walker(clause, NULL);
179 }
static bool contain_agg_clause_walker(Node *node, void *context)
Definition: clauses.c:182

References contain_agg_clause_walker().

Referenced by get_eclass_for_sort_expr(), and subquery_planner().

◆ contain_agg_clause_walker()

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

Definition at line 182 of file clauses.c.

183 {
184  if (node == NULL)
185  return false;
186  if (IsA(node, Aggref))
187  {
188  Assert(((Aggref *) node)->agglevelsup == 0);
189  return true; /* abort the tree traversal and return true */
190  }
191  if (IsA(node, GroupingFunc))
192  {
193  Assert(((GroupingFunc *) node)->agglevelsup == 0);
194  return true; /* abort the tree traversal and return true */
195  }
196  Assert(!IsA(node, SubLink));
197  return expression_tree_walker(node, contain_agg_clause_walker, context);
198 }
Assert(fmt[strlen(fmt) - 1] !='\n')
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1904
#define IsA(nodeptr, _type_)
Definition: nodes.h:589

References Assert(), expression_tree_walker(), and IsA.

Referenced by contain_agg_clause().

◆ contain_context_dependent_node()

static bool contain_context_dependent_node ( Node clause)
static

Definition at line 1066 of file clauses.c.

1067 {
1068  int flags = 0;
1069 
1070  return contain_context_dependent_node_walker(clause, &flags);
1071 }
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:1076

References contain_context_dependent_node_walker().

Referenced by inline_function().

◆ contain_context_dependent_node_walker()

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

Definition at line 1076 of file clauses.c.

1077 {
1078  if (node == NULL)
1079  return false;
1080  if (IsA(node, CaseTestExpr))
1081  return !(*flags & CCDN_CASETESTEXPR_OK);
1082  else if (IsA(node, CaseExpr))
1083  {
1084  CaseExpr *caseexpr = (CaseExpr *) node;
1085 
1086  /*
1087  * If this CASE doesn't have a test expression, then it doesn't create
1088  * a context in which CaseTestExprs should appear, so just fall
1089  * through and treat it as a generic expression node.
1090  */
1091  if (caseexpr->arg)
1092  {
1093  int save_flags = *flags;
1094  bool res;
1095 
1096  /*
1097  * Note: in principle, we could distinguish the various sub-parts
1098  * of a CASE construct and set the flag bit only for some of them,
1099  * since we are only expecting CaseTestExprs to appear in the
1100  * "expr" subtree of the CaseWhen nodes. But it doesn't really
1101  * seem worth any extra code. If there are any bare CaseTestExprs
1102  * elsewhere in the CASE, something's wrong already.
1103  */
1104  *flags |= CCDN_CASETESTEXPR_OK;
1105  res = expression_tree_walker(node,
1107  (void *) flags);
1108  *flags = save_flags;
1109  return res;
1110  }
1111  }
1112  else if (IsA(node, ArrayCoerceExpr))
1113  {
1114  ArrayCoerceExpr *ac = (ArrayCoerceExpr *) node;
1115  int save_flags;
1116  bool res;
1117 
1118  /* Check the array expression */
1119  if (contain_context_dependent_node_walker((Node *) ac->arg, flags))
1120  return true;
1121 
1122  /* Check the elemexpr, which is allowed to contain CaseTestExpr */
1123  save_flags = *flags;
1124  *flags |= CCDN_CASETESTEXPR_OK;
1126  flags);
1127  *flags = save_flags;
1128  return res;
1129  }
1131  (void *) flags);
1132 }
#define CCDN_CASETESTEXPR_OK
Definition: clauses.c:1073
Expr * elemexpr
Definition: primnodes.h:905
Expr * arg
Definition: primnodes.h:978

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

Referenced by contain_context_dependent_node().

◆ contain_exec_param()

bool contain_exec_param ( Node clause,
List param_ids 
)

Definition at line 1024 of file clauses.c.

1025 {
1026  return contain_exec_param_walker(clause, param_ids);
1027 }
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition: clauses.c:1030

References contain_exec_param_walker().

Referenced by test_opexpr_is_hashable().

◆ contain_exec_param_walker()

static bool contain_exec_param_walker ( Node node,
List param_ids 
)
static

Definition at line 1030 of file clauses.c.

1031 {
1032  if (node == NULL)
1033  return false;
1034  if (IsA(node, Param))
1035  {
1036  Param *p = (Param *) node;
1037 
1038  if (p->paramkind == PARAM_EXEC &&
1039  list_member_int(param_ids, p->paramid))
1040  return true;
1041  }
1042  return expression_tree_walker(node, contain_exec_param_walker, param_ids);
1043 }
bool list_member_int(const List *list, int datum)
Definition: list.c:681
@ PARAM_EXEC
Definition: primnodes.h:259
int paramid
Definition: primnodes.h:268
ParamKind paramkind
Definition: primnodes.h:267

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

Referenced by contain_exec_param().

◆ contain_leaked_vars()

bool contain_leaked_vars ( Node clause)

Definition at line 1150 of file clauses.c.

1151 {
1152  return contain_leaked_vars_walker(clause, NULL);
1153 }
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1162

References contain_leaked_vars_walker().

Referenced by make_restrictinfo_internal(), and qual_is_pushdown_safe().

◆ contain_leaked_vars_checker()

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

Definition at line 1156 of file clauses.c.

1157 {
1158  return !get_func_leakproof(func_id);
1159 }
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1808

References get_func_leakproof().

Referenced by contain_leaked_vars_walker().

◆ contain_leaked_vars_walker()

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

Definition at line 1162 of file clauses.c.

1163 {
1164  if (node == NULL)
1165  return false;
1166 
1167  switch (nodeTag(node))
1168  {
1169  case T_Var:
1170  case T_Const:
1171  case T_Param:
1172  case T_ArrayExpr:
1173  case T_FieldSelect:
1174  case T_FieldStore:
1175  case T_NamedArgExpr:
1176  case T_BoolExpr:
1177  case T_RelabelType:
1178  case T_CollateExpr:
1179  case T_CaseExpr:
1180  case T_CaseTestExpr:
1181  case T_RowExpr:
1182  case T_SQLValueFunction:
1183  case T_NullTest:
1184  case T_BooleanTest:
1185  case T_NextValueExpr:
1186  case T_List:
1187 
1188  /*
1189  * We know these node types don't contain function calls; but
1190  * something further down in the node tree might.
1191  */
1192  break;
1193 
1194  case T_FuncExpr:
1195  case T_OpExpr:
1196  case T_DistinctExpr:
1197  case T_NullIfExpr:
1198  case T_ScalarArrayOpExpr:
1199  case T_CoerceViaIO:
1200  case T_ArrayCoerceExpr:
1201 
1202  /*
1203  * If node contains a leaky function call, and there's any Var
1204  * underneath it, reject.
1205  */
1207  context) &&
1208  contain_var_clause(node))
1209  return true;
1210  break;
1211 
1212  case T_SubscriptingRef:
1213  {
1214  SubscriptingRef *sbsref = (SubscriptingRef *) node;
1215  const SubscriptRoutines *sbsroutines;
1216 
1217  /* Consult the subscripting support method info */
1218  sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype,
1219  NULL);
1220  if (!sbsroutines ||
1221  !(sbsref->refassgnexpr != NULL ?
1222  sbsroutines->store_leakproof :
1223  sbsroutines->fetch_leakproof))
1224  {
1225  /* Node is leaky, so reject if it contains Vars */
1226  if (contain_var_clause(node))
1227  return true;
1228  }
1229  }
1230  break;
1231 
1232  case T_RowCompareExpr:
1233  {
1234  /*
1235  * It's worth special-casing this because a leaky comparison
1236  * function only compromises one pair of row elements, which
1237  * might not contain Vars while others do.
1238  */
1239  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1240  ListCell *opid;
1241  ListCell *larg;
1242  ListCell *rarg;
1243 
1244  forthree(opid, rcexpr->opnos,
1245  larg, rcexpr->largs,
1246  rarg, rcexpr->rargs)
1247  {
1248  Oid funcid = get_opcode(lfirst_oid(opid));
1249 
1250  if (!get_func_leakproof(funcid) &&
1251  (contain_var_clause((Node *) lfirst(larg)) ||
1252  contain_var_clause((Node *) lfirst(rarg))))
1253  return true;
1254  }
1255  }
1256  break;
1257 
1258  case T_MinMaxExpr:
1259  {
1260  /*
1261  * MinMaxExpr is leakproof if the comparison function it calls
1262  * is leakproof.
1263  */
1264  MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
1265  TypeCacheEntry *typentry;
1266  bool leakproof;
1267 
1268  /* Look up the btree comparison function for the datatype */
1269  typentry = lookup_type_cache(minmaxexpr->minmaxtype,
1271  if (OidIsValid(typentry->cmp_proc))
1272  leakproof = get_func_leakproof(typentry->cmp_proc);
1273  else
1274  {
1275  /*
1276  * The executor will throw an error, but here we just
1277  * treat the missing function as leaky.
1278  */
1279  leakproof = false;
1280  }
1281 
1282  if (!leakproof &&
1283  contain_var_clause((Node *) minmaxexpr->args))
1284  return true;
1285  }
1286  break;
1287 
1288  case T_CurrentOfExpr:
1289 
1290  /*
1291  * WHERE CURRENT OF doesn't contain leaky function calls.
1292  * Moreover, it is essential that this is considered non-leaky,
1293  * since the planner must always generate a TID scan when CURRENT
1294  * OF is present -- cf. cost_tidscan.
1295  */
1296  return false;
1297 
1298  default:
1299 
1300  /*
1301  * If we don't recognize the node tag, assume it might be leaky.
1302  * This prevents an unexpected security hole if someone adds a new
1303  * node type that can call a function.
1304  */
1305  return true;
1306  }
1308  context);
1309 }
static bool contain_leaked_vars_checker(Oid func_id, void *context)
Definition: clauses.c:1156
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1256
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition: lsyscache.c:3077
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1721
#define nodeTag(nodeptr)
Definition: nodes.h:543
@ T_FieldStore
Definition: nodes.h:174
@ T_List
Definition: nodes.h:302
@ T_FieldSelect
Definition: nodes.h:173
@ T_ArrayExpr
Definition: nodes.h:183
@ T_CollateExpr
Definition: nodes.h:179
@ T_BoolExpr
Definition: nodes.h:169
@ T_OpExpr
Definition: nodes.h:165
@ T_ScalarArrayOpExpr
Definition: nodes.h:168
@ T_CaseExpr
Definition: nodes.h:180
@ T_RelabelType
Definition: nodes.h:175
@ T_RowExpr
Definition: nodes.h:184
@ T_ArrayCoerceExpr
Definition: nodes.h:177
@ T_MinMaxExpr
Definition: nodes.h:187
@ T_CurrentOfExpr
Definition: nodes.h:195
@ T_BooleanTest
Definition: nodes.h:191
@ T_SQLValueFunction
Definition: nodes.h:188
@ T_NamedArgExpr
Definition: nodes.h:164
@ T_Const
Definition: nodes.h:157
@ T_CoerceViaIO
Definition: nodes.h:176
@ T_NextValueExpr
Definition: nodes.h:196
@ T_Param
Definition: nodes.h:158
@ T_DistinctExpr
Definition: nodes.h:166
@ T_FuncExpr
Definition: nodes.h:163
@ T_Var
Definition: nodes.h:156
@ T_RowCompareExpr
Definition: nodes.h:185
@ T_CaseTestExpr
Definition: nodes.h:182
@ T_NullTest
Definition: nodes.h:190
@ T_SubscriptingRef
Definition: nodes.h:162
@ T_NullIfExpr
Definition: nodes.h:167
#define lfirst(lc)
Definition: pg_list.h:169
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:491
#define lfirst_oid(lc)
Definition: pg_list.h:171
List * args
Definition: primnodes.h:1152
Oid minmaxtype
Definition: primnodes.h:1148
Expr * refassgnexpr
Definition: primnodes.h:451
Oid refcontainertype
Definition: primnodes.h:439
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
#define TYPECACHE_CMP_PROC
Definition: typcache.h:139
bool contain_var_clause(Node *node)
Definition: var.c:400

References MinMaxExpr::args, check_functions_in_node(), TypeCacheEntry::cmp_proc, contain_leaked_vars_checker(), contain_var_clause(), expression_tree_walker(), SubscriptRoutines::fetch_leakproof, forthree, get_func_leakproof(), get_opcode(), getSubscriptingRoutines(), RowCompareExpr::largs, lfirst, lfirst_oid, lookup_type_cache(), MinMaxExpr::minmaxtype, nodeTag, OidIsValid, RowCompareExpr::opnos, RowCompareExpr::rargs, SubscriptingRef::refassgnexpr, SubscriptingRef::refcontainertype, SubscriptRoutines::store_leakproof, 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().

◆ contain_mutable_functions()

◆ contain_mutable_functions_checker()

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

Definition at line 370 of file clauses.c.

371 {
372  return (func_volatile(func_id) != PROVOLATILE_IMMUTABLE);
373 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1751

References func_volatile().

Referenced by contain_mutable_functions_walker().

◆ contain_mutable_functions_walker()

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

Definition at line 376 of file clauses.c.

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

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

Referenced by contain_mutable_functions().

◆ contain_non_const_walker()

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

Definition at line 3539 of file clauses.c.

3540 {
3541  if (node == NULL)
3542  return false;
3543  if (IsA(node, Const))
3544  return false;
3545  if (IsA(node, List))
3546  return expression_tree_walker(node, contain_non_const_walker, context);
3547  /* Otherwise, abort the tree traversal and return true */
3548  return true;
3549 }
static bool contain_non_const_walker(Node *node, void *context)
Definition: clauses.c:3539

References expression_tree_walker(), and IsA.

◆ contain_nonstrict_functions()

bool contain_nonstrict_functions ( Node clause)

Definition at line 880 of file clauses.c.

881 {
882  return contain_nonstrict_functions_walker(clause, NULL);
883 }
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:892

References contain_nonstrict_functions_walker().

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

◆ contain_nonstrict_functions_checker()

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

Definition at line 886 of file clauses.c.

887 {
888  return !func_strict(func_id);
889 }
bool func_strict(Oid funcid)
Definition: lsyscache.c:1732

References func_strict().

Referenced by contain_nonstrict_functions_walker().

◆ contain_nonstrict_functions_walker()

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

Definition at line 892 of file clauses.c.

893 {
894  if (node == NULL)
895  return false;
896  if (IsA(node, Aggref))
897  {
898  /* an aggregate could return non-null with null input */
899  return true;
900  }
901  if (IsA(node, GroupingFunc))
902  {
903  /*
904  * A GroupingFunc doesn't evaluate its arguments, and therefore must
905  * be treated as nonstrict.
906  */
907  return true;
908  }
909  if (IsA(node, WindowFunc))
910  {
911  /* a window function could return non-null with null input */
912  return true;
913  }
914  if (IsA(node, SubscriptingRef))
915  {
916  SubscriptingRef *sbsref = (SubscriptingRef *) node;
917  const SubscriptRoutines *sbsroutines;
918 
919  /* Subscripting assignment is always presumed nonstrict */
920  if (sbsref->refassgnexpr != NULL)
921  return true;
922  /* Otherwise we must look up the subscripting support methods */
923  sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
924  if (!(sbsroutines && sbsroutines->fetch_strict))
925  return true;
926  /* else fall through to check args */
927  }
928  if (IsA(node, DistinctExpr))
929  {
930  /* IS DISTINCT FROM is inherently non-strict */
931  return true;
932  }
933  if (IsA(node, NullIfExpr))
934  {
935  /* NULLIF is inherently non-strict */
936  return true;
937  }
938  if (IsA(node, BoolExpr))
939  {
940  BoolExpr *expr = (BoolExpr *) node;
941 
942  switch (expr->boolop)
943  {
944  case AND_EXPR:
945  case OR_EXPR:
946  /* AND, OR are inherently non-strict */
947  return true;
948  default:
949  break;
950  }
951  }
952  if (IsA(node, SubLink))
953  {
954  /* In some cases a sublink might be strict, but in general not */
955  return true;
956  }
957  if (IsA(node, SubPlan))
958  return true;
959  if (IsA(node, AlternativeSubPlan))
960  return true;
961  if (IsA(node, FieldStore))
962  return true;
963  if (IsA(node, CoerceViaIO))
964  {
965  /*
966  * CoerceViaIO is strict regardless of whether the I/O functions are,
967  * so just go look at its argument; asking check_functions_in_node is
968  * useless expense and could deliver the wrong answer.
969  */
971  context);
972  }
973  if (IsA(node, ArrayCoerceExpr))
974  {
975  /*
976  * ArrayCoerceExpr is strict at the array level, regardless of what
977  * the per-element expression is; so we should ignore elemexpr and
978  * recurse only into the arg.
979  */
981  context);
982  }
983  if (IsA(node, CaseExpr))
984  return true;
985  if (IsA(node, ArrayExpr))
986  return true;
987  if (IsA(node, RowExpr))
988  return true;
989  if (IsA(node, RowCompareExpr))
990  return true;
991  if (IsA(node, CoalesceExpr))
992  return true;
993  if (IsA(node, MinMaxExpr))
994  return true;
995  if (IsA(node, XmlExpr))
996  return true;
997  if (IsA(node, NullTest))
998  return true;
999  if (IsA(node, BooleanTest))
1000  return true;
1001 
1002  /* Check other function-containing nodes */
1004  context))
1005  return true;
1006 
1008  context);
1009 }
static bool contain_nonstrict_functions_checker(Oid func_id, void *context)
Definition: clauses.c:886
void * arg
@ AND_EXPR
Definition: primnodes.h:619
@ OR_EXPR
Definition: primnodes.h:619
BoolExprType boolop
Definition: primnodes.h:625

References AND_EXPR, arg, BoolExpr::boolop, check_functions_in_node(), contain_nonstrict_functions_checker(), expression_tree_walker(), SubscriptRoutines::fetch_strict, getSubscriptingRoutines(), IsA, OR_EXPR, SubscriptingRef::refassgnexpr, and SubscriptingRef::refcontainertype.

Referenced by contain_nonstrict_functions().

◆ contain_subplans()

bool contain_subplans ( Node clause)

Definition at line 329 of file clauses.c.

330 {
331  return contain_subplans_walker(clause, NULL);
332 }
static bool contain_subplans_walker(Node *node, void *context)
Definition: clauses.c:335

References contain_subplans_walker().

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

◆ contain_subplans_walker()

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

Definition at line 335 of file clauses.c.

336 {
337  if (node == NULL)
338  return false;
339  if (IsA(node, SubPlan) ||
340  IsA(node, AlternativeSubPlan) ||
341  IsA(node, SubLink))
342  return true; /* abort the tree traversal and return true */
343  return expression_tree_walker(node, contain_subplans_walker, context);
344 }

References expression_tree_walker(), and IsA.

Referenced by contain_subplans().

◆ contain_volatile_functions()

◆ contain_volatile_functions_checker()

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

Definition at line 459 of file clauses.c.

460 {
461  return (func_volatile(func_id) == PROVOLATILE_VOLATILE);
462 }

References func_volatile().

Referenced by contain_volatile_functions_walker().

◆ contain_volatile_functions_not_nextval()

bool contain_volatile_functions_not_nextval ( Node clause)

Definition at line 560 of file clauses.c.

561 {
563 }
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:573

References contain_volatile_functions_not_nextval_walker().

Referenced by BeginCopyFrom().

◆ contain_volatile_functions_not_nextval_checker()

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

Definition at line 566 of file clauses.c.

567 {
568  return (func_id != F_NEXTVAL &&
569  func_volatile(func_id) == PROVOLATILE_VOLATILE);
570 }

References func_volatile().

Referenced by contain_volatile_functions_not_nextval_walker().

◆ contain_volatile_functions_not_nextval_walker()

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

Definition at line 573 of file clauses.c.

574 {
575  if (node == NULL)
576  return false;
577  /* Check for volatile functions in node itself */
578  if (check_functions_in_node(node,
580  context))
581  return true;
582 
583  /*
584  * See notes in contain_mutable_functions_walker about why we treat
585  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
586  * SQLValueFunction is stable. Hence, none of them are of interest here.
587  * Also, since we're intentionally ignoring nextval(), presumably we
588  * should ignore NextValueExpr.
589  */
590 
591  /* Recurse to check arguments */
592  if (IsA(node, Query))
593  {
594  /* Recurse into subselects */
595  return query_tree_walker((Query *) node,
597  context, 0);
598  }
599  return expression_tree_walker(node,
601  context);
602 }
static bool contain_volatile_functions_not_nextval_checker(Oid func_id, void *context)
Definition: clauses.c:566

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

◆ contain_volatile_functions_walker()

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

Definition at line 465 of file clauses.c.

466 {
467  if (node == NULL)
468  return false;
469  /* Check for volatile functions in node itself */
471  context))
472  return true;
473 
474  if (IsA(node, NextValueExpr))
475  {
476  /* NextValueExpr is volatile */
477  return true;
478  }
479 
480  if (IsA(node, RestrictInfo))
481  {
482  RestrictInfo *rinfo = (RestrictInfo *) node;
483 
484  /*
485  * For RestrictInfo, check if we've checked the volatility of it
486  * before. If so, we can just use the cached value and not bother
487  * checking it again. Otherwise, check it and cache if whether we
488  * found any volatile functions.
489  */
490  if (rinfo->has_volatile == VOLATILITY_NOVOLATILE)
491  return false;
492  else if (rinfo->has_volatile == VOLATILITY_VOLATILE)
493  return true;
494  else
495  {
496  bool hasvolatile;
497 
498  hasvolatile = contain_volatile_functions_walker((Node *) rinfo->clause,
499  context);
500  if (hasvolatile)
502  else
504 
505  return hasvolatile;
506  }
507  }
508 
509  if (IsA(node, PathTarget))
510  {
511  PathTarget *target = (PathTarget *) node;
512 
513  /*
514  * We also do caching for PathTarget the same as we do above for
515  * RestrictInfos.
516  */
518  return false;
519  else if (target->has_volatile_expr == VOLATILITY_VOLATILE)
520  return true;
521  else
522  {
523  bool hasvolatile;
524 
525  hasvolatile = contain_volatile_functions_walker((Node *) target->exprs,
526  context);
527 
528  if (hasvolatile)
530  else
532 
533  return hasvolatile;
534  }
535  }
536 
537  /*
538  * See notes in contain_mutable_functions_walker about why we treat
539  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
540  * SQLValueFunction is stable. Hence, none of them are of interest here.
541  */
542 
543  /* Recurse to check arguments */
544  if (IsA(node, Query))
545  {
546  /* Recurse into subselects */
547  return query_tree_walker((Query *) node,
549  context, 0);
550  }
552  context);
553 }
static bool contain_volatile_functions_checker(Oid func_id, void *context)
Definition: clauses.c:459
@ VOLATILITY_NOVOLATILE
Definition: pathnodes.h:1082
@ VOLATILITY_VOLATILE
Definition: pathnodes.h:1081
VolatileFunctionStatus has_volatile_expr
Definition: pathnodes.h:1115
List * exprs
Definition: pathnodes.h:1111
VolatileFunctionStatus has_volatile
Definition: pathnodes.h:2071
Expr * clause
Definition: pathnodes.h:2059

References check_functions_in_node(), RestrictInfo::clause, contain_volatile_functions_checker(), expression_tree_walker(), PathTarget::exprs, RestrictInfo::has_volatile, PathTarget::has_volatile_expr, IsA, query_tree_walker(), VOLATILITY_NOVOLATILE, and VOLATILITY_VOLATILE.

Referenced by contain_volatile_functions().

◆ contain_window_function()

bool contain_window_function ( Node clause)

Definition at line 213 of file clauses.c.

214 {
215  return contain_windowfuncs(clause);
216 }
bool contain_windowfuncs(Node *node)
Definition: rewriteManip.c:197

References contain_windowfuncs().

Referenced by get_eclass_for_sort_expr(), and qual_is_pushdown_safe().

◆ convert_saop_to_hashed_saop()

void convert_saop_to_hashed_saop ( Node node)

Definition at line 2127 of file clauses.c.

2128 {
2129  (void) convert_saop_to_hashed_saop_walker(node, NULL);
2130 }
static bool convert_saop_to_hashed_saop_walker(Node *node, void *context)
Definition: clauses.c:2133

References convert_saop_to_hashed_saop_walker().

Referenced by preprocess_expression().

◆ convert_saop_to_hashed_saop_walker()

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

Definition at line 2133 of file clauses.c.

2134 {
2135  if (node == NULL)
2136  return false;
2137 
2138  if (IsA(node, ScalarArrayOpExpr))
2139  {
2140  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) node;
2141  Expr *arrayarg = (Expr *) lsecond(saop->args);
2142  Oid lefthashfunc;
2143  Oid righthashfunc;
2144 
2145  if (arrayarg && IsA(arrayarg, Const) &&
2146  !((Const *) arrayarg)->constisnull)
2147  {
2148  if (saop->useOr)
2149  {
2150  if (get_op_hash_functions(saop->opno, &lefthashfunc, &righthashfunc) &&
2151  lefthashfunc == righthashfunc)
2152  {
2153  Datum arrdatum = ((Const *) arrayarg)->constvalue;
2154  ArrayType *arr = (ArrayType *) DatumGetPointer(arrdatum);
2155  int nitems;
2156 
2157  /*
2158  * Only fill in the hash functions if the array looks
2159  * large enough for it to be worth hashing instead of
2160  * doing a linear search.
2161  */
2162  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
2163 
2164  if (nitems >= MIN_ARRAY_SIZE_FOR_HASHED_SAOP)
2165  {
2166  /* Looks good. Fill in the hash functions */
2167  saop->hashfuncid = lefthashfunc;
2168  }
2169  return true;
2170  }
2171  }
2172  else /* !saop->useOr */
2173  {
2174  Oid negator = get_negator(saop->opno);
2175 
2176  /*
2177  * Check if this is a NOT IN using an operator whose negator
2178  * is hashable. If so we can still build a hash table and
2179  * just ensure the lookup items are not in the hash table.
2180  */
2181  if (OidIsValid(negator) &&
2182  get_op_hash_functions(negator, &lefthashfunc, &righthashfunc) &&
2183  lefthashfunc == righthashfunc)
2184  {
2185  Datum arrdatum = ((Const *) arrayarg)->constvalue;
2186  ArrayType *arr = (ArrayType *) DatumGetPointer(arrdatum);
2187  int nitems;
2188 
2189  /*
2190  * Only fill in the hash functions if the array looks
2191  * large enough for it to be worth hashing instead of
2192  * doing a linear search.
2193  */
2194  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
2195 
2196  if (nitems >= MIN_ARRAY_SIZE_FOR_HASHED_SAOP)
2197  {
2198  /* Looks good. Fill in the hash functions */
2199  saop->hashfuncid = lefthashfunc;
2200 
2201  /*
2202  * Also set the negfuncid. The executor will need
2203  * that to perform hashtable lookups.
2204  */
2205  saop->negfuncid = get_opcode(negator);
2206  }
2207  return true;
2208  }
2209  }
2210  }
2211  }
2212 
2214 }
#define ARR_NDIM(a)
Definition: array.h:283
#define ARR_DIMS(a)
Definition: array.h:287
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
#define MIN_ARRAY_SIZE_FOR_HASHED_SAOP
Definition: clauses.c:2110
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition: lsyscache.c:508
Oid get_negator(Oid opno)
Definition: lsyscache.c:1504
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetPointer(X)
Definition: postgres.h:593

References ScalarArrayOpExpr::args, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), DatumGetPointer, expression_tree_walker(), get_negator(), get_op_hash_functions(), get_opcode(), ScalarArrayOpExpr::hashfuncid, IsA, lsecond, MIN_ARRAY_SIZE_FOR_HASHED_SAOP, ScalarArrayOpExpr::negfuncid, OidIsValid, ScalarArrayOpExpr::opno, and ScalarArrayOpExpr::useOr.

Referenced by convert_saop_to_hashed_saop().

◆ ece_function_is_safe()

static bool ece_function_is_safe ( Oid  funcid,
eval_const_expressions_context context 
)
static

Definition at line 3555 of file clauses.c.

3556 {
3557  char provolatile = func_volatile(funcid);
3558 
3559  /*
3560  * Ordinarily we are only allowed to simplify immutable functions. But for
3561  * purposes of estimation, we consider it okay to simplify functions that
3562  * are merely stable; the risk that the result might change from planning
3563  * time to execution time is worth taking in preference to not being able
3564  * to estimate the value at all.
3565  */
3566  if (provolatile == PROVOLATILE_IMMUTABLE)
3567  return true;
3568  if (context->estimate && provolatile == PROVOLATILE_STABLE)
3569  return true;
3570  return false;
3571 }

References eval_const_expressions_context::estimate, and func_volatile().

Referenced by eval_const_expressions_mutator().

◆ estimate_expression_value()

Node* estimate_expression_value ( PlannerInfo root,
Node node 
)

Definition at line 2235 of file clauses.c.

2236 {
2238 
2239  context.boundParams = root->glob->boundParams; /* bound Params */
2240  /* we do not need to mark the plan as depending on inlined functions */
2241  context.root = NULL;
2242  context.active_fns = NIL; /* nothing being recursively simplified */
2243  context.case_val = NULL; /* no CASE being examined */
2244  context.estimate = true; /* unsafe transformations OK */
2245  return eval_const_expressions_mutator(node, &context);
2246 }
#define NIL
Definition: pg_list.h:65
ParamListInfo boundParams
Definition: pathnodes.h:94
PlannerGlobal * glob
Definition: pathnodes.h:164
ParamListInfo boundParams
Definition: clauses.c:60

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_ext(), generate_series_int4_support(), generate_series_int8_support(), get_restriction_variable(), gincost_opexpr(), gincost_scalararrayopexpr(), preprocess_limit(), scalararraysel(), system_rows_samplescangetsamplesize(), system_samplescangetsamplesize(), and system_time_samplescangetsamplesize().

◆ eval_const_expressions()

Node* eval_const_expressions ( PlannerInfo root,
Node node 
)

◆ eval_const_expressions_mutator()

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

Definition at line 2280 of file clauses.c.

2282 {
2283  if (node == NULL)
2284  return NULL;
2285  switch (nodeTag(node))
2286  {
2287  case T_Param:
2288  {
2289  Param *param = (Param *) node;
2290  ParamListInfo paramLI = context->boundParams;
2291 
2292  /* Look to see if we've been given a value for this Param */
2293  if (param->paramkind == PARAM_EXTERN &&
2294  paramLI != NULL &&
2295  param->paramid > 0 &&
2296  param->paramid <= paramLI->numParams)
2297  {
2298  ParamExternData *prm;
2299  ParamExternData prmdata;
2300 
2301  /*
2302  * Give hook a chance in case parameter is dynamic. Tell
2303  * it that this fetch is speculative, so it should avoid
2304  * erroring out if parameter is unavailable.
2305  */
2306  if (paramLI->paramFetch != NULL)
2307  prm = paramLI->paramFetch(paramLI, param->paramid,
2308  true, &prmdata);
2309  else
2310  prm = &paramLI->params[param->paramid - 1];
2311 
2312  /*
2313  * We don't just check OidIsValid, but insist that the
2314  * fetched type match the Param, just in case the hook did
2315  * something unexpected. No need to throw an error here
2316  * though; leave that for runtime.
2317  */
2318  if (OidIsValid(prm->ptype) &&
2319  prm->ptype == param->paramtype)
2320  {
2321  /* OK to substitute parameter value? */
2322  if (context->estimate ||
2323  (prm->pflags & PARAM_FLAG_CONST))
2324  {
2325  /*
2326  * Return a Const representing the param value.
2327  * Must copy pass-by-ref datatypes, since the
2328  * Param might be in a memory context
2329  * shorter-lived than our output plan should be.
2330  */
2331  int16 typLen;
2332  bool typByVal;
2333  Datum pval;
2334  Const *con;
2335 
2336  get_typlenbyval(param->paramtype,
2337  &typLen, &typByVal);
2338  if (prm->isnull || typByVal)
2339  pval = prm->value;
2340  else
2341  pval = datumCopy(prm->value, typByVal, typLen);
2342  con = makeConst(param->paramtype,
2343  param->paramtypmod,
2344  param->paramcollid,
2345  (int) typLen,
2346  pval,
2347  prm->isnull,
2348  typByVal);
2349  con->location = param->location;
2350  return (Node *) con;
2351  }
2352  }
2353  }
2354 
2355  /*
2356  * Not replaceable, so just copy the Param (no need to
2357  * recurse)
2358  */
2359  return (Node *) copyObject(param);
2360  }
2361  case T_WindowFunc:
2362  {
2363  WindowFunc *expr = (WindowFunc *) node;
2364  Oid funcid = expr->winfnoid;
2365  List *args;
2366  Expr *aggfilter;
2367  HeapTuple func_tuple;
2368  WindowFunc *newexpr;
2369 
2370  /*
2371  * We can't really simplify a WindowFunc node, but we mustn't
2372  * just fall through to the default processing, because we
2373  * have to apply expand_function_arguments to its argument
2374  * list. That takes care of inserting default arguments and
2375  * expanding named-argument notation.
2376  */
2377  func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2378  if (!HeapTupleIsValid(func_tuple))
2379  elog(ERROR, "cache lookup failed for function %u", funcid);
2380 
2382  false, expr->wintype,
2383  func_tuple);
2384 
2385  ReleaseSysCache(func_tuple);
2386 
2387  /* Now, recursively simplify the args (which are a List) */
2388  args = (List *)
2391  (void *) context);
2392  /* ... and the filter expression, which isn't */
2393  aggfilter = (Expr *)
2395  context);
2396 
2397  /* And build the replacement WindowFunc node */
2398  newexpr = makeNode(WindowFunc);
2399  newexpr->winfnoid = expr->winfnoid;
2400  newexpr->wintype = expr->wintype;
2401  newexpr->wincollid = expr->wincollid;
2402  newexpr->inputcollid = expr->inputcollid;
2403  newexpr->args = args;
2404  newexpr->aggfilter = aggfilter;
2405  newexpr->winref = expr->winref;
2406  newexpr->winstar = expr->winstar;
2407  newexpr->winagg = expr->winagg;
2408  newexpr->location = expr->location;
2409 
2410  return (Node *) newexpr;
2411  }
2412  case T_FuncExpr:
2413  {
2414  FuncExpr *expr = (FuncExpr *) node;
2415  List *args = expr->args;
2416  Expr *simple;
2417  FuncExpr *newexpr;
2418 
2419  /*
2420  * Code for op/func reduction is pretty bulky, so split it out
2421  * as a separate function. Note: exprTypmod normally returns
2422  * -1 for a FuncExpr, but not when the node is recognizably a
2423  * length coercion; we want to preserve the typmod in the
2424  * eventual Const if so.
2425  */
2426  simple = simplify_function(expr->funcid,
2427  expr->funcresulttype,
2428  exprTypmod(node),
2429  expr->funccollid,
2430  expr->inputcollid,
2431  &args,
2432  expr->funcvariadic,
2433  true,
2434  true,
2435  context);
2436  if (simple) /* successfully simplified it */
2437  return (Node *) simple;
2438 
2439  /*
2440  * The expression cannot be simplified any further, so build
2441  * and return a replacement FuncExpr node using the
2442  * possibly-simplified arguments. Note that we have also
2443  * converted the argument list to positional notation.
2444  */
2445  newexpr = makeNode(FuncExpr);
2446  newexpr->funcid = expr->funcid;
2447  newexpr->funcresulttype = expr->funcresulttype;
2448  newexpr->funcretset = expr->funcretset;
2449  newexpr->funcvariadic = expr->funcvariadic;
2450  newexpr->funcformat = expr->funcformat;
2451  newexpr->funccollid = expr->funccollid;
2452  newexpr->inputcollid = expr->inputcollid;
2453  newexpr->args = args;
2454  newexpr->location = expr->location;
2455  return (Node *) newexpr;
2456  }
2457  case T_OpExpr:
2458  {
2459  OpExpr *expr = (OpExpr *) node;
2460  List *args = expr->args;
2461  Expr *simple;
2462  OpExpr *newexpr;
2463 
2464  /*
2465  * Need to get OID of underlying function. Okay to scribble
2466  * on input to this extent.
2467  */
2468  set_opfuncid(expr);
2469 
2470  /*
2471  * Code for op/func reduction is pretty bulky, so split it out
2472  * as a separate function.
2473  */
2474  simple = simplify_function(expr->opfuncid,
2475  expr->opresulttype, -1,
2476  expr->opcollid,
2477  expr->inputcollid,
2478  &args,
2479  false,
2480  true,
2481  true,
2482  context);
2483  if (simple) /* successfully simplified it */
2484  return (Node *) simple;
2485 
2486  /*
2487  * If the operator is boolean equality or inequality, we know
2488  * how to simplify cases involving one constant and one
2489  * non-constant argument.
2490  */
2491  if (expr->opno == BooleanEqualOperator ||
2492  expr->opno == BooleanNotEqualOperator)
2493  {
2494  simple = (Expr *) simplify_boolean_equality(expr->opno,
2495  args);
2496  if (simple) /* successfully simplified it */
2497  return (Node *) simple;
2498  }
2499 
2500  /*
2501  * The expression cannot be simplified any further, so build
2502  * and return a replacement OpExpr node using the
2503  * possibly-simplified arguments.
2504  */
2505  newexpr = makeNode(OpExpr);
2506  newexpr->opno = expr->opno;
2507  newexpr->opfuncid = expr->opfuncid;
2508  newexpr->opresulttype = expr->opresulttype;
2509  newexpr->opretset = expr->opretset;
2510  newexpr->opcollid = expr->opcollid;
2511  newexpr->inputcollid = expr->inputcollid;
2512  newexpr->args = args;
2513  newexpr->location = expr->location;
2514  return (Node *) newexpr;
2515  }
2516  case T_DistinctExpr:
2517  {
2518  DistinctExpr *expr = (DistinctExpr *) node;
2519  List *args;
2520  ListCell *arg;
2521  bool has_null_input = false;
2522  bool all_null_input = true;
2523  bool has_nonconst_input = false;
2524  Expr *simple;
2525  DistinctExpr *newexpr;
2526 
2527  /*
2528  * Reduce constants in the DistinctExpr's arguments. We know
2529  * args is either NIL or a List node, so we can call
2530  * expression_tree_mutator directly rather than recursing to
2531  * self.
2532  */
2533  args = (List *) expression_tree_mutator((Node *) expr->args,
2535  (void *) context);
2536 
2537  /*
2538  * We must do our own check for NULLs because DistinctExpr has
2539  * different results for NULL input than the underlying
2540  * operator does.
2541  */
2542  foreach(arg, args)
2543  {
2544  if (IsA(lfirst(arg), Const))
2545  {
2546  has_null_input |= ((Const *) lfirst(arg))->constisnull;
2547  all_null_input &= ((Const *) lfirst(arg))->constisnull;
2548  }
2549  else
2550  has_nonconst_input = true;
2551  }
2552 
2553  /* all constants? then can optimize this out */
2554  if (!has_nonconst_input)
2555  {
2556  /* all nulls? then not distinct */
2557  if (all_null_input)
2558  return makeBoolConst(false, false);
2559 
2560  /* one null? then distinct */
2561  if (has_null_input)
2562  return makeBoolConst(true, false);
2563 
2564  /* otherwise try to evaluate the '=' operator */
2565  /* (NOT okay to try to inline it, though!) */
2566 
2567  /*
2568  * Need to get OID of underlying function. Okay to
2569  * scribble on input to this extent.
2570  */
2571  set_opfuncid((OpExpr *) expr); /* rely on struct
2572  * equivalence */
2573 
2574  /*
2575  * Code for op/func reduction is pretty bulky, so split it
2576  * out as a separate function.
2577  */
2578  simple = simplify_function(expr->opfuncid,
2579  expr->opresulttype, -1,
2580  expr->opcollid,
2581  expr->inputcollid,
2582  &args,
2583  false,
2584  false,
2585  false,
2586  context);
2587  if (simple) /* successfully simplified it */
2588  {
2589  /*
2590  * Since the underlying operator is "=", must negate
2591  * its result
2592  */
2593  Const *csimple = castNode(Const, simple);
2594 
2595  csimple->constvalue =
2596  BoolGetDatum(!DatumGetBool(csimple->constvalue));
2597  return (Node *) csimple;
2598  }
2599  }
2600 
2601  /*
2602  * The expression cannot be simplified any further, so build
2603  * and return a replacement DistinctExpr node using the
2604  * possibly-simplified arguments.
2605  */
2606  newexpr = makeNode(DistinctExpr);
2607  newexpr->opno = expr->opno;
2608  newexpr->opfuncid = expr->opfuncid;
2609  newexpr->opresulttype = expr->opresulttype;
2610  newexpr->opretset = expr->opretset;
2611  newexpr->opcollid = expr->opcollid;
2612  newexpr->inputcollid = expr->inputcollid;
2613  newexpr->args = args;
2614  newexpr->location = expr->location;
2615  return (Node *) newexpr;
2616  }
2617  case T_NullIfExpr:
2618  {
2619  NullIfExpr *expr;
2620  ListCell *arg;
2621  bool has_nonconst_input = false;
2622 
2623  /* Copy the node and const-simplify its arguments */
2624  expr = (NullIfExpr *) ece_generic_processing(node);
2625 
2626  /* If either argument is NULL they can't be equal */
2627  foreach(arg, expr->args)
2628  {
2629  if (!IsA(lfirst(arg), Const))
2630  has_nonconst_input = true;
2631  else if (((Const *) lfirst(arg))->constisnull)
2632  return (Node *) linitial(expr->args);
2633  }
2634 
2635  /*
2636  * Need to get OID of underlying function before checking if
2637  * the function is OK to evaluate.
2638  */
2639  set_opfuncid((OpExpr *) expr);
2640 
2641  if (!has_nonconst_input &&
2642  ece_function_is_safe(expr->opfuncid, context))
2643  return ece_evaluate_expr(expr);
2644 
2645  return (Node *) expr;
2646  }
2647  case T_ScalarArrayOpExpr:
2648  {
2649  ScalarArrayOpExpr *saop;
2650 
2651  /* Copy the node and const-simplify its arguments */
2652  saop = (ScalarArrayOpExpr *) ece_generic_processing(node);
2653 
2654  /* Make sure we know underlying function */
2655  set_sa_opfuncid(saop);
2656 
2657  /*
2658  * If all arguments are Consts, and it's a safe function, we
2659  * can fold to a constant
2660  */
2661  if (ece_all_arguments_const(saop) &&
2662  ece_function_is_safe(saop->opfuncid, context))
2663  return ece_evaluate_expr(saop);
2664  return (Node *) saop;
2665  }
2666  case T_BoolExpr:
2667  {
2668  BoolExpr *expr = (BoolExpr *) node;
2669 
2670  switch (expr->boolop)
2671  {
2672  case OR_EXPR:
2673  {
2674  List *newargs;
2675  bool haveNull = false;
2676  bool forceTrue = false;
2677 
2678  newargs = simplify_or_arguments(expr->args,
2679  context,
2680  &haveNull,
2681  &forceTrue);
2682  if (forceTrue)
2683  return makeBoolConst(true, false);
2684  if (haveNull)
2685  newargs = lappend(newargs,
2686  makeBoolConst(false, true));
2687  /* If all the inputs are FALSE, result is FALSE */
2688  if (newargs == NIL)
2689  return makeBoolConst(false, false);
2690 
2691  /*
2692  * If only one nonconst-or-NULL input, it's the
2693  * result
2694  */
2695  if (list_length(newargs) == 1)
2696  return (Node *) linitial(newargs);
2697  /* Else we still need an OR node */
2698  return (Node *) make_orclause(newargs);
2699  }
2700  case AND_EXPR:
2701  {
2702  List *newargs;
2703  bool haveNull = false;
2704  bool forceFalse = false;
2705 
2706  newargs = simplify_and_arguments(expr->args,
2707  context,
2708  &haveNull,
2709  &forceFalse);
2710  if (forceFalse)
2711  return makeBoolConst(false, false);
2712  if (haveNull)
2713  newargs = lappend(newargs,
2714  makeBoolConst(false, true));
2715  /* If all the inputs are TRUE, result is TRUE */
2716  if (newargs == NIL)
2717  return makeBoolConst(true, false);
2718 
2719  /*
2720  * If only one nonconst-or-NULL input, it's the
2721  * result
2722  */
2723  if (list_length(newargs) == 1)
2724  return (Node *) linitial(newargs);
2725  /* Else we still need an AND node */
2726  return (Node *) make_andclause(newargs);
2727  }
2728  case NOT_EXPR:
2729  {
2730  Node *arg;
2731 
2732  Assert(list_length(expr->args) == 1);
2734  context);
2735 
2736  /*
2737  * Use negate_clause() to see if we can simplify
2738  * away the NOT.
2739  */
2740  return negate_clause(arg);
2741  }
2742  default:
2743  elog(ERROR, "unrecognized boolop: %d",
2744  (int) expr->boolop);
2745  break;
2746  }
2747  break;
2748  }
2749  case T_SubPlan:
2750  case T_AlternativeSubPlan:
2751 
2752  /*
2753  * Return a SubPlan unchanged --- too late to do anything with it.
2754  *
2755  * XXX should we ereport() here instead? Probably this routine
2756  * should never be invoked after SubPlan creation.
2757  */
2758  return node;
2759  case T_RelabelType:
2760  {
2761  RelabelType *relabel = (RelabelType *) node;
2762  Node *arg;
2763 
2764  /* Simplify the input ... */
2765  arg = eval_const_expressions_mutator((Node *) relabel->arg,
2766  context);
2767  /* ... and attach a new RelabelType node, if needed */
2768  return applyRelabelType(arg,
2769  relabel->resulttype,
2770  relabel->resulttypmod,
2771  relabel->resultcollid,
2772  relabel->relabelformat,
2773  relabel->location,
2774  true);
2775  }
2776  case T_CoerceViaIO:
2777  {
2778  CoerceViaIO *expr = (CoerceViaIO *) node;
2779  List *args;
2780  Oid outfunc;
2781  bool outtypisvarlena;
2782  Oid infunc;
2783  Oid intypioparam;
2784  Expr *simple;
2785  CoerceViaIO *newexpr;
2786 
2787  /* Make a List so we can use simplify_function */
2788  args = list_make1(expr->arg);
2789 
2790  /*
2791  * CoerceViaIO represents calling the source type's output
2792  * function then the result type's input function. So, try to
2793  * simplify it as though it were a stack of two such function
2794  * calls. First we need to know what the functions are.
2795  *
2796  * Note that the coercion functions are assumed not to care
2797  * about input collation, so we just pass InvalidOid for that.
2798  */
2799  getTypeOutputInfo(exprType((Node *) expr->arg),
2800  &outfunc, &outtypisvarlena);
2802  &infunc, &intypioparam);
2803 
2804  simple = simplify_function(outfunc,
2805  CSTRINGOID, -1,
2806  InvalidOid,
2807  InvalidOid,
2808  &args,
2809  false,
2810  true,
2811  true,
2812  context);
2813  if (simple) /* successfully simplified output fn */
2814  {
2815  /*
2816  * Input functions may want 1 to 3 arguments. We always
2817  * supply all three, trusting that nothing downstream will
2818  * complain.
2819  */
2820  args = list_make3(simple,
2821  makeConst(OIDOID,
2822  -1,
2823  InvalidOid,
2824  sizeof(Oid),
2825  ObjectIdGetDatum(intypioparam),
2826  false,
2827  true),
2828  makeConst(INT4OID,
2829  -1,
2830  InvalidOid,
2831  sizeof(int32),
2832  Int32GetDatum(-1),
2833  false,
2834  true));
2835 
2836  simple = simplify_function(infunc,
2837  expr->resulttype, -1,
2838  expr->resultcollid,
2839  InvalidOid,
2840  &args,
2841  false,
2842  false,
2843  true,
2844  context);
2845  if (simple) /* successfully simplified input fn */
2846  return (Node *) simple;
2847  }
2848 
2849  /*
2850  * The expression cannot be simplified any further, so build
2851  * and return a replacement CoerceViaIO node using the
2852  * possibly-simplified argument.
2853  */
2854  newexpr = makeNode(CoerceViaIO);
2855  newexpr->arg = (Expr *) linitial(args);
2856  newexpr->resulttype = expr->resulttype;
2857  newexpr->resultcollid = expr->resultcollid;
2858  newexpr->coerceformat = expr->coerceformat;
2859  newexpr->location = expr->location;
2860  return (Node *) newexpr;
2861  }
2862  case T_ArrayCoerceExpr:
2863  {
2865  Node *save_case_val;
2866 
2867  /*
2868  * Copy the node and const-simplify its arguments. We can't
2869  * use ece_generic_processing() here because we need to mess
2870  * with case_val only while processing the elemexpr.
2871  */
2872  memcpy(ac, node, sizeof(ArrayCoerceExpr));
2873  ac->arg = (Expr *)
2875  context);
2876 
2877  /*
2878  * Set up for the CaseTestExpr node contained in the elemexpr.
2879  * We must prevent it from absorbing any outer CASE value.
2880  */
2881  save_case_val = context->case_val;
2882  context->case_val = NULL;
2883 
2884  ac->elemexpr = (Expr *)
2886  context);
2887 
2888  context->case_val = save_case_val;
2889 
2890  /*
2891  * If constant argument and the per-element expression is
2892  * immutable, we can simplify the whole thing to a constant.
2893  * Exception: although contain_mutable_functions considers
2894  * CoerceToDomain immutable for historical reasons, let's not
2895  * do so here; this ensures coercion to an array-over-domain
2896  * does not apply the domain's constraints until runtime.
2897  */
2898  if (ac->arg && IsA(ac->arg, Const) &&
2899  ac->elemexpr && !IsA(ac->elemexpr, CoerceToDomain) &&
2901  return ece_evaluate_expr(ac);
2902 
2903  return (Node *) ac;
2904  }
2905  case T_CollateExpr:
2906  {
2907  /*
2908  * We replace CollateExpr with RelabelType, so as to improve
2909  * uniformity of expression representation and thus simplify
2910  * comparison of expressions. Hence this looks very nearly
2911  * the same as the RelabelType case, and we can apply the same
2912  * optimizations to avoid unnecessary RelabelTypes.
2913  */
2914  CollateExpr *collate = (CollateExpr *) node;
2915  Node *arg;
2916 
2917  /* Simplify the input ... */
2918  arg = eval_const_expressions_mutator((Node *) collate->arg,
2919  context);
2920  /* ... and attach a new RelabelType node, if needed */
2921  return applyRelabelType(arg,
2922  exprType(arg),
2923  exprTypmod(arg),
2924  collate->collOid,
2926  collate->location,
2927  true);
2928  }
2929  case T_CaseExpr:
2930  {
2931  /*----------
2932  * CASE expressions can be simplified if there are constant
2933  * condition clauses:
2934  * FALSE (or NULL): drop the alternative
2935  * TRUE: drop all remaining alternatives
2936  * If the first non-FALSE alternative is a constant TRUE,
2937  * we can simplify the entire CASE to that alternative's
2938  * expression. If there are no non-FALSE alternatives,
2939  * we simplify the entire CASE to the default result (ELSE).
2940  *
2941  * If we have a simple-form CASE with constant test
2942  * expression, we substitute the constant value for contained
2943  * CaseTestExpr placeholder nodes, so that we have the
2944  * opportunity to reduce constant test conditions. For
2945  * example this allows
2946  * CASE 0 WHEN 0 THEN 1 ELSE 1/0 END
2947  * to reduce to 1 rather than drawing a divide-by-0 error.
2948  * Note that when the test expression is constant, we don't
2949  * have to include it in the resulting CASE; for example
2950  * CASE 0 WHEN x THEN y ELSE z END
2951  * is transformed by the parser to
2952  * CASE 0 WHEN CaseTestExpr = x THEN y ELSE z END
2953  * which we can simplify to
2954  * CASE WHEN 0 = x THEN y ELSE z END
2955  * It is not necessary for the executor to evaluate the "arg"
2956  * expression when executing the CASE, since any contained
2957  * CaseTestExprs that might have referred to it will have been
2958  * replaced by the constant.
2959  *----------
2960  */
2961  CaseExpr *caseexpr = (CaseExpr *) node;
2962  CaseExpr *newcase;
2963  Node *save_case_val;
2964  Node *newarg;
2965  List *newargs;
2966  bool const_true_cond;
2967  Node *defresult = NULL;
2968  ListCell *arg;
2969 
2970  /* Simplify the test expression, if any */
2971  newarg = eval_const_expressions_mutator((Node *) caseexpr->arg,
2972  context);
2973 
2974  /* Set up for contained CaseTestExpr nodes */
2975  save_case_val = context->case_val;
2976  if (newarg && IsA(newarg, Const))
2977  {
2978  context->case_val = newarg;
2979  newarg = NULL; /* not needed anymore, see above */
2980  }
2981  else
2982  context->case_val = NULL;
2983 
2984  /* Simplify the WHEN clauses */
2985  newargs = NIL;
2986  const_true_cond = false;
2987  foreach(arg, caseexpr->args)
2988  {
2989  CaseWhen *oldcasewhen = lfirst_node(CaseWhen, arg);
2990  Node *casecond;
2991  Node *caseresult;
2992 
2993  /* Simplify this alternative's test condition */
2994  casecond = eval_const_expressions_mutator((Node *) oldcasewhen->expr,
2995  context);
2996 
2997  /*
2998  * If the test condition is constant FALSE (or NULL), then
2999  * drop this WHEN clause completely, without processing
3000  * the result.
3001  */
3002  if (casecond && IsA(casecond, Const))
3003  {
3004  Const *const_input = (Const *) casecond;
3005 
3006  if (const_input->constisnull ||
3007  !DatumGetBool(const_input->constvalue))
3008  continue; /* drop alternative with FALSE cond */
3009  /* Else it's constant TRUE */
3010  const_true_cond = true;
3011  }
3012 
3013  /* Simplify this alternative's result value */
3014  caseresult = eval_const_expressions_mutator((Node *) oldcasewhen->result,
3015  context);
3016 
3017  /* If non-constant test condition, emit a new WHEN node */
3018  if (!const_true_cond)
3019  {
3020  CaseWhen *newcasewhen = makeNode(CaseWhen);
3021 
3022  newcasewhen->expr = (Expr *) casecond;
3023  newcasewhen->result = (Expr *) caseresult;
3024  newcasewhen->location = oldcasewhen->location;
3025  newargs = lappend(newargs, newcasewhen);
3026  continue;
3027  }
3028 
3029  /*
3030  * Found a TRUE condition, so none of the remaining
3031  * alternatives can be reached. We treat the result as
3032  * the default result.
3033  */
3034  defresult = caseresult;
3035  break;
3036  }
3037 
3038  /* Simplify the default result, unless we replaced it above */
3039  if (!const_true_cond)
3040  defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult,
3041  context);
3042 
3043  context->case_val = save_case_val;
3044 
3045  /*
3046  * If no non-FALSE alternatives, CASE reduces to the default
3047  * result
3048  */
3049  if (newargs == NIL)
3050  return defresult;
3051  /* Otherwise we need a new CASE node */
3052  newcase = makeNode(CaseExpr);
3053  newcase->casetype = caseexpr->casetype;
3054  newcase->casecollid = caseexpr->casecollid;
3055  newcase->arg = (Expr *) newarg;
3056  newcase->args = newargs;
3057  newcase->defresult = (Expr *) defresult;
3058  newcase->location = caseexpr->location;
3059  return (Node *) newcase;
3060  }
3061  case T_CaseTestExpr:
3062  {
3063  /*
3064  * If we know a constant test value for the current CASE
3065  * construct, substitute it for the placeholder. Else just
3066  * return the placeholder as-is.
3067  */
3068  if (context->case_val)
3069  return copyObject(context->case_val);
3070  else
3071  return copyObject(node);
3072  }
3073  case T_SubscriptingRef:
3074  case T_ArrayExpr:
3075  case T_RowExpr:
3076  case T_MinMaxExpr:
3077  {
3078  /*
3079  * Generic handling for node types whose own processing is
3080  * known to be immutable, and for which we need no smarts
3081  * beyond "simplify if all inputs are constants".
3082  *
3083  * Treating SubscriptingRef this way assumes that subscripting
3084  * fetch and assignment are both immutable. This constrains
3085  * type-specific subscripting implementations; maybe we should
3086  * relax it someday.
3087  *
3088  * Treating MinMaxExpr this way amounts to assuming that the
3089  * btree comparison function it calls is immutable; see the
3090  * reasoning in contain_mutable_functions_walker.
3091  */
3092 
3093  /* Copy the node and const-simplify its arguments */
3094  node = ece_generic_processing(node);
3095  /* If all arguments are Consts, we can fold to a constant */
3096  if (ece_all_arguments_const(node))
3097  return ece_evaluate_expr(node);
3098  return node;
3099  }
3100  case T_CoalesceExpr:
3101  {
3102  CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
3103  CoalesceExpr *newcoalesce;
3104  List *newargs;
3105  ListCell *arg;
3106 
3107  newargs = NIL;
3108  foreach(arg, coalesceexpr->args)
3109  {
3110  Node *e;
3111 
3113  context);
3114 
3115  /*
3116  * We can remove null constants from the list. For a
3117  * non-null constant, if it has not been preceded by any
3118  * other non-null-constant expressions then it is the
3119  * result. Otherwise, it's the next argument, but we can
3120  * drop following arguments since they will never be
3121  * reached.
3122  */
3123  if (IsA(e, Const))
3124  {
3125  if (((Const *) e)->constisnull)
3126  continue; /* drop null constant */
3127  if (newargs == NIL)
3128  return e; /* first expr */
3129  newargs = lappend(newargs, e);
3130  break;
3131  }
3132  newargs = lappend(newargs, e);
3133  }
3134 
3135  /*
3136  * If all the arguments were constant null, the result is just
3137  * null
3138  */
3139  if (newargs == NIL)
3140  return (Node *) makeNullConst(coalesceexpr->coalescetype,
3141  -1,
3142  coalesceexpr->coalescecollid);
3143 
3144  newcoalesce = makeNode(CoalesceExpr);
3145  newcoalesce->coalescetype = coalesceexpr->coalescetype;
3146  newcoalesce->coalescecollid = coalesceexpr->coalescecollid;
3147  newcoalesce->args = newargs;
3148  newcoalesce->location = coalesceexpr->location;
3149  return (Node *) newcoalesce;
3150  }
3151  case T_SQLValueFunction:
3152  {
3153  /*
3154  * All variants of SQLValueFunction are stable, so if we are
3155  * estimating the expression's value, we should evaluate the
3156  * current function value. Otherwise just copy.
3157  */
3158  SQLValueFunction *svf = (SQLValueFunction *) node;
3159 
3160  if (context->estimate)
3161  return (Node *) evaluate_expr((Expr *) svf,
3162  svf->type,
3163  svf->typmod,
3164  InvalidOid);
3165  else
3166  return copyObject((Node *) svf);
3167  }
3168  case T_FieldSelect:
3169  {
3170  /*
3171  * We can optimize field selection from a whole-row Var into a
3172  * simple Var. (This case won't be generated directly by the
3173  * parser, because ParseComplexProjection short-circuits it.
3174  * But it can arise while simplifying functions.) Also, we
3175  * can optimize field selection from a RowExpr construct, or
3176  * of course from a constant.
3177  *
3178  * However, replacing a whole-row Var in this way has a
3179  * pitfall: if we've already built the rel targetlist for the
3180  * source relation, then the whole-row Var is scheduled to be
3181  * produced by the relation scan, but the simple Var probably
3182  * isn't, which will lead to a failure in setrefs.c. This is
3183  * not a problem when handling simple single-level queries, in
3184  * which expression simplification always happens first. It
3185  * is a risk for lateral references from subqueries, though.
3186  * To avoid such failures, don't optimize uplevel references.
3187  *
3188  * We must also check that the declared type of the field is
3189  * still the same as when the FieldSelect was created --- this
3190  * can change if someone did ALTER COLUMN TYPE on the rowtype.
3191  * If it isn't, we skip the optimization; the case will
3192  * probably fail at runtime, but that's not our problem here.
3193  */
3194  FieldSelect *fselect = (FieldSelect *) node;
3195  FieldSelect *newfselect;
3196  Node *arg;
3197 
3198  arg = eval_const_expressions_mutator((Node *) fselect->arg,
3199  context);
3200  if (arg && IsA(arg, Var) &&
3201  ((Var *) arg)->varattno == InvalidAttrNumber &&
3202  ((Var *) arg)->varlevelsup == 0)
3203  {
3204  if (rowtype_field_matches(((Var *) arg)->vartype,
3205  fselect->fieldnum,
3206  fselect->resulttype,
3207  fselect->resulttypmod,
3208  fselect->resultcollid))
3209  return (Node *) makeVar(((Var *) arg)->varno,
3210  fselect->fieldnum,
3211  fselect->resulttype,
3212  fselect->resulttypmod,
3213  fselect->resultcollid,
3214  ((Var *) arg)->varlevelsup);
3215  }
3216  if (arg && IsA(arg, RowExpr))
3217  {
3218  RowExpr *rowexpr = (RowExpr *) arg;
3219 
3220  if (fselect->fieldnum > 0 &&
3221  fselect->fieldnum <= list_length(rowexpr->args))
3222  {
3223  Node *fld = (Node *) list_nth(rowexpr->args,
3224  fselect->fieldnum - 1);
3225 
3226  if (rowtype_field_matches(rowexpr->row_typeid,
3227  fselect->fieldnum,
3228  fselect->resulttype,
3229  fselect->resulttypmod,
3230  fselect->resultcollid) &&
3231  fselect->resulttype == exprType(fld) &&
3232  fselect->resulttypmod == exprTypmod(fld) &&
3233  fselect->resultcollid == exprCollation(fld))
3234  return fld;
3235  }
3236  }
3237  newfselect = makeNode(FieldSelect);
3238  newfselect->arg = (Expr *) arg;
3239  newfselect->fieldnum = fselect->fieldnum;
3240  newfselect->resulttype = fselect->resulttype;
3241  newfselect->resulttypmod = fselect->resulttypmod;
3242  newfselect->resultcollid = fselect->resultcollid;
3243  if (arg && IsA(arg, Const))
3244  {
3245  Const *con = (Const *) arg;
3246 
3248  newfselect->fieldnum,
3249  newfselect->resulttype,
3250  newfselect->resulttypmod,
3251  newfselect->resultcollid))
3252  return ece_evaluate_expr(newfselect);
3253  }
3254  return (Node *) newfselect;
3255  }
3256  case T_NullTest:
3257  {
3258  NullTest *ntest = (NullTest *) node;
3259  NullTest *newntest;
3260  Node *arg;
3261 
3263  context);
3264  if (ntest->argisrow && arg && IsA(arg, RowExpr))
3265  {
3266  /*
3267  * We break ROW(...) IS [NOT] NULL into separate tests on
3268  * its component fields. This form is usually more
3269  * efficient to evaluate, as well as being more amenable
3270  * to optimization.
3271  */
3272  RowExpr *rarg = (RowExpr *) arg;
3273  List *newargs = NIL;
3274  ListCell *l;
3275 
3276  foreach(l, rarg->args)
3277  {
3278  Node *relem = (Node *) lfirst(l);
3279 
3280  /*
3281  * A constant field refutes the whole NullTest if it's
3282  * of the wrong nullness; else we can discard it.
3283  */
3284  if (relem && IsA(relem, Const))
3285  {
3286  Const *carg = (Const *) relem;
3287 
3288  if (carg->constisnull ?
3289  (ntest->nulltesttype == IS_NOT_NULL) :
3290  (ntest->nulltesttype == IS_NULL))
3291  return makeBoolConst(false, false);
3292  continue;
3293  }
3294 
3295  /*
3296  * Else, make a scalar (argisrow == false) NullTest
3297  * for this field. Scalar semantics are required
3298  * because IS [NOT] NULL doesn't recurse; see comments
3299  * in ExecEvalRowNullInt().
3300  */
3301  newntest = makeNode(NullTest);
3302  newntest->arg = (Expr *) relem;
3303  newntest->nulltesttype = ntest->nulltesttype;
3304  newntest->argisrow = false;
3305  newntest->location = ntest->location;
3306  newargs = lappend(newargs, newntest);
3307  }
3308  /* If all the inputs were constants, result is TRUE */
3309  if (newargs == NIL)
3310  return makeBoolConst(true, false);
3311  /* If only one nonconst input, it's the result */
3312  if (list_length(newargs) == 1)
3313  return (Node *) linitial(newargs);
3314  /* Else we need an AND node */
3315  return (Node *) make_andclause(newargs);
3316  }
3317  if (!ntest->argisrow && arg && IsA(arg, Const))
3318  {
3319  Const *carg = (Const *) arg;
3320  bool result;
3321 
3322  switch (ntest->nulltesttype)
3323  {
3324  case IS_NULL:
3325  result = carg->constisnull;
3326  break;
3327  case IS_NOT_NULL:
3328  result = !carg->constisnull;
3329  break;
3330  default:
3331  elog(ERROR, "unrecognized nulltesttype: %d",
3332  (int) ntest->nulltesttype);
3333  result = false; /* keep compiler quiet */
3334  break;
3335  }
3336 
3337  return makeBoolConst(result, false);
3338  }
3339 
3340  newntest = makeNode(NullTest);
3341  newntest->arg = (Expr *) arg;
3342  newntest->nulltesttype = ntest->nulltesttype;
3343  newntest->argisrow = ntest->argisrow;
3344  newntest->location = ntest->location;
3345  return (Node *) newntest;
3346  }
3347  case T_BooleanTest:
3348  {
3349  /*
3350  * This case could be folded into the generic handling used
3351  * for ArrayExpr etc. But because the simplification logic is
3352  * so trivial, applying evaluate_expr() to perform it would be
3353  * a heavy overhead. BooleanTest is probably common enough to
3354  * justify keeping this bespoke implementation.
3355  */
3356  BooleanTest *btest = (BooleanTest *) node;
3357  BooleanTest *newbtest;
3358  Node *arg;
3359 
3361  context);
3362  if (arg && IsA(arg, Const))
3363  {
3364  Const *carg = (Const *) arg;
3365  bool result;
3366 
3367  switch (btest->booltesttype)
3368  {
3369  case IS_TRUE:
3370  result = (!carg->constisnull &&
3371  DatumGetBool(carg->constvalue));
3372  break;
3373  case IS_NOT_TRUE:
3374  result = (carg->constisnull ||
3375  !DatumGetBool(carg->constvalue));
3376  break;
3377  case IS_FALSE:
3378  result = (!carg->constisnull &&
3379  !DatumGetBool(carg->constvalue));
3380  break;
3381  case IS_NOT_FALSE:
3382  result = (carg->constisnull ||
3383  DatumGetBool(carg->constvalue));
3384  break;
3385  case IS_UNKNOWN:
3386  result = carg->constisnull;
3387  break;
3388  case IS_NOT_UNKNOWN:
3389  result = !carg->constisnull;
3390  break;
3391  default:
3392  elog(ERROR, "unrecognized booltesttype: %d",
3393  (int) btest->booltesttype);
3394  result = false; /* keep compiler quiet */
3395  break;
3396  }
3397 
3398  return makeBoolConst(result, false);
3399  }
3400 
3401  newbtest = makeNode(BooleanTest);
3402  newbtest->arg = (Expr *) arg;
3403  newbtest->booltesttype = btest->booltesttype;
3404  newbtest->location = btest->location;
3405  return (Node *) newbtest;
3406  }
3407  case T_CoerceToDomain:
3408  {
3409  /*
3410  * If the domain currently has no constraints, we replace the
3411  * CoerceToDomain node with a simple RelabelType, which is
3412  * both far faster to execute and more amenable to later
3413  * optimization. We must then mark the plan as needing to be
3414  * rebuilt if the domain's constraints change.
3415  *
3416  * Also, in estimation mode, always replace CoerceToDomain
3417  * nodes, effectively assuming that the coercion will succeed.
3418  */
3419  CoerceToDomain *cdomain = (CoerceToDomain *) node;
3420  CoerceToDomain *newcdomain;
3421  Node *arg;
3422 
3423  arg = eval_const_expressions_mutator((Node *) cdomain->arg,
3424  context);
3425  if (context->estimate ||
3426  !DomainHasConstraints(cdomain->resulttype))
3427  {
3428  /* Record dependency, if this isn't estimation mode */
3429  if (context->root && !context->estimate)
3430  record_plan_type_dependency(context->root,
3431  cdomain->resulttype);
3432 
3433  /* Generate RelabelType to substitute for CoerceToDomain */
3434  return applyRelabelType(arg,
3435  cdomain->resulttype,
3436  cdomain->resulttypmod,
3437  cdomain->resultcollid,
3438  cdomain->coercionformat,
3439  cdomain->location,
3440  true);
3441  }
3442 
3443  newcdomain = makeNode(CoerceToDomain);
3444  newcdomain->arg = (Expr *) arg;
3445  newcdomain->resulttype = cdomain->resulttype;
3446  newcdomain->resulttypmod = cdomain->resulttypmod;
3447  newcdomain->resultcollid = cdomain->resultcollid;
3448  newcdomain->coercionformat = cdomain->coercionformat;
3449  newcdomain->location = cdomain->location;
3450  return (Node *) newcdomain;
3451  }
3452  case T_PlaceHolderVar:
3453 
3454  /*
3455  * In estimation mode, just strip the PlaceHolderVar node
3456  * altogether; this amounts to estimating that the contained value
3457  * won't be forced to null by an outer join. In regular mode we
3458  * just use the default behavior (ie, simplify the expression but
3459  * leave the PlaceHolderVar node intact).
3460  */
3461  if (context->estimate)
3462  {
3463  PlaceHolderVar *phv = (PlaceHolderVar *) node;
3464 
3465  return eval_const_expressions_mutator((Node *) phv->phexpr,
3466  context);
3467  }
3468  break;
3469  case T_ConvertRowtypeExpr:
3470  {
3472  Node *arg;
3473  ConvertRowtypeExpr *newcre;
3474 
3476  context);
3477 
3478  newcre = makeNode(ConvertRowtypeExpr);
3479  newcre->resulttype = cre->resulttype;
3480  newcre->convertformat = cre->convertformat;
3481  newcre->location = cre->location;
3482 
3483  /*
3484  * In case of a nested ConvertRowtypeExpr, we can convert the
3485  * leaf row directly to the topmost row format without any
3486  * intermediate conversions. (This works because
3487  * ConvertRowtypeExpr is used only for child->parent
3488  * conversion in inheritance trees, which works by exact match
3489  * of column name, and a column absent in an intermediate
3490  * result can't be present in the final result.)
3491  *
3492  * No need to check more than one level deep, because the
3493  * above recursion will have flattened anything else.
3494  */
3495  if (arg != NULL && IsA(arg, ConvertRowtypeExpr))
3496  {
3498 
3499  arg = (Node *) argcre->arg;
3500 
3501  /*
3502  * Make sure an outer implicit conversion can't hide an
3503  * inner explicit one.
3504  */
3506  newcre->convertformat = argcre->convertformat;
3507  }
3508 
3509  newcre->arg = (Expr *) arg;
3510 
3511  if (arg != NULL && IsA(arg, Const))
3512  return ece_evaluate_expr((Node *) newcre);
3513  return (Node *) newcre;
3514  }
3515  default:
3516  break;
3517  }
3518 
3519  /*
3520  * For any node type not handled above, copy the node unchanged but
3521  * const-simplify its subexpressions. This is the correct thing for node
3522  * types whose behavior might change between planning and execution, such
3523  * as CurrentOfExpr. It's also a safe default for new node types not
3524  * known to this routine.
3525  */
3526  return ece_generic_processing(node);
3527 }
#define InvalidAttrNumber
Definition: attnum.h:23
signed short int16
Definition: c.h:428
signed int int32
Definition: c.h:429
static List * simplify_or_arguments(List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceTrue)
Definition: clauses.c:3593
static bool rowtype_field_matches(Oid rowtypeid, int fieldnum, Oid expectedtype, int32 expectedtypmod, Oid expectedcollation)
Definition: clauses.c:2027
#define ece_all_arguments_const(node)
Definition: clauses.c:2266
#define ece_evaluate_expr(node)
Definition: clauses.c:2270
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:364
#define ece_generic_processing(node)
Definition: clauses.c:2257
List * expand_function_arguments(List *args, bool include_out_arguments, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:3978
static bool ece_function_is_safe(Oid funcid, eval_const_expressions_context *context)
Definition: clauses.c:3555
static List * simplify_and_arguments(List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceFalse)
Definition: clauses.c:3699
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:3862
static Node * simplify_boolean_equality(Oid opno, List *args)
Definition: clauses.c:3793
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * lappend(List *list, void *datum)
Definition: list.c:336
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2854
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2198
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2821
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:337
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:299
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:636
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:357
Expr * make_orclause(List *orclauses)
Definition: makefuncs.c:652
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:267
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:759
Node * applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat, int rlocation, bool overwrite_ok)
Definition: nodeFuncs.c:582
void set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
Definition: nodeFuncs.c:1694
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1683
#define copyObject(obj)
Definition: nodes.h:654
@ T_AlternativeSubPlan
Definition: nodes.h:172
@ T_CoalesceExpr
Definition: nodes.h:186
@ T_WindowFunc
Definition: nodes.h:161
@ T_ConvertRowtypeExpr
Definition: nodes.h:178
@ T_SubPlan
Definition: nodes.h:171
@ T_CoerceToDomain
Definition: nodes.h:192
@ T_PlaceHolderVar
Definition: nodes.h:272
#define makeNode(_type_)
Definition: nodes.h:586
#define castNode(_type_, nodeptr)
Definition: nodes.h:607
#define PARAM_FLAG_CONST
Definition: params.h:88
#define lfirst_node(type, lc)
Definition: pg_list.h:172
#define list_make1(x1)
Definition: pg_list.h:206
#define list_make3(x1, x2, x3)
Definition: pg_list.h:210
static void * list_nth(const List *list, int n)
Definition: pg_list.h:278
#define DatumGetBool(X)
Definition: postgres.h:437
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define BoolGetDatum(X)
Definition: postgres.h:446
#define Int32GetDatum(X)
Definition: postgres.h:523
Node * negate_clause(Node *node)
Definition: prepqual.c:74
e
Definition: preproc-init.c:82
@ IS_NOT_TRUE
Definition: primnodes.h:1282
@ IS_NOT_FALSE
Definition: primnodes.h:1282
@ IS_NOT_UNKNOWN
Definition: primnodes.h:1282
@ IS_TRUE
Definition: primnodes.h:1282
@ IS_UNKNOWN
Definition: primnodes.h:1282
@ IS_FALSE
Definition: primnodes.h:1282
@ NOT_EXPR
Definition: primnodes.h:619
@ PARAM_EXTERN
Definition: primnodes.h:258
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:485
@ IS_NULL
Definition: primnodes.h:1259
@ IS_NOT_NULL
Definition: primnodes.h:1259
struct Const Const
void record_plan_type_dependency(PlannerInfo *root, Oid typid)
Definition: setrefs.c:3044
List * args
Definition: primnodes.h:626
BoolTestType booltesttype
Definition: primnodes.h:1289
Expr * arg
Definition: primnodes.h:1288
int location
Definition: primnodes.h:981
Oid casecollid
Definition: primnodes.h:977
Oid casetype
Definition: primnodes.h:976
Expr * defresult
Definition: primnodes.h:980
List * args
Definition: primnodes.h:979
Expr * result
Definition: primnodes.h:991
Expr * expr
Definition: primnodes.h:990
int location
Definition: primnodes.h:992
List * args
Definition: primnodes.h:1132
Oid coalescetype
Definition: primnodes.h:1130
Oid coalescecollid
Definition: primnodes.h:1131
CoercionForm coercionformat
Definition: primnodes.h:1309
int32 resulttypmod
Definition: primnodes.h:1307
Expr * arg
Definition: primnodes.h:880
CoercionForm coerceformat
Definition: primnodes.h:884
Oid resultcollid
Definition: primnodes.h:883
int location
Definition: primnodes.h:885
Oid resulttype
Definition: primnodes.h:881
Expr * arg
Definition: primnodes.h:946
int location
Definition: primnodes.h:948
Oid consttype
Definition: primnodes.h:215
Datum constvalue
Definition: primnodes.h:219
bool constisnull
Definition: primnodes.h:220
int location
Definition: primnodes.h:226
CoercionForm convertformat
Definition: primnodes.h:932
NodeTag type
Definition: primnodes.h:138
AttrNumber fieldnum
Definition: primnodes.h:809
Oid resulttype
Definition: primnodes.h:810
Oid resultcollid
Definition: primnodes.h:813
Expr * arg
Definition: primnodes.h:808
int32 resulttypmod
Definition: primnodes.h:812
Oid funccollid
Definition: primnodes.h:501
bool funcretset
Definition: primnodes.h:497
Oid funcid
Definition: primnodes.h:495
bool funcvariadic
Definition: primnodes.h:498
List * args
Definition: primnodes.h:503
CoercionForm funcformat
Definition: primnodes.h:500
Oid inputcollid
Definition: primnodes.h:502
int location
Definition: primnodes.h:504
Oid funcresulttype
Definition: primnodes.h:496
NullTestType nulltesttype
Definition: primnodes.h:1266
int location
Definition: primnodes.h:1268
bool argisrow
Definition: primnodes.h:1267
Expr * arg
Definition: primnodes.h:1265
bool opretset
Definition: primnodes.h:545
int location
Definition: primnodes.h:549
Oid opcollid
Definition: primnodes.h:546
Oid inputcollid
Definition: primnodes.h:547
Oid opresulttype
Definition: primnodes.h:544
bool isnull
Definition: params.h:93
uint16 pflags
Definition: params.h:94
Datum value
Definition: params.h:92
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:125
ParamFetchHook paramFetch
Definition: params.h:112
int32 paramtypmod
Definition: primnodes.h:270
Oid paramtype
Definition: primnodes.h:269
int location
Definition: primnodes.h:272
Oid paramcollid
Definition: primnodes.h:271
int location
Definition: primnodes.h:865
Oid resultcollid
Definition: primnodes.h:863
int32 resulttypmod
Definition: primnodes.h:862
CoercionForm relabelformat
Definition: primnodes.h:864
Oid resulttype
Definition: primnodes.h:861
Expr * arg
Definition: primnodes.h:860
Oid row_typeid
Definition: primnodes.h:1069
List * args
Definition: primnodes.h:1068
Definition: primnodes.h:187
bool winagg
Definition: primnodes.h:394
Oid inputcollid
Definition: primnodes.h:389
List * args
Definition: primnodes.h:390
Index winref
Definition: primnodes.h:392
Expr * aggfilter
Definition: primnodes.h:391
int location
Definition: primnodes.h:395
Oid wincollid
Definition: primnodes.h:388
Oid winfnoid
Definition: primnodes.h:386
bool winstar
Definition: primnodes.h:393
Oid wintype
Definition: primnodes.h:387
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1198
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1150
@ PROCOID
Definition: syscache.h:77
bool DomainHasConstraints(Oid type_id)
Definition: typcache.c:1392

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, if(), 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(), Const::location, Param::location, 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_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_PlaceHolderVar, T_RelabelType, T_RowExpr, T_ScalarArrayOpExpr, T_SQLValueFunction, T_SubPlan, T_SubscriptingRef, T_WindowFunc, SQLValueFunction::type, SQLValueFunction::typmod, 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().

◆ evaluate_expr()

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

Definition at line 4786 of file clauses.c.

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

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

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

4238 {
4239  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4240  bool has_nonconst_input = false;
4241  bool has_null_input = false;
4242  ListCell *arg;
4243  FuncExpr *newexpr;
4244 
4245  /*
4246  * Can't simplify if it returns a set.
4247  */
4248  if (funcform->proretset)
4249  return NULL;
4250 
4251  /*
4252  * Can't simplify if it returns RECORD. The immediate problem is that it
4253  * will be needing an expected tupdesc which we can't supply here.
4254  *
4255  * In the case where it has OUT parameters, it could get by without an
4256  * expected tupdesc, but we still have issues: get_expr_result_type()
4257  * doesn't know how to extract type info from a RECORD constant, and in
4258  * the case of a NULL function result there doesn't seem to be any clean
4259  * way to fix that. In view of the likelihood of there being still other
4260  * gotchas, seems best to leave the function call unreduced.
4261  */
4262  if (funcform->prorettype == RECORDOID)
4263  return NULL;
4264 
4265  /*
4266  * Check for constant inputs and especially constant-NULL inputs.
4267  */
4268  foreach(arg, args)
4269  {
4270  if (IsA(lfirst(arg), Const))
4271  has_null_input |= ((Const *) lfirst(arg))->constisnull;
4272  else
4273  has_nonconst_input = true;
4274  }
4275 
4276  /*
4277  * If the function is strict and has a constant-NULL input, it will never
4278  * be called at all, so we can replace the call by a NULL constant, even
4279  * if there are other inputs that aren't constant, and even if the
4280  * function is not otherwise immutable.
4281  */
4282  if (funcform->proisstrict && has_null_input)
4283  return (Expr *) makeNullConst(result_type, result_typmod,
4284  result_collid);
4285 
4286  /*
4287  * Otherwise, can simplify only if all inputs are constants. (For a
4288  * non-strict function, constant NULL inputs are treated the same as
4289  * constant non-NULL inputs.)
4290  */
4291  if (has_nonconst_input)
4292  return NULL;
4293 
4294  /*
4295  * Ordinarily we are only allowed to simplify immutable functions. But for
4296  * purposes of estimation, we consider it okay to simplify functions that
4297  * are merely stable; the risk that the result might change from planning
4298  * time to execution time is worth taking in preference to not being able
4299  * to estimate the value at all.
4300  */
4301  if (funcform->provolatile == PROVOLATILE_IMMUTABLE)
4302  /* okay */ ;
4303  else if (context->estimate && funcform->provolatile == PROVOLATILE_STABLE)
4304  /* okay */ ;
4305  else
4306  return NULL;
4307 
4308  /*
4309  * OK, looks like we can simplify this operator/function.
4310  *
4311  * Build a new FuncExpr node containing the already-simplified arguments.
4312  */
4313  newexpr = makeNode(FuncExpr);
4314  newexpr->funcid = funcid;
4315  newexpr->funcresulttype = result_type;
4316  newexpr->funcretset = false;
4317  newexpr->funcvariadic = funcvariadic;
4318  newexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
4319  newexpr->funccollid = result_collid; /* doesn't matter */
4320  newexpr->inputcollid = input_collid;
4321  newexpr->args = args;
4322  newexpr->location = -1;
4323 
4324  return evaluate_expr((Expr *) newexpr, result_type, result_typmod,
4325  result_collid);
4326 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
@ COERCE_EXPLICIT_CALL
Definition: primnodes.h:483

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

◆ expand_function_arguments()

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

Definition at line 3978 of file clauses.c.

3980 {
3981  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
3982  Oid *proargtypes = funcform->proargtypes.values;
3983  int pronargs = funcform->pronargs;
3984  bool has_named_args = false;
3985  ListCell *lc;
3986 
3987  /*
3988  * If we are asked to match to OUT arguments, then use the proallargtypes
3989  * array (which includes those); otherwise use proargtypes (which
3990  * doesn't). Of course, if proallargtypes is null, we always use
3991  * proargtypes. (Fetching proallargtypes is annoyingly expensive
3992  * considering that we may have nothing to do here, but fortunately the
3993  * common case is include_out_arguments == false.)
3994  */
3995  if (include_out_arguments)
3996  {
3997  Datum proallargtypes;
3998  bool isNull;
3999 
4000  proallargtypes = SysCacheGetAttr(PROCOID, func_tuple,
4001  Anum_pg_proc_proallargtypes,
4002  &isNull);
4003  if (!isNull)
4004  {
4005  ArrayType *arr = DatumGetArrayTypeP(proallargtypes);
4006 
4007  pronargs = ARR_DIMS(arr)[0];
4008  if (ARR_NDIM(arr) != 1 ||
4009  pronargs < 0 ||
4010  ARR_HASNULL(arr) ||
4011  ARR_ELEMTYPE(arr) != OIDOID)
4012  elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
4013  Assert(pronargs >= funcform->pronargs);
4014  proargtypes = (Oid *) ARR_DATA_PTR(arr);
4015  }
4016  }
4017 
4018  /* Do we have any named arguments? */
4019  foreach(lc, args)
4020  {
4021  Node *arg = (Node *) lfirst(lc);
4022 
4023  if (IsA(arg, NamedArgExpr))
4024  {
4025  has_named_args = true;
4026  break;
4027  }
4028  }
4029 
4030  /* If so, we must apply reorder_function_arguments */
4031  if (has_named_args)
4032  {
4033  args = reorder_function_arguments(args, pronargs, func_tuple);
4034  /* Recheck argument types and add casts if needed */
4035  recheck_cast_function_args(args, result_type,
4036  proargtypes, pronargs,
4037  func_tuple);
4038  }
4039  else if (list_length(args) < pronargs)
4040  {
4041  /* No named args, but we seem to be short some defaults */
4042  args = add_function_defaults(args, pronargs, func_tuple);
4043  /* Recheck argument types and add casts if needed */
4044  recheck_cast_function_args(args, result_type,
4045  proargtypes, pronargs,
4046  func_tuple);
4047  }
4048 
4049  return args;
4050 }
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_HASNULL(a)
Definition: array.h:284
static List * add_function_defaults(List *args, int pronargs, HeapTuple func_tuple)
Definition: clauses.c:4129
static List * reorder_function_arguments(List *args, int pronargs, HeapTuple func_tuple)
Definition: clauses.c:4059
static void recheck_cast_function_args(List *args, Oid result_type, Oid *proargtypes, int pronargs, HeapTuple func_tuple)
Definition: clauses.c:4188
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1411

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

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

◆ expression_returns_set_rows()

double expression_returns_set_rows ( PlannerInfo root,
Node clause 
)

Definition at line 288 of file clauses.c.

289 {
290  if (clause == NULL)
291  return 1.0;
292  if (IsA(clause, FuncExpr))
293  {
294  FuncExpr *expr = (FuncExpr *) clause;
295 
296  if (expr->funcretset)
297  return clamp_row_est(get_function_rows(root, expr->funcid, clause));
298  }
299  if (IsA(clause, OpExpr))
300  {
301  OpExpr *expr = (OpExpr *) clause;
302 
303  if (expr->opretset)
304  {
305  set_opfuncid(expr);
306  return clamp_row_est(get_function_rows(root, expr->opfuncid, clause));
307  }
308  }
309  return 1.0;
310 }
double clamp_row_est(double nrows)
Definition: costsize.c:199
double get_function_rows(PlannerInfo *root, Oid funcid, Node *node)
Definition: plancat.c:2049

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

◆ fetch_function_defaults()

static List * fetch_function_defaults ( HeapTuple  func_tuple)
static

Definition at line 4153 of file clauses.c.

4154 {
4155  List *defaults;
4156  Datum proargdefaults;
4157  bool isnull;
4158  char *str;
4159 
4160  /* The error cases here shouldn't happen, but check anyway */
4161  proargdefaults = SysCacheGetAttr(PROCOID, func_tuple,
4162  Anum_pg_proc_proargdefaults,
4163  &isnull);
4164  if (isnull)
4165  elog(ERROR, "not enough default arguments");
4166  str = TextDatumGetCString(proargdefaults);
4167  defaults = castNode(List, stringToNode(str));
4168  pfree(str);
4169  return defaults;
4170 }
#define TextDatumGetCString(d)
Definition: builtins.h:86
void pfree(void *pointer)
Definition: mcxt.c:1169
void * stringToNode(const char *str)
Definition: read.c:89

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

Referenced by add_function_defaults(), and reorder_function_arguments().

◆ find_forced_null_var()

Var* find_forced_null_var ( Node node)

Definition at line 1820 of file clauses.c.

1821 {
1822  if (node == NULL)
1823  return NULL;
1824  if (IsA(node, NullTest))
1825  {
1826  /* check for var IS NULL */
1827  NullTest *expr = (NullTest *) node;
1828 
1829  if (expr->nulltesttype == IS_NULL && !expr->argisrow)
1830  {
1831  Var *var = (Var *) expr->arg;
1832 
1833  if (var && IsA(var, Var) &&
1834  var->varlevelsup == 0)
1835  return var;
1836  }
1837  }
1838  else if (IsA(node, BooleanTest))
1839  {
1840  /* var IS UNKNOWN is equivalent to var IS NULL */
1841  BooleanTest *expr = (BooleanTest *) node;
1842 
1843  if (expr->booltesttype == IS_UNKNOWN)
1844  {
1845  Var *var = (Var *) expr->arg;
1846 
1847  if (var && IsA(var, Var) &&
1848  var->varlevelsup == 0)
1849  return var;
1850  }
1851  }
1852  return NULL;
1853 }
Index varlevelsup
Definition: primnodes.h:196

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

Referenced by check_redundant_nullability_qual(), and find_forced_null_vars().

◆ find_forced_null_vars()

List* find_forced_null_vars ( Node node)

Definition at line 1761 of file clauses.c.

1762 {
1763  List *result = NIL;
1764  Var *var;
1765  ListCell *l;
1766 
1767  if (node == NULL)
1768  return NIL;
1769  /* Check single-clause cases using subroutine */
1770  var = find_forced_null_var(node);
1771  if (var)
1772  {
1773  result = list_make1(var);
1774  }
1775  /* Otherwise, handle AND-conditions */
1776  else if (IsA(node, List))
1777  {
1778  /*
1779  * At top level, we are examining an implicit-AND list: if any of the
1780  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1781  */
1782  foreach(l, (List *) node)
1783  {
1784  result = list_concat(result,
1786  }
1787  }
1788  else if (IsA(node, BoolExpr))
1789  {
1790  BoolExpr *expr = (BoolExpr *) node;
1791 
1792  /*
1793  * We don't bother considering the OR case, because it's fairly
1794  * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
1795  * the NOT case isn't worth expending code on.
1796  */
1797  if (expr->boolop == AND_EXPR)
1798  {
1799  /* At top level we can just recurse (to the List case) */
1800  result = find_forced_null_vars((Node *) expr->args);
1801  }
1802  }
1803  return result;
1804 }
Var * find_forced_null_var(Node *node)
Definition: clauses.c:1820
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1761
List * list_concat(List *list1, const List *list2)
Definition: list.c:540

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

Referenced by reduce_outer_joins_pass2().

◆ find_nonnullable_rels()

Relids find_nonnullable_rels ( Node clause)

Definition at line 1343 of file clauses.c.

1344 {
1345  return find_nonnullable_rels_walker(clause, true);
1346 }
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1349

References find_nonnullable_rels_walker().

Referenced by make_outerjoininfo(), and reduce_outer_joins_pass2().

◆ find_nonnullable_rels_walker()

static Relids find_nonnullable_rels_walker ( Node node,
bool  top_level 
)
static

Definition at line 1349 of file clauses.c.

1350 {
1351  Relids result = NULL;
1352  ListCell *l;
1353 
1354  if (node == NULL)
1355  return NULL;
1356  if (IsA(node, Var))
1357  {
1358  Var *var = (Var *) node;
1359 
1360  if (var->varlevelsup == 0)
1361  result = bms_make_singleton(var->varno);
1362  }
1363  else if (IsA(node, List))
1364  {
1365  /*
1366  * At top level, we are examining an implicit-AND list: if any of the
1367  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1368  * not at top level, we are examining the arguments of a strict
1369  * function: if any of them produce NULL then the result of the
1370  * function must be NULL. So in both cases, the set of nonnullable
1371  * rels is the union of those found in the arms, and we pass down the
1372  * top_level flag unmodified.
1373  */
1374  foreach(l, (List *) node)
1375  {
1376  result = bms_join(result,
1378  top_level));
1379  }
1380  }
1381  else if (IsA(node, FuncExpr))
1382  {
1383  FuncExpr *expr = (FuncExpr *) node;
1384 
1385  if (func_strict(expr->funcid))
1386  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1387  }
1388  else if (IsA(node, OpExpr))
1389  {
1390  OpExpr *expr = (OpExpr *) node;
1391 
1392  set_opfuncid(expr);
1393  if (func_strict(expr->opfuncid))
1394  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1395  }
1396  else if (IsA(node, ScalarArrayOpExpr))
1397  {
1398  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1399 
1400  if (is_strict_saop(expr, true))
1401  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1402  }
1403  else if (IsA(node, BoolExpr))
1404  {
1405  BoolExpr *expr = (BoolExpr *) node;
1406 
1407  switch (expr->boolop)
1408  {
1409  case AND_EXPR:
1410  /* At top level we can just recurse (to the List case) */
1411  if (top_level)
1412  {
1413  result = find_nonnullable_rels_walker((Node *) expr->args,
1414  top_level);
1415  break;
1416  }
1417 
1418  /*
1419  * Below top level, even if one arm produces NULL, the result
1420  * could be FALSE (hence not NULL). However, if *all* the
1421  * arms produce NULL then the result is NULL, so we can take
1422  * the intersection of the sets of nonnullable rels, just as
1423  * for OR. Fall through to share code.
1424  */
1425  /* FALL THRU */
1426  case OR_EXPR:
1427 
1428  /*
1429  * OR is strict if all of its arms are, so we can take the
1430  * intersection of the sets of nonnullable rels for each arm.
1431  * This works for both values of top_level.
1432  */
1433  foreach(l, expr->args)
1434  {
1435  Relids subresult;
1436 
1437  subresult = find_nonnullable_rels_walker(lfirst(l),
1438  top_level);
1439  if (result == NULL) /* first subresult? */
1440  result = subresult;
1441  else
1442  result = bms_int_members(result, subresult);
1443 
1444  /*
1445  * If the intersection is empty, we can stop looking. This
1446  * also justifies the test for first-subresult above.
1447  */
1448  if (bms_is_empty(result))
1449  break;
1450  }
1451  break;
1452  case NOT_EXPR:
1453  /* NOT will return null if its arg is null */
1454  result = find_nonnullable_rels_walker((Node *) expr->args,
1455  false);
1456  break;
1457  default:
1458  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1459  break;
1460  }
1461  }
1462  else if (IsA(node, RelabelType))
1463  {
1464  RelabelType *expr = (RelabelType *) node;
1465 
1466  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1467  }
1468  else if (IsA(node, CoerceViaIO))
1469  {
1470  /* not clear this is useful, but it can't hurt */
1471  CoerceViaIO *expr = (CoerceViaIO *) node;
1472 
1473  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1474  }
1475  else if (IsA(node, ArrayCoerceExpr))
1476  {
1477  /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1478  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1479 
1480  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1481  }
1482  else if (IsA(node, ConvertRowtypeExpr))
1483  {
1484  /* not clear this is useful, but it can't hurt */
1485  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1486 
1487  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1488  }
1489  else if (IsA(node, CollateExpr))
1490  {
1491  CollateExpr *expr = (CollateExpr *) node;
1492 
1493  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1494  }
1495  else if (IsA(node, NullTest))
1496  {
1497  /* IS NOT NULL can be considered strict, but only at top level */
1498  NullTest *expr = (NullTest *) node;
1499 
1500  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1501  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1502  }
1503  else if (IsA(node, BooleanTest))
1504  {
1505  /* Boolean tests that reject NULL are strict at top level */
1506  BooleanTest *expr = (BooleanTest *) node;
1507 
1508  if (top_level &&
1509  (expr->booltesttype == IS_TRUE ||
1510  expr->booltesttype == IS_FALSE ||
1511  expr->booltesttype == IS_NOT_UNKNOWN))
1512  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1513  }
1514  else if (IsA(node, PlaceHolderVar))
1515  {
1516  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1517 
1518  /*
1519  * If the contained expression forces any rels non-nullable, so does
1520  * the PHV.
1521  */
1522  result = find_nonnullable_rels_walker((Node *) phv->phexpr, top_level);
1523 
1524  /*
1525  * If the PHV's syntactic scope is exactly one rel, it will be forced
1526  * to be evaluated at that rel, and so it will behave like a Var of
1527  * that rel: if the rel's entire output goes to null, so will the PHV.
1528  * (If the syntactic scope is a join, we know that the PHV will go to
1529  * null if the whole join does; but that is AND semantics while we
1530  * need OR semantics for find_nonnullable_rels' result, so we can't do
1531  * anything with the knowledge.)
1532  */
1533  if (phv->phlevelsup == 0 &&
1535  result = bms_add_members(result, phv->phrels);
1536  }
1537  return result;
1538 }
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:951
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:795
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:904
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:703
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:674
@ BMS_SINGLETON
Definition: bitmapset.h:69
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition: clauses.c:1869
Index phlevelsup
Definition: pathnodes.h:2188
int varno
Definition: primnodes.h:189

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

◆ find_nonnullable_vars()

List* find_nonnullable_vars ( Node clause)

Definition at line 1568 of file clauses.c.

1569 {
1570  return find_nonnullable_vars_walker(clause, true);
1571 }
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1574

References find_nonnullable_vars_walker().

Referenced by reduce_outer_joins_pass2().

◆ find_nonnullable_vars_walker()

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

Definition at line 1574 of file clauses.c.

1575 {
1576  List *result = NIL;
1577  ListCell *l;
1578 
1579  if (node == NULL)
1580  return NIL;
1581  if (IsA(node, Var))
1582  {
1583  Var *var = (Var *) node;
1584 
1585  if (var->varlevelsup == 0)
1586  result = list_make1(var);
1587  }
1588  else if (IsA(node, List))
1589  {
1590  /*
1591  * At top level, we are examining an implicit-AND list: if any of the
1592  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1593  * not at top level, we are examining the arguments of a strict
1594  * function: if any of them produce NULL then the result of the
1595  * function must be NULL. So in both cases, the set of nonnullable
1596  * vars is the union of those found in the arms, and we pass down the
1597  * top_level flag unmodified.
1598  */
1599  foreach(l, (List *) node)
1600  {
1601  result = list_concat(result,
1603  top_level));
1604  }
1605  }
1606  else if (IsA(node, FuncExpr))
1607  {
1608  FuncExpr *expr = (FuncExpr *) node;
1609 
1610  if (func_strict(expr->funcid))
1611  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1612  }
1613  else if (IsA(node, OpExpr))
1614  {
1615  OpExpr *expr = (OpExpr *) node;
1616 
1617  set_opfuncid(expr);
1618  if (func_strict(expr->opfuncid))
1619  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1620  }
1621  else if (IsA(node, ScalarArrayOpExpr))
1622  {
1623  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1624 
1625  if (is_strict_saop(expr, true))
1626  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1627  }
1628  else if (IsA(node, BoolExpr))
1629  {
1630  BoolExpr *expr = (BoolExpr *) node;
1631 
1632  switch (expr->boolop)
1633  {
1634  case AND_EXPR:
1635  /* At top level we can just recurse (to the List case) */
1636  if (top_level)
1637  {
1638  result = find_nonnullable_vars_walker((Node *) expr->args,
1639  top_level);
1640  break;
1641  }
1642 
1643  /*
1644  * Below top level, even if one arm produces NULL, the result
1645  * could be FALSE (hence not NULL). However, if *all* the
1646  * arms produce NULL then the result is NULL, so we can take
1647  * the intersection of the sets of nonnullable vars, just as
1648  * for OR. Fall through to share code.
1649  */
1650  /* FALL THRU */
1651  case OR_EXPR:
1652 
1653  /*
1654  * OR is strict if all of its arms are, so we can take the
1655  * intersection of the sets of nonnullable vars for each arm.
1656  * This works for both values of top_level.
1657  */
1658  foreach(l, expr->args)
1659  {
1660  List *subresult;
1661 
1662  subresult = find_nonnullable_vars_walker(lfirst(l),
1663  top_level);
1664  if (result == NIL) /* first subresult? */
1665  result = subresult;
1666  else
1667  result = list_intersection(result, subresult);
1668 
1669  /*
1670  * If the intersection is empty, we can stop looking. This
1671  * also justifies the test for first-subresult above.
1672  */
1673  if (result == NIL)
1674  break;
1675  }
1676  break;
1677  case NOT_EXPR:
1678  /* NOT will return null if its arg is null */
1679  result = find_nonnullable_vars_walker((Node *) expr->args,
1680  false);
1681  break;
1682  default:
1683  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1684  break;
1685  }
1686  }
1687  else if (IsA(node, RelabelType))
1688  {
1689  RelabelType *expr = (RelabelType *) node;
1690 
1691  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1692  }
1693  else if (IsA(node, CoerceViaIO))
1694  {
1695  /* not clear this is useful, but it can't hurt */
1696  CoerceViaIO *expr = (CoerceViaIO *) node;
1697 
1698  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1699  }
1700  else if (IsA(node, ArrayCoerceExpr))
1701  {
1702  /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1703  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1704 
1705  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1706  }
1707  else if (IsA(node, ConvertRowtypeExpr))
1708  {
1709  /* not clear this is useful, but it can't hurt */
1710  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1711 
1712  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1713  }
1714  else if (IsA(node, CollateExpr))
1715  {
1716  CollateExpr *expr = (CollateExpr *) node;
1717 
1718  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1719  }
1720  else if (IsA(node, NullTest))
1721  {
1722  /* IS NOT NULL can be considered strict, but only at top level */
1723  NullTest *expr = (NullTest *) node;
1724 
1725  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1726  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1727  }
1728  else if (IsA(node, BooleanTest))
1729  {
1730  /* Boolean tests that reject NULL are strict at top level */
1731  BooleanTest *expr = (BooleanTest *) node;
1732 
1733  if (top_level &&
1734  (expr->booltesttype == IS_TRUE ||
1735  expr->booltesttype == IS_FALSE ||
1736  expr->booltesttype == IS_NOT_UNKNOWN))
1737  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1738  }
1739  else if (IsA(node, PlaceHolderVar))
1740  {
1741  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1742 
1743  result = find_nonnullable_vars_walker((Node *) phv->phexpr, top_level);
1744  }
1745  return result;
1746 }
List * list_intersection(const List *list1, const List *list2)
Definition: list.c:1133

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

◆ find_window_functions()

WindowFuncLists* find_window_functions ( Node clause,
Index  maxWinRef 
)

Definition at line 226 of file clauses.c.

227 {
228  WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
229 
230  lists->numWindowFuncs = 0;
231  lists->maxWinRef = maxWinRef;
232  lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
233  (void) find_window_functions_walker(clause, lists);
234  return lists;
235 }
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:238
void * palloc0(Size size)
Definition: mcxt.c:1093
void * palloc(Size size)
Definition: mcxt.c:1062
List ** windowFuncs
Definition: clauses.h:23
Index maxWinRef
Definition: clauses.h:22
int numWindowFuncs
Definition: clauses.h:21

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

Referenced by grouping_planner().

◆ find_window_functions_walker()

static bool find_window_functions_walker ( Node node,
WindowFuncLists lists 
)
static

Definition at line 238 of file clauses.c.

239 {
240  if (node == NULL)
241  return false;
242  if (IsA(node, WindowFunc))
243  {
244  WindowFunc *wfunc = (WindowFunc *) node;
245 
246  /* winref is unsigned, so one-sided test is OK */
247  if (wfunc->winref > lists->maxWinRef)
248  elog(ERROR, "WindowFunc contains out-of-range winref %u",
249  wfunc->winref);
250  /* eliminate duplicates, so that we avoid repeated computation */
251  if (!list_member(lists->windowFuncs[wfunc->winref], wfunc))
252  {
253  lists->windowFuncs[wfunc->winref] =
254  lappend(lists->windowFuncs[wfunc->winref], wfunc);
255  lists->numWindowFuncs++;
256  }
257 
258  /*
259  * We assume that the parser checked that there are no window
260  * functions in the arguments or filter clause. Hence, we need not
261  * recurse into them. (If either the parser or the planner screws up
262  * on this point, the executor will still catch it; see ExecInitExpr.)
263  */
264  return false;
265  }
266  Assert(!IsA(node, SubLink));
268  (void *) lists);
269 }
bool list_member(const List *list, const void *datum)
Definition: list.c:640

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

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

4365 {
4366  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4367  char *src;
4368  Datum tmp;
4369  bool isNull;
4370  MemoryContext oldcxt;
4371  MemoryContext mycxt;
4372  inline_error_callback_arg callback_arg;
4373  ErrorContextCallback sqlerrcontext;
4374  FuncExpr *fexpr;
4376  TupleDesc rettupdesc;
4377  ParseState *pstate;
4378  List *raw_parsetree_list;
4379  List *querytree_list;
4380  Query *querytree;
4381  Node *newexpr;
4382  int *usecounts;
4383  ListCell *arg;
4384  int i;
4385 
4386  /*
4387  * Forget it if the function is not SQL-language or has other showstopper
4388  * properties. (The prokind and nargs checks are just paranoia.)
4389  */
4390  if (funcform->prolang != SQLlanguageId ||
4391  funcform->prokind != PROKIND_FUNCTION ||
4392  funcform->prosecdef ||
4393  funcform->proretset ||
4394  funcform->prorettype == RECORDOID ||
4395  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL) ||
4396  funcform->pronargs != list_length(args))
4397  return NULL;
4398 
4399  /* Check for recursive function, and give up trying to expand if so */
4400  if (list_member_oid(context->active_fns, funcid))
4401  return NULL;
4402 
4403  /* Check permission to call function (fail later, if not) */
4405  return NULL;
4406 
4407  /* Check whether a plugin wants to hook function entry/exit */
4408  if (FmgrHookIsNeeded(funcid))
4409  return NULL;
4410 
4411  /*
4412  * Make a temporary memory context, so that we don't leak all the stuff
4413  * that parsing might create.
4414  */
4416  "inline_function",
4418  oldcxt = MemoryContextSwitchTo(mycxt);
4419 
4420  /*
4421  * We need a dummy FuncExpr node containing the already-simplified
4422  * arguments. (In some cases we don't really need it, but building it is
4423  * cheap enough that it's not worth contortions to avoid.)
4424  */
4425  fexpr = makeNode(FuncExpr);
4426  fexpr->funcid = funcid;
4427  fexpr->funcresulttype = result_type;
4428  fexpr->funcretset = false;
4429  fexpr->funcvariadic = funcvariadic;
4430  fexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
4431  fexpr->funccollid = result_collid; /* doesn't matter */
4432  fexpr->inputcollid = input_collid;
4433  fexpr->args = args;
4434  fexpr->location = -1;
4435 
4436  /* Fetch the function body */
4437  tmp = SysCacheGetAttr(PROCOID,
4438  func_tuple,
4439  Anum_pg_proc_prosrc,
4440  &isNull);
4441  if (isNull)
4442  elog(ERROR, "null prosrc for function %u", funcid);
4443  src = TextDatumGetCString(tmp);
4444 
4445  /*
4446  * Setup error traceback support for ereport(). This is so that we can
4447  * finger the function that bad information came from.
4448  */
4449  callback_arg.proname = NameStr(funcform->proname);
4450  callback_arg.prosrc = src;
4451 
4452  sqlerrcontext.callback = sql_inline_error_callback;
4453  sqlerrcontext.arg = (void *) &callback_arg;
4454  sqlerrcontext.previous = error_context_stack;
4455  error_context_stack = &sqlerrcontext;
4456 
4457  /* If we have prosqlbody, pay attention to that not prosrc */
4458  tmp = SysCacheGetAttr(PROCOID,
4459  func_tuple,
4460  Anum_pg_proc_prosqlbody,
4461  &isNull);
4462  if (!isNull)
4463  {
4464  Node *n;
4465  List *querytree_list;
4466 
4468  if (IsA(n, List))
4469  querytree_list = linitial_node(List, castNode(List, n));
4470  else
4471  querytree_list = list_make1(n);
4472  if (list_length(querytree_list) != 1)
4473  goto fail;
4474  querytree = linitial(querytree_list);
4475 
4476  /*
4477  * Because we'll insist below that the querytree have an empty rtable
4478  * and no sublinks, it cannot have any relation references that need
4479  * to be locked or rewritten. So we can omit those steps.
4480  */
4481  }
4482  else
4483  {
4484  /* Set up to handle parameters while parsing the function body. */
4485  pinfo = prepare_sql_fn_parse_info(func_tuple,
4486  (Node *) fexpr,
4487  input_collid);
4488 
4489  /*
4490  * We just do parsing and parse analysis, not rewriting, because
4491  * rewriting will not affect table-free-SELECT-only queries, which is
4492  * all that we care about. Also, we can punt as soon as we detect
4493  * more than one command in the function body.
4494  */
4495  raw_parsetree_list = pg_parse_query(src);
4496  if (list_length(raw_parsetree_list) != 1)
4497  goto fail;
4498 
4499  pstate = make_parsestate(NULL);
4500  pstate->p_sourcetext = src;
4501  sql_fn_parser_setup(pstate, pinfo);
4502 
4503  querytree = transformTopLevelStmt(pstate, linitial(raw_parsetree_list));
4504 
4505  free_parsestate(pstate);
4506  }
4507 
4508  /*
4509  * The single command must be a simple "SELECT expression".
4510  *
4511  * Note: if you change the tests involved in this, see also plpgsql's
4512  * exec_simple_check_plan(). That generally needs to have the same idea
4513  * of what's a "simple expression", so that inlining a function that
4514  * previously wasn't inlined won't change plpgsql's conclusion.
4515  */
4516  if (!IsA(querytree, Query) ||
4517  querytree->commandType != CMD_SELECT ||
4518  querytree->hasAggs ||
4519  querytree->hasWindowFuncs ||
4520  querytree->hasTargetSRFs ||
4521  querytree->hasSubLinks ||
4522  querytree->cteList ||
4523  querytree->rtable ||
4524  querytree->jointree->fromlist ||
4525  querytree->jointree->quals ||
4526  querytree->groupClause ||
4527  querytree->groupingSets ||
4528  querytree->havingQual ||
4529  querytree->windowClause ||
4530  querytree->distinctClause ||
4531  querytree->sortClause ||
4532  querytree->limitOffset ||
4533  querytree->limitCount ||
4534  querytree->setOperations ||
4535  list_length(querytree->targetList) != 1)
4536  goto fail;
4537 
4538  /* If the function result is composite, resolve it */
4539  (void) get_expr_result_type((Node *) fexpr,
4540  NULL,
4541  &rettupdesc);
4542 
4543  /*
4544  * Make sure the function (still) returns what it's declared to. This
4545  * will raise an error if wrong, but that's okay since the function would
4546  * fail at runtime anyway. Note that check_sql_fn_retval will also insert
4547  * a coercion if needed to make the tlist expression match the declared
4548  * type of the function.
4549  *
4550  * Note: we do not try this until we have verified that no rewriting was
4551  * needed; that's probably not important, but let's be careful.
4552  */
4553  querytree_list = list_make1(querytree);
4554  if (check_sql_fn_retval(list_make1(querytree_list),
4555  result_type, rettupdesc,
4556  false, NULL))
4557  goto fail; /* reject whole-tuple-result cases */
4558 
4559  /*
4560  * Given the tests above, check_sql_fn_retval shouldn't have decided to
4561  * inject a projection step, but let's just make sure.
4562  */
4563  if (querytree != linitial(querytree_list))
4564  goto fail;
4565 
4566  /* Now we can grab the tlist expression */
4567  newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr;
4568 
4569  /*
4570  * If the SQL function returns VOID, we can only inline it if it is a
4571  * SELECT of an expression returning VOID (ie, it's just a redirection to
4572  * another VOID-returning function). In all non-VOID-returning cases,
4573  * check_sql_fn_retval should ensure that newexpr returns the function's
4574  * declared result type, so this test shouldn't fail otherwise; but we may
4575  * as well cope gracefully if it does.
4576  */
4577  if (exprType(newexpr) != result_type)
4578  goto fail;
4579 
4580  /*
4581  * Additional validity checks on the expression. It mustn't be more
4582  * volatile than the surrounding function (this is to avoid breaking hacks
4583  * that involve pretending a function is immutable when it really ain't).
4584  * If the surrounding function is declared strict, then the expression
4585  * must contain only strict constructs and must use all of the function
4586  * parameters (this is overkill, but an exact analysis is hard).
4587  */
4588  if (funcform->provolatile == PROVOLATILE_IMMUTABLE &&
4589  contain_mutable_functions(newexpr))
4590  goto fail;
4591  else if (funcform->provolatile == PROVOLATILE_STABLE &&
4592  contain_volatile_functions(newexpr))
4593  goto fail;
4594 
4595  if (funcform->proisstrict &&
4596  contain_nonstrict_functions(newexpr))
4597  goto fail;
4598 
4599  /*
4600  * If any parameter expression contains a context-dependent node, we can't
4601  * inline, for fear of putting such a node into the wrong context.
4602  */
4604  goto fail;
4605 
4606  /*
4607  * We may be able to do it; there are still checks on parameter usage to
4608  * make, but those are most easily done in combination with the actual
4609  * substitution of the inputs. So start building expression with inputs
4610  * substituted.
4611  */
4612  usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
4613  newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
4614  args, usecounts);
4615 
4616  /* Now check for parameter usage */
4617  i = 0;
4618  foreach(arg, args)
4619  {
4620  Node *param = lfirst(arg);
4621 
4622  if (usecounts[i] == 0)
4623  {
4624  /* Param not used at all: uncool if func is strict */
4625  if (funcform->proisstrict)
4626  goto fail;
4627  }
4628  else if (usecounts[i] != 1)
4629  {
4630  /* Param used multiple times: uncool if expensive or volatile */
4631  QualCost eval_cost;
4632 
4633  /*
4634  * We define "expensive" as "contains any subplan or more than 10
4635  * operators". Note that the subplan search has to be done
4636  * explicitly, since cost_qual_eval() will barf on unplanned
4637  * subselects.
4638  */
4639  if (contain_subplans(param))
4640  goto fail;
4641  cost_qual_eval(&eval_cost, list_make1(param), NULL);
4642  if (eval_cost.startup + eval_cost.per_tuple >
4643  10 * cpu_operator_cost)
4644  goto fail;
4645 
4646  /*
4647  * Check volatility last since this is more expensive than the
4648  * above tests
4649  */
4650  if (contain_volatile_functions(param))
4651  goto fail;
4652  }
4653  i++;
4654  }
4655 
4656  /*
4657  * Whew --- we can make the substitution. Copy the modified expression
4658  * out of the temporary memory context, and clean up.
4659  */
4660  MemoryContextSwitchTo(oldcxt);
4661 
4662  newexpr = copyObject(newexpr);
4663 
4664  MemoryContextDelete(mycxt);
4665 
4666  /*
4667  * If the result is of a collatable type, force the result to expose the
4668  * correct collation. In most cases this does not matter, but it's
4669  * possible that the function result is used directly as a sort key or in
4670  * other places where we expect exprCollation() to tell the truth.
4671  */
4672  if (OidIsValid(result_collid))
4673  {
4674  Oid exprcoll = exprCollation(newexpr);
4675 
4676  if (OidIsValid(exprcoll) && exprcoll != result_collid)
4677  {
4678  CollateExpr *newnode = makeNode(CollateExpr);
4679 
4680  newnode->arg = (Expr *) newexpr;
4681  newnode->collOid = result_collid;
4682  newnode->location = -1;
4683 
4684  newexpr = (Node *) newnode;
4685  }
4686  }
4687 
4688  /*
4689  * Since there is now no trace of the function in the plan tree, we must
4690  * explicitly record the plan's dependency on the function.
4691  */
4692  if (context->root)
4693  record_plan_function_dependency(context->root, funcid);
4694 
4695  /*
4696  * Recursively try to simplify the modified expression. Here we must add
4697  * the current function to the context list of active functions.
4698  */
4699  context->active_fns = lappend_oid(context->active_fns, funcid);
4700  newexpr = eval_const_expressions_mutator(newexpr, context);
4701  context->active_fns = list_delete_last(context->active_fns);
4702 
4703  error_context_stack = sqlerrcontext.previous;
4704 
4705  return (Expr *) newexpr;
4706 
4707  /* Here if func is not inlinable: release temp memory and return NULL */
4708 fail:
4709  MemoryContextSwitchTo(oldcxt);
4710  MemoryContextDelete(mycxt);
4711  error_context_stack = sqlerrcontext.previous;
4712 
4713  return NULL;
4714 }
Datum querytree(PG_FUNCTION_ARGS)
Definition: _int_bool.c:664
@ ACLCHECK_OK
Definition: acl.h:179
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4720
#define NameStr(name)
Definition: c.h:681
static Node * substitute_actual_parameters(Node *expr, int nargs, List *args, int *usecounts)
Definition: clauses.c:4720
static void sql_inline_error_callback(void *arg)
Definition: clauses.c:4762
static bool contain_context_dependent_node(Node *clause)
Definition: clauses.c:1066
bool contain_nonstrict_functions(Node *clause)
Definition: clauses.c:880
bool contain_subplans(Node *clause)
Definition: clauses.c:329
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:453
double cpu_operator_cost
Definition: costsize.c:123
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:4308
ErrorContextCallback * error_context_stack
Definition: elog.c:93
#define FmgrHookIsNeeded(fn_oid)
Definition: fmgr.h:779
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:223
bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, bool insertDroppedCols, List **resultTargetList)
Definition: functions.c:1599
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition: functions.c:265
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
Definition: functions.c:176
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
int i
Definition: isn.c:73
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:701
List * list_delete_last(List *list)
Definition: list.c:916
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
Oid GetUserId(void)
Definition: miscinit.c:495
@ CMD_SELECT
Definition: nodes.h:685
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
#define ACL_EXECUTE
Definition: parsenodes.h:89
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:213
#define linitial_node(type, l)
Definition: pg_list.h:177
List * pg_parse_query(const char *query_string)
Definition: postgres.c:595
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:3004
struct ErrorContextCallback * previous
Definition: elog.h:232
void(* callback)(void *arg)
Definition: elog.h:233
const char * p_sourcetext
Definition: parse_node.h:181
Cost per_tuple
Definition: pathnodes.h:46
Cost startup
Definition: pathnodes.h:45

References ACL_EXECUTE, ACLCHECK_OK, eval_const_expressions_context::active_fns, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, arg, CollateExpr::arg, ErrorContextCallback::arg, generate_unaccent_rules::args, FuncExpr::args, ErrorContextCallback::callback, castNode, check_sql_fn_retval(), CMD_SELECT, COERCE_EXPLICIT_CALL, CollateExpr::collOid, contain_context_dependent_node(), contain_mutable_functions(), contain_nonstrict_functions(), contain_subplans(), contain_volatile_functions(), copyObject, cost_qual_eval(), cpu_operator_cost, CurrentMemoryContext, elog, ERROR, error_context_stack, eval_const_expressions_mutator(), exprCollation(), exprType(), FmgrHookIsNeeded, free_parsestate(), FuncExpr::funccollid, FuncExpr::funcformat, FuncExpr::funcid, FuncExpr::funcresulttype, FuncExpr::funcretset, FuncExpr::funcvariadic, get_expr_result_type(), GETSTRUCT, GetUserId(), heap_attisnull(), i, FuncExpr::inputcollid, IsA, lappend_oid(), lfirst, linitial, linitial_node, 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, querytree(), record_plan_function_dependency(), eval_const_expressions_context::root, sql_fn_parser_setup(), sql_inline_error_callback(), QualCost::startup, stringToNode(), substitute_actual_parameters(), SysCacheGetAttr(), TextDatumGetCString, and transformTopLevelStmt().

Referenced by simplify_function().

◆ inline_set_returning_function()

Query* inline_set_returning_function ( PlannerInfo root,
RangeTblEntry rte 
)

Definition at line 4878 of file clauses.c.

4879 {
4880  RangeTblFunction *rtfunc;
4881  FuncExpr *fexpr;
4882  Oid func_oid;
4883  HeapTuple func_tuple;
4884  Form_pg_proc funcform;
4885  char *src;
4886  Datum tmp;
4887  bool isNull;
4888  MemoryContext oldcxt;
4889  MemoryContext mycxt;
4890  inline_error_callback_arg callback_arg;
4891  ErrorContextCallback sqlerrcontext;
4893  TypeFuncClass functypclass;
4894  TupleDesc rettupdesc;
4895  List *raw_parsetree_list;
4896  List *querytree_list;
4897  Query *querytree;
4898 
4899  Assert(rte->rtekind == RTE_FUNCTION);
4900 
4901  /*
4902  * It doesn't make a lot of sense for a SQL SRF to refer to itself in its
4903  * own FROM clause, since that must cause infinite recursion at runtime.
4904  * It will cause this code to recurse too, so check for stack overflow.
4905  * (There's no need to do more.)
4906  */
4908 
4909  /* Fail if the RTE has ORDINALITY - we don't implement that here. */
4910  if (rte->funcordinality)
4911  return NULL;
4912 
4913  /* Fail if RTE isn't a single, simple FuncExpr */
4914  if (list_length(rte->functions) != 1)
4915  return NULL;
4916  rtfunc = (RangeTblFunction *) linitial(rte->functions);
4917 
4918  if (!IsA(rtfunc->funcexpr, FuncExpr))
4919  return NULL;
4920  fexpr = (FuncExpr *) rtfunc->funcexpr;
4921 
4922  func_oid = fexpr->funcid;
4923 
4924  /*
4925  * The function must be declared to return a set, else inlining would
4926  * change the results if the contained SELECT didn't return exactly one
4927  * row.
4928  */
4929  if (!fexpr->funcretset)
4930  return NULL;
4931 
4932  /*
4933  * Refuse to inline if the arguments contain any volatile functions or
4934  * sub-selects. Volatile functions are rejected because inlining may
4935  * result in the arguments being evaluated multiple times, risking a
4936  * change in behavior. Sub-selects are rejected partly for implementation
4937  * reasons (pushing them down another level might change their behavior)
4938  * and partly because they're likely to be expensive and so multiple
4939  * evaluation would be bad.
4940  */
4941  if (contain_volatile_functions((Node *) fexpr->args) ||
4942  contain_subplans((Node *) fexpr->args))
4943  return NULL;
4944 
4945  /* Check permission to call function (fail later, if not) */
4946  if (pg_proc_aclcheck(func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
4947  return NULL;
4948 
4949  /* Check whether a plugin wants to hook function entry/exit */
4950  if (FmgrHookIsNeeded(func_oid))
4951  return NULL;
4952 
4953  /*
4954  * OK, let's take a look at the function's pg_proc entry.
4955  */
4956  func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid));
4957  if (!HeapTupleIsValid(func_tuple))
4958  elog(ERROR, "cache lookup failed for function %u", func_oid);
4959  funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4960 
4961  /*
4962  * Forget it if the function is not SQL-language or has other showstopper
4963  * properties. In particular it mustn't be declared STRICT, since we
4964  * couldn't enforce that. It also mustn't be VOLATILE, because that is
4965  * supposed to cause it to be executed with its own snapshot, rather than
4966  * sharing the snapshot of the calling query. We also disallow returning
4967  * SETOF VOID, because inlining would result in exposing the actual result
4968  * of the function's last SELECT, which should not happen in that case.
4969  * (Rechecking prokind, proretset, and pronargs is just paranoia.)
4970  */
4971  if (funcform->prolang != SQLlanguageId ||
4972  funcform->prokind != PROKIND_FUNCTION ||
4973  funcform->proisstrict ||
4974  funcform->provolatile == PROVOLATILE_VOLATILE ||
4975  funcform->prorettype == VOIDOID ||
4976  funcform->prosecdef ||
4977  !funcform->proretset ||
4978  list_length(fexpr->args) != funcform->pronargs ||
4979  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL))
4980  {
4981  ReleaseSysCache(func_tuple);
4982  return NULL;
4983  }
4984 
4985  /*
4986  * Make a temporary memory context, so that we don't leak all the stuff
4987  * that parsing might create.
4988  */
4990  "inline_set_returning_function",
4992  oldcxt = MemoryContextSwitchTo(mycxt);
4993 
4994  /* Fetch the function body */
4995  tmp = SysCacheGetAttr(PROCOID,
4996  func_tuple,
4997  Anum_pg_proc_prosrc,
4998  &isNull);
4999  if (isNull)
5000  elog(ERROR, "null prosrc for function %u", func_oid);
5001  src = TextDatumGetCString(tmp);
5002 
5003  /*
5004  * Setup error traceback support for ereport(). This is so that we can
5005  * finger the function that bad information came from.
5006  */
5007  callback_arg.proname = NameStr(funcform->proname);
5008  callback_arg.prosrc = src;
5009 
5010  sqlerrcontext.callback = sql_inline_error_callback;
5011  sqlerrcontext.arg = (void *) &callback_arg;
5012  sqlerrcontext.previous = error_context_stack;
5013  error_context_stack = &sqlerrcontext;
5014 
5015  /* If we have prosqlbody, pay attention to that not prosrc */
5016  tmp = SysCacheGetAttr(PROCOID,
5017  func_tuple,
5018  Anum_pg_proc_prosqlbody,
5019  &isNull);
5020  if (!isNull)
5021  {
5022  Node *n;
5023 
5025  if (IsA(n, List))
5026  querytree_list = linitial_node(List, castNode(List, n));
5027  else
5028  querytree_list = list_make1(n);
5029  if (list_length(querytree_list) != 1)
5030  goto fail;
5031  querytree = linitial(querytree_list);
5032 
5033  /* Acquire necessary locks, then apply rewriter. */
5034  AcquireRewriteLocks(querytree, true, false);
5035  querytree_list = pg_rewrite_query(querytree);
5036  if (list_length(querytree_list) != 1)
5037  goto fail;
5038  querytree = linitial(querytree_list);
5039  }
5040  else
5041  {
5042  /*
5043  * Set up to handle parameters while parsing the function body. We
5044  * can use the FuncExpr just created as the input for
5045  * prepare_sql_fn_parse_info.
5046  */
5047  pinfo = prepare_sql_fn_parse_info(func_tuple,
5048  (Node *) fexpr,
5049  fexpr->inputcollid);
5050 
5051  /*
5052  * Parse, analyze, and rewrite (unlike inline_function(), we can't
5053  * skip rewriting here). We can fail as soon as we find more than one
5054  * query, though.
5055  */
5056  raw_parsetree_list = pg_parse_query(src);
5057  if (list_length(raw_parsetree_list) != 1)
5058  goto fail;
5059 
5060  querytree_list = pg_analyze_and_rewrite_params(linitial(raw_parsetree_list),
5061  src,
5063  pinfo, NULL);
5064  if (list_length(querytree_list) != 1)
5065  goto fail;
5066  querytree = linitial(querytree_list);
5067  }
5068 
5069  /*
5070  * Also resolve the actual function result tupdesc, if composite. If the
5071  * function is just declared to return RECORD, dig the info out of the AS
5072  * clause.
5073  */
5074  functypclass = get_expr_result_type((Node *) fexpr, NULL, &rettupdesc);
5075  if (functypclass == TYPEFUNC_RECORD)
5076  rettupdesc = BuildDescFromLists(rtfunc->funccolnames,
5077  rtfunc->funccoltypes,
5078  rtfunc->funccoltypmods,
5079  rtfunc->funccolcollations);
5080 
5081  /*
5082  * The single command must be a plain SELECT.
5083  */
5084  if (!IsA(querytree, Query) ||
5085  querytree->commandType != CMD_SELECT)
5086  goto fail;
5087 
5088  /*
5089  * Make sure the function (still) returns what it's declared to. This
5090  * will raise an error if wrong, but that's okay since the function would
5091  * fail at runtime anyway. Note that check_sql_fn_retval will also insert
5092  * coercions if needed to make the tlist expression(s) match the declared
5093  * type of the function. We also ask it to insert dummy NULL columns for
5094  * any dropped columns in rettupdesc, so that the elements of the modified
5095  * tlist match up to the attribute numbers.
5096  *
5097  * If the function returns a composite type, don't inline unless the check
5098  * shows it's returning a whole tuple result; otherwise what it's
5099  * returning is a single composite column which is not what we need.
5100  */
5101  if (!check_sql_fn_retval(list_make1(querytree_list),
5102  fexpr->funcresulttype, rettupdesc,
5103  true, NULL) &&
5104  (functypclass == TYPEFUNC_COMPOSITE ||
5105  functypclass == TYPEFUNC_COMPOSITE_DOMAIN ||
5106  functypclass == TYPEFUNC_RECORD))
5107  goto fail; /* reject not-whole-tuple-result cases */
5108 
5109  /*
5110  * check_sql_fn_retval might've inserted a projection step, but that's
5111  * fine; just make sure we use the upper Query.
5112  */
5113  querytree = linitial_node(Query, querytree_list);
5114 
5115  /*
5116  * Looks good --- substitute parameters into the query.
5117  */
5119  funcform->pronargs,
5120  fexpr->args);
5121 
5122  /*
5123  * Copy the modified query out of the temporary memory context, and clean
5124  * up.
5125  */
5126  MemoryContextSwitchTo(oldcxt);
5127 
5129 
5130  MemoryContextDelete(mycxt);
5131  error_context_stack = sqlerrcontext.previous;
5132  ReleaseSysCache(func_tuple);
5133 
5134  /*
5135  * We don't have to fix collations here because the upper query is already
5136  * parsed, ie, the collations in the RTE are what count.
5137  */
5138 
5139  /*
5140  * Since there is now no trace of the function in the plan tree, we must
5141  * explicitly record the plan's dependency on the function.
5142  */
5143  record_plan_function_dependency(root, func_oid);
5144 
5145  return querytree;
5146 
5147  /* Here if func is not inlinable: release temp memory and return NULL */
5148 fail:
5149  MemoryContextSwitchTo(oldcxt);
5150  MemoryContextDelete(mycxt);
5151  error_context_stack = sqlerrcontext.previous;
5152  ReleaseSysCache(func_tuple);
5153 
5154  return NULL;
5155 }
static Query * substitute_actual_srf_parameters(Query *expr, int nargs, List *args)
Definition: clauses.c:5164
TypeFuncClass
Definition: funcapi.h:147
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
@ TYPEFUNC_RECORD
Definition: funcapi.h:151
@ TYPEFUNC_COMPOSITE_DOMAIN
Definition: funcapi.h:150
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
Definition: params.h:108
@ RTE_FUNCTION
Definition: parsenodes.h:993
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:680
List * pg_rewrite_query(Query *query)
Definition: postgres.c:738
void check_stack_depth(void)
Definition: postgres.c:3470
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
bool funcordinality
Definition: parsenodes.h:1102
List * functions
Definition: parsenodes.h:1101
RTEKind rtekind
Definition: parsenodes.h:1007
List * funccolcollations
Definition: parsenodes.h:1192
List * funccoltypmods
Definition: parsenodes.h:1191
TupleDesc BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
Definition: tupdesc.c:877

References ACL_EXECUTE, ACLCHECK_OK, AcquireRewriteLocks(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, FuncExpr::args, Assert(), BuildDescFromLists(), ErrorContextCallback::callback, castNode, check_sql_fn_retval(), check_stack_depth(), CMD_SELECT, 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::funcresulttype, FuncExpr::funcretset, RangeTblEntry::functions, get_expr_result_type(), GETSTRUCT, GetUserId(), heap_attisnull(), HeapTupleIsValid, if(), IsA, linitial, linitial_node, list_length(), list_make1, MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, ObjectIdGetDatum, pg_analyze_and_rewrite_params(), pg_parse_query(), pg_proc_aclcheck(), pg_rewrite_query(), 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(), stringToNode(), substitute_actual_srf_parameters(), SysCacheGetAttr(), TextDatumGetCString, TYPEFUNC_COMPOSITE, TYPEFUNC_COMPOSITE_DOMAIN, and TYPEFUNC_RECORD.

Referenced by preprocess_function_rtes().

◆ is_parallel_safe()

bool is_parallel_safe ( PlannerInfo root,
Node node 
)

Definition at line 640 of file clauses.c.

641 {
643  PlannerInfo *proot;
644  ListCell *l;
645 
646  /*
647  * Even if the original querytree contained nothing unsafe, we need to
648  * search the expression if we have generated any PARAM_EXEC Params while
649  * planning, because those are parallel-restricted and there might be one
650  * in this expression. But otherwise we don't need to look.
651  */
652  if (root->glob->maxParallelHazard == PROPARALLEL_SAFE &&
653  root->glob->paramExecTypes == NIL)
654  return true;
655  /* Else use max_parallel_hazard's search logic, but stop on RESTRICTED */
656  context.max_hazard = PROPARALLEL_SAFE;
657  context.max_interesting = PROPARALLEL_RESTRICTED;
658  context.safe_param_ids = NIL;
659 
660  /*
661  * The params that refer to the same or parent query level are considered
662  * parallel-safe. The idea is that we compute such params at Gather or
663  * Gather Merge node and pass their value to workers.
664  */
665  for (proot = root; proot != NULL; proot = proot->parent_root)
666  {
667  foreach(l, proot->init_plans)
668  {
669  SubPlan *initsubplan = (SubPlan *) lfirst(l);
670 
671  context.safe_param_ids = list_concat(context.safe_param_ids,
672  initsubplan->setParam);
673  }
674  }
675 
676  return !max_parallel_hazard_walker(node, &context);
677 }
static bool max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
Definition: clauses.c:716
char maxParallelHazard
Definition: pathnodes.h:130
List * paramExecTypes
Definition: pathnodes.h:114
List * init_plans
Definition: pathnodes.h:242
PlannerInfo * parent_root
Definition: pathnodes.h:168
List * setParam
Definition: primnodes.h:770

References PlannerInfo::glob, PlannerInfo::init_plans, lfirst, list_concat(), max_parallel_hazard_context::max_hazard, max_parallel_hazard_context::max_interesting, max_parallel_hazard_walker(), PlannerGlobal::maxParallelHazard, NIL, PlannerGlobal::paramExecTypes, PlannerInfo::parent_root, max_parallel_hazard_context::safe_param_ids, and SubPlan::setParam.

Referenced by apply_projection_to_path(), build_join_rel(), create_projection_path(), create_set_projection_path(), create_window_paths(), find_computable_ec_member(), grouping_planner(), make_grouping_rel(), plan_create_index_workers(), query_planner(), relation_can_be_sorted_early(), and set_rel_consider_parallel().

◆ is_pseudo_constant_clause()

bool is_pseudo_constant_clause ( Node clause)

Definition at line 1931 of file clauses.c.

1932 {
1933  /*
1934  * We could implement this check in one recursive scan. But since the
1935  * check for volatile functions is both moderately expensive and unlikely
1936  * to fail, it seems better to look for Vars first and only check for
1937  * volatile functions if we find no Vars.
1938  */
1939  if (!contain_var_clause(clause) &&
1940  !contain_volatile_functions(clause))
1941  return true;
1942  return false;
1943 }

References contain_var_clause(), and contain_volatile_functions().

Referenced by clauselist_selectivity_ext(), dependency_is_compatible_clause(), and dependency_is_compatible_expression().

◆ is_pseudo_constant_clause_relids()

bool is_pseudo_constant_clause_relids ( Node clause,
Relids  relids 
)

Definition at line 1951 of file clauses.c.

1952 {
1953  if (bms_is_empty(relids) &&
1954  !contain_volatile_functions(clause))
1955  return true;
1956  return false;
1957 }

References bms_is_empty(), and contain_volatile_functions().

Referenced by clauselist_selectivity_ext().

◆ is_strict_saop()

static bool is_strict_saop ( ScalarArrayOpExpr expr,
bool  falseOK 
)
static

Definition at line 1869 of file clauses.c.

1870 {
1871  Node *rightop;
1872 
1873  /* The contained operator must be strict. */
1874  set_sa_opfuncid(expr);
1875  if (!func_strict(expr->opfuncid))
1876  return false;
1877  /* If ANY and falseOK, that's all we need to check. */
1878  if (expr->useOr && falseOK)
1879  return true;
1880  /* Else, we have to see if the array is provably non-empty. */
1881  Assert(list_length(expr->args) == 2);
1882  rightop = (Node *) lsecond(expr->args);
1883  if (rightop && IsA(rightop, Const))
1884  {
1885  Datum arraydatum = ((Const *) rightop)->constvalue;
1886  bool arrayisnull = ((Const *) rightop)->constisnull;
1887  ArrayType *arrayval;
1888  int nitems;
1889 
1890  if (arrayisnull)
1891  return false;
1892  arrayval = DatumGetArrayTypeP(arraydatum);
1893  nitems = ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval));
1894  if (nitems > 0)
1895  return true;
1896  }
1897  else if (rightop && IsA(rightop, ArrayExpr))
1898  {
1899  ArrayExpr *arrayexpr = (ArrayExpr *) rightop;
1900 
1901  if (arrayexpr->elements != NIL && !arrayexpr->multidims)
1902  return true;
1903  }
1904  return false;
1905 }
bool multidims
Definition: primnodes.h:1038
List * elements
Definition: primnodes.h:1037

References ScalarArrayOpExpr::args, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), Assert(), DatumGetArrayTypeP, ArrayExpr::elements, func_strict(), IsA, list_length(), lsecond, ArrayExpr::multidims, NIL, ScalarArrayOpExpr::opfuncid, set_sa_opfuncid(), and ScalarArrayOpExpr::useOr.

Referenced by find_nonnullable_rels_walker(), and find_nonnullable_vars_walker().

◆ max_parallel_hazard()

char max_parallel_hazard ( Query parse)

Definition at line 621 of file clauses.c.

622 {
624 
625  context.max_hazard = PROPARALLEL_SAFE;
626  context.max_interesting = PROPARALLEL_UNSAFE;
627  context.safe_param_ids = NIL;
628  (void) max_parallel_hazard_walker((Node *) parse, &context);
629  return context.max_hazard;
630 }
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:673

References max_parallel_hazard_context::max_hazard, max_parallel_hazard_context::max_interesting, max_parallel_hazard_walker(), NIL, parse(), and max_parallel_hazard_context::safe_param_ids.

Referenced by standard_planner().

◆ max_parallel_hazard_checker()

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

Definition at line 709 of file clauses.c.

710 {
711  return max_parallel_hazard_test(func_parallel(func_id),
712  (max_parallel_hazard_context *) context);
713 }
static bool max_parallel_hazard_test(char proparallel, max_parallel_hazard_context *context)
Definition: clauses.c:681
char func_parallel(Oid funcid)
Definition: lsyscache.c:1770

References func_parallel(), and max_parallel_hazard_test().

Referenced by max_parallel_hazard_walker().

◆ max_parallel_hazard_test()

static bool max_parallel_hazard_test ( char  proparallel,
max_parallel_hazard_context context 
)
static

Definition at line 681 of file clauses.c.

682 {
683  switch (proparallel)
684  {
685  case PROPARALLEL_SAFE:
686  /* nothing to see here, move along */
687  break;
688  case PROPARALLEL_RESTRICTED:
689  /* increase max_hazard to RESTRICTED */
690  Assert(context->max_hazard != PROPARALLEL_UNSAFE);
691  context->max_hazard = proparallel;
692  /* done if we are not expecting any unsafe functions */
693  if (context->max_interesting == proparallel)
694  return true;
695  break;
696  case PROPARALLEL_UNSAFE:
697  context->max_hazard = proparallel;
698  /* we're always done at the first unsafe construct */
699  return true;
700  default:
701  elog(ERROR, "unrecognized proparallel value \"%c\"", proparallel);
702  break;
703  }
704  return false;
705 }

References Assert(), elog, ERROR, max_parallel_hazard_context::max_hazard, and max_parallel_hazard_context::max_interesting.

Referenced by max_parallel_hazard_checker(), and max_parallel_hazard_walker().

◆ max_parallel_hazard_walker()

static bool max_parallel_hazard_walker ( Node node,
max_parallel_hazard_context context 
)
static

Definition at line 716 of file clauses.c.

717 {
718  if (node == NULL)
719  return false;
720 
721  /* Check for hazardous functions in node itself */
723  context))
724  return true;
725 
726  /*
727  * It should be OK to treat MinMaxExpr as parallel-safe, since btree
728  * opclass support functions are generally parallel-safe. XmlExpr is a
729  * bit more dubious but we can probably get away with it. We err on the
730  * side of caution by treating CoerceToDomain as parallel-restricted.
731  * (Note: in principle that's wrong because a domain constraint could
732  * contain a parallel-unsafe function; but useful constraints probably
733  * never would have such, and assuming they do would cripple use of
734  * parallel query in the presence of domain types.) SQLValueFunction
735  * should be safe in all cases. NextValueExpr is parallel-unsafe.
736  */
737  if (IsA(node, CoerceToDomain))
738  {
739  if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
740  return true;
741  }
742 
743  else if (IsA(node, NextValueExpr))
744  {
745  if (max_parallel_hazard_test(PROPARALLEL_UNSAFE, context))
746  return true;
<