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

Go to the source code of this file.

Data Structures

struct  get_agg_clause_costs_context
 
struct  eval_const_expressions_context
 
struct  substitute_actual_parameters_context
 
struct  substitute_actual_srf_parameters_context
 
struct  inline_error_callback_arg
 
struct  max_parallel_hazard_context
 

Macros

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

Functions

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

Macro Definition Documentation

◆ CCDN_CASETESTEXPR_OK

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

Definition at line 1284 of file clauses.c.

Referenced by contain_context_dependent_node_walker().

◆ ece_all_arguments_const

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

Definition at line 2351 of file clauses.c.

Referenced by eval_const_expressions_mutator().

◆ ece_evaluate_expr

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

Definition at line 2355 of file clauses.c.

Referenced by eval_const_expressions_mutator().

◆ ece_generic_processing

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

Definition at line 2342 of file clauses.c.

Referenced by eval_const_expressions_mutator().

Function Documentation

◆ add_function_defaults()

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

Definition at line 4128 of file clauses.c.

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

Referenced by expand_function_arguments().

4129 {
4130  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4131  int nargsprovided = list_length(args);
4132  List *defaults;
4133  int ndelete;
4134 
4135  /* Get all the default expressions from the pg_proc tuple */
4136  defaults = fetch_function_defaults(func_tuple);
4137 
4138  /* Delete any unused defaults from the list */
4139  ndelete = nargsprovided + list_length(defaults) - funcform->pronargs;
4140  if (ndelete < 0)
4141  elog(ERROR, "not enough default arguments");
4142  if (ndelete > 0)
4143  defaults = list_copy_tail(defaults, ndelete);
4144 
4145  /* And form the combined argument list, not modifying the input list */
4146  return list_concat_copy(args, defaults);
4147 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1422
#define ERROR
Definition: elog.h:43
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:552
static List * fetch_function_defaults(HeapTuple func_tuple)
Definition: clauses.c:4153
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
static int list_length(const List *l)
Definition: pg_list.h:169
#define elog(elevel,...)
Definition: elog.h:214
Definition: pg_list.h:50

◆ CommuteOpExpr()

void CommuteOpExpr ( OpExpr clause)

Definition at line 2180 of file clauses.c.

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

Referenced by get_switched_clauses().

2181 {
2182  Oid opoid;
2183  Node *temp;
2184 
2185  /* Sanity checks: caller is at fault if these fail */
2186  if (!is_opclause(clause) ||
2187  list_length(clause->args) != 2)
2188  elog(ERROR, "cannot commute non-binary-operator clause");
2189 
2190  opoid = get_commutator(clause->opno);
2191 
2192  if (!OidIsValid(opoid))
2193  elog(ERROR, "could not find commutator for operator %u",
2194  clause->opno);
2195 
2196  /*
2197  * modify the clause in-place!
2198  */
2199  clause->opno = opoid;
2200  clause->opfuncid = InvalidOid;
2201  /* opresulttype, opretset, opcollid, inputcollid need not change */
2202 
2203  temp = linitial(clause->args);
2204  linitial(clause->args) = lsecond(clause->args);
2205  lsecond(clause->args) = temp;
2206 }
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1421
Definition: nodes.h:529
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
#define lsecond(l)
Definition: pg_list.h:200
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
Oid opfuncid
Definition: primnodes.h:517
#define InvalidOid
Definition: postgres_ext.h:36
static int list_length(const List *l)
Definition: pg_list.h:169
#define elog(elevel,...)
Definition: elog.h:214
Oid opno
Definition: primnodes.h:516
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:66
List * args
Definition: primnodes.h:522

◆ contain_agg_clause()

bool contain_agg_clause ( Node clause)

Definition at line 179 of file clauses.c.

References contain_agg_clause_walker().

Referenced by get_eclass_for_sort_expr(), and subquery_planner().

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

◆ contain_agg_clause_walker()

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

Definition at line 185 of file clauses.c.

References Assert, expression_tree_walker(), and IsA.

Referenced by contain_agg_clause().

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 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
static bool contain_agg_clause_walker(Node *node, void *context)
Definition: clauses.c:185
#define Assert(condition)
Definition: c.h:745
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888

◆ contain_context_dependent_node()

static bool contain_context_dependent_node ( Node clause)
static

Definition at line 1277 of file clauses.c.

References contain_context_dependent_node_walker().

Referenced by inline_function().

1278 {
1279  int flags = 0;
1280 
1281  return contain_context_dependent_node_walker(clause, &flags);
1282 }
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:1287

◆ contain_context_dependent_node_walker()

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

Definition at line 1287 of file clauses.c.

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

Referenced by contain_context_dependent_node().

1288 {
1289  if (node == NULL)
1290  return false;
1291  if (IsA(node, CaseTestExpr))
1292  return !(*flags & CCDN_CASETESTEXPR_OK);
1293  else if (IsA(node, CaseExpr))
1294  {
1295  CaseExpr *caseexpr = (CaseExpr *) node;
1296 
1297  /*
1298  * If this CASE doesn't have a test expression, then it doesn't create
1299  * a context in which CaseTestExprs should appear, so just fall
1300  * through and treat it as a generic expression node.
1301  */
1302  if (caseexpr->arg)
1303  {
1304  int save_flags = *flags;
1305  bool res;
1306 
1307  /*
1308  * Note: in principle, we could distinguish the various sub-parts
1309  * of a CASE construct and set the flag bit only for some of them,
1310  * since we are only expecting CaseTestExprs to appear in the
1311  * "expr" subtree of the CaseWhen nodes. But it doesn't really
1312  * seem worth any extra code. If there are any bare CaseTestExprs
1313  * elsewhere in the CASE, something's wrong already.
1314  */
1315  *flags |= CCDN_CASETESTEXPR_OK;
1316  res = expression_tree_walker(node,
1318  (void *) flags);
1319  *flags = save_flags;
1320  return res;
1321  }
1322  }
1323  else if (IsA(node, ArrayCoerceExpr))
1324  {
1325  ArrayCoerceExpr *ac = (ArrayCoerceExpr *) node;
1326  int save_flags;
1327  bool res;
1328 
1329  /* Check the array expression */
1330  if (contain_context_dependent_node_walker((Node *) ac->arg, flags))
1331  return true;
1332 
1333  /* Check the elemexpr, which is allowed to contain CaseTestExpr */
1334  save_flags = *flags;
1335  *flags |= CCDN_CASETESTEXPR_OK;
1337  flags);
1338  *flags = save_flags;
1339  return res;
1340  }
1342  (void *) flags);
1343 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Definition: nodes.h:529
#define CCDN_CASETESTEXPR_OK
Definition: clauses.c:1284
Expr * elemexpr
Definition: primnodes.h:859
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
Expr * arg
Definition: primnodes.h:932
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:1287

◆ contain_exec_param()

bool contain_exec_param ( Node clause,
List param_ids 
)

Definition at line 1235 of file clauses.c.

References contain_exec_param_walker().

Referenced by test_opexpr_is_hashable().

1236 {
1237  return contain_exec_param_walker(clause, param_ids);
1238 }
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition: clauses.c:1241

◆ contain_exec_param_walker()

static bool contain_exec_param_walker ( Node node,
List param_ids 
)
static

Definition at line 1241 of file clauses.c.

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

Referenced by contain_exec_param().

1242 {
1243  if (node == NULL)
1244  return false;
1245  if (IsA(node, Param))
1246  {
1247  Param *p = (Param *) node;
1248 
1249  if (p->paramkind == PARAM_EXEC &&
1250  list_member_int(param_ids, p->paramid))
1251  return true;
1252  }
1253  return expression_tree_walker(node, contain_exec_param_walker, param_ids);
1254 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
ParamKind paramkind
Definition: primnodes.h:262
bool list_member_int(const List *list, int datum)
Definition: list.c:654
int paramid
Definition: primnodes.h:263
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition: clauses.c:1241

◆ contain_leaked_vars()

bool contain_leaked_vars ( Node clause)

Definition at line 1361 of file clauses.c.

References contain_leaked_vars_walker().

Referenced by make_restrictinfo_internal(), and qual_is_pushdown_safe().

1362 {
1363  return contain_leaked_vars_walker(clause, NULL);
1364 }
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1373

◆ contain_leaked_vars_checker()

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

Definition at line 1367 of file clauses.c.

References get_func_leakproof().

Referenced by contain_leaked_vars_walker().

1368 {
1369  return !get_func_leakproof(func_id);
1370 }
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1749

◆ contain_leaked_vars_walker()

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

Definition at line 1373 of file clauses.c.

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

Referenced by contain_leaked_vars().

1374 {
1375  if (node == NULL)
1376  return false;
1377 
1378  switch (nodeTag(node))
1379  {
1380  case T_Var:
1381  case T_Const:
1382  case T_Param:
1383  case T_ArrayExpr:
1384  case T_FieldSelect:
1385  case T_FieldStore:
1386  case T_NamedArgExpr:
1387  case T_BoolExpr:
1388  case T_RelabelType:
1389  case T_CollateExpr:
1390  case T_CaseExpr:
1391  case T_CaseTestExpr:
1392  case T_RowExpr:
1393  case T_SQLValueFunction:
1394  case T_NullTest:
1395  case T_BooleanTest:
1396  case T_NextValueExpr:
1397  case T_List:
1398 
1399  /*
1400  * We know these node types don't contain function calls; but
1401  * something further down in the node tree might.
1402  */
1403  break;
1404 
1405  case T_FuncExpr:
1406  case T_OpExpr:
1407  case T_DistinctExpr:
1408  case T_NullIfExpr:
1409  case T_ScalarArrayOpExpr:
1410  case T_CoerceViaIO:
1411  case T_ArrayCoerceExpr:
1412  case T_SubscriptingRef:
1413 
1414  /*
1415  * If node contains a leaky function call, and there's any Var
1416  * underneath it, reject.
1417  */
1419  context) &&
1420  contain_var_clause(node))
1421  return true;
1422  break;
1423 
1424  case T_RowCompareExpr:
1425  {
1426  /*
1427  * It's worth special-casing this because a leaky comparison
1428  * function only compromises one pair of row elements, which
1429  * might not contain Vars while others do.
1430  */
1431  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1432  ListCell *opid;
1433  ListCell *larg;
1434  ListCell *rarg;
1435 
1436  forthree(opid, rcexpr->opnos,
1437  larg, rcexpr->largs,
1438  rarg, rcexpr->rargs)
1439  {
1440  Oid funcid = get_opcode(lfirst_oid(opid));
1441 
1442  if (!get_func_leakproof(funcid) &&
1443  (contain_var_clause((Node *) lfirst(larg)) ||
1444  contain_var_clause((Node *) lfirst(rarg))))
1445  return true;
1446  }
1447  }
1448  break;
1449 
1450  case T_MinMaxExpr:
1451  {
1452  /*
1453  * MinMaxExpr is leakproof if the comparison function it calls
1454  * is leakproof.
1455  */
1456  MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
1457  TypeCacheEntry *typentry;
1458  bool leakproof;
1459 
1460  /* Look up the btree comparison function for the datatype */
1461  typentry = lookup_type_cache(minmaxexpr->minmaxtype,
1463  if (OidIsValid(typentry->cmp_proc))
1464  leakproof = get_func_leakproof(typentry->cmp_proc);
1465  else
1466  {
1467  /*
1468  * The executor will throw an error, but here we just
1469  * treat the missing function as leaky.
1470  */
1471  leakproof = false;
1472  }
1473 
1474  if (!leakproof &&
1475  contain_var_clause((Node *) minmaxexpr->args))
1476  return true;
1477  }
1478  break;
1479 
1480  case T_CurrentOfExpr:
1481 
1482  /*
1483  * WHERE CURRENT OF doesn't contain leaky function calls.
1484  * Moreover, it is essential that this is considered non-leaky,
1485  * since the planner must always generate a TID scan when CURRENT
1486  * OF is present -- cf. cost_tidscan.
1487  */
1488  return false;
1489 
1490  default:
1491 
1492  /*
1493  * If we don't recognize the node tag, assume it might be leaky.
1494  * This prevents an unexpected security hole if someone adds a new
1495  * node type that can call a function.
1496  */
1497  return true;
1498  }
1500  context);
1501 }
Oid minmaxtype
Definition: primnodes.h:1102
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1749
List * args
Definition: primnodes.h:1106
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:464
Definition: nodes.h:529
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
Definition: nodes.h:300
Definition: nodes.h:154
Definition: nodes.h:153
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1202
#define TYPECACHE_CMP_PROC
Definition: typcache.h:133
#define lfirst(lc)
Definition: pg_list.h:190
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
#define nodeTag(nodeptr)
Definition: nodes.h:534
static bool contain_leaked_vars_checker(Oid func_id, void *context)
Definition: clauses.c:1367
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1373
#define lfirst_oid(lc)
Definition: pg_list.h:192
Definition: nodes.h:155

◆ contain_mutable_functions()

◆ contain_mutable_functions_checker()

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

Definition at line 651 of file clauses.c.

References func_volatile().

Referenced by contain_mutable_functions_walker().

652 {
653  return (func_volatile(func_id) != PROVOLATILE_IMMUTABLE);
654 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1692

◆ contain_mutable_functions_walker()

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

Definition at line 657 of file clauses.c.

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

Referenced by contain_mutable_functions().

658 {
659  if (node == NULL)
660  return false;
661  /* Check for mutable functions in node itself */
663  context))
664  return true;
665 
666  if (IsA(node, SQLValueFunction))
667  {
668  /* all variants of SQLValueFunction are stable */
669  return true;
670  }
671 
672  if (IsA(node, NextValueExpr))
673  {
674  /* NextValueExpr is volatile */
675  return true;
676  }
677 
678  /*
679  * It should be safe to treat MinMaxExpr as immutable, because it will
680  * depend on a non-cross-type btree comparison function, and those should
681  * always be immutable. Treating XmlExpr as immutable is more dubious,
682  * and treating CoerceToDomain as immutable is outright dangerous. But we
683  * have done so historically, and changing this would probably cause more
684  * problems than it would fix. In practice, if you have a non-immutable
685  * domain constraint you are in for pain anyhow.
686  */
687 
688  /* Recurse to check arguments */
689  if (IsA(node, Query))
690  {
691  /* Recurse into subselects */
692  return query_tree_walker((Query *) node,
694  context, 0);
695  }
697  context);
698 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2322
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
static bool contain_mutable_functions_walker(Node *node, void *context)
Definition: clauses.c:657
static bool contain_mutable_functions_checker(Oid func_id, void *context)
Definition: clauses.c:651
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888

◆ contain_non_const_walker()

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

Definition at line 3585 of file clauses.c.

References expression_tree_walker(), and IsA.

3586 {
3587  if (node == NULL)
3588  return false;
3589  if (IsA(node, Const))
3590  return false;
3591  if (IsA(node, List))
3592  return expression_tree_walker(node, contain_non_const_walker, context);
3593  /* Otherwise, abort the tree traversal and return true */
3594  return true;
3595 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
Definition: pg_list.h:50
static bool contain_non_const_walker(Node *node, void *context)
Definition: clauses.c:3585

◆ contain_nonstrict_functions()

bool contain_nonstrict_functions ( Node clause)

Definition at line 1094 of file clauses.c.

References contain_nonstrict_functions_walker().

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

1095 {
1096  return contain_nonstrict_functions_walker(clause, NULL);
1097 }
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:1106

◆ contain_nonstrict_functions_checker()

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

Definition at line 1100 of file clauses.c.

References func_strict().

Referenced by contain_nonstrict_functions_walker().

1101 {
1102  return !func_strict(func_id);
1103 }
bool func_strict(Oid funcid)
Definition: lsyscache.c:1673

◆ contain_nonstrict_functions_walker()

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

Definition at line 1106 of file clauses.c.

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

Referenced by contain_nonstrict_functions().

1107 {
1108  if (node == NULL)
1109  return false;
1110  if (IsA(node, Aggref))
1111  {
1112  /* an aggregate could return non-null with null input */
1113  return true;
1114  }
1115  if (IsA(node, GroupingFunc))
1116  {
1117  /*
1118  * A GroupingFunc doesn't evaluate its arguments, and therefore must
1119  * be treated as nonstrict.
1120  */
1121  return true;
1122  }
1123  if (IsA(node, WindowFunc))
1124  {
1125  /* a window function could return non-null with null input */
1126  return true;
1127  }
1128  if (IsA(node, SubscriptingRef))
1129  {
1130  /*
1131  * subscripting assignment is nonstrict, but subscripting itself is
1132  * strict
1133  */
1134  if (((SubscriptingRef *) node)->refassgnexpr != NULL)
1135  return true;
1136 
1137  /* else fall through to check args */
1138  }
1139  if (IsA(node, DistinctExpr))
1140  {
1141  /* IS DISTINCT FROM is inherently non-strict */
1142  return true;
1143  }
1144  if (IsA(node, NullIfExpr))
1145  {
1146  /* NULLIF is inherently non-strict */
1147  return true;
1148  }
1149  if (IsA(node, BoolExpr))
1150  {
1151  BoolExpr *expr = (BoolExpr *) node;
1152 
1153  switch (expr->boolop)
1154  {
1155  case AND_EXPR:
1156  case OR_EXPR:
1157  /* AND, OR are inherently non-strict */
1158  return true;
1159  default:
1160  break;
1161  }
1162  }
1163  if (IsA(node, SubLink))
1164  {
1165  /* In some cases a sublink might be strict, but in general not */
1166  return true;
1167  }
1168  if (IsA(node, SubPlan))
1169  return true;
1170  if (IsA(node, AlternativeSubPlan))
1171  return true;
1172  if (IsA(node, FieldStore))
1173  return true;
1174  if (IsA(node, CoerceViaIO))
1175  {
1176  /*
1177  * CoerceViaIO is strict regardless of whether the I/O functions are,
1178  * so just go look at its argument; asking check_functions_in_node is
1179  * useless expense and could deliver the wrong answer.
1180  */
1181  return contain_nonstrict_functions_walker((Node *) ((CoerceViaIO *) node)->arg,
1182  context);
1183  }
1184  if (IsA(node, ArrayCoerceExpr))
1185  {
1186  /*
1187  * ArrayCoerceExpr is strict at the array level, regardless of what
1188  * the per-element expression is; so we should ignore elemexpr and
1189  * recurse only into the arg.
1190  */
1192  context);
1193  }
1194  if (IsA(node, CaseExpr))
1195  return true;
1196  if (IsA(node, ArrayExpr))
1197  return true;
1198  if (IsA(node, RowExpr))
1199  return true;
1200  if (IsA(node, RowCompareExpr))
1201  return true;
1202  if (IsA(node, CoalesceExpr))
1203  return true;
1204  if (IsA(node, MinMaxExpr))
1205  return true;
1206  if (IsA(node, XmlExpr))
1207  return true;
1208  if (IsA(node, NullTest))
1209  return true;
1210  if (IsA(node, BooleanTest))
1211  return true;
1212 
1213  /* Check other function-containing nodes */
1215  context))
1216  return true;
1217 
1219  context);
1220 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Definition: nodes.h:529
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:1106
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
BoolExprType boolop
Definition: primnodes.h:582
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
void * arg
static bool contain_nonstrict_functions_checker(Oid func_id, void *context)
Definition: clauses.c:1100

◆ contain_subplans()

bool contain_subplans ( Node clause)

Definition at line 610 of file clauses.c.

References contain_subplans_walker().

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

611 {
612  return contain_subplans_walker(clause, NULL);
613 }
static bool contain_subplans_walker(Node *node, void *context)
Definition: clauses.c:616

◆ contain_subplans_walker()

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

Definition at line 616 of file clauses.c.

References expression_tree_walker(), and IsA.

Referenced by contain_subplans().

617 {
618  if (node == NULL)
619  return false;
620  if (IsA(node, SubPlan) ||
621  IsA(node, AlternativeSubPlan) ||
622  IsA(node, SubLink))
623  return true; /* abort the tree traversal and return true */
624  return expression_tree_walker(node, contain_subplans_walker, context);
625 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
static bool contain_subplans_walker(Node *node, void *context)
Definition: clauses.c:616

◆ contain_volatile_functions()

◆ contain_volatile_functions_checker()

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

Definition at line 730 of file clauses.c.

References func_volatile().

Referenced by contain_volatile_functions_walker().

731 {
732  return (func_volatile(func_id) == PROVOLATILE_VOLATILE);
733 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1692

◆ contain_volatile_functions_not_nextval()

bool contain_volatile_functions_not_nextval ( Node clause)

Definition at line 774 of file clauses.c.

References contain_volatile_functions_not_nextval_walker().

Referenced by BeginCopyFrom().

775 {
777 }
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:787

◆ contain_volatile_functions_not_nextval_checker()

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

Definition at line 780 of file clauses.c.

References func_volatile().

Referenced by contain_volatile_functions_not_nextval_walker().

781 {
782  return (func_id != F_NEXTVAL_OID &&
783  func_volatile(func_id) == PROVOLATILE_VOLATILE);
784 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1692

◆ contain_volatile_functions_not_nextval_walker()

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

Definition at line 787 of file clauses.c.

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

Referenced by contain_volatile_functions_not_nextval().

788 {
789  if (node == NULL)
790  return false;
791  /* Check for volatile functions in node itself */
792  if (check_functions_in_node(node,
794  context))
795  return true;
796 
797  /*
798  * See notes in contain_mutable_functions_walker about why we treat
799  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
800  * SQLValueFunction is stable. Hence, none of them are of interest here.
801  * Also, since we're intentionally ignoring nextval(), presumably we
802  * should ignore NextValueExpr.
803  */
804 
805  /* Recurse to check arguments */
806  if (IsA(node, Query))
807  {
808  /* Recurse into subselects */
809  return query_tree_walker((Query *) node,
811  context, 0);
812  }
813  return expression_tree_walker(node,
815  context);
816 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2322
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:787
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
static bool contain_volatile_functions_not_nextval_checker(Oid func_id, void *context)
Definition: clauses.c:780

◆ contain_volatile_functions_walker()

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

Definition at line 736 of file clauses.c.

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

Referenced by contain_volatile_functions().

737 {
738  if (node == NULL)
739  return false;
740  /* Check for volatile functions in node itself */
742  context))
743  return true;
744 
745  if (IsA(node, NextValueExpr))
746  {
747  /* NextValueExpr is volatile */
748  return true;
749  }
750 
751  /*
752  * See notes in contain_mutable_functions_walker about why we treat
753  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
754  * SQLValueFunction is stable. Hence, none of them are of interest here.
755  */
756 
757  /* Recurse to check arguments */
758  if (IsA(node, Query))
759  {
760  /* Recurse into subselects */
761  return query_tree_walker((Query *) node,
763  context, 0);
764  }
766  context);
767 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2322
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1705
static bool contain_volatile_functions_walker(Node *node, void *context)
Definition: clauses.c:736
static bool contain_volatile_functions_checker(Oid func_id, void *context)
Definition: clauses.c:730
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888

◆ contain_window_function()

bool contain_window_function ( Node clause)

Definition at line 494 of file clauses.c.

References contain_windowfuncs().

Referenced by get_eclass_for_sort_expr(), and qual_is_pushdown_safe().

495 {
496  return contain_windowfuncs(clause);
497 }
bool contain_windowfuncs(Node *node)
Definition: rewriteManip.c:197

◆ ece_function_is_safe()

static bool ece_function_is_safe ( Oid  funcid,
eval_const_expressions_context context 
)
static

Definition at line 3601 of file clauses.c.

References eval_const_expressions_context::estimate, and func_volatile().

Referenced by eval_const_expressions_mutator().

3602 {
3603  char provolatile = func_volatile(funcid);
3604 
3605  /*
3606  * Ordinarily we are only allowed to simplify immutable functions. But for
3607  * purposes of estimation, we consider it okay to simplify functions that
3608  * are merely stable; the risk that the result might change from planning
3609  * time to execution time is worth taking in preference to not being able
3610  * to estimate the value at all.
3611  */
3612  if (provolatile == PROVOLATILE_IMMUTABLE)
3613  return true;
3614  if (context->estimate && provolatile == PROVOLATILE_STABLE)
3615  return true;
3616  return false;
3617 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1692

◆ estimate_expression_value()

Node* estimate_expression_value ( PlannerInfo root,
Node node 
)

Definition at line 2320 of file clauses.c.

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

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

2321 {
2323 
2324  context.boundParams = root->glob->boundParams; /* bound Params */
2325  /* we do not need to mark the plan as depending on inlined functions */
2326  context.root = NULL;
2327  context.active_fns = NIL; /* nothing being recursively simplified */
2328  context.case_val = NULL; /* no CASE being examined */
2329  context.estimate = true; /* unsafe transformations OK */
2330  return eval_const_expressions_mutator(node, &context);
2331 }
#define NIL
Definition: pg_list.h:65
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2365
ParamListInfo boundParams
Definition: clauses.c:66
PlannerGlobal * glob
Definition: pathnodes.h:181
ParamListInfo boundParams
Definition: pathnodes.h:109

◆ eval_const_expressions()

Node* eval_const_expressions ( PlannerInfo root,
Node node 
)

Definition at line 2287 of file clauses.c.

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

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

2288 {
2290 
2291  if (root)
2292  context.boundParams = root->glob->boundParams; /* bound Params */
2293  else
2294  context.boundParams = NULL;
2295  context.root = root; /* for inlined-function dependencies */
2296  context.active_fns = NIL; /* nothing being recursively simplified */
2297  context.case_val = NULL; /* no CASE being examined */
2298  context.estimate = false; /* safe transformations only */
2299  return eval_const_expressions_mutator(node, &context);
2300 }
#define NIL
Definition: pg_list.h:65
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2365
ParamListInfo boundParams
Definition: clauses.c:66
PlannerGlobal * glob
Definition: pathnodes.h:181
ParamListInfo boundParams
Definition: pathnodes.h:109

◆ eval_const_expressions_mutator()

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

Definition at line 2365 of file clauses.c.

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

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

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

◆ evaluate_expr()

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

Definition at line 4756 of file clauses.c.

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

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

4758 {
4759  EState *estate;
4760  ExprState *exprstate;
4761  MemoryContext oldcontext;
4762  Datum const_val;
4763  bool const_is_null;
4764  int16 resultTypLen;
4765  bool resultTypByVal;
4766 
4767  /*
4768  * To use the executor, we need an EState.
4769  */
4770  estate = CreateExecutorState();
4771 
4772  /* We can use the estate's working context to avoid memory leaks. */
4773  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
4774 
4775  /* Make sure any opfuncids are filled in. */
4776  fix_opfuncids((Node *) expr);
4777 
4778  /*
4779  * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
4780  * because it'd result in recursively invoking eval_const_expressions.)
4781  */
4782  exprstate = ExecInitExpr(expr, NULL);
4783 
4784  /*
4785  * And evaluate it.
4786  *
4787  * It is OK to use a default econtext because none of the ExecEvalExpr()
4788  * code used in this situation will use econtext. That might seem
4789  * fortuitous, but it's not so unreasonable --- a constant expression does
4790  * not depend on context, by definition, n'est ce pas?
4791  */
4792  const_val = ExecEvalExprSwitchContext(exprstate,
4793  GetPerTupleExprContext(estate),
4794  &const_is_null);
4795 
4796  /* Get info needed about result datatype */
4797  get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
4798 
4799  /* Get back to outer memory context */
4800  MemoryContextSwitchTo(oldcontext);
4801 
4802  /*
4803  * Must copy result out of sub-context used by expression eval.
4804  *
4805  * Also, if it's varlena, forcibly detoast it. This protects us against
4806  * storing TOAST pointers into plans that might outlive the referenced
4807  * data. (makeConst would handle detoasting anyway, but it's worth a few
4808  * extra lines here so that we can do the copy and detoast in one step.)
4809  */
4810  if (!const_is_null)
4811  {
4812  if (resultTypLen == -1)
4813  const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
4814  else
4815  const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
4816  }
4817 
4818  /* Release all the junk we just created */
4819  FreeExecutorState(estate);
4820 
4821  /*
4822  * Make the constant result node.
4823  */
4824  return (Expr *) makeConst(result_type, result_typmod, result_collation,
4825  resultTypLen,
4826  const_val, const_is_null,
4827  resultTypByVal);
4828 }
signed short int16
Definition: c.h:361
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:305
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
#define PointerGetDatum(X)
Definition: postgres.h:556
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1636
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:529
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:299
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
#define GetPerTupleExprContext(estate)
Definition: executor.h:507
MemoryContext es_query_cxt
Definition: execnodes.h:552
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
EState * CreateExecutorState(void)
Definition: execUtils.c:89
uintptr_t Datum
Definition: postgres.h:367
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2139
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123

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

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

Referenced by simplify_function().

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

◆ expand_function_arguments()

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

Definition at line 4015 of file clauses.c.

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

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

4016 {
4017  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4018  bool has_named_args = false;
4019  ListCell *lc;
4020 
4021  /* Do we have any named arguments? */
4022  foreach(lc, args)
4023  {
4024  Node *arg = (Node *) lfirst(lc);
4025 
4026  if (IsA(arg, NamedArgExpr))
4027  {
4028  has_named_args = true;
4029  break;
4030  }
4031  }
4032 
4033  /* If so, we must apply reorder_function_arguments */
4034  if (has_named_args)
4035  {
4036  args = reorder_function_arguments(args, func_tuple);
4037  /* Recheck argument types and add casts if needed */
4038  recheck_cast_function_args(args, result_type, func_tuple);
4039  }
4040  else if (list_length(args) < funcform->pronargs)
4041  {
4042  /* No named args, but we seem to be short some defaults */
4043  args = add_function_defaults(args, func_tuple);
4044  /* Recheck argument types and add casts if needed */
4045  recheck_cast_function_args(args, result_type, func_tuple);
4046  }
4047 
4048  return args;
4049 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Definition: nodes.h:529
static void recheck_cast_function_args(List *args, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:4188
static List * add_function_defaults(List *args, HeapTuple func_tuple)
Definition: clauses.c:4128
static List * reorder_function_arguments(List *args, HeapTuple func_tuple)
Definition: clauses.c:4058
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
void * arg

◆ expression_returns_set_rows()

double expression_returns_set_rows ( PlannerInfo root,
Node clause 
)

Definition at line 569 of file clauses.c.

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

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

570 {
571  if (clause == NULL)
572  return 1.0;
573  if (IsA(clause, FuncExpr))
574  {
575  FuncExpr *expr = (FuncExpr *) clause;
576 
577  if (expr->funcretset)
578  return clamp_row_est(get_function_rows(root, expr->funcid, clause));
579  }
580  if (IsA(clause, OpExpr))
581  {
582  OpExpr *expr = (OpExpr *) clause;
583 
584  if (expr->opretset)
585  {
586  set_opfuncid(expr);
587  return clamp_row_est(get_function_rows(root, expr->opfuncid, clause));
588  }
589  }
590  return 1.0;
591 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
bool funcretset
Definition: primnodes.h:471
Oid funcid
Definition: primnodes.h:469
Oid opfuncid
Definition: primnodes.h:517
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1667
double clamp_row_est(double nrows)
Definition: costsize.c:189
bool opretset
Definition: primnodes.h:519
double get_function_rows(PlannerInfo *root, Oid funcid, Node *node)
Definition: plancat.c:1966

◆ fetch_function_defaults()

static List * fetch_function_defaults ( HeapTuple  func_tuple)
static

Definition at line 4153 of file clauses.c.

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

Referenced by add_function_defaults(), and reorder_function_arguments().

4154 {
4155  List *defaults;
4156  Datum proargdefaults;
4157  bool isnull;
4158  char *str;
4159 
4160  /* The error cases here shouldn't happen, but check anyway */
4161  proargdefaults = SysCacheGetAttr(PROCOID, func_tuple,
4162  Anum_pg_proc_proargdefaults,
4163  &isnull);
4164  if (isnull)
4165  elog(ERROR, "not enough default arguments");
4166  str = TextDatumGetCString(proargdefaults);
4167  defaults = castNode(List, stringToNode(str));
4168  pfree(str);
4169  return defaults;
4170 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:598
void * stringToNode(const char *str)
Definition: read.c:89
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:43
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define elog(elevel,...)
Definition: elog.h:214
Definition: pg_list.h:50

◆ find_forced_null_var()

Var* find_forced_null_var ( Node node)

Definition at line 2012 of file clauses.c.

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

Referenced by check_redundant_nullability_qual(), and find_forced_null_vars().

2013 {
2014  if (node == NULL)
2015  return NULL;
2016  if (IsA(node, NullTest))
2017  {
2018  /* check for var IS NULL */
2019  NullTest *expr = (NullTest *) node;
2020 
2021  if (expr->nulltesttype == IS_NULL && !expr->argisrow)
2022  {
2023  Var *var = (Var *) expr->arg;
2024 
2025  if (var && IsA(var, Var) &&
2026  var->varlevelsup == 0)
2027  return var;
2028  }
2029  }
2030  else if (IsA(node, BooleanTest))
2031  {
2032  /* var IS UNKNOWN is equivalent to var IS NULL */
2033  BooleanTest *expr = (BooleanTest *) node;
2034 
2035  if (expr->booltesttype == IS_UNKNOWN)
2036  {
2037  Var *var = (Var *) expr->arg;
2038 
2039  if (var && IsA(var, Var) &&
2040  var->varlevelsup == 0)
2041  return var;
2042  }
2043  }
2044  return NULL;
2045 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Index varlevelsup
Definition: primnodes.h:191
Definition: primnodes.h:181
Expr * arg
Definition: primnodes.h:1219
Expr * arg
Definition: primnodes.h:1242
BoolTestType booltesttype
Definition: primnodes.h:1243
NullTestType nulltesttype
Definition: primnodes.h:1220
bool argisrow
Definition: primnodes.h:1221

◆ find_forced_null_vars()

List* find_forced_null_vars ( Node node)

Definition at line 1953 of file clauses.c.

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

Referenced by find_forced_null_vars(), and reduce_outer_joins_pass2().

1954 {
1955  List *result = NIL;
1956  Var *var;
1957  ListCell *l;
1958 
1959  if (node == NULL)
1960  return NIL;
1961  /* Check single-clause cases using subroutine */
1962  var = find_forced_null_var(node);
1963  if (var)
1964  {
1965  result = list_make1(var);
1966  }
1967  /* Otherwise, handle AND-conditions */
1968  else if (IsA(node, List))
1969  {
1970  /*
1971  * At top level, we are examining an implicit-AND list: if any of the
1972  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1973  */
1974  foreach(l, (List *) node)
1975  {
1976  result = list_concat(result,
1978  }
1979  }
1980  else if (IsA(node, BoolExpr))
1981  {
1982  BoolExpr *expr = (BoolExpr *) node;
1983 
1984  /*
1985  * We don't bother considering the OR case, because it's fairly
1986  * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
1987  * the NOT case isn't worth expending code on.
1988  */
1989  if (expr->boolop == AND_EXPR)
1990  {
1991  /* At top level we can just recurse (to the List case) */
1992  result = find_forced_null_vars((Node *) expr->args);
1993  }
1994  }
1995  return result;
1996 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Definition: nodes.h:529
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
Definition: primnodes.h:181
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1953
#define list_make1(x1)
Definition: pg_list.h:227
BoolExprType boolop
Definition: primnodes.h:582
#define lfirst(lc)
Definition: pg_list.h:190
List * args
Definition: primnodes.h:583
Definition: pg_list.h:50
Var * find_forced_null_var(Node *node)
Definition: clauses.c:2012

◆ find_nonnullable_rels()

Relids find_nonnullable_rels ( Node clause)

Definition at line 1535 of file clauses.c.

References find_nonnullable_rels_walker().

Referenced by make_outerjoininfo(), and reduce_outer_joins_pass2().

1536 {
1537  return find_nonnullable_rels_walker(clause, true);
1538 }
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1541

◆ find_nonnullable_rels_walker()

static Relids find_nonnullable_rels_walker ( Node node,
bool  top_level 
)
static

Definition at line 1541 of file clauses.c.

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

Referenced by find_nonnullable_rels().

1542 {
1543  Relids result = NULL;
1544  ListCell *l;
1545 
1546  if (node == NULL)
1547  return NULL;
1548  if (IsA(node, Var))
1549  {
1550  Var *var = (Var *) node;
1551 
1552  if (var->varlevelsup == 0)
1553  result = bms_make_singleton(var->varno);
1554  }
1555  else if (IsA(node, List))
1556  {
1557  /*
1558  * At top level, we are examining an implicit-AND list: if any of the
1559  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1560  * not at top level, we are examining the arguments of a strict
1561  * function: if any of them produce NULL then the result of the
1562  * function must be NULL. So in both cases, the set of nonnullable
1563  * rels is the union of those found in the arms, and we pass down the
1564  * top_level flag unmodified.
1565  */
1566  foreach(l, (List *) node)
1567  {
1568  result = bms_join(result,
1570  top_level));
1571  }
1572  }
1573  else if (IsA(node, FuncExpr))
1574  {
1575  FuncExpr *expr = (FuncExpr *) node;
1576 
1577  if (func_strict(expr->funcid))
1578  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1579  }
1580  else if (IsA(node, OpExpr))
1581  {
1582  OpExpr *expr = (OpExpr *) node;
1583 
1584  set_opfuncid(expr);
1585  if (func_strict(expr->opfuncid))
1586  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1587  }
1588  else if (IsA(node, ScalarArrayOpExpr))
1589  {
1590  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1591 
1592  if (is_strict_saop(expr, true))
1593  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1594  }
1595  else if (IsA(node, BoolExpr))
1596  {
1597  BoolExpr *expr = (BoolExpr *) node;
1598 
1599  switch (expr->boolop)
1600  {
1601  case AND_EXPR:
1602  /* At top level we can just recurse (to the List case) */
1603  if (top_level)
1604  {
1605  result = find_nonnullable_rels_walker((Node *) expr->args,
1606  top_level);
1607  break;
1608  }
1609 
1610  /*
1611  * Below top level, even if one arm produces NULL, the result
1612  * could be FALSE (hence not NULL). However, if *all* the
1613  * arms produce NULL then the result is NULL, so we can take
1614  * the intersection of the sets of nonnullable rels, just as
1615  * for OR. Fall through to share code.
1616  */
1617  /* FALL THRU */
1618  case OR_EXPR:
1619 
1620  /*
1621  * OR is strict if all of its arms are, so we can take the
1622  * intersection of the sets of nonnullable rels for each arm.
1623  * This works for both values of top_level.
1624  */
1625  foreach(l, expr->args)
1626  {
1627  Relids subresult;
1628 
1629  subresult = find_nonnullable_rels_walker(lfirst(l),
1630  top_level);
1631  if (result == NULL) /* first subresult? */
1632  result = subresult;
1633  else
1634  result = bms_int_members(result, subresult);
1635 
1636  /*
1637  * If the intersection is empty, we can stop looking. This
1638  * also justifies the test for first-subresult above.
1639  */
1640  if (bms_is_empty(result))
1641  break;
1642  }
1643  break;
1644  case NOT_EXPR:
1645  /* NOT will return null if its arg is null */
1646  result = find_nonnullable_rels_walker((Node *) expr->args,
1647  false);
1648  break;
1649  default:
1650  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1651  break;
1652  }
1653  }
1654  else if (IsA(node, RelabelType))
1655  {
1656  RelabelType *expr = (RelabelType *) node;
1657 
1658  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1659  }
1660  else if (IsA(node, CoerceViaIO))
1661  {
1662  /* not clear this is useful, but it can't hurt */
1663  CoerceViaIO *expr = (CoerceViaIO *) node;
1664 
1665  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1666  }
1667  else if (IsA(node, ArrayCoerceExpr))
1668  {
1669  /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1670  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1671 
1672  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1673  }
1674  else if (IsA(node, ConvertRowtypeExpr))
1675  {
1676  /* not clear this is useful, but it can't hurt */
1677  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1678 
1679  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1680  }
1681  else if (IsA(node, CollateExpr))
1682  {
1683  CollateExpr *expr = (CollateExpr *) node;
1684 
1685  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1686  }
1687  else if (IsA(node, NullTest))
1688  {
1689  /* IS NOT NULL can be considered strict, but only at top level */
1690  NullTest *expr = (NullTest *) node;
1691 
1692  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1693  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1694  }
1695  else if (IsA(node, BooleanTest))
1696  {
1697  /* Boolean tests that reject NULL are strict at top level */
1698  BooleanTest *expr = (BooleanTest *) node;
1699 
1700  if (top_level &&
1701  (expr->booltesttype == IS_TRUE ||
1702  expr->booltesttype == IS_FALSE ||
1703  expr->booltesttype == IS_NOT_UNKNOWN))
1704  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1705  }
1706  else if (IsA(node, PlaceHolderVar))
1707  {
1708  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1709 
1710  /*
1711  * If the contained expression forces any rels non-nullable, so does
1712  * the PHV.
1713  */
1714  result = find_nonnullable_rels_walker((Node *) phv->phexpr, top_level);
1715 
1716  /*
1717  * If the PHV's syntactic scope is exactly one rel, it will be forced
1718  * to be evaluated at that rel, and so it will behave like a Var of
1719  * that rel: if the rel's entire output goes to null, so will the PHV.
1720  * (If the syntactic scope is a join, we know that the PHV will go to
1721  * null if the whole join does; but that is AND semantics while we
1722  * need OR semantics for find_nonnullable_rels' result, so we can't do
1723  * anything with the knowledge.)
1724  */
1725  if (phv->phlevelsup == 0 &&
1727  result = bms_add_members(result, phv->phrels);
1728  }
1729  return result;
1730 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Index varlevelsup
Definition: primnodes.h:191
List * args
Definition: primnodes.h:477
Expr * arg
Definition: primnodes.h:814
Definition: nodes.h:529
Definition: primnodes.h:181
Oid funcid
Definition: primnodes.h:469
#define ERROR
Definition: elog.h:43
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:949
BoolExprType boolop
Definition: primnodes.h:582
Expr * arg
Definition: primnodes.h:1219
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
Expr * arg
Definition: primnodes.h:1242
Expr * arg
Definition: primnodes.h:834
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
Index varno
Definition: primnodes.h:184
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:672
BoolTestType booltesttype
Definition: primnodes.h:1243
Oid opfuncid
Definition: primnodes.h:517
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1541
NullTestType nulltesttype
Definition: primnodes.h:1220
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition: clauses.c:2061
#define lfirst(lc)
Definition: pg_list.h:190
Expr * arg
Definition: primnodes.h:900
List * args
Definition: primnodes.h:583
bool func_strict(Oid funcid)
Definition: lsyscache.c:1673
Index phlevelsup
Definition: pathnodes.h:2107
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1667
#define elog(elevel,...)
Definition: elog.h:214
bool argisrow
Definition: primnodes.h:1221
List * args
Definition: primnodes.h:522
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:902
Definition: pg_list.h:50
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:793

◆ find_nonnullable_vars()

List* find_nonnullable_vars ( Node clause)

Definition at line 1760 of file clauses.c.

References find_nonnullable_vars_walker().

Referenced by reduce_outer_joins_pass2().

1761 {
1762  return find_nonnullable_vars_walker(clause, true);
1763 }
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1766

◆ find_nonnullable_vars_walker()

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

Definition at line 1766 of file clauses.c.

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

Referenced by find_nonnullable_vars().

1767 {
1768  List *result = NIL;
1769  ListCell *l;
1770 
1771  if (node == NULL)
1772  return NIL;
1773  if (IsA(node, Var))
1774  {
1775  Var *var = (Var *) node;
1776 
1777  if (var->varlevelsup == 0)
1778  result = list_make1(var);
1779  }
1780  else if (IsA(node, List))
1781  {
1782  /*
1783  * At top level, we are examining an implicit-AND list: if any of the
1784  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1785  * not at top level, we are examining the arguments of a strict
1786  * function: if any of them produce NULL then the result of the
1787  * function must be NULL. So in both cases, the set of nonnullable
1788  * vars is the union of those found in the arms, and we pass down the
1789  * top_level flag unmodified.
1790  */
1791  foreach(l, (List *) node)
1792  {
1793  result = list_concat(result,
1795  top_level));
1796  }
1797  }
1798  else if (IsA(node, FuncExpr))
1799  {
1800  FuncExpr *expr = (FuncExpr *) node;
1801 
1802  if (func_strict(expr->funcid))
1803  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1804  }
1805  else if (IsA(node, OpExpr))
1806  {
1807  OpExpr *expr = (OpExpr *) node;
1808 
1809  set_opfuncid(expr);
1810  if (func_strict(expr->opfuncid))
1811  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1812  }
1813  else if (IsA(node, ScalarArrayOpExpr))
1814  {
1815  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1816 
1817  if (is_strict_saop(expr, true))
1818  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1819  }
1820  else if (IsA(node, BoolExpr))
1821  {
1822  BoolExpr *expr = (BoolExpr *) node;
1823 
1824  switch (expr->boolop)
1825  {
1826  case AND_EXPR:
1827  /* At top level we can just recurse (to the List case) */
1828  if (top_level)
1829  {
1830  result = find_nonnullable_vars_walker((Node *) expr->args,
1831  top_level);
1832  break;
1833  }
1834 
1835  /*
1836  * Below top level, even if one arm produces NULL, the result
1837  * could be FALSE (hence not NULL). However, if *all* the
1838  * arms produce NULL then the result is NULL, so we can take
1839  * the intersection of the sets of nonnullable vars, just as
1840  * for OR. Fall through to share code.
1841  */
1842  /* FALL THRU */
1843  case OR_EXPR:
1844 
1845  /*
1846  * OR is strict if all of its arms are, so we can take the
1847  * intersection of the sets of nonnullable vars for each arm.
1848  * This works for both values of top_level.
1849  */
1850  foreach(l, expr->args)
1851  {
1852  List *subresult;
1853 
1854  subresult = find_nonnullable_vars_walker(lfirst(l),
1855  top_level);
1856  if (result == NIL) /* first subresult? */
1857  result = subresult;
1858  else
1859  result = list_intersection(result, subresult);
1860 
1861  /*
1862  * If the intersection is empty, we can stop looking. This
1863  * also justifies the test for first-subresult above.
1864  */
1865  if (result == NIL)
1866  break;
1867  }
1868  break;
1869  case NOT_EXPR:
1870  /* NOT will return null if its arg is null */
1871  result = find_nonnullable_vars_walker((Node *) expr->args,
1872  false);
1873  break;
1874  default:
1875  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1876  break;
1877  }
1878  }
1879  else if (IsA(node, RelabelType))
1880  {
1881  RelabelType *expr = (RelabelType *) node;
1882 
1883  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1884  }
1885  else if (IsA(node, CoerceViaIO))
1886  {
1887  /* not clear this is useful, but it can't hurt */
1888  CoerceViaIO *expr = (CoerceViaIO *) node;
1889 
1890  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1891  }
1892  else if (IsA(node, ArrayCoerceExpr))
1893  {
1894  /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1895  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1896 
1897  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1898  }
1899  else if (IsA(node, ConvertRowtypeExpr))
1900  {
1901  /* not clear this is useful, but it can't hurt */
1902  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1903 
1904  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1905  }
1906  else if (IsA(node, CollateExpr))
1907  {
1908  CollateExpr *expr = (CollateExpr *) node;
1909 
1910  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1911  }
1912  else if (IsA(node, NullTest))
1913  {
1914  /* IS NOT NULL can be considered strict, but only at top level */
1915  NullTest *expr = (NullTest *) node;
1916 
1917  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1918  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1919  }
1920  else if (IsA(node, BooleanTest))
1921  {
1922  /* Boolean tests that reject NULL are strict at top level */
1923  BooleanTest *expr = (BooleanTest *) node;
1924 
1925  if (top_level &&
1926  (expr->booltesttype == IS_TRUE ||
1927  expr->booltesttype == IS_FALSE ||
1928  expr->booltesttype == IS_NOT_UNKNOWN))
1929  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1930  }
1931  else if (IsA(node, PlaceHolderVar))
1932  {
1933  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1934 
1935  result = find_nonnullable_vars_walker((Node *) phv->phexpr, top_level);
1936  }
1937  return result;
1938 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Index varlevelsup
Definition: primnodes.h:191
List * args
Definition: primnodes.h:477
Expr * arg
Definition: primnodes.h:814
Definition: nodes.h:529
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
Definition: primnodes.h:181
#define list_make1(x1)
Definition: pg_list.h:227
Oid funcid
Definition: primnodes.h:469
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:582
Expr * arg
Definition: primnodes.h:1219
Expr * arg
Definition: primnodes.h:1242
List * list_intersection(const List *list1, const List *list2)
Definition: list.c:1018
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1766
Expr * arg
Definition: primnodes.h:834
BoolTestType booltesttype
Definition: primnodes.h:1243
Oid opfuncid
Definition: primnodes.h:517
NullTestType nulltesttype
Definition: primnodes.h:1220
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition: clauses.c:2061
#define lfirst(lc)
Definition: pg_list.h:190
Expr * arg
Definition: primnodes.h:900
List * args
Definition: primnodes.h:583
bool func_strict(Oid funcid)
Definition: lsyscache.c:1673
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1667
#define elog(elevel,...)
Definition: elog.h:214
bool argisrow
Definition: primnodes.h:1221
List * args
Definition: primnodes.h:522
Definition: pg_list.h:50

◆ find_window_functions()

WindowFuncLists* find_window_functions ( Node clause,
Index  maxWinRef 
)

Definition at line 507 of file clauses.c.

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

Referenced by grouping_planner().

508 {
509  WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
510 
511  lists->numWindowFuncs = 0;
512  lists->maxWinRef = maxWinRef;
513  lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
514  (void) find_window_functions_walker(clause, lists);
515  return lists;
516 }
Index maxWinRef
Definition: clauses.h:23
int numWindowFuncs
Definition: clauses.h:22
void * palloc0(Size size)
Definition: mcxt.c:981
void * palloc(Size size)
Definition: mcxt.c:950
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:519
Definition: pg_list.h:50
List ** windowFuncs
Definition: clauses.h:24

◆ find_window_functions_walker()

static bool find_window_functions_walker ( Node node,
WindowFuncLists lists 
)
static

Definition at line 519 of file clauses.c.

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

Referenced by find_window_functions().

520 {
521  if (node == NULL)
522  return false;
523  if (IsA(node, WindowFunc))
524  {
525  WindowFunc *wfunc = (WindowFunc *) node;
526 
527  /* winref is unsigned, so one-sided test is OK */
528  if (wfunc->winref > lists->maxWinRef)
529  elog(ERROR, "WindowFunc contains out-of-range winref %u",
530  wfunc->winref);
531  /* eliminate duplicates, so that we avoid repeated computation */
532  if (!list_member(lists->windowFuncs[wfunc->winref], wfunc))
533  {
534  lists->windowFuncs[wfunc->winref] =
535  lappend(lists->windowFuncs[wfunc->winref], wfunc);
536  lists->numWindowFuncs++;
537  }
538 
539  /*
540  * We assume that the parser checked that there are no window
541  * functions in the arguments or filter clause. Hence, we need not
542  * recurse into them. (If either the parser or the planner screws up
543  * on this point, the executor will still catch it; see ExecInitExpr.)
544  */
545  return false;
546  }
547  Assert(!IsA(node, SubLink));
549  (void *) lists);
550 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Index maxWinRef
Definition: clauses.h:23
int numWindowFuncs
Definition: clauses.h:22
Index winref
Definition: primnodes.h:379
#define ERROR
Definition: elog.h:43
bool list_member(const List *list, const void *datum)
Definition: list.c:613
List * lappend(List *list, void *datum)
Definition: list.c:321
#define Assert(condition)
Definition: c.h:745
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
#define elog(elevel,...)
Definition: elog.h:214
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:519
List ** windowFuncs
Definition: clauses.h:24

◆ get_agg_clause_costs()

void get_agg_clause_costs ( PlannerInfo root,
Node clause,
AggSplit  aggsplit,
AggClauseCosts costs 
)

Definition at line 229 of file clauses.c.

References get_agg_clause_costs_context::aggsplit, get_agg_clause_costs_context::costs, get_agg_clause_costs_walker(), and get_agg_clause_costs_context::root.

Referenced by create_partial_grouping_paths(), estimate_path_cost_size(), and grouping_planner().

231 {
233 
234  context.root = root;
235  context.aggsplit = aggsplit;
236  context.costs = costs;
237  (void) get_agg_clause_costs_walker(clause, &context);
238 }
AggClauseCosts * costs
Definition: clauses.c:61
static bool get_agg_clause_costs_walker(Node *node, get_agg_clause_costs_context *context)
Definition: clauses.c:241

◆ get_agg_clause_costs_walker()

static bool get_agg_clause_costs_walker ( Node node,
get_agg_clause_costs_context context 
)
static

Definition at line 241 of file clauses.c.

References add_function_cost(), Aggref::aggdirectargs, Aggref::aggdistinct, Aggref::aggfilter, AGGFNOID, Aggref::aggfnoid, Aggref::agglevelsup, Aggref::aggorder, get_agg_clause_costs_context::aggsplit, Aggref::aggtranstype, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_SMALL_INITSIZE, Aggref::args, Assert, cost_qual_eval_node(), get_agg_clause_costs_context::costs, DO_AGGSPLIT_COMBINE, DO_AGGSPLIT_DESERIALIZE, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, elog, ERROR, TargetEntry::expr, expression_tree_walker(), exprType(), exprTypmod(), AggClauseCosts::finalCost, FUNC_MAX_ARGS, get_aggregate_argtypes(), get_typavgwidth(), get_typbyval(), GETSTRUCT, AggClauseCosts::hasNonPartial, AggClauseCosts::hasNonSerial, HeapTupleIsValid, IsA, linitial, MAXALIGN, NIL, AggClauseCosts::numAggs, AggClauseCosts::numOrderedAggs, ObjectIdGetDatum, OidIsValid, QualCost::per_tuple, ReleaseSysCache(), resolve_aggregate_transtype(), get_agg_clause_costs_context::root, SearchSysCache1(), QualCost::startup, AggClauseCosts::transCost, and AggClauseCosts::transitionSpace.

Referenced by get_agg_clause_costs().

242 {
243  if (node == NULL)
244  return false;
245  if (IsA(node, Aggref))
246  {
247  Aggref *aggref = (Aggref *) node;
248  AggClauseCosts *costs = context->costs;
249  HeapTuple aggTuple;
250  Form_pg_aggregate aggform;
251  Oid aggtransfn;
252  Oid aggfinalfn;
253  Oid aggcombinefn;
254  Oid aggserialfn;
255  Oid aggdeserialfn;
256  Oid aggtranstype;
257  int32 aggtransspace;
258  QualCost argcosts;
259 
260  Assert(aggref->agglevelsup == 0);
261 
262  /*
263  * Fetch info about aggregate from pg_aggregate. Note it's correct to
264  * ignore the moving-aggregate variant, since what we're concerned
265  * with here is aggregates not window functions.
266  */
267  aggTuple = SearchSysCache1(AGGFNOID,
268  ObjectIdGetDatum(aggref->aggfnoid));
269  if (!HeapTupleIsValid(aggTuple))
270  elog(ERROR, "cache lookup failed for aggregate %u",
271  aggref->aggfnoid);
272  aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
273  aggtransfn = aggform->aggtransfn;
274  aggfinalfn = aggform->aggfinalfn;
275  aggcombinefn = aggform->aggcombinefn;
276  aggserialfn = aggform->aggserialfn;
277  aggdeserialfn = aggform->aggdeserialfn;
278  aggtranstype = aggform->aggtranstype;
279  aggtransspace = aggform->aggtransspace;
280  ReleaseSysCache(aggTuple);
281 
282  /*
283  * Resolve the possibly-polymorphic aggregate transition type, unless
284  * already done in a previous pass over the expression.
285  */
286  if (OidIsValid(aggref->aggtranstype))
287  aggtranstype = aggref->aggtranstype;
288  else
289  {
290  Oid inputTypes[FUNC_MAX_ARGS];
291  int numArguments;
292 
293  /* extract argument types (ignoring any ORDER BY expressions) */
294  numArguments = get_aggregate_argtypes(aggref, inputTypes);
295 
296  /* resolve actual type of transition state, if polymorphic */
297  aggtranstype = resolve_aggregate_transtype(aggref->aggfnoid,
298  aggtranstype,
299  inputTypes,
300  numArguments);
301  aggref->aggtranstype = aggtranstype;
302  }
303 
304  /*
305  * Count it, and check for cases requiring ordered input. Note that
306  * ordered-set aggs always have nonempty aggorder. Any ordered-input
307  * case also defeats partial aggregation.
308  */
309  costs->numAggs++;
310  if (aggref->aggorder != NIL || aggref->aggdistinct != NIL)
311  {
312  costs->numOrderedAggs++;
313  costs->hasNonPartial = true;
314  }
315 
316  /*
317  * Check whether partial aggregation is feasible, unless we already
318  * found out that we can't do it.
319  */
320  if (!costs->hasNonPartial)
321  {
322  /*
323  * If there is no combine function, then partial aggregation is
324  * not possible.
325  */
326  if (!OidIsValid(aggcombinefn))
327  costs->hasNonPartial = true;
328 
329  /*
330  * If we have any aggs with transtype INTERNAL then we must check
331  * whether they have serialization/deserialization functions; if
332  * not, we can't serialize partial-aggregation results.
333  */
334  else if (aggtranstype == INTERNALOID &&
335  (!OidIsValid(aggserialfn) || !OidIsValid(aggdeserialfn)))
336  costs->hasNonSerial = true;
337  }
338 
339  /*
340  * Add the appropriate component function execution costs to
341  * appropriate totals.
342  */
343  if (DO_AGGSPLIT_COMBINE(context->aggsplit))
344  {
345  /* charge for combining previously aggregated states */
346  add_function_cost(context->root, aggcombinefn, NULL,
347  &costs->transCost);
348  }
349  else
350  add_function_cost(context->root, aggtransfn, NULL,
351  &costs->transCost);
352  if (DO_AGGSPLIT_DESERIALIZE(context->aggsplit) &&
353  OidIsValid(aggdeserialfn))
354  add_function_cost(context->root, aggdeserialfn, NULL,
355  &costs->transCost);
356  if (DO_AGGSPLIT_SERIALIZE(context->aggsplit) &&
357  OidIsValid(aggserialfn))
358  add_function_cost(context->root, aggserialfn, NULL,
359  &costs->finalCost);
360  if (!DO_AGGSPLIT_SKIPFINAL(context->aggsplit) &&
361  OidIsValid(aggfinalfn))
362  add_function_cost(context->root, aggfinalfn, NULL,
363  &costs->finalCost);
364 
365  /*
366  * These costs are incurred only by the initial aggregate node, so we
367  * mustn't include them again at upper levels.
368  */
369  if (!DO_AGGSPLIT_COMBINE(context->aggsplit))
370  {
371  /* add the input expressions' cost to per-input-row costs */
372  cost_qual_eval_node(&argcosts, (Node *) aggref->args, context->root);
373  costs->transCost.startup += argcosts.startup;
374  costs->transCost.per_tuple += argcosts.per_tuple;
375 
376  /*
377  * Add any filter's cost to per-input-row costs.
378  *
379  * XXX Ideally we should reduce input expression costs according
380  * to filter selectivity, but it's not clear it's worth the
381  * trouble.
382  */
383  if (aggref->aggfilter)
384  {
385  cost_qual_eval_node(&argcosts, (Node *) aggref->aggfilter,
386  context->root);
387  costs->transCost.startup += argcosts.startup;
388  costs->transCost.per_tuple += argcosts.per_tuple;
389  }
390  }
391 
392  /*
393  * If there are direct arguments, treat their evaluation cost like the
394  * cost of the finalfn.
395  */
396  if (aggref->aggdirectargs)
397  {
398  cost_qual_eval_node(&argcosts, (Node *) aggref->aggdirectargs,
399  context->root);
400  costs->finalCost.startup += argcosts.startup;
401  costs->finalCost.per_tuple += argcosts.per_tuple;
402  }
403 
404  /*
405  * If the transition type is pass-by-value then it doesn't add
406  * anything to the required size of the hashtable. If it is
407  * pass-by-reference then we have to add the estimated size of the
408  * value itself, plus palloc overhead.
409  */
410  if (!get_typbyval(aggtranstype))
411  {
412  int32 avgwidth;
413 
414  /* Use average width if aggregate definition gave one */
415  if (aggtransspace > 0)
416  avgwidth = aggtransspace;
417  else if (aggtransfn == F_ARRAY_APPEND)
418  {
419  /*
420  * If the transition function is array_append(), it'll use an
421  * expanded array as transvalue, which will occupy at least
422  * ALLOCSET_SMALL_INITSIZE and possibly more. Use that as the
423  * estimate for lack of a better idea.
424  */
425  avgwidth = ALLOCSET_SMALL_INITSIZE;
426  }
427  else
428  {
429  /*
430  * If transition state is of same type as first aggregated
431  * input, assume it's the same typmod (same width) as well.
432  * This works for cases like MAX/MIN and is probably somewhat
433  * reasonable otherwise.
434  */
435  int32 aggtranstypmod = -1;
436 
437  if (aggref->args)
438  {
439  TargetEntry *tle = (TargetEntry *) linitial(aggref->args);
440 
441  if (aggtranstype == exprType((Node *) tle->expr))
442  aggtranstypmod = exprTypmod((Node *) tle->expr);
443  }
444 
445  avgwidth = get_typavgwidth(aggtranstype, aggtranstypmod);
446  }
447 
448  avgwidth = MAXALIGN(avgwidth);
449  costs->transitionSpace += avgwidth + 2 * sizeof(void *);
450  }
451  else if (aggtranstype == INTERNALOID)
452  {
453  /*
454  * INTERNAL transition type is a special case: although INTERNAL
455  * is pass-by-value, it's almost certainly being used as a pointer
456  * to some large data structure. The aggregate definition can
457  * provide an estimate of the size. If it doesn't, then we assume
458  * ALLOCSET_DEFAULT_INITSIZE, which is a good guess if the data is
459  * being kept in a private memory context, as is done by
460  * array_agg() for instance.
461  */
462  if (aggtransspace > 0)
463  costs->transitionSpace += aggtransspace;
464  else
466  }
467 
468  /*
469  * We assume that the parser checked that there are no aggregates (of
470  * this level anyway) in the aggregated arguments, direct arguments,
471  * or filter clause. Hence, we need not recurse into any of them.
472  */
473  return false;
474  }
475  Assert(!IsA(node, SubLink));
477  (void *) context);
478 }
List * aggdistinct
Definition: primnodes.h:321
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition: costsize.c:4082
#define NIL
Definition: pg_list.h:65
AggClauseCosts * costs
Definition: clauses.c:61
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:275
QualCost finalCost
Definition: pathnodes.h:63
Definition: nodes.h:529
List * args
Definition: primnodes.h:319
bool hasNonSerial
Definition: pathnodes.h:61
void add_function_cost(PlannerInfo *root, Oid funcid, Node *node, QualCost *cost)
Definition: plancat.c:1905
bool hasNonPartial
Definition: pathnodes.h:60
QualCost transCost
Definition: pathnodes.h:62
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:791
Cost startup
Definition: pathnodes.h:45
static bool get_agg_clause_costs_walker(Node *node, get_agg_clause_costs_context *context)
Definition: clauses.c:241
signed int int32
Definition: c.h:362
#define FUNC_MAX_ARGS
bool get_typbyval(Oid typid)
Definition: lsyscache.c:2110
Cost per_tuple
Definition: pathnodes.h:46
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:793
#define linitial(l)
Definition: pg_list.h:195
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
List * aggorder
Definition: primnodes.h:320
Index agglevelsup
Definition: primnodes.h:327
List * aggdirectargs
Definition: primnodes.h:318
int numOrderedAggs
Definition: pathnodes.h:59
#define ALLOCSET_SMALL_INITSIZE
Definition: memutils.h:200
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
int32 get_typavgwidth(Oid typid, int32 typmod)
Definition: lsyscache.c:2466
Oid aggfnoid
Definition: primnodes.h:312
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:745
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:109
Expr * expr
Definition: primnodes.h:1407
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:792
Expr * aggfilter
Definition: primnodes.h:322
#define MAXALIGN(LEN)
Definition: c.h:698
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:794
#define elog(elevel,...)
Definition: elog.h:214
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:190
Oid aggtranstype
Definition: primnodes.h:316
Size transitionSpace
Definition: pathnodes.h:64
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1819
Oid resolve_aggregate_transtype(Oid aggfuncid, Oid aggtranstype, Oid *inputTypes, int numArguments)
Definition: parse_agg.c:1845

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

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

Referenced by simplify_function().

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