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/multibitmapset.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/json.h"
#include "utils/jsonb.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 1096 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 2335 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:4854
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:43
Definition: nodes.h:129

Definition at line 2339 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:2349
#define expression_tree_mutator(n, m, c)
Definition: nodeFuncs.h:153

Definition at line 2326 of file clauses.c.

◆ MIN_ARRAY_SIZE_FOR_HASHED_SAOP

#define MIN_ARRAY_SIZE_FOR_HASHED_SAOP   9

Definition at line 2178 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 4207 of file clauses.c.

4208 {
4209  int nargsprovided = list_length(args);
4210  List *defaults;
4211  int ndelete;
4212 
4213  /* Get all the default expressions from the pg_proc tuple */
4214  defaults = fetch_function_defaults(func_tuple);
4215 
4216  /* Delete any unused defaults from the list */
4217  ndelete = nargsprovided + list_length(defaults) - pronargs;
4218  if (ndelete < 0)
4219  elog(ERROR, "not enough default arguments");
4220  if (ndelete > 0)
4221  defaults = list_delete_first_n(defaults, ndelete);
4222 
4223  /* And form the combined argument list, not modifying the input list */
4224  return list_concat_copy(args, defaults);
4225 }
static List * fetch_function_defaults(HeapTuple func_tuple)
Definition: clauses.c:4231
#define ERROR
Definition: elog.h:39
List * list_delete_first_n(List *list, int n)
Definition: list.c:982
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:597
static int list_length(const List *l)
Definition: pg_list.h:152
int16 pronargs
Definition: pg_proc.h:81
Definition: pg_list.h:54

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

2057 {
2058  Oid opoid;
2059  Node *temp;
2060 
2061  /* Sanity checks: caller is at fault if these fail */
2062  if (!is_opclause(clause) ||
2063  list_length(clause->args) != 2)
2064  elog(ERROR, "cannot commute non-binary-operator clause");
2065 
2066  opoid = get_commutator(clause->opno);
2067 
2068  if (!OidIsValid(opoid))
2069  elog(ERROR, "could not find commutator for operator %u",
2070  clause->opno);
2071 
2072  /*
2073  * modify the clause in-place!
2074  */
2075  clause->opno = opoid;
2076  clause->opfuncid = InvalidOid;
2077  /* opresulttype, opretset, opcollid, inputcollid need not change */
2078 
2079  temp = linitial(clause->args);
2080  linitial(clause->args) = lsecond(clause->args);
2081  lsecond(clause->args) = temp;
2082 }
#define OidIsValid(objectId)
Definition: c.h:759
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1491
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:74
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
Oid opno
Definition: primnodes.h:745
List * args
Definition: primnodes.h:763

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

Referenced by get_switched_clauses().

◆ contain_agg_clause()

bool contain_agg_clause ( Node clause)

Definition at line 179 of file clauses.c.

180 {
181  return contain_agg_clause_walker(clause, NULL);
182 }
static bool contain_agg_clause_walker(Node *node, void *context)
Definition: clauses.c:185

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

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

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

1090 {
1091  int flags = 0;
1092 
1093  return contain_context_dependent_node_walker(clause, &flags);
1094 }
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:1099

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

1100 {
1101  if (node == NULL)
1102  return false;
1103  if (IsA(node, CaseTestExpr))
1104  return !(*flags & CCDN_CASETESTEXPR_OK);
1105  else if (IsA(node, CaseExpr))
1106  {
1107  CaseExpr *caseexpr = (CaseExpr *) node;
1108 
1109  /*
1110  * If this CASE doesn't have a test expression, then it doesn't create
1111  * a context in which CaseTestExprs should appear, so just fall
1112  * through and treat it as a generic expression node.
1113  */
1114  if (caseexpr->arg)
1115  {
1116  int save_flags = *flags;
1117  bool res;
1118 
1119  /*
1120  * Note: in principle, we could distinguish the various sub-parts
1121  * of a CASE construct and set the flag bit only for some of them,
1122  * since we are only expecting CaseTestExprs to appear in the
1123  * "expr" subtree of the CaseWhen nodes. But it doesn't really
1124  * seem worth any extra code. If there are any bare CaseTestExprs
1125  * elsewhere in the CASE, something's wrong already.
1126  */
1127  *flags |= CCDN_CASETESTEXPR_OK;
1128  res = expression_tree_walker(node,
1130  (void *) flags);
1131  *flags = save_flags;
1132  return res;
1133  }
1134  }
1135  else if (IsA(node, ArrayCoerceExpr))
1136  {
1137  ArrayCoerceExpr *ac = (ArrayCoerceExpr *) node;
1138  int save_flags;
1139  bool res;
1140 
1141  /* Check the array expression */
1142  if (contain_context_dependent_node_walker((Node *) ac->arg, flags))
1143  return true;
1144 
1145  /* Check the elemexpr, which is allowed to contain CaseTestExpr */
1146  save_flags = *flags;
1147  *flags |= CCDN_CASETESTEXPR_OK;
1149  flags);
1150  *flags = save_flags;
1151  return res;
1152  }
1154  (void *) flags);
1155 }
#define CCDN_CASETESTEXPR_OK
Definition: clauses.c:1096
Expr * arg
Definition: primnodes.h:1240

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

1048 {
1049  return contain_exec_param_walker(clause, param_ids);
1050 }
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition: clauses.c:1053

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

1054 {
1055  if (node == NULL)
1056  return false;
1057  if (IsA(node, Param))
1058  {
1059  Param *p = (Param *) node;
1060 
1061  if (p->paramkind == PARAM_EXEC &&
1062  list_member_int(param_ids, p->paramid))
1063  return true;
1064  }
1065  return expression_tree_walker(node, contain_exec_param_walker, param_ids);
1066 }
bool list_member_int(const List *list, int datum)
Definition: list.c:701
@ PARAM_EXEC
Definition: primnodes.h:346
int paramid
Definition: primnodes.h:355
ParamKind paramkind
Definition: primnodes.h:354

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

1174 {
1175  return contain_leaked_vars_walker(clause, NULL);
1176 }
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1185

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

1180 {
1181  return !get_func_leakproof(func_id);
1182 }
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1819

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

1186 {
1187  if (node == NULL)
1188  return false;
1189 
1190  switch (nodeTag(node))
1191  {
1192  case T_Var:
1193  case T_Const:
1194  case T_Param:
1195  case T_ArrayExpr:
1196  case T_FieldSelect:
1197  case T_FieldStore:
1198  case T_NamedArgExpr:
1199  case T_BoolExpr:
1200  case T_RelabelType:
1201  case T_CollateExpr:
1202  case T_CaseExpr:
1203  case T_CaseTestExpr:
1204  case T_RowExpr:
1205  case T_NullTest:
1206  case T_BooleanTest:
1207  case T_NextValueExpr:
1208  case T_List:
1209 
1210  /*
1211  * We know these node types don't contain function calls; but
1212  * something further down in the node tree might.
1213  */
1214  break;
1215 
1216  case T_FuncExpr:
1217  case T_OpExpr:
1218  case T_DistinctExpr:
1219  case T_NullIfExpr:
1220  case T_ScalarArrayOpExpr:
1221  case T_CoerceViaIO:
1222  case T_ArrayCoerceExpr:
1223 
1224  /*
1225  * If node contains a leaky function call, and there's any Var
1226  * underneath it, reject.
1227  */
1229  context) &&
1230  contain_var_clause(node))
1231  return true;
1232  break;
1233 
1234  case T_SubscriptingRef:
1235  {
1236  SubscriptingRef *sbsref = (SubscriptingRef *) node;
1237  const SubscriptRoutines *sbsroutines;
1238 
1239  /* Consult the subscripting support method info */
1240  sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype,
1241  NULL);
1242  if (!sbsroutines ||
1243  !(sbsref->refassgnexpr != NULL ?
1244  sbsroutines->store_leakproof :
1245  sbsroutines->fetch_leakproof))
1246  {
1247  /* Node is leaky, so reject if it contains Vars */
1248  if (contain_var_clause(node))
1249  return true;
1250  }
1251  }
1252  break;
1253 
1254  case T_RowCompareExpr:
1255  {
1256  /*
1257  * It's worth special-casing this because a leaky comparison
1258  * function only compromises one pair of row elements, which
1259  * might not contain Vars while others do.
1260  */
1261  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1262  ListCell *opid;
1263  ListCell *larg;
1264  ListCell *rarg;
1265 
1266  forthree(opid, rcexpr->opnos,
1267  larg, rcexpr->largs,
1268  rarg, rcexpr->rargs)
1269  {
1270  Oid funcid = get_opcode(lfirst_oid(opid));
1271 
1272  if (!get_func_leakproof(funcid) &&
1273  (contain_var_clause((Node *) lfirst(larg)) ||
1274  contain_var_clause((Node *) lfirst(rarg))))
1275  return true;
1276  }
1277  }
1278  break;
1279 
1280  case T_MinMaxExpr:
1281  {
1282  /*
1283  * MinMaxExpr is leakproof if the comparison function it calls
1284  * is leakproof.
1285  */
1286  MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
1287  TypeCacheEntry *typentry;
1288  bool leakproof;
1289 
1290  /* Look up the btree comparison function for the datatype */
1291  typentry = lookup_type_cache(minmaxexpr->minmaxtype,
1293  if (OidIsValid(typentry->cmp_proc))
1294  leakproof = get_func_leakproof(typentry->cmp_proc);
1295  else
1296  {
1297  /*
1298  * The executor will throw an error, but here we just
1299  * treat the missing function as leaky.
1300  */
1301  leakproof = false;
1302  }
1303 
1304  if (!leakproof &&
1305  contain_var_clause((Node *) minmaxexpr->args))
1306  return true;
1307  }
1308  break;
1309 
1310  case T_CurrentOfExpr:
1311 
1312  /*
1313  * WHERE CURRENT OF doesn't contain leaky function calls.
1314  * Moreover, it is essential that this is considered non-leaky,
1315  * since the planner must always generate a TID scan when CURRENT
1316  * OF is present -- cf. cost_tidscan.
1317  */
1318  return false;
1319 
1320  default:
1321 
1322  /*
1323  * If we don't recognize the node tag, assume it might be leaky.
1324  * This prevents an unexpected security hole if someone adds a new
1325  * node type that can call a function.
1326  */
1327  return true;
1328  }
1330  context);
1331 }
static bool contain_leaked_vars_checker(Oid func_id, void *context)
Definition: clauses.c:1179
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1267
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition: lsyscache.c:3088
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1772
#define nodeTag(nodeptr)
Definition: nodes.h:133
#define lfirst(lc)
Definition: pg_list.h:172
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:512
#define lfirst_oid(lc)
Definition: pg_list.h:174
List * args
Definition: primnodes.h:1443
Expr * refassgnexpr
Definition: primnodes.h:630
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:403

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(), nodeTag, OidIsValid, RowCompareExpr::rargs, SubscriptingRef::refassgnexpr, SubscriptRoutines::store_leakproof, 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 373 of file clauses.c.

374 {
375  return (func_volatile(func_id) != PROVOLATILE_IMMUTABLE);
376 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1762

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

380 {
381  if (node == NULL)
382  return false;
383  /* Check for mutable functions in node itself */
385  context))
386  return true;
387 
388  if (IsA(node, JsonConstructorExpr))
389  {
390  const JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
391  ListCell *lc;
392  bool is_jsonb;
393 
394  is_jsonb = ctor->returning->format->format_type == JS_FORMAT_JSONB;
395 
396  /*
397  * Check argument_type => json[b] conversions specifically. We still
398  * recurse to check 'args' below, but here we want to specifically
399  * check whether or not the emitted clause would fail to be immutable
400  * because of TimeZone, for example.
401  */
402  foreach(lc, ctor->args)
403  {
404  Oid typid = exprType(lfirst(lc));
405 
406  if (is_jsonb ?
407  !to_jsonb_is_immutable(typid) :
408  !to_json_is_immutable(typid))
409  return true;
410  }
411 
412  /* Check all subnodes */
413  }
414 
415  if (IsA(node, NextValueExpr))
416  {
417  /* NextValueExpr is volatile */
418  return true;
419  }
420 
421  /*
422  * It should be safe to treat MinMaxExpr as immutable, because it will
423  * depend on a non-cross-type btree comparison function, and those should
424  * always be immutable. Treating XmlExpr as immutable is more dubious,
425  * and treating CoerceToDomain as immutable is outright dangerous. But we
426  * have done so historically, and changing this would probably cause more
427  * problems than it would fix. In practice, if you have a non-immutable
428  * domain constraint you are in for pain anyhow.
429  */
430 
431  /* Recurse to check arguments */
432  if (IsA(node, Query))
433  {
434  /* Recurse into subselects */
435  return query_tree_walker((Query *) node,
437  context, 0);
438  }
440  context);
441 }
static bool contain_mutable_functions_checker(Oid func_id, void *context)
Definition: clauses.c:373
bool to_json_is_immutable(Oid typoid)
Definition: json.c:782
bool to_jsonb_is_immutable(Oid typoid)
Definition: jsonb.c:1161
#define query_tree_walker(q, w, c, f)
Definition: nodeFuncs.h:156
@ JS_FORMAT_JSONB
Definition: primnodes.h:1521
JsonReturning * returning
Definition: primnodes.h:1580
JsonFormatType format_type
Definition: primnodes.h:1532
JsonFormat * format
Definition: primnodes.h:1544

References JsonConstructorExpr::args, check_functions_in_node(), contain_mutable_functions_checker(), expression_tree_walker, exprType(), JsonReturning::format, JsonFormat::format_type, IsA, JS_FORMAT_JSONB, lfirst, query_tree_walker, JsonConstructorExpr::returning, to_json_is_immutable(), and to_jsonb_is_immutable().

Referenced by contain_mutable_functions().

◆ contain_non_const_walker()

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

Definition at line 3617 of file clauses.c.

3618 {
3619  if (node == NULL)
3620  return false;
3621  if (IsA(node, Const))
3622  return false;
3623  if (IsA(node, List))
3624  return expression_tree_walker(node, contain_non_const_walker, context);
3625  /* Otherwise, abort the tree traversal and return true */
3626  return true;
3627 }
static bool contain_non_const_walker(Node *node, void *context)
Definition: clauses.c:3617

References expression_tree_walker, and IsA.

◆ contain_nonstrict_functions()

bool contain_nonstrict_functions ( Node clause)

Definition at line 903 of file clauses.c.

904 {
905  return contain_nonstrict_functions_walker(clause, NULL);
906 }
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:915

References contain_nonstrict_functions_walker().

Referenced by inline_function().

◆ contain_nonstrict_functions_checker()

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

Definition at line 909 of file clauses.c.

910 {
911  return !func_strict(func_id);
912 }
bool func_strict(Oid funcid)
Definition: lsyscache.c:1743

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

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

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

Referenced by contain_nonstrict_functions().

◆ contain_subplans()

bool contain_subplans ( Node clause)

Definition at line 332 of file clauses.c.

333 {
334  return contain_subplans_walker(clause, NULL);
335 }
static bool contain_subplans_walker(Node *node, void *context)
Definition: clauses.c:338

References contain_subplans_walker().

Referenced by convert_EXISTS_to_ANY(), ExecInitValuesScan(), find_window_run_conditions(), initialize_peragg(), 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 338 of file clauses.c.

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

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

484 {
485  return (func_volatile(func_id) == PROVOLATILE_VOLATILE);
486 }

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

585 {
587 }
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:597

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

591 {
592  return (func_id != F_NEXTVAL &&
593  func_volatile(func_id) == PROVOLATILE_VOLATILE);
594 }

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

598 {
599  if (node == NULL)
600  return false;
601  /* Check for volatile functions in node itself */
602  if (check_functions_in_node(node,
604  context))
605  return true;
606 
607  /*
608  * See notes in contain_mutable_functions_walker about why we treat
609  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable. Hence, none of
610  * them are of interest here. Also, since we're intentionally ignoring
611  * nextval(), presumably we should ignore NextValueExpr.
612  */
613 
614  /* Recurse to check arguments */
615  if (IsA(node, Query))
616  {
617  /* Recurse into subselects */
618  return query_tree_walker((Query *) node,
620  context, 0);
621  }
622  return expression_tree_walker(node,
624  context);
625 }
static bool contain_volatile_functions_not_nextval_checker(Oid func_id, void *context)
Definition: clauses.c:590

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

490 {
491  if (node == NULL)
492  return false;
493  /* Check for volatile functions in node itself */
495  context))
496  return true;
497 
498  if (IsA(node, NextValueExpr))
499  {
500  /* NextValueExpr is volatile */
501  return true;
502  }
503 
504  if (IsA(node, RestrictInfo))
505  {
506  RestrictInfo *rinfo = (RestrictInfo *) node;
507 
508  /*
509  * For RestrictInfo, check if we've checked the volatility of it
510  * before. If so, we can just use the cached value and not bother
511  * checking it again. Otherwise, check it and cache if whether we
512  * found any volatile functions.
513  */
514  if (rinfo->has_volatile == VOLATILITY_NOVOLATILE)
515  return false;
516  else if (rinfo->has_volatile == VOLATILITY_VOLATILE)
517  return true;
518  else
519  {
520  bool hasvolatile;
521 
522  hasvolatile = contain_volatile_functions_walker((Node *) rinfo->clause,
523  context);
524  if (hasvolatile)
525  rinfo->has_volatile = VOLATILITY_VOLATILE;
526  else
527  rinfo->has_volatile = VOLATILITY_NOVOLATILE;
528 
529  return hasvolatile;
530  }
531  }
532 
533  if (IsA(node, PathTarget))
534  {
535  PathTarget *target = (PathTarget *) node;
536 
537  /*
538  * We also do caching for PathTarget the same as we do above for
539  * RestrictInfos.
540  */
542  return false;
543  else if (target->has_volatile_expr == VOLATILITY_VOLATILE)
544  return true;
545  else
546  {
547  bool hasvolatile;
548 
549  hasvolatile = contain_volatile_functions_walker((Node *) target->exprs,
550  context);
551 
552  if (hasvolatile)
554  else
556 
557  return hasvolatile;
558  }
559  }
560 
561  /*
562  * See notes in contain_mutable_functions_walker about why we treat
563  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable. Hence, none of
564  * them are of interest here.
565  */
566 
567  /* Recurse to check arguments */
568  if (IsA(node, Query))
569  {
570  /* Recurse into subselects */
571  return query_tree_walker((Query *) node,
573  context, 0);
574  }
576  context);
577 }
static bool contain_volatile_functions_checker(Oid func_id, void *context)
Definition: clauses.c:483
@ VOLATILITY_NOVOLATILE
Definition: pathnodes.h:1474
@ VOLATILITY_VOLATILE
Definition: pathnodes.h:1473
VolatileFunctionStatus has_volatile_expr
Definition: pathnodes.h:1519
List * exprs
Definition: pathnodes.h:1507
Expr * clause
Definition: pathnodes.h:2513

References check_functions_in_node(), RestrictInfo::clause, contain_volatile_functions_checker(), expression_tree_walker, PathTarget::exprs, 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 216 of file clauses.c.

217 {
218  return contain_windowfuncs(clause);
219 }
bool contain_windowfuncs(Node *node)
Definition: rewriteManip.c:215

References contain_windowfuncs().

Referenced by get_eclass_for_sort_expr().

◆ convert_saop_to_hashed_saop()

void convert_saop_to_hashed_saop ( Node node)

Definition at line 2196 of file clauses.c.

2197 {
2198  (void) convert_saop_to_hashed_saop_walker(node, NULL);
2199 }
static bool convert_saop_to_hashed_saop_walker(Node *node, void *context)
Definition: clauses.c:2202

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

2203 {
2204  if (node == NULL)
2205  return false;
2206 
2207  if (IsA(node, ScalarArrayOpExpr))
2208  {
2209  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) node;
2210  Expr *arrayarg = (Expr *) lsecond(saop->args);
2211  Oid lefthashfunc;
2212  Oid righthashfunc;
2213 
2214  if (arrayarg && IsA(arrayarg, Const) &&
2215  !((Const *) arrayarg)->constisnull)
2216  {
2217  if (saop->useOr)
2218  {
2219  if (get_op_hash_functions(saop->opno, &lefthashfunc, &righthashfunc) &&
2220  lefthashfunc == righthashfunc)
2221  {
2222  Datum arrdatum = ((Const *) arrayarg)->constvalue;
2223  ArrayType *arr = (ArrayType *) DatumGetPointer(arrdatum);
2224  int nitems;
2225 
2226  /*
2227  * Only fill in the hash functions if the array looks
2228  * large enough for it to be worth hashing instead of
2229  * doing a linear search.
2230  */
2231  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
2232 
2234  {
2235  /* Looks good. Fill in the hash functions */
2236  saop->hashfuncid = lefthashfunc;
2237  }
2238  return true;
2239  }
2240  }
2241  else /* !saop->useOr */
2242  {
2243  Oid negator = get_negator(saop->opno);
2244 
2245  /*
2246  * Check if this is a NOT IN using an operator whose negator
2247  * is hashable. If so we can still build a hash table and
2248  * just ensure the lookup items are not in the hash table.
2249  */
2250  if (OidIsValid(negator) &&
2251  get_op_hash_functions(negator, &lefthashfunc, &righthashfunc) &&
2252  lefthashfunc == righthashfunc)
2253  {
2254  Datum arrdatum = ((Const *) arrayarg)->constvalue;
2255  ArrayType *arr = (ArrayType *) DatumGetPointer(arrdatum);
2256  int nitems;
2257 
2258  /*
2259  * Only fill in the hash functions if the array looks
2260  * large enough for it to be worth hashing instead of
2261  * doing a linear search.
2262  */
2263  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
2264 
2266  {
2267  /* Looks good. Fill in the hash functions */
2268  saop->hashfuncid = lefthashfunc;
2269 
2270  /*
2271  * Also set the negfuncid. The executor will need
2272  * that to perform hashtable lookups.
2273  */
2274  saop->negfuncid = get_opcode(negator);
2275  }
2276  return true;
2277  }
2278  }
2279  }
2280  }
2281 
2283 }
#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:2178
#define nitems(x)
Definition: indent.h:31
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition: lsyscache.c:509
Oid get_negator(Oid opno)
Definition: lsyscache.c:1515
uintptr_t Datum
Definition: postgres.h:64
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312

References ScalarArrayOpExpr::args, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), DatumGetPointer(), expression_tree_walker, get_negator(), get_op_hash_functions(), get_opcode(), IsA, lsecond, MIN_ARRAY_SIZE_FOR_HASHED_SAOP, nitems, 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 3633 of file clauses.c.

3634 {
3635  char provolatile = func_volatile(funcid);
3636 
3637  /*
3638  * Ordinarily we are only allowed to simplify immutable functions. But for
3639  * purposes of estimation, we consider it okay to simplify functions that
3640  * are merely stable; the risk that the result might change from planning
3641  * time to execution time is worth taking in preference to not being able
3642  * to estimate the value at all.
3643  */
3644  if (provolatile == PROVOLATILE_IMMUTABLE)
3645  return true;
3646  if (context->estimate && provolatile == PROVOLATILE_STABLE)
3647  return true;
3648  return false;
3649 }

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

2305 {
2307 
2308  context.boundParams = root->glob->boundParams; /* bound Params */
2309  /* we do not need to mark the plan as depending on inlined functions */
2310  context.root = NULL;
2311  context.active_fns = NIL; /* nothing being recursively simplified */
2312  context.case_val = NULL; /* no CASE being examined */
2313  context.estimate = true; /* unsafe transformations OK */
2314  return eval_const_expressions_mutator(node, &context);
2315 }
#define NIL
Definition: pg_list.h:68
PlannerGlobal * glob
Definition: pathnodes.h:205
ParamListInfo boundParams
Definition: clauses.c:63

References eval_const_expressions_context::active_fns, eval_const_expressions_context::boundParams, eval_const_expressions_context::case_val, eval_const_expressions_context::estimate, eval_const_expressions_mutator(), 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()

◆ eval_const_expressions_mutator()

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

Definition at line 2349 of file clauses.c.

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

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

4856 {
4857  EState *estate;
4858  ExprState *exprstate;
4859  MemoryContext oldcontext;
4860  Datum const_val;
4861  bool const_is_null;
4862  int16 resultTypLen;
4863  bool resultTypByVal;
4864 
4865  /*
4866  * To use the executor, we need an EState.
4867  */
4868  estate = CreateExecutorState();
4869 
4870  /* We can use the estate's working context to avoid memory leaks. */
4871  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
4872 
4873  /* Make sure any opfuncids are filled in. */
4874  fix_opfuncids((Node *) expr);
4875 
4876  /*
4877  * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
4878  * because it'd result in recursively invoking eval_const_expressions.)
4879  */
4880  exprstate = ExecInitExpr(expr, NULL);
4881 
4882  /*
4883  * And evaluate it.
4884  *
4885  * It is OK to use a default econtext because none of the ExecEvalExpr()
4886  * code used in this situation will use econtext. That might seem
4887  * fortuitous, but it's not so unreasonable --- a constant expression does
4888  * not depend on context, by definition, n'est ce pas?
4889  */
4890  const_val = ExecEvalExprSwitchContext(exprstate,
4891  GetPerTupleExprContext(estate),
4892  &const_is_null);
4893 
4894  /* Get info needed about result datatype */
4895  get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
4896 
4897  /* Get back to outer memory context */
4898  MemoryContextSwitchTo(oldcontext);
4899 
4900  /*
4901  * Must copy result out of sub-context used by expression eval.
4902  *
4903  * Also, if it's varlena, forcibly detoast it. This protects us against
4904  * storing TOAST pointers into plans that might outlive the referenced
4905  * data. (makeConst would handle detoasting anyway, but it's worth a few
4906  * extra lines here so that we can do the copy and detoast in one step.)
4907  */
4908  if (!const_is_null)
4909  {
4910  if (resultTypLen == -1)
4911  const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
4912  else
4913  const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
4914  }
4915 
4916  /* Release all the junk we just created */
4917  FreeExecutorState(estate);
4918 
4919  /*
4920  * Make the constant result node.
4921  */
4922  return (Expr *) makeConst(result_type, result_typmod, result_collation,
4923  resultTypLen,
4924  const_val, const_is_null,
4925  resultTypByVal);
4926 }
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:127
EState * CreateExecutorState(void)
Definition: execUtils.c:93
void FreeExecutorState(EState *estate)
Definition: execUtils.c:194
#define GetPerTupleExprContext(estate)
Definition: executor.h:548
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:346
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1703
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
MemoryContext es_query_cxt
Definition: execnodes.h:660

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

4311 {
4312  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4313  bool has_nonconst_input = false;
4314  bool has_null_input = false;
4315  ListCell *arg;
4316  FuncExpr *newexpr;
4317 
4318  /*
4319  * Can't simplify if it returns a set.
4320  */
4321  if (funcform->proretset)
4322  return NULL;
4323 
4324  /*
4325  * Can't simplify if it returns RECORD. The immediate problem is that it
4326  * will be needing an expected tupdesc which we can't supply here.
4327  *
4328  * In the case where it has OUT parameters, it could get by without an
4329  * expected tupdesc, but we still have issues: get_expr_result_type()
4330  * doesn't know how to extract type info from a RECORD constant, and in
4331  * the case of a NULL function result there doesn't seem to be any clean
4332  * way to fix that. In view of the likelihood of there being still other
4333  * gotchas, seems best to leave the function call unreduced.
4334  */
4335  if (funcform->prorettype == RECORDOID)
4336  return NULL;
4337 
4338  /*
4339  * Check for constant inputs and especially constant-NULL inputs.
4340  */
4341  foreach(arg, args)
4342  {
4343  if (IsA(lfirst(arg), Const))
4344  has_null_input |= ((Const *) lfirst(arg))->constisnull;
4345  else
4346  has_nonconst_input = true;
4347  }
4348 
4349  /*
4350  * If the function is strict and has a constant-NULL input, it will never
4351  * be called at all, so we can replace the call by a NULL constant, even
4352  * if there are other inputs that aren't constant, and even if the
4353  * function is not otherwise immutable.
4354  */
4355  if (funcform->proisstrict && has_null_input)
4356  return (Expr *) makeNullConst(result_type, result_typmod,
4357  result_collid);
4358 
4359  /*
4360  * Otherwise, can simplify only if all inputs are constants. (For a
4361  * non-strict function, constant NULL inputs are treated the same as
4362  * constant non-NULL inputs.)
4363  */
4364  if (has_nonconst_input)
4365  return NULL;
4366 
4367  /*
4368  * Ordinarily we are only allowed to simplify immutable functions. But for
4369  * purposes of estimation, we consider it okay to simplify functions that
4370  * are merely stable; the risk that the result might change from planning
4371  * time to execution time is worth taking in preference to not being able
4372  * to estimate the value at all.
4373  */
4374  if (funcform->provolatile == PROVOLATILE_IMMUTABLE)
4375  /* okay */ ;
4376  else if (context->estimate && funcform->provolatile == PROVOLATILE_STABLE)
4377  /* okay */ ;
4378  else
4379  return NULL;
4380 
4381  /*
4382  * OK, looks like we can simplify this operator/function.
4383  *
4384  * Build a new FuncExpr node containing the already-simplified arguments.
4385  */
4386  newexpr = makeNode(FuncExpr);
4387  newexpr->funcid = funcid;
4388  newexpr->funcresulttype = result_type;
4389  newexpr->funcretset = false;
4390  newexpr->funcvariadic = funcvariadic;
4391  newexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
4392  newexpr->funccollid = result_collid; /* doesn't matter */
4393  newexpr->inputcollid = input_collid;
4394  newexpr->args = args;
4395  newexpr->location = -1;
4396 
4397  return evaluate_expr((Expr *) newexpr, result_type, result_typmod,
4398  result_collid);
4399 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
@ COERCE_EXPLICIT_CALL
Definition: primnodes.h:661

References arg, generate_unaccent_rules::args, FuncExpr::args, COERCE_EXPLICIT_CALL, eval_const_expressions_context::estimate, evaluate_expr(), FuncExpr::funcid, GETSTRUCT, 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 4056 of file clauses.c.

4058 {
4059  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4060  Oid *proargtypes = funcform->proargtypes.values;
4061  int pronargs = funcform->pronargs;
4062  bool has_named_args = false;
4063  ListCell *lc;
4064 
4065  /*
4066  * If we are asked to match to OUT arguments, then use the proallargtypes
4067  * array (which includes those); otherwise use proargtypes (which
4068  * doesn't). Of course, if proallargtypes is null, we always use
4069  * proargtypes. (Fetching proallargtypes is annoyingly expensive
4070  * considering that we may have nothing to do here, but fortunately the
4071  * common case is include_out_arguments == false.)
4072  */
4073  if (include_out_arguments)
4074  {
4075  Datum proallargtypes;
4076  bool isNull;
4077 
4078  proallargtypes = SysCacheGetAttr(PROCOID, func_tuple,
4079  Anum_pg_proc_proallargtypes,
4080  &isNull);
4081  if (!isNull)
4082  {
4083  ArrayType *arr = DatumGetArrayTypeP(proallargtypes);
4084 
4085  pronargs = ARR_DIMS(arr)[0];
4086  if (ARR_NDIM(arr) != 1 ||
4087  pronargs < 0 ||
4088  ARR_HASNULL(arr) ||
4089  ARR_ELEMTYPE(arr) != OIDOID)
4090  elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
4091  Assert(pronargs >= funcform->pronargs);
4092  proargtypes = (Oid *) ARR_DATA_PTR(arr);
4093  }
4094  }
4095 
4096  /* Do we have any named arguments? */
4097  foreach(lc, args)
4098  {
4099  Node *arg = (Node *) lfirst(lc);
4100 
4101  if (IsA(arg, NamedArgExpr))
4102  {
4103  has_named_args = true;
4104  break;
4105  }
4106  }
4107 
4108  /* If so, we must apply reorder_function_arguments */
4109  if (has_named_args)
4110  {
4111  args = reorder_function_arguments(args, pronargs, func_tuple);
4112  /* Recheck argument types and add casts if needed */
4113  recheck_cast_function_args(args, result_type,
4114  proargtypes, pronargs,
4115  func_tuple);
4116  }
4117  else if (list_length(args) < pronargs)
4118  {
4119  /* No named args, but we seem to be short some defaults */
4120  args = add_function_defaults(args, pronargs, func_tuple);
4121  /* Recheck argument types and add casts if needed */
4122  recheck_cast_function_args(args, result_type,
4123  proargtypes, pronargs,
4124  func_tuple);
4125  }
4126 
4127  return args;
4128 }
#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:4207
static List * reorder_function_arguments(List *args, int pronargs, HeapTuple func_tuple)
Definition: clauses.c:4137
static void recheck_cast_function_args(List *args, Oid result_type, Oid *proargtypes, int pronargs, HeapTuple func_tuple)
Definition: clauses.c:4261
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1079

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

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

References clamp_row_est(), FuncExpr::funcid, get_function_rows(), IsA, 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 4231 of file clauses.c.

4232 {
4233  List *defaults;
4234  Datum proargdefaults;
4235  char *str;
4236 
4237  proargdefaults = SysCacheGetAttrNotNull(PROCOID, func_tuple,
4238  Anum_pg_proc_proargdefaults);
4239  str = TextDatumGetCString(proargdefaults);
4240  defaults = castNode(List, stringToNode(str));
4241  pfree(str);
4242  return defaults;
4243 }
#define TextDatumGetCString(d)
Definition: builtins.h:95
void pfree(void *pointer)
Definition: mcxt.c:1436
void * stringToNode(const char *str)
Definition: read.c:90
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:1110

References castNode, pfree(), PROCOID, generate_unaccent_rules::str, stringToNode(), SysCacheGetAttrNotNull(), 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 1886 of file clauses.c.

1887 {
1888  if (node == NULL)
1889  return NULL;
1890  if (IsA(node, NullTest))
1891  {
1892  /* check for var IS NULL */
1893  NullTest *expr = (NullTest *) node;
1894 
1895  if (expr->nulltesttype == IS_NULL && !expr->argisrow)
1896  {
1897  Var *var = (Var *) expr->arg;
1898 
1899  if (var && IsA(var, Var) &&
1900  var->varlevelsup == 0)
1901  return var;
1902  }
1903  }
1904  else if (IsA(node, BooleanTest))
1905  {
1906  /* var IS UNKNOWN is equivalent to var IS NULL */
1907  BooleanTest *expr = (BooleanTest *) node;
1908 
1909  if (expr->booltesttype == IS_UNKNOWN)
1910  {
1911  Var *var = (Var *) expr->arg;
1912 
1913  if (var && IsA(var, Var) &&
1914  var->varlevelsup == 0)
1915  return var;
1916  }
1917  }
1918  return NULL;
1919 }
Index varlevelsup
Definition: primnodes.h:258

References NullTest::arg, BooleanTest::arg, 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 1825 of file clauses.c.

1826 {
1827  List *result = NIL;
1828  Var *var;
1829  ListCell *l;
1830 
1831  if (node == NULL)
1832  return NIL;
1833  /* Check single-clause cases using subroutine */
1834  var = find_forced_null_var(node);
1835  if (var)
1836  {
1837  result = mbms_add_member(result,
1838  var->varno,
1840  }
1841  /* Otherwise, handle AND-conditions */
1842  else if (IsA(node, List))
1843  {
1844  /*
1845  * At top level, we are examining an implicit-AND list: if any of the
1846  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1847  */
1848  foreach(l, (List *) node)
1849  {
1850  result = mbms_add_members(result,
1852  }
1853  }
1854  else if (IsA(node, BoolExpr))
1855  {
1856  BoolExpr *expr = (BoolExpr *) node;
1857 
1858  /*
1859  * We don't bother considering the OR case, because it's fairly
1860  * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
1861  * the NOT case isn't worth expending code on.
1862  */
1863  if (expr->boolop == AND_EXPR)
1864  {
1865  /* At top level we can just recurse (to the List case) */
1866  result = find_forced_null_vars((Node *) expr->args);
1867  }
1868  }
1869  return result;
1870 }
Var * find_forced_null_var(Node *node)
Definition: clauses.c:1886
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1825
List * mbms_add_member(List *a, int listidx, int bitidx)
List * mbms_add_members(List *a, const List *b)
AttrNumber varattno
Definition: primnodes.h:238
int varno
Definition: primnodes.h:233
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27

References AND_EXPR, BoolExpr::args, BoolExpr::boolop, find_forced_null_var(), FirstLowInvalidHeapAttributeNumber, IsA, lfirst, mbms_add_member(), mbms_add_members(), NIL, Var::varattno, and Var::varno.

Referenced by reduce_outer_joins_pass2().

◆ find_nonnullable_rels()

Relids find_nonnullable_rels ( Node clause)

Definition at line 1365 of file clauses.c.

1366 {
1367  return find_nonnullable_rels_walker(clause, true);
1368 }
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1371

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

1372 {
1373  Relids result = NULL;
1374  ListCell *l;
1375 
1376  if (node == NULL)
1377  return NULL;
1378  if (IsA(node, Var))
1379  {
1380  Var *var = (Var *) node;
1381 
1382  if (var->varlevelsup == 0)
1383  result = bms_make_singleton(var->varno);
1384  }
1385  else if (IsA(node, List))
1386  {
1387  /*
1388  * At top level, we are examining an implicit-AND list: if any of the
1389  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1390  * not at top level, we are examining the arguments of a strict
1391  * function: if any of them produce NULL then the result of the
1392  * function must be NULL. So in both cases, the set of nonnullable
1393  * rels is the union of those found in the arms, and we pass down the
1394  * top_level flag unmodified.
1395  */
1396  foreach(l, (List *) node)
1397  {
1398  result = bms_join(result,
1400  top_level));
1401  }
1402  }
1403  else if (IsA(node, FuncExpr))
1404  {
1405  FuncExpr *expr = (FuncExpr *) node;
1406 
1407  if (func_strict(expr->funcid))
1408  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1409  }
1410  else if (IsA(node, OpExpr))
1411  {
1412  OpExpr *expr = (OpExpr *) node;
1413 
1414  set_opfuncid(expr);
1415  if (func_strict(expr->opfuncid))
1416  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1417  }
1418  else if (IsA(node, ScalarArrayOpExpr))
1419  {
1420  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1421 
1422  if (is_strict_saop(expr, true))
1423  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1424  }
1425  else if (IsA(node, BoolExpr))
1426  {
1427  BoolExpr *expr = (BoolExpr *) node;
1428 
1429  switch (expr->boolop)
1430  {
1431  case AND_EXPR:
1432  /* At top level we can just recurse (to the List case) */
1433  if (top_level)
1434  {
1435  result = find_nonnullable_rels_walker((Node *) expr->args,
1436  top_level);
1437  break;
1438  }
1439 
1440  /*
1441  * Below top level, even if one arm produces NULL, the result
1442  * could be FALSE (hence not NULL). However, if *all* the
1443  * arms produce NULL then the result is NULL, so we can take
1444  * the intersection of the sets of nonnullable rels, just as
1445  * for OR. Fall through to share code.
1446  */
1447  /* FALL THRU */
1448  case OR_EXPR:
1449 
1450  /*
1451  * OR is strict if all of its arms are, so we can take the
1452  * intersection of the sets of nonnullable rels for each arm.
1453  * This works for both values of top_level.
1454  */
1455  foreach(l, expr->args)
1456  {
1457  Relids subresult;
1458 
1459  subresult = find_nonnullable_rels_walker(lfirst(l),
1460  top_level);
1461  if (result == NULL) /* first subresult? */
1462  result = subresult;
1463  else
1464  result = bms_int_members(result, subresult);
1465 
1466  /*
1467  * If the intersection is empty, we can stop looking. This
1468  * also justifies the test for first-subresult above.
1469  */
1470  if (bms_is_empty(result))
1471  break;
1472  }
1473  break;
1474  case NOT_EXPR:
1475  /* NOT will return null if its arg is null */
1476  result = find_nonnullable_rels_walker((Node *) expr->args,
1477  false);
1478  break;
1479  default:
1480  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1481  break;
1482  }
1483  }
1484  else if (IsA(node, RelabelType))
1485  {
1486  RelabelType *expr = (RelabelType *) node;
1487 
1488  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1489  }
1490  else if (IsA(node, CoerceViaIO))
1491  {
1492  /* not clear this is useful, but it can't hurt */
1493  CoerceViaIO *expr = (CoerceViaIO *) node;
1494 
1495  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1496  }
1497  else if (IsA(node, ArrayCoerceExpr))
1498  {
1499  /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1500  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1501 
1502  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1503  }
1504  else if (IsA(node, ConvertRowtypeExpr))
1505  {
1506  /* not clear this is useful, but it can't hurt */
1507  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1508 
1509  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1510  }
1511  else if (IsA(node, CollateExpr))
1512  {
1513  CollateExpr *expr = (CollateExpr *) node;
1514 
1515  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1516  }
1517  else if (IsA(node, NullTest))
1518  {
1519  /* IS NOT NULL can be considered strict, but only at top level */
1520  NullTest *expr = (NullTest *) node;
1521 
1522  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1523  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1524  }
1525  else if (IsA(node, BooleanTest))
1526  {
1527  /* Boolean tests that reject NULL are strict at top level */
1528  BooleanTest *expr = (BooleanTest *) node;
1529 
1530  if (top_level &&
1531  (expr->booltesttype == IS_TRUE ||
1532  expr->booltesttype == IS_FALSE ||
1533  expr->booltesttype == IS_NOT_UNKNOWN))
1534  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1535  }
1536  else if (IsA(node, SubPlan))
1537  {
1538  SubPlan *splan = (SubPlan *) node;
1539 
1540  /*
1541  * For some types of SubPlan, we can infer strictness from Vars in the
1542  * testexpr (the LHS of the original SubLink).
1543  *
1544  * For ANY_SUBLINK, if the subquery produces zero rows, the result is
1545  * always FALSE. If the subquery produces more than one row, the
1546  * per-row results of the testexpr are combined using OR semantics.
1547  * Hence ANY_SUBLINK can be strict only at top level, but there it's
1548  * as strict as the testexpr is.
1549  *
1550  * For ROWCOMPARE_SUBLINK, if the subquery produces zero rows, the
1551  * result is always NULL. Otherwise, the result is as strict as the
1552  * testexpr is. So we can check regardless of top_level.
1553  *
1554  * We can't prove anything for other sublink types (in particular,
1555  * note that ALL_SUBLINK will return TRUE if the subquery is empty).
1556  */
1557  if ((top_level && splan->subLinkType == ANY_SUBLINK) ||
1558  splan->subLinkType == ROWCOMPARE_SUBLINK)
1559  result = find_nonnullable_rels_walker(splan->testexpr, top_level);
1560  }
1561  else if (IsA(node, PlaceHolderVar))
1562  {
1563  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1564 
1565  /*
1566  * If the contained expression forces any rels non-nullable, so does
1567  * the PHV.
1568  */
1569  result = find_nonnullable_rels_walker((Node *) phv->phexpr, top_level);
1570 
1571  /*
1572  * If the PHV's syntactic scope is exactly one rel, it will be forced
1573  * to be evaluated at that rel, and so it will behave like a Var of
1574  * that rel: if the rel's entire output goes to null, so will the PHV.
1575  * (If the syntactic scope is a join, we know that the PHV will go to
1576  * null if the whole join does; but that is AND semantics while we
1577  * need OR semantics for find_nonnullable_rels' result, so we can't do
1578  * anything with the knowledge.)
1579  */
1580  if (phv->phlevelsup == 0 &&
1581  bms_membership(phv->phrels) == BMS_SINGLETON)
1582  result = bms_add_members(result, phv->phrels);
1583  }
1584  return result;
1585 }
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:987
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:818
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:928
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:691
#define bms_is_empty(a)
Definition: bitmapset.h:105
@ BMS_SINGLETON
Definition: bitmapset.h:72
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition: clauses.c:1935
@ ANY_SUBLINK
Definition: primnodes.h:926
@ ROWCOMPARE_SUBLINK
Definition: primnodes.h:927
static SPIPlanPtr splan
Definition: regress.c:270
Index phlevelsup
Definition: pathnodes.h:2740

References AND_EXPR, ANY_SUBLINK, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, NullTest::arg, BooleanTest::arg, 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, OR_EXPR, PlaceHolderVar::phlevelsup, ROWCOMPARE_SUBLINK, set_opfuncid(), splan, Var::varlevelsup, and Var::varno.

Referenced by find_nonnullable_rels().

◆ find_nonnullable_vars()

List* find_nonnullable_vars ( Node clause)

Definition at line 1616 of file clauses.c.

1617 {
1618  return find_nonnullable_vars_walker(clause, true);
1619 }
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1622

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

1623 {
1624  List *result = NIL;
1625  ListCell *l;
1626 
1627  if (node == NULL)
1628  return NIL;
1629  if (IsA(node, Var))
1630  {
1631  Var *var = (Var *) node;
1632 
1633  if (var->varlevelsup == 0)
1634  result = mbms_add_member(result,
1635  var->varno,
1637  }
1638  else if (IsA(node, List))
1639  {
1640  /*
1641  * At top level, we are examining an implicit-AND list: if any of the
1642  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1643  * not at top level, we are examining the arguments of a strict
1644  * function: if any of them produce NULL then the result of the
1645  * function must be NULL. So in both cases, the set of nonnullable
1646  * vars is the union of those found in the arms, and we pass down the
1647  * top_level flag unmodified.
1648  */
1649  foreach(l, (List *) node)
1650  {
1651  result = mbms_add_members(result,
1653  top_level));
1654  }
1655  }
1656  else if (IsA(node, FuncExpr))
1657  {
1658  FuncExpr *expr = (FuncExpr *) node;
1659 
1660  if (func_strict(expr->funcid))
1661  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1662  }
1663  else if (IsA(node, OpExpr))
1664  {
1665  OpExpr *expr = (OpExpr *) node;
1666 
1667  set_opfuncid(expr);
1668  if (func_strict(expr->opfuncid))
1669  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1670  }
1671  else if (IsA(node, ScalarArrayOpExpr))
1672  {
1673  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1674 
1675  if (is_strict_saop(expr, true))
1676  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1677  }
1678  else if (IsA(node, BoolExpr))
1679  {
1680  BoolExpr *expr = (BoolExpr *) node;
1681 
1682  switch (expr->boolop)
1683  {
1684  case AND_EXPR:
1685 
1686  /*
1687  * At top level we can just recurse (to the List case), since
1688  * the result should be the union of what we can prove in each
1689  * arm.
1690  */
1691  if (top_level)
1692  {
1693  result = find_nonnullable_vars_walker((Node *) expr->args,
1694  top_level);
1695  break;
1696  }
1697 
1698  /*
1699  * Below top level, even if one arm produces NULL, the result
1700  * could be FALSE (hence not NULL). However, if *all* the
1701  * arms produce NULL then the result is NULL, so we can take
1702  * the intersection of the sets of nonnullable vars, just as
1703  * for OR. Fall through to share code.
1704  */
1705  /* FALL THRU */
1706  case OR_EXPR:
1707 
1708  /*
1709  * OR is strict if all of its arms are, so we can take the
1710  * intersection of the sets of nonnullable vars for each arm.
1711  * This works for both values of top_level.
1712  */
1713  foreach(l, expr->args)
1714  {
1715  List *subresult;
1716 
1717  subresult = find_nonnullable_vars_walker(lfirst(l),
1718  top_level);
1719  if (result == NIL) /* first subresult? */
1720  result = subresult;
1721  else
1722  result = mbms_int_members(result, subresult);
1723 
1724  /*
1725  * If the intersection is empty, we can stop looking. This
1726  * also justifies the test for first-subresult above.
1727  */
1728  if (result == NIL)
1729  break;
1730  }
1731  break;
1732  case NOT_EXPR:
1733  /* NOT will return null if its arg is null */
1734  result = find_nonnullable_vars_walker((Node *) expr->args,
1735  false);
1736  break;
1737  default:
1738  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1739  break;
1740  }
1741  }
1742  else if (IsA(node, RelabelType))
1743  {
1744  RelabelType *expr = (RelabelType *) node;
1745 
1746  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1747  }
1748  else if (IsA(node, CoerceViaIO))
1749  {
1750  /* not clear this is useful, but it can't hurt */
1751  CoerceViaIO *expr = (CoerceViaIO *) node;
1752 
1753  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1754  }
1755  else if (IsA(node, ArrayCoerceExpr))
1756  {
1757  /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1758  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1759 
1760  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1761  }
1762  else if (IsA(node, ConvertRowtypeExpr))
1763  {
1764  /* not clear this is useful, but it can't hurt */
1765  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1766 
1767  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1768  }
1769  else if (IsA(node, CollateExpr))
1770  {
1771  CollateExpr *expr = (CollateExpr *) node;
1772 
1773  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1774  }
1775  else if (IsA(node, NullTest))
1776  {
1777  /* IS NOT NULL can be considered strict, but only at top level */
1778  NullTest *expr = (NullTest *) node;
1779 
1780  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1781  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1782  }
1783  else if (IsA(node, BooleanTest))
1784  {
1785  /* Boolean tests that reject NULL are strict at top level */
1786  BooleanTest *expr = (BooleanTest *) node;
1787 
1788  if (top_level &&
1789  (expr->booltesttype == IS_TRUE ||
1790  expr->booltesttype == IS_FALSE ||
1791  expr->booltesttype == IS_NOT_UNKNOWN))
1792  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1793  }
1794  else if (IsA(node, SubPlan))
1795  {
1796  SubPlan *splan = (SubPlan *) node;
1797 
1798  /* See analysis in find_nonnullable_rels_walker */
1799  if ((top_level && splan->subLinkType == ANY_SUBLINK) ||
1800  splan->subLinkType == ROWCOMPARE_SUBLINK)
1801  result = find_nonnullable_vars_walker(splan->testexpr, top_level);
1802  }
1803  else if (IsA(node, PlaceHolderVar))
1804  {
1805  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1806 
1807  result = find_nonnullable_vars_walker((Node *) phv->phexpr, top_level);
1808  }
1809  return result;
1810 }
List * mbms_int_members(List *a, const List *b)

References AND_EXPR, ANY_SUBLINK, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, NullTest::arg, BooleanTest::arg, FuncExpr::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, elog(), ERROR, FirstLowInvalidHeapAttributeNumber, func_strict(), FuncExpr::funcid, IS_FALSE, IS_NOT_NULL, IS_NOT_UNKNOWN, is_strict_saop(), IS_TRUE, IsA, lfirst, mbms_add_member(), mbms_add_members(), mbms_int_members(), NIL, NOT_EXPR, NullTest::nulltesttype, OR_EXPR, ROWCOMPARE_SUBLINK, set_opfuncid(), splan, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by find_nonnullable_vars().

◆ find_window_functions()

WindowFuncLists* find_window_functions ( Node clause,
Index  maxWinRef 
)

Definition at line 229 of file clauses.c.

230 {
231  WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
232 
233  lists->numWindowFuncs = 0;
234  lists->maxWinRef = maxWinRef;
235  lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
236  (void) find_window_functions_walker(clause, lists);
237  return lists;
238 }
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:241
void * palloc0(Size size)
Definition: mcxt.c:1241
void * palloc(Size size)
Definition: mcxt.c:1210
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 241 of file clauses.c.

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

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

4438 {
4439  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4440  char *src;
4441  Datum tmp;
4442  bool isNull;
4443  MemoryContext oldcxt;
4444  MemoryContext mycxt;
4445  inline_error_callback_arg callback_arg;
4446  ErrorContextCallback sqlerrcontext;
4447  FuncExpr *fexpr;
4449  TupleDesc rettupdesc;
4450  ParseState *pstate;
4451  List *raw_parsetree_list;
4452  List *querytree_list;
4453  Query *querytree;
4454  Node *newexpr;
4455  int *usecounts;
4456  ListCell *arg;
4457  int i;
4458 
4459  /*
4460  * Forget it if the function is not SQL-language or has other showstopper
4461  * properties. (The prokind and nargs checks are just paranoia.)
4462  */
4463  if (funcform->prolang != SQLlanguageId ||
4464  funcform->prokind != PROKIND_FUNCTION ||
4465  funcform->prosecdef ||
4466  funcform->proretset ||
4467  funcform->prorettype == RECORDOID ||
4468  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL) ||
4469  funcform->pronargs != list_length(args))
4470  return NULL;
4471 
4472  /* Check for recursive function, and give up trying to expand if so */
4473  if (list_member_oid(context->active_fns, funcid))
4474  return NULL;
4475 
4476  /* Check permission to call function (fail later, if not) */
4477  if (object_aclcheck(ProcedureRelationId, funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
4478  return NULL;
4479 
4480  /* Check whether a plugin wants to hook function entry/exit */
4481  if (FmgrHookIsNeeded(funcid))
4482  return NULL;
4483 
4484  /*
4485  * Make a temporary memory context, so that we don't leak all the stuff
4486  * that parsing might create.
4487  */
4489  "inline_function",
4491  oldcxt = MemoryContextSwitchTo(mycxt);
4492 
4493  /*
4494  * We need a dummy FuncExpr node containing the already-simplified
4495  * arguments. (In some cases we don't really need it, but building it is
4496  * cheap enough that it's not worth contortions to avoid.)
4497  */
4498  fexpr = makeNode(FuncExpr);
4499  fexpr->funcid = funcid;
4500  fexpr->funcresulttype = result_type;
4501  fexpr->funcretset = false;
4502  fexpr->funcvariadic = funcvariadic;
4503  fexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
4504  fexpr->funccollid = result_collid; /* doesn't matter */
4505  fexpr->inputcollid = input_collid;
4506  fexpr->args = args;
4507  fexpr->location = -1;
4508 
4509  /* Fetch the function body */
4510  tmp = SysCacheGetAttrNotNull(PROCOID, func_tuple, Anum_pg_proc_prosrc);
4511  src = TextDatumGetCString(tmp);
4512 
4513  /*
4514  * Setup error traceback support for ereport(). This is so that we can
4515  * finger the function that bad information came from.
4516  */
4517  callback_arg.proname = NameStr(funcform->proname);
4518  callback_arg.prosrc = src;
4519 
4520  sqlerrcontext.callback = sql_inline_error_callback;
4521  sqlerrcontext.arg = (void *) &callback_arg;
4522  sqlerrcontext.previous = error_context_stack;
4523  error_context_stack = &sqlerrcontext;
4524 
4525  /* If we have prosqlbody, pay attention to that not prosrc */
4526  tmp = SysCacheGetAttr(PROCOID,
4527  func_tuple,
4528  Anum_pg_proc_prosqlbody,
4529  &isNull);
4530  if (!isNull)
4531  {
4532  Node *n;
4533  List *query_list;
4534 
4536  if (IsA(n, List))
4537  query_list = linitial_node(List, castNode(List, n));
4538  else
4539  query_list = list_make1(n);
4540  if (list_length(query_list) != 1)
4541  goto fail;
4542  querytree = linitial(query_list);
4543 
4544  /*
4545  * Because we'll insist below that the querytree have an empty rtable
4546  * and no sublinks, it cannot have any relation references that need
4547  * to be locked or rewritten. So we can omit those steps.
4548  */
4549  }
4550  else
4551  {
4552  /* Set up to handle parameters while parsing the function body. */
4553  pinfo = prepare_sql_fn_parse_info(func_tuple,
4554  (Node *) fexpr,
4555  input_collid);
4556 
4557  /*
4558  * We just do parsing and parse analysis, not rewriting, because
4559  * rewriting will not affect table-free-SELECT-only queries, which is
4560  * all that we care about. Also, we can punt as soon as we detect
4561  * more than one command in the function body.
4562  */
4563  raw_parsetree_list = pg_parse_query(src);
4564  if (list_length(raw_parsetree_list) != 1)
4565  goto fail;
4566 
4567  pstate = make_parsestate(NULL);
4568  pstate->p_sourcetext = src;
4569  sql_fn_parser_setup(pstate, pinfo);
4570 
4571  querytree = transformTopLevelStmt(pstate, linitial(raw_parsetree_list));
4572 
4573  free_parsestate(pstate);
4574  }
4575 
4576  /*
4577  * The single command must be a simple "SELECT expression".
4578  *
4579  * Note: if you change the tests involved in this, see also plpgsql's
4580  * exec_simple_check_plan(). That generally needs to have the same idea
4581  * of what's a "simple expression", so that inlining a function that
4582  * previously wasn't inlined won't change plpgsql's conclusion.
4583  */
4584  if (!IsA(querytree, Query) ||
4585  querytree->commandType != CMD_SELECT ||
4586  querytree->hasAggs ||
4587  querytree->hasWindowFuncs ||
4588  querytree->hasTargetSRFs ||
4589  querytree->hasSubLinks ||
4590  querytree->cteList ||
4591  querytree->rtable ||
4592  querytree->jointree->fromlist ||
4593  querytree->jointree->quals ||
4594  querytree->groupClause ||
4595  querytree->groupingSets ||
4596  querytree->havingQual ||
4597  querytree->windowClause ||
4598  querytree->distinctClause ||
4599  querytree->sortClause ||
4600  querytree->limitOffset ||
4601  querytree->limitCount ||
4602  querytree->setOperations ||
4603  list_length(querytree->targetList) != 1)
4604  goto fail;
4605 
4606  /* If the function result is composite, resolve it */
4607  (void) get_expr_result_type((Node *) fexpr,
4608  NULL,
4609  &rettupdesc);
4610 
4611  /*
4612  * Make sure the function (still) returns what it's declared to. This
4613  * will raise an error if wrong, but that's okay since the function would
4614  * fail at runtime anyway. Note that check_sql_fn_retval will also insert
4615  * a coercion if needed to make the tlist expression match the declared
4616  * type of the function.
4617  *
4618  * Note: we do not try this until we have verified that no rewriting was
4619  * needed; that's probably not important, but let's be careful.
4620  */
4621  querytree_list = list_make1(querytree);
4622  if (check_sql_fn_retval(list_make1(querytree_list),
4623  result_type, rettupdesc,
4624  false, NULL))
4625  goto fail; /* reject whole-tuple-result cases */
4626 
4627  /*
4628  * Given the tests above, check_sql_fn_retval shouldn't have decided to
4629  * inject a projection step, but let's just make sure.
4630  */
4631  if (querytree != linitial(querytree_list))
4632  goto fail;
4633 
4634  /* Now we can grab the tlist expression */
4635  newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr;
4636 
4637  /*
4638  * If the SQL function returns VOID, we can only inline it if it is a
4639  * SELECT of an expression returning VOID (ie, it's just a redirection to
4640  * another VOID-returning function). In all non-VOID-returning cases,
4641  * check_sql_fn_retval should ensure that newexpr returns the function's
4642  * declared result type, so this test shouldn't fail otherwise; but we may
4643  * as well cope gracefully if it does.
4644  */
4645  if (exprType(newexpr) != result_type)
4646  goto fail;
4647 
4648  /*
4649  * Additional validity checks on the expression. It mustn't be more
4650  * volatile than the surrounding function (this is to avoid breaking hacks
4651  * that involve pretending a function is immutable when it really ain't).
4652  * If the surrounding function is declared strict, then the expression
4653  * must contain only strict constructs and must use all of the function
4654  * parameters (this is overkill, but an exact analysis is hard).
4655  */
4656  if (funcform->provolatile == PROVOLATILE_IMMUTABLE &&
4657  contain_mutable_functions(newexpr))
4658  goto fail;
4659  else if (funcform->provolatile == PROVOLATILE_STABLE &&
4660  contain_volatile_functions(newexpr))
4661  goto fail;
4662 
4663  if (funcform->proisstrict &&
4664  contain_nonstrict_functions(newexpr))
4665  goto fail;
4666 
4667  /*
4668  * If any parameter expression contains a context-dependent node, we can't
4669  * inline, for fear of putting such a node into the wrong context.
4670  */
4672  goto fail;
4673 
4674  /*
4675  * We may be able to do it; there are still checks on parameter usage to
4676  * make, but those are most easily done in combination with the actual
4677  * substitution of the inputs. So start building expression with inputs
4678  * substituted.
4679  */
4680  usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
4681  newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
4682  args, usecounts);
4683 
4684  /* Now check for parameter usage */
4685  i = 0;
4686  foreach(arg, args)
4687  {
4688  Node *param = lfirst(arg);
4689 
4690  if (usecounts[i] == 0)
4691  {
4692  /* Param not used at all: uncool if func is strict */
4693  if (funcform->proisstrict)
4694  goto fail;
4695  }
4696  else if (usecounts[i] != 1)
4697  {
4698  /* Param used multiple times: uncool if expensive or volatile */
4699  QualCost eval_cost;
4700 
4701  /*
4702  * We define "expensive" as "contains any subplan or more than 10
4703  * operators". Note that the subplan search has to be done
4704  * explicitly, since cost_qual_eval() will barf on unplanned
4705  * subselects.
4706  */
4707  if (contain_subplans(param))
4708  goto fail;
4709  cost_qual_eval(&eval_cost, list_make1(param), NULL);
4710  if (eval_cost.startup + eval_cost.per_tuple >
4711  10 * cpu_operator_cost)
4712  goto fail;
4713 
4714  /*
4715  * Check volatility last since this is more expensive than the
4716  * above tests
4717  */
4718  if (contain_volatile_functions(param))
4719  goto fail;
4720  }
4721  i++;
4722  }
4723 
4724  /*
4725  * Whew --- we can make the substitution. Copy the modified expression
4726  * out of the temporary memory context, and clean up.
4727  */
4728  MemoryContextSwitchTo(oldcxt);
4729 
4730  newexpr = copyObject(newexpr);
4731 
4732  MemoryContextDelete(mycxt);
4733 
4734  /*
4735  * If the result is of a collatable type, force the result to expose the
4736  * correct collation. In most cases this does not matter, but it's
4737  * possible that the function result is used directly as a sort key or in
4738  * other places where we expect exprCollation() to tell the truth.
4739  */
4740  if (OidIsValid(result_collid))
4741  {
4742  Oid exprcoll = exprCollation(newexpr);
4743 
4744  if (OidIsValid(exprcoll) && exprcoll != result_collid)
4745  {
4746  CollateExpr *newnode = makeNode(CollateExpr);
4747 
4748  newnode->arg = (Expr *) newexpr;
4749  newnode->collOid = result_collid;
4750  newnode->location = -1;
4751 
4752  newexpr = (Node *) newnode;
4753  }
4754  }
4755 
4756  /*
4757  * Since there is now no trace of the function in the plan tree, we must
4758  * explicitly record the plan's dependency on the function.
4759  */
4760  if (context->root)
4761  record_plan_function_dependency(context->root, funcid);
4762 
4763  /*
4764  * Recursively try to simplify the modified expression. Here we must add
4765  * the current function to the context list of active functions.
4766  */
4767  context->active_fns = lappend_oid(context->active_fns, funcid);
4768  newexpr = eval_const_expressions_mutator(newexpr, context);
4769  context->active_fns = list_delete_last(context->active_fns);
4770 
4771  error_context_stack = sqlerrcontext.previous;
4772 
4773  return (Expr *) newexpr;
4774 
4775  /* Here if func is not inlinable: release temp memory and return NULL */
4776 fail:
4777  MemoryContextSwitchTo(oldcxt);
4778  MemoryContextDelete(mycxt);
4779  error_context_stack = sqlerrcontext.previous;
4780 
4781  return NULL;
4782 }
Datum querytree(PG_FUNCTION_ARGS)
Definition: _int_bool.c:666
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3775
#define NameStr(name)
Definition: c.h:730
static Node * substitute_actual_parameters(Node *expr, int nargs, List *args, int *usecounts)
Definition: clauses.c:4788
static void sql_inline_error_callback(void *arg)
Definition: clauses.c:4830
static bool contain_context_dependent_node(Node *clause)
Definition: clauses.c:1089
bool contain_nonstrict_functions(Node *clause)
Definition: clauses.c:903
bool contain_subplans(Node *clause)
Definition: clauses.c:332
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:477
double cpu_operator_cost
Definition: costsize.c:124
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:4370
ErrorContextCallback * error_context_stack
Definition: elog.c:95
#define FmgrHookIsNeeded(fn_oid)
Definition: fmgr.h:797
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:292
bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, bool insertDroppedCols, List **resultTargetList)
Definition: functions.c:1607
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:374
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:721
List * list_delete_last(List *list)
Definition: list.c:956
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:387
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
Oid GetUserId(void)
Definition: miscinit.c:510
@ CMD_SELECT
Definition: nodes.h:276
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:90
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:251
#define linitial_node(type, l)
Definition: pg_list.h:181
List * pg_parse_query(const char *query_string)
Definition: postgres.c:577
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:3422
struct ErrorContextCallback * previous
Definition: elog.h:295
void(* callback)(void *arg)
Definition: elog.h:296
const char * p_sourcetext
Definition: parse_node.h:192
Cost per_tuple
Definition: pathnodes.h:48
Cost startup
Definition: pathnodes.h:47

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, error_context_stack, eval_const_expressions_mutator(), exprCollation(), exprType(), FmgrHookIsNeeded, free_parsestate(), FuncExpr::funcid, get_expr_result_type(), GETSTRUCT, GetUserId(), heap_attisnull(), i, 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, object_aclcheck(), OidIsValid, ParseState::p_sourcetext, palloc0(), QualCost::per_tuple, pg_parse_query(), 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(), SysCacheGetAttrNotNull(), TextDatumGetCString, and transformTopLevelStmt().

Referenced by simplify_function().

◆ inline_set_returning_function()

Query* inline_set_returning_function ( PlannerInfo root,
RangeTblEntry rte 
)

Definition at line 4946 of file clauses.c.

4947 {
4948  RangeTblFunction *rtfunc;
4949  FuncExpr *fexpr;
4950  Oid func_oid;
4951  HeapTuple func_tuple;
4952  Form_pg_proc funcform;
4953  char *src;
4954  Datum tmp;
4955  bool isNull;
4956  MemoryContext oldcxt;
4957  MemoryContext mycxt;
4958  inline_error_callback_arg callback_arg;
4959  ErrorContextCallback sqlerrcontext;
4961  TypeFuncClass functypclass;
4962  TupleDesc rettupdesc;
4963  List *raw_parsetree_list;
4964  List *querytree_list;
4965  Query *querytree;
4966 
4967  Assert(rte->rtekind == RTE_FUNCTION);
4968 
4969  /*
4970  * It doesn't make a lot of sense for a SQL SRF to refer to itself in its
4971  * own FROM clause, since that must cause infinite recursion at runtime.
4972  * It will cause this code to recurse too, so check for stack overflow.
4973  * (There's no need to do more.)
4974  */
4976 
4977  /* Fail if the RTE has ORDINALITY - we don't implement that here. */
4978  if (rte->funcordinality)
4979  return NULL;
4980 
4981  /* Fail if RTE isn't a single, simple FuncExpr */
4982  if (list_length(rte->functions) != 1)
4983  return NULL;
4984  rtfunc = (RangeTblFunction *) linitial(rte->functions);
4985 
4986  if (!IsA(rtfunc->funcexpr, FuncExpr))
4987  return NULL;
4988  fexpr = (FuncExpr *) rtfunc->funcexpr;
4989 
4990  func_oid = fexpr->funcid;
4991 
4992  /*
4993  * The function must be declared to return a set, else inlining would
4994  * change the results if the contained SELECT didn't return exactly one
4995  * row.
4996  */
4997  if (!fexpr->funcretset)
4998  return NULL;
4999 
5000  /*
5001  * Refuse to inline if the arguments contain any volatile functions or
5002  * sub-selects. Volatile functions are rejected because inlining may
5003  * result in the arguments being evaluated multiple times, risking a
5004  * change in behavior. Sub-selects are rejected partly for implementation
5005  * reasons (pushing them down another level might change their behavior)
5006  * and partly because they're likely to be expensive and so multiple
5007  * evaluation would be bad.
5008  */
5009  if (contain_volatile_functions((Node *) fexpr->args) ||
5010  contain_subplans((Node *) fexpr->args))
5011  return NULL;
5012 
5013  /* Check permission to call function (fail later, if not) */
5014  if (object_aclcheck(ProcedureRelationId, func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
5015  return NULL;
5016 
5017  /* Check whether a plugin wants to hook function entry/exit */
5018  if (FmgrHookIsNeeded(func_oid))
5019  return NULL;
5020 
5021  /*
5022  * OK, let's take a look at the function's pg_proc entry.
5023  */
5024  func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid));
5025  if (!HeapTupleIsValid(func_tuple))
5026  elog(ERROR, "cache lookup failed for function %u", func_oid);
5027  funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
5028 
5029  /*
5030  * Forget it if the function is not SQL-language or has other showstopper
5031  * properties. In particular it mustn't be declared STRICT, since we
5032  * couldn't enforce that. It also mustn't be VOLATILE, because that is
5033  * supposed to cause it to be executed with its own snapshot, rather than
5034  * sharing the snapshot of the calling query. We also disallow returning
5035  * SETOF VOID, because inlining would result in exposing the actual result
5036  * of the function's last SELECT, which should not happen in that case.
5037  * (Rechecking prokind, proretset, and pronargs is just paranoia.)
5038  */
5039  if (funcform->prolang != SQLlanguageId ||
5040  funcform->prokind != PROKIND_FUNCTION ||
5041  funcform->proisstrict ||
5042  funcform->provolatile == PROVOLATILE_VOLATILE ||
5043  funcform->prorettype == VOIDOID ||
5044  funcform->prosecdef ||
5045  !funcform->proretset ||
5046  list_length(fexpr->args) != funcform->pronargs ||
5047  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL))
5048  {
5049  ReleaseSysCache(func_tuple);
5050  return NULL;
5051  }
5052 
5053  /*
5054  * Make a temporary memory context, so that we don't leak all the stuff
5055  * that parsing might create.
5056  */
5058  "inline_set_returning_function",
5060  oldcxt = MemoryContextSwitchTo(mycxt);
5061 
5062  /* Fetch the function body */
5063  tmp = SysCacheGetAttrNotNull(PROCOID, func_tuple, Anum_pg_proc_prosrc);
5064  src = TextDatumGetCString(tmp);
5065 
5066  /*
5067  * Setup error traceback support for ereport(). This is so that we can
5068  * finger the function that bad information came from.
5069  */
5070  callback_arg.proname = NameStr(funcform->proname);
5071  callback_arg.prosrc = src;
5072 
5073  sqlerrcontext.callback = sql_inline_error_callback;
5074  sqlerrcontext.arg = (void *) &callback_arg;
5075  sqlerrcontext.previous = error_context_stack;
5076  error_context_stack = &sqlerrcontext;
5077 
5078  /* If we have prosqlbody, pay attention to that not prosrc */
5079  tmp = SysCacheGetAttr(PROCOID,
5080  func_tuple,
5081  Anum_pg_proc_prosqlbody,
5082  &isNull);
5083  if (!isNull)
5084  {
5085  Node *n;
5086 
5088  if (IsA(n, List))
5089  querytree_list = linitial_node(List, castNode(List, n));
5090  else
5091  querytree_list = list_make1(n);
5092  if (list_length(querytree_list) != 1)
5093  goto fail;
5094  querytree = linitial(querytree_list);
5095 
5096  /* Acquire necessary locks, then apply rewriter. */
5097  AcquireRewriteLocks(querytree, true, false);
5098  querytree_list = pg_rewrite_query(querytree);
5099  if (list_length(querytree_list) != 1)
5100  goto fail;
5101  querytree = linitial(querytree_list);
5102  }
5103  else
5104  {
5105  /*
5106  * Set up to handle parameters while parsing the function body. We
5107  * can use the FuncExpr just created as the input for
5108  * prepare_sql_fn_parse_info.
5109  */
5110  pinfo = prepare_sql_fn_parse_info(func_tuple,
5111  (Node *) fexpr,
5112  fexpr->inputcollid);
5113 
5114  /*
5115  * Parse, analyze, and rewrite (unlike inline_function(), we can't
5116  * skip rewriting here). We can fail as soon as we find more than one
5117  * query, though.
5118  */
5119  raw_parsetree_list = pg_parse_query(src);
5120  if (list_length(raw_parsetree_list) != 1)
5121  goto fail;
5122 
5123  querytree_list = pg_analyze_and_rewrite_withcb(linitial(raw_parsetree_list),
5124  src,
5126  pinfo, NULL);
5127  if (list_length(querytree_list) != 1)
5128  goto fail;
5129  querytree = linitial(querytree_list);
5130  }
5131 
5132  /*
5133  * Also resolve the actual function result tupdesc, if composite. If the
5134  * function is just declared to return RECORD, dig the info out of the AS
5135  * clause.
5136  */
5137  functypclass = get_expr_result_type((Node *) fexpr, NULL, &rettupdesc);
5138  if (functypclass == TYPEFUNC_RECORD)
5139  rettupdesc = BuildDescFromLists(rtfunc->funccolnames,
5140  rtfunc->funccoltypes,
5141  rtfunc->funccoltypmods,
5142  rtfunc->funccolcollations);
5143 
5144  /*
5145  * The single command must be a plain SELECT.
5146  */
5147  if (!IsA(querytree, Query) ||
5148  querytree->commandType != CMD_SELECT)
5149  goto fail;
5150 
5151  /*
5152  * Make sure the function (still) returns what it's declared to. This
5153  * will raise an error if wrong, but that's okay since the function would
5154  * fail at runtime anyway. Note that check_sql_fn_retval will also insert
5155  * coercions if needed to make the tlist expression(s) match the declared
5156  * type of the function. We also ask it to insert dummy NULL columns for
5157  * any dropped columns in rettupdesc, so that the elements of the modified
5158  * tlist match up to the attribute numbers.
5159  *
5160  * If the function returns a composite type, don't inline unless the check
5161  * shows it's returning a whole tuple result; otherwise what it's
5162  * returning is a single composite column which is not what we need.
5163  */
5164  if (!check_sql_fn_retval(list_make1(querytree_list),
5165  fexpr->funcresulttype, rettupdesc,
5166  true, NULL) &&
5167  (functypclass == TYPEFUNC_COMPOSITE ||
5168  functypclass == TYPEFUNC_COMPOSITE_DOMAIN ||
5169  functypclass == TYPEFUNC_RECORD))
5170  goto fail; /* reject not-whole-tuple-result cases */
5171 
5172  /*
5173  * check_sql_fn_retval might've inserted a projection step, but that's
5174  * fine; just make sure we use the upper Query.
5175  */
5176  querytree = linitial_node(Query, querytree_list);
5177 
5178  /*
5179  * Looks good --- substitute parameters into the query.
5180  */
5182  funcform->pronargs,
5183  fexpr->args);
5184 
5185  /*
5186  * Copy the modified query out of the temporary memory context, and clean
5187  * up.
5188  */
5189  MemoryContextSwitchTo(oldcxt);
5190 
5192 
5193  MemoryContextDelete(mycxt);
5194  error_context_stack = sqlerrcontext.previous;
5195  ReleaseSysCache(func_tuple);
5196 
5197  /*
5198  * We don't have to fix collations here because the upper query is already
5199  * parsed, ie, the collations in the RTE are what count.
5200  */
5201 
5202  /*
5203  * Since there is now no trace of the function in the plan tree, we must
5204  * explicitly record the plan's dependency on the function.
5205  */
5206  record_plan_function_dependency(root, func_oid);
5207 
5208  return querytree;
5209 
5210  /* Here if func is not inlinable: release temp memory and return NULL */
5211 fail:
5212  MemoryContextSwitchTo(oldcxt);
5213  MemoryContextDelete(mycxt);
5214  error_context_stack = sqlerrcontext.previous;
5215  ReleaseSysCache(func_tuple);
5216 
5217  return NULL;
5218 }
static Query * substitute_actual_srf_parameters(Query *expr, int nargs, List *args)
Definition: clauses.c:5227
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:1017
List * pg_analyze_and_rewrite_withcb(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:730
List * pg_rewrite_query(Query *query)
Definition: postgres.c:770
void check_stack_depth(void)
Definition: postgres.c:3461
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
bool funcordinality
Definition: parsenodes.h:1149
List * functions
Definition: parsenodes.h:1148
RTEKind rtekind
Definition: parsenodes.h:1033
TupleDesc BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
Definition: tupdesc.c:894

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::funcexpr, FuncExpr::funcid, RangeTblEntry::funcordinality, RangeTblEntry::functions, get_expr_result_type(), GETSTRUCT, GetUserId(), heap_attisnull(), HeapTupleIsValid, if(), IsA, linitial, linitial_node, list_length(), list_make1, MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, object_aclcheck(), ObjectIdGetDatum(), pg_analyze_and_rewrite_withcb(), pg_parse_query(), 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(), SysCacheGetAttrNotNull(), 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 663 of file clauses.c.

664 {
666  PlannerInfo *proot;
667  ListCell *l;
668 
669  /*
670  * Even if the original querytree contained nothing unsafe, we need to
671  * search the expression if we have generated any PARAM_EXEC Params while
672  * planning, because those are parallel-restricted and there might be one
673  * in this expression. But otherwise we don't need to look.
674  */
675  if (root->glob->maxParallelHazard == PROPARALLEL_SAFE &&
676  root->glob->paramExecTypes == NIL)
677  return true;
678  /* Else use max_parallel_hazard's search logic, but stop on RESTRICTED */
679  context.max_hazard = PROPARALLEL_SAFE;
680  context.max_interesting = PROPARALLEL_RESTRICTED;
681  context.safe_param_ids = NIL;
682 
683  /*
684  * The params that refer to the same or parent query level are considered
685  * parallel-safe. The idea is that we compute such params at Gather or
686  * Gather Merge node and pass their value to workers.
687  */
688  for (proot = root; proot != NULL; proot = proot->parent_root)
689  {
690  foreach(l, proot->init_plans)
691  {
692  SubPlan *initsubplan = (SubPlan *) lfirst(l);
693 
694  context.safe_param_ids = list_concat(context.safe_param_ids,
695  initsubplan->setParam);
696  }
697  }
698 
699  return !max_parallel_hazard_walker(node, &context);
700 }
static bool max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
Definition: clauses.c:739
List * list_concat(List *list1, const List *list2)
Definition: list.c:560
char maxParallelHazard
Definition: pathnodes.h:162
List * paramExecTypes
Definition: pathnodes.h:138
List * init_plans
Definition: pathnodes.h:299
List * setParam
Definition: primnodes.h:1015

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

1998 {
1999  /*
2000  * We could implement this check in one recursive scan. But since the
2001  * check for volatile functions is both moderately expensive and unlikely
2002  * to fail, it seems better to look for Vars first and only check for
2003  * volatile functions if we find no Vars.
2004  */
2005  if (!contain_var_clause(clause) &&
2006  !contain_volatile_functions(clause))
2007  return true;
2008  return false;
2009 }

References contain_var_clause(), and contain_volatile_functions().

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

◆ is_pseudo_constant_clause_relids()

bool is_pseudo_constant_clause_relids ( Node clause,
Relids  relids 
)

Definition at line 2017 of file clauses.c.

2018 {
2019  if (bms_is_empty(relids) &&
2020  !contain_volatile_functions(clause))
2021  return true;
2022  return false;
2023 }

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

1936 {
1937  Node *rightop;
1938 
1939  /* The contained operator must be strict. */
1940  set_sa_opfuncid(expr);
1941  if (!func_strict(expr->opfuncid))
1942  return false;
1943  /* If ANY and falseOK, that's all we need to check. */
1944  if (expr->useOr && falseOK)
1945  return true;
1946  /* Else, we have to see if the array is provably non-empty. */
1947  Assert(list_length(expr->args) == 2);
1948  rightop = (Node *) lsecond(expr->args);
1949  if (rightop && IsA(rightop, Const))
1950  {
1951  Datum arraydatum = ((Const *) rightop)->constvalue;
1952  bool arrayisnull = ((Const *) rightop)->constisnull;
1953  ArrayType *arrayval;
1954  int nitems;
1955 
1956  if (arrayisnull)
1957  return false;
1958  arrayval = DatumGetArrayTypeP(arraydatum);
1959  nitems = ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval));
1960  if (nitems > 0)
1961  return true;
1962  }
1963  else if (rightop && IsA(rightop, ArrayExpr))
1964  {
1965  ArrayExpr *arrayexpr = (ArrayExpr *) rightop;
1966 
1967  if (arrayexpr->elements != NIL && !arrayexpr->multidims)
1968  return true;
1969  }
1970  return false;
1971 }
List * elements
Definition: primnodes.h:1305

References ScalarArrayOpExpr::args, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), Assert(), DatumGetArrayTypeP, ArrayExpr::elements, func_strict(), IsA, list_length(), lsecond, NIL, nitems, 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 644 of file clauses.c.

645 {
647 
648  context.max_hazard = PROPARALLEL_SAFE;
649  context.max_interesting = PROPARALLEL_UNSAFE;
650  context.safe_param_ids = NIL;
651  (void) max_parallel_hazard_walker((Node *) parse, &context);
652  return context.max_hazard;
653 }
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717

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

733 {
734  return max_parallel_hazard_test(func_parallel(func_id),
735  (max_parallel_hazard_context *) context);
736 }
static bool max_parallel_hazard_test(char proparallel, max_parallel_hazard_context *context)
Definition: clauses.c:704
char func_parallel(Oid funcid)
Definition: lsyscache.c:1781

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

705 {
706  switch (proparallel)
707  {
708  case PROPARALLEL_SAFE:
709  /* nothing to see here, move along */
710  break;
711  case PROPARALLEL_RESTRICTED:
712  /* increase max_hazard to RESTRICTED */
713  Assert(context->max_hazard != PROPARALLEL_UNSAFE);
714  context->max_hazard = proparallel;
715  /* done if we are not expecting any unsafe functions */
716  if (context->max_interesting == proparallel)
717  return true;
718  break;
719  case PROPARALLEL_UNSAFE:
720  context->max_hazard = proparallel;
721  /* we're always done at the first unsafe construct */
722  return true;
723  default:
724  elog(ERROR, "unrecognized proparallel value \"%c\"", proparallel);
725  break;
726  }
727  return false;
728 }

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

740 {
741  if (node == NULL)
742  return false;
743 
744  /* Check for hazardous functions in node itself */
746  context))
747  return true;
748 
749  /*
750  * It should be OK to treat MinMaxExpr as parallel-safe, since btree
751  * opclass support functions are generally parallel-safe. XmlExpr is a
752  * bit more dubious but we can probably get away with it. We err on the
753  * side of caution by treating CoerceToDomain as parallel-restricted.
754  * (Note: in principle that's wrong because a domain constraint could
755  * contain a parallel-unsafe function; but useful constraints probably
756  * never would have such, and assuming they do would cripple use of
757  * parallel query in the presence of domain types.) NextValueExpr is
758  * parallel-unsafe.
759  */
760  if (IsA(node, CoerceToDomain))
761  {
762  if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
763  return true;
764  }
765 
766  else if (IsA(node, NextValueExpr))
767  {
768  if (max_parallel_hazard_test(PROPARALLEL_UNSAFE, context))
769  return true;
770  }
771 
772  /*
773  * Treat window functions as parallel-restricted because we aren't sure
774  * whether the input row ordering is fully deterministic, and the output
775  * of window functions might vary across workers if not. (In some cases,
776  * like where the window frame orders by a primary key, we could relax
777  * this restriction. But it doesn't currently seem worth expending extra
778  * effort to do so.)
779  */
780  else if (IsA(node, WindowFunc))
781  {
782  if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
783  return true;
784  }
785 
786  /*
787  * As a notational convenience for callers, look through RestrictInfo.
788  */
789  else if (IsA(node, RestrictInfo))
790  {
791  RestrictInfo *rinfo = (RestrictInfo *) node;
792 
793  return max_parallel_hazard_walker((Node *) rinfo->clause, context);
794  }
795 
796  /*
797  * Really we should not see SubLink during a max_interesting == restricted
798  * scan, but if we do, return true.
799  */
800  else if (IsA(node, SubLink))
801  {
802  if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
803  return true;
804  }
805 
806  /*
807  * Only parallel-safe SubPlans can be sent to workers. Within the
808  * testexpr of the SubPlan, Params representing the output columns of the
809  * subplan can be treated as parallel-safe, so temporarily add their IDs
810  * to the safe_param_ids list while examining the testexpr.
811  */
812  else if (IsA(node, SubPlan))
813  {
814  SubPlan *subplan = (SubPlan *) node;
815  List *save_safe_param_ids;
816 
817  if (!subplan->parallel_safe &&
818  max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
819  return true;
820  save_safe_param_ids = context->safe_param_ids;
821  context->safe_param_ids = list_concat_copy(context->safe_param_ids,
822  subplan->paramIds);
823  if (max_parallel_hazard_walker(subplan->testexpr, context))
824  return true; /* no need to restore safe_param_ids */
825  list_free(context->safe_param_ids);
826  context->safe_param_ids = save_safe_param_ids;
827  /* we must also check args, but no special Param treatment there */
828  if (max_parallel_hazard_walker((Node *) subplan->args, context))
829  return true;
830  /* don't want to recurse normally, so we're done */
831  return false;
832  }
833 
834  /*
835  * We can't pass Params to workers at the moment either, so they are also
836  * parallel-restricted, unless they are PARAM_EXTERN Params or are
837  * PARAM_EXEC Params listed in safe_param_ids, meaning they could be
838  * either generated within workers or can be computed by the leader and
839  * then their value can be passed to workers.
840  */
841  else if (IsA(node, Param))
842  {
843  Param *param = (Param *) node;
844 
845  if (param->paramkind == PARAM_EXTERN)
846  return false;
847 
848  if (param->paramkind != PARAM_EXEC ||
849  !list_member_int(context->safe_param_ids, param->paramid))
850  {
851  if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
852  return true;
853  }
854  return false; /* nothing to recurse to */
855  }
856 
857  /*
858  * When we're first invoked on a completely unplanned tree, we must
859  * recurse into subqueries so to as to locate parallel-unsafe constructs
860  * anywhere in the tree.
861  */
862  else if (IsA(node, Query))
863  {
864  Query *query = (Query *) node;
865 
866  /* SELECT FOR UPDATE/SHARE must be treated as unsafe */
867  if (query->rowMarks != NULL)
868  {
869  context->max_hazard = PROPARALLEL_UNSAFE;
870  return true;
871  }
872 
873  /* Recurse into subselects */
874  return query_tree_walker(query,
876  context, 0);
877  }
878 
879  /* Recurse to check arguments */
880  return expression_tree_walker(node,
882  context);
883 }
static bool max_parallel_hazard_checker(Oid func_id, void *context)
Definition: clauses.c:732
void list_free(List *list)
Definition: list.c:1545
List * rowMarks
Definition: parsenodes.h:215
List * args
Definition: primnodes.h:1018
List * paramIds
Definition: primnodes.h:995
Node * testexpr
Definition: primnodes.h:994
bool parallel_safe
Definition: primnodes.h:1011

References SubPlan::args, check_functions_in_node(), RestrictInfo::clause, expression_tree_walker, IsA, list_concat_copy(), list_free(), list_member_int(), max_parallel_hazard_context::max_hazard, max_parallel_hazard_checker(), max_parallel_hazard_test(), SubPlan::parallel_safe, PARAM_EXEC, PARAM_EXTERN, Param::paramid, SubPlan::paramIds, Param::paramkind, query_tree_walker, Query::rowMarks, max_parallel_hazard_context::safe_param_ids, and SubPlan::testexpr.

Referenced by is_parallel_safe(), and max_parallel_hazard().

◆ NumRelids()

int NumRelids ( PlannerInfo root,
Node clause 
)

Definition at line 2039 of file clauses.c.

2040 {
2041  int result;
2042  Relids varnos = pull_varnos(root, clause);
2043 
2044  varnos = bms_del_members(varnos, root->outer_join_rels);
2045  result = bms_num_members(varnos);
2046  bms_free(varnos);
2047  return result;
2048 }
void bms_free(Bitmapset *a)
Definition: bitmapset.c:209
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:665
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:960
Relids outer_join_rels
Definition: pathnodes.h:261
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:108

References bms_del_members(), bms_free(), bms_num_members(), PlannerInfo::outer_join_rels, and pull_varnos().

Referenced by clauselist_selectivity_ext(), rowcomparesel(), and treat_as_join_clause().

◆ pull_paramids()

Bitmapset* pull_paramids ( Expr expr)

Definition at line 5287 of file clauses.c.

5288 {
5289  Bitmapset *result = NULL;
5290 
5291  (void) pull_paramids_walker((Node *) expr, &result);
5292 
5293  return result;
5294 }
static bool pull_paramids_walker(Node *node, Bitmapset **context)
Definition: clauses.c:5297

References pull_paramids_walker().

Referenced by create_memoize_plan().

◆ pull_paramids_walker()

static bool pull_paramids_walker ( Node node,
Bitmapset **  context 
)
static

Definition at line 5297 of file clauses.c.

5298 {
5299  if (node == NULL)
5300  return false;
5301  if (IsA(node, Param))
5302  {
5303  Param *param = (Param *) node;
5304 
5305  *context = bms_add_member(*context, param->paramid);
5306  return false;
5307  }
5309  (void *) context);
5310 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:755

References bms_add_member(), expression_tree_walker, IsA, and Param::paramid.

Referenced by pull_paramids().

◆ recheck_cast_function_args()

static void recheck_cast_function_args ( List args,
Oid  result_type,
Oid proargtypes,
int  pronargs,
HeapTuple  func_tuple 
)
static

Definition at line 4261 of file clauses.c.

4264 {
4265  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4266  int nargs;
4267  Oid actual_arg_types[FUNC_MAX_ARGS];
4268  Oid declared_arg_types[FUNC_MAX_ARGS];
4269  Oid rettype;
4270  ListCell *lc;
4271 
4273  elog(ERROR, "too many function arguments");
4274  nargs = 0;
4275  foreach(lc, args)
4276  {
4277  actual_arg_types[nargs++] = exprType((Node *) lfirst(lc));
4278  }
4279  Assert(nargs == pronargs);
4280  memcpy(declared_arg_types, proargtypes, pronargs * sizeof(Oid));
4281  rettype = enforce_generic_type_consistency(actual_arg_types,
4282  declared_arg_types,
4283  nargs,
4284  funcform->prorettype,
4285  false);
4286  /* let's just check we got the same answer as the parser did ... */
4287  if (rettype != result_type)
4288  elog(ERROR, "function's resolved result type changed during planning");
4289 
4290  /* perform any necessary typecasting of arguments */
4291  make_fn_arguments(NULL, args, actual_arg_types, declared_arg_types);
4292 }