PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "optimizer/var.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_IN_CASEEXPR   0x0001 /* CaseTestExpr okay here? */
 

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_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 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 Listexpand_function_arguments (List *args, Oid result_type, HeapTuple func_tuple)
 
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 Exprevaluate_expr (Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
 
static Querysubstitute_actual_srf_parameters (Query *expr, int nargs, List *args)
 
static Nodesubstitute_actual_srf_parameters_mutator (Node *node, substitute_actual_srf_parameters_context *context)
 
static bool tlist_matches_coltypelist (List *tlist, List *coltypelist)
 
Exprmake_opclause (Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
 
Nodeget_leftop (const Expr *clause)
 
Nodeget_rightop (const Expr *clause)
 
bool not_clause (Node *clause)
 
Exprmake_notclause (Expr *notclause)
 
Exprget_notclausearg (Expr *notclause)
 
bool or_clause (Node *clause)
 
Exprmake_orclause (List *orclauses)
 
bool and_clause (Node *clause)
 
Exprmake_andclause (List *andclauses)
 
Nodemake_and_qual (Node *qual1, Node *qual2)
 
Exprmake_ands_explicit (List *andclauses)
 
Listmake_ands_implicit (Expr *clause)
 
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 (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_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)
 
void CommuteRowCompareExpr (RowCompareExpr *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)
 
Queryinline_set_returning_function (PlannerInfo *root, RangeTblEntry *rte)
 

Macro Definition Documentation

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

Definition at line 1422 of file clauses.c.

Referenced by contain_context_dependent_node_walker().

Function Documentation

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

Definition at line 4097 of file clauses.c.

References elog, ERROR, fetch_function_defaults(), GETSTRUCT, list_concat(), list_copy(), list_delete_first(), and list_length().

Referenced by expand_function_arguments().

4098 {
4099  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4100  int nargsprovided = list_length(args);
4101  List *defaults;
4102  int ndelete;
4103 
4104  /* Get all the default expressions from the pg_proc tuple */
4105  defaults = fetch_function_defaults(func_tuple);
4106 
4107  /* Delete any unused defaults from the list */
4108  ndelete = nargsprovided + list_length(defaults) - funcform->pronargs;
4109  if (ndelete < 0)
4110  elog(ERROR, "not enough default arguments");
4111  while (ndelete-- > 0)
4112  defaults = list_delete_first(defaults);
4113 
4114  /* And form the combined argument list, not modifying the input list */
4115  return list_concat(list_copy(args), defaults);
4116 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
List * list_copy(const List *oldlist)
Definition: list.c:1160
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define ERROR
Definition: elog.h:43
static List * fetch_function_defaults(HeapTuple func_tuple)
Definition: clauses.c:4122
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
static int list_length(const List *l)
Definition: pg_list.h:89
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
List * list_delete_first(List *list)
Definition: list.c:666
bool and_clause ( Node clause)
void CommuteOpExpr ( OpExpr clause)

Definition at line 2253 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 fix_indexqual_references(), and get_switched_clauses().

2254 {
2255  Oid opoid;
2256  Node *temp;
2257 
2258  /* Sanity checks: caller is at fault if these fail */
2259  if (!is_opclause(clause) ||
2260  list_length(clause->args) != 2)
2261  elog(ERROR, "cannot commute non-binary-operator clause");
2262 
2263  opoid = get_commutator(clause->opno);
2264 
2265  if (!OidIsValid(opoid))
2266  elog(ERROR, "could not find commutator for operator %u",
2267  clause->opno);
2268 
2269  /*
2270  * modify the clause in-place!
2271  */
2272  clause->opno = opoid;
2273  clause->opfuncid = InvalidOid;
2274  /* opresulttype, opretset, opcollid, inputcollid need not change */
2275 
2276  temp = linitial(clause->args);
2277  linitial(clause->args) = lsecond(clause->args);
2278  lsecond(clause->args) = temp;
2279 }
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1313
Definition: nodes.h:509
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
#define lsecond(l)
Definition: pg_list.h:116
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
#define is_opclause(clause)
Definition: clauses.h:20
Oid opfuncid
Definition: primnodes.h:497
#define InvalidOid
Definition: postgres_ext.h:36
static int list_length(const List *l)
Definition: pg_list.h:89
Oid opno
Definition: primnodes.h:496
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:502
void CommuteRowCompareExpr ( RowCompareExpr clause)

Definition at line 2287 of file clauses.c.

References elog, ERROR, get_commutator(), IsA, lappend_oid(), RowCompareExpr::largs, lfirst_oid, NIL, OidIsValid, RowCompareExpr::opnos, RowCompareExpr::rargs, RowCompareExpr::rctype, ROWCOMPARE_GE, ROWCOMPARE_GT, ROWCOMPARE_LE, and ROWCOMPARE_LT.

Referenced by fix_indexqual_references().

2288 {
2289  List *newops;
2290  List *temp;
2291  ListCell *l;
2292 
2293  /* Sanity checks: caller is at fault if these fail */
2294  if (!IsA(clause, RowCompareExpr))
2295  elog(ERROR, "expected a RowCompareExpr");
2296 
2297  /* Build list of commuted operators */
2298  newops = NIL;
2299  foreach(l, clause->opnos)
2300  {
2301  Oid opoid = lfirst_oid(l);
2302 
2303  opoid = get_commutator(opoid);
2304  if (!OidIsValid(opoid))
2305  elog(ERROR, "could not find commutator for operator %u",
2306  lfirst_oid(l));
2307  newops = lappend_oid(newops, opoid);
2308  }
2309 
2310  /*
2311  * modify the clause in-place!
2312  */
2313  switch (clause->rctype)
2314  {
2315  case ROWCOMPARE_LT:
2316  clause->rctype = ROWCOMPARE_GT;
2317  break;
2318  case ROWCOMPARE_LE:
2319  clause->rctype = ROWCOMPARE_GE;
2320  break;
2321  case ROWCOMPARE_GE:
2322  clause->rctype = ROWCOMPARE_LE;
2323  break;
2324  case ROWCOMPARE_GT:
2325  clause->rctype = ROWCOMPARE_LT;
2326  break;
2327  default:
2328  elog(ERROR, "unexpected RowCompare type: %d",
2329  (int) clause->rctype);
2330  break;
2331  }
2332 
2333  clause->opnos = newops;
2334 
2335  /*
2336  * Note: we need not change the opfamilies list; we assume any btree
2337  * opfamily containing an operator will also contain its commutator.
2338  * Collations don't change either.
2339  */
2340 
2341  temp = clause->largs;
2342  clause->largs = clause->rargs;
2343  clause->rargs = temp;
2344 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1313
RowCompareType rctype
Definition: primnodes.h:1031
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:532
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
#define lfirst_oid(lc)
Definition: pg_list.h:108
bool contain_agg_clause ( Node clause)

Definition at line 417 of file clauses.c.

References contain_agg_clause_walker().

Referenced by get_eclass_for_sort_expr(), and subquery_planner().

418 {
419  return contain_agg_clause_walker(clause, NULL);
420 }
static bool contain_agg_clause_walker(Node *node, void *context)
Definition: clauses.c:423
static bool contain_agg_clause_walker ( Node node,
void *  context 
)
static

Definition at line 423 of file clauses.c.

References Assert, expression_tree_walker(), and IsA.

Referenced by contain_agg_clause().

424 {
425  if (node == NULL)
426  return false;
427  if (IsA(node, Aggref))
428  {
429  Assert(((Aggref *) node)->agglevelsup == 0);
430  return true; /* abort the tree traversal and return true */
431  }
432  if (IsA(node, GroupingFunc))
433  {
434  Assert(((GroupingFunc *) node)->agglevelsup == 0);
435  return true; /* abort the tree traversal and return true */
436  }
437  Assert(!IsA(node, SubLink));
438  return expression_tree_walker(node, contain_agg_clause_walker, context);
439 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
static bool contain_agg_clause_walker(Node *node, void *context)
Definition: clauses.c:423
#define Assert(condition)
Definition: c.h:664
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
static bool contain_context_dependent_node ( Node clause)
static

Definition at line 1415 of file clauses.c.

References contain_context_dependent_node_walker().

Referenced by inline_function().

1416 {
1417  int flags = 0;
1418 
1419  return contain_context_dependent_node_walker(clause, &flags);
1420 }
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:1425
static bool contain_context_dependent_node_walker ( Node node,
int *  flags 
)
static

Definition at line 1425 of file clauses.c.

References CaseExpr::arg, CCDN_IN_CASEEXPR, expression_tree_walker(), and IsA.

Referenced by contain_context_dependent_node().

1426 {
1427  if (node == NULL)
1428  return false;
1429  if (IsA(node, CaseTestExpr))
1430  return !(*flags & CCDN_IN_CASEEXPR);
1431  if (IsA(node, CaseExpr))
1432  {
1433  CaseExpr *caseexpr = (CaseExpr *) node;
1434 
1435  /*
1436  * If this CASE doesn't have a test expression, then it doesn't create
1437  * a context in which CaseTestExprs should appear, so just fall
1438  * through and treat it as a generic expression node.
1439  */
1440  if (caseexpr->arg)
1441  {
1442  int save_flags = *flags;
1443  bool res;
1444 
1445  /*
1446  * Note: in principle, we could distinguish the various sub-parts
1447  * of a CASE construct and set the flag bit only for some of them,
1448  * since we are only expecting CaseTestExprs to appear in the
1449  * "expr" subtree of the CaseWhen nodes. But it doesn't really
1450  * seem worth any extra code. If there are any bare CaseTestExprs
1451  * elsewhere in the CASE, something's wrong already.
1452  */
1453  *flags |= CCDN_IN_CASEEXPR;
1454  res = expression_tree_walker(node,
1456  (void *) flags);
1457  *flags = save_flags;
1458  return res;
1459  }
1460  }
1462  (void *) flags);
1463 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define CCDN_IN_CASEEXPR
Definition: clauses.c:1422
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
Expr * arg
Definition: primnodes.h:908
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:1425
bool contain_leaked_vars ( Node clause)

Definition at line 1481 of file clauses.c.

References contain_leaked_vars_walker().

Referenced by make_restrictinfo_internal(), and qual_is_pushdown_safe().

1482 {
1483  return contain_leaked_vars_walker(clause, NULL);
1484 }
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1493
static bool contain_leaked_vars_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 1487 of file clauses.c.

References get_func_leakproof().

Referenced by contain_leaked_vars_walker().

1488 {
1489  return !get_func_leakproof(func_id);
1490 }
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1622
static bool contain_leaked_vars_walker ( Node node,
void *  context 
)
static

Definition at line 1493 of file clauses.c.

References check_functions_in_node(), contain_leaked_vars_checker(), contain_var_clause(), expression_tree_walker(), forthree, get_func_leakproof(), get_opcode(), RowCompareExpr::largs, lfirst, lfirst_oid, nodeTag, RowCompareExpr::opnos, RowCompareExpr::rargs, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, 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, and T_Var.

Referenced by contain_leaked_vars().

1494 {
1495  if (node == NULL)
1496  return false;
1497 
1498  switch (nodeTag(node))
1499  {
1500  case T_Var:
1501  case T_Const:
1502  case T_Param:
1503  case T_ArrayRef:
1504  case T_ArrayExpr:
1505  case T_FieldSelect:
1506  case T_FieldStore:
1507  case T_NamedArgExpr:
1508  case T_BoolExpr:
1509  case T_RelabelType:
1510  case T_CollateExpr:
1511  case T_CaseExpr:
1512  case T_CaseTestExpr:
1513  case T_RowExpr:
1514  case T_MinMaxExpr:
1515  case T_SQLValueFunction:
1516  case T_NullTest:
1517  case T_BooleanTest:
1518  case T_NextValueExpr:
1519  case T_List:
1520 
1521  /*
1522  * We know these node types don't contain function calls; but
1523  * something further down in the node tree might.
1524  */
1525  break;
1526 
1527  case T_FuncExpr:
1528  case T_OpExpr:
1529  case T_DistinctExpr:
1530  case T_NullIfExpr:
1531  case T_ScalarArrayOpExpr:
1532  case T_CoerceViaIO:
1533  case T_ArrayCoerceExpr:
1534 
1535  /*
1536  * If node contains a leaky function call, and there's any Var
1537  * underneath it, reject.
1538  */
1540  context) &&
1541  contain_var_clause(node))
1542  return true;
1543  break;
1544 
1545  case T_RowCompareExpr:
1546  {
1547  /*
1548  * It's worth special-casing this because a leaky comparison
1549  * function only compromises one pair of row elements, which
1550  * might not contain Vars while others do.
1551  */
1552  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1553  ListCell *opid;
1554  ListCell *larg;
1555  ListCell *rarg;
1556 
1557  forthree(opid, rcexpr->opnos,
1558  larg, rcexpr->largs,
1559  rarg, rcexpr->rargs)
1560  {
1561  Oid funcid = get_opcode(lfirst_oid(opid));
1562 
1563  if (!get_func_leakproof(funcid) &&
1564  (contain_var_clause((Node *) lfirst(larg)) ||
1565  contain_var_clause((Node *) lfirst(rarg))))
1566  return true;
1567  }
1568  }
1569  break;
1570 
1571  case T_CurrentOfExpr:
1572 
1573  /*
1574  * WHERE CURRENT OF doesn't contain leaky function calls.
1575  * Moreover, it is essential that this is considered non-leaky,
1576  * since the planner must always generate a TID scan when CURRENT
1577  * OF is present -- c.f. cost_tidscan.
1578  */
1579  return false;
1580 
1581  default:
1582 
1583  /*
1584  * If we don't recognize the node tag, assume it might be leaky.
1585  * This prevents an unexpected security hole if someone adds a new
1586  * node type that can call a function.
1587  */
1588  return true;
1589  }
1591  context);
1592 }
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1622
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:203
Definition: nodes.h:509
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1651
Definition: nodes.h:291
Definition: nodes.h:147
Definition: nodes.h:146
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
#define lfirst(lc)
Definition: pg_list.h:106
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
#define nodeTag(nodeptr)
Definition: nodes.h:514
static bool contain_leaked_vars_checker(Oid func_id, void *context)
Definition: clauses.c:1487
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1493
#define lfirst_oid(lc)
Definition: pg_list.h:108
Definition: nodes.h:148
bool contain_mutable_functions ( Node clause)
static bool contain_mutable_functions_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 884 of file clauses.c.

References func_volatile(), and PROVOLATILE_IMMUTABLE.

Referenced by contain_mutable_functions_walker().

885 {
886  return (func_volatile(func_id) != PROVOLATILE_IMMUTABLE);
887 }
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5533
char func_volatile(Oid funcid)
Definition: lsyscache.c:1584
static bool contain_mutable_functions_walker ( Node node,
void *  context 
)
static

Definition at line 890 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().

891 {
892  if (node == NULL)
893  return false;
894  /* Check for mutable functions in node itself */
896  context))
897  return true;
898 
899  if (IsA(node, SQLValueFunction))
900  {
901  /* all variants of SQLValueFunction are stable */
902  return true;
903  }
904 
905  if (IsA(node, NextValueExpr))
906  {
907  /* NextValueExpr is volatile */
908  return true;
909  }
910 
911  /*
912  * It should be safe to treat MinMaxExpr as immutable, because it will
913  * depend on a non-cross-type btree comparison function, and those should
914  * always be immutable. Treating XmlExpr as immutable is more dubious,
915  * and treating CoerceToDomain as immutable is outright dangerous. But we
916  * have done so historically, and changing this would probably cause more
917  * problems than it would fix. In practice, if you have a non-immutable
918  * domain constraint you are in for pain anyhow.
919  */
920 
921  /* Recurse to check arguments */
922  if (IsA(node, Query))
923  {
924  /* Recurse into subselects */
925  return query_tree_walker((Query *) node,
927  context, 0);
928  }
930  context);
931 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2246
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
static bool contain_mutable_functions_walker(Node *node, void *context)
Definition: clauses.c:890
static bool contain_mutable_functions_checker(Oid func_id, void *context)
Definition: clauses.c:884
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1651
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
bool contain_nonstrict_functions ( Node clause)

Definition at line 1288 of file clauses.c.

References contain_nonstrict_functions_walker().

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

1289 {
1290  return contain_nonstrict_functions_walker(clause, NULL);
1291 }
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:1300
static bool contain_nonstrict_functions_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 1294 of file clauses.c.

References func_strict().

Referenced by contain_nonstrict_functions_walker().

1295 {
1296  return !func_strict(func_id);
1297 }
bool func_strict(Oid funcid)
Definition: lsyscache.c:1565
static bool contain_nonstrict_functions_walker ( Node node,
void *  context 
)
static

Definition at line 1300 of file clauses.c.

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

Referenced by contain_nonstrict_functions().

1301 {
1302  if (node == NULL)
1303  return false;
1304  if (IsA(node, Aggref))
1305  {
1306  /* an aggregate could return non-null with null input */
1307  return true;
1308  }
1309  if (IsA(node, GroupingFunc))
1310  {
1311  /*
1312  * A GroupingFunc doesn't evaluate its arguments, and therefore must
1313  * be treated as nonstrict.
1314  */
1315  return true;
1316  }
1317  if (IsA(node, WindowFunc))
1318  {
1319  /* a window function could return non-null with null input */
1320  return true;
1321  }
1322  if (IsA(node, ArrayRef))
1323  {
1324  /* array assignment is nonstrict, but subscripting is strict */
1325  if (((ArrayRef *) node)->refassgnexpr != NULL)
1326  return true;
1327  /* else fall through to check args */
1328  }
1329  if (IsA(node, DistinctExpr))
1330  {
1331  /* IS DISTINCT FROM is inherently non-strict */
1332  return true;
1333  }
1334  if (IsA(node, NullIfExpr))
1335  {
1336  /* NULLIF is inherently non-strict */
1337  return true;
1338  }
1339  if (IsA(node, BoolExpr))
1340  {
1341  BoolExpr *expr = (BoolExpr *) node;
1342 
1343  switch (expr->boolop)
1344  {
1345  case AND_EXPR:
1346  case OR_EXPR:
1347  /* AND, OR are inherently non-strict */
1348  return true;
1349  default:
1350  break;
1351  }
1352  }
1353  if (IsA(node, SubLink))
1354  {
1355  /* In some cases a sublink might be strict, but in general not */
1356  return true;
1357  }
1358  if (IsA(node, SubPlan))
1359  return true;
1360  if (IsA(node, AlternativeSubPlan))
1361  return true;
1362  if (IsA(node, FieldStore))
1363  return true;
1364  if (IsA(node, CaseExpr))
1365  return true;
1366  if (IsA(node, ArrayExpr))
1367  return true;
1368  if (IsA(node, RowExpr))
1369  return true;
1370  if (IsA(node, RowCompareExpr))
1371  return true;
1372  if (IsA(node, CoalesceExpr))
1373  return true;
1374  if (IsA(node, MinMaxExpr))
1375  return true;
1376  if (IsA(node, XmlExpr))
1377  return true;
1378  if (IsA(node, NullTest))
1379  return true;
1380  if (IsA(node, BooleanTest))
1381  return true;
1382 
1383  /*
1384  * Check other function-containing nodes; but ArrayCoerceExpr is strict at
1385  * the array level, regardless of elemfunc.
1386  */
1387  if (!IsA(node, ArrayCoerceExpr) &&
1389  context))
1390  return true;
1392  context);
1393 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:1300
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1651
BoolExprType boolop
Definition: primnodes.h:562
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
static bool contain_nonstrict_functions_checker(Oid func_id, void *context)
Definition: clauses.c:1294
bool contain_subplans ( Node clause)

Definition at line 843 of file clauses.c.

References contain_subplans_walker().

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

844 {
845  return contain_subplans_walker(clause, NULL);
846 }
static bool contain_subplans_walker(Node *node, void *context)
Definition: clauses.c:849
static bool contain_subplans_walker ( Node node,
void *  context 
)
static

Definition at line 849 of file clauses.c.

References expression_tree_walker(), and IsA.

Referenced by contain_subplans().

850 {
851  if (node == NULL)
852  return false;
853  if (IsA(node, SubPlan) ||
854  IsA(node, AlternativeSubPlan) ||
855  IsA(node, SubLink))
856  return true; /* abort the tree traversal and return true */
857  return expression_tree_walker(node, contain_subplans_walker, context);
858 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
static bool contain_subplans_walker(Node *node, void *context)
Definition: clauses.c:849
static bool contain_volatile_functions_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 963 of file clauses.c.

References func_volatile(), and PROVOLATILE_VOLATILE.

Referenced by contain_volatile_functions_walker().

964 {
965  return (func_volatile(func_id) == PROVOLATILE_VOLATILE);
966 }
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5535
char func_volatile(Oid funcid)
Definition: lsyscache.c:1584
bool contain_volatile_functions_not_nextval ( Node clause)

Definition at line 1007 of file clauses.c.

References contain_volatile_functions_not_nextval_walker().

Referenced by BeginCopyFrom().

1008 {
1009  return contain_volatile_functions_not_nextval_walker(clause, NULL);
1010 }
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:1020
static bool contain_volatile_functions_not_nextval_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 1013 of file clauses.c.

References func_volatile(), and PROVOLATILE_VOLATILE.

Referenced by contain_volatile_functions_not_nextval_walker().

1014 {
1015  return (func_id != F_NEXTVAL_OID &&
1016  func_volatile(func_id) == PROVOLATILE_VOLATILE);
1017 }
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5535
char func_volatile(Oid funcid)
Definition: lsyscache.c:1584
static bool contain_volatile_functions_not_nextval_walker ( Node node,
void *  context 
)
static

Definition at line 1020 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().

1021 {
1022  if (node == NULL)
1023  return false;
1024  /* Check for volatile functions in node itself */
1025  if (check_functions_in_node(node,
1027  context))
1028  return true;
1029 
1030  /*
1031  * See notes in contain_mutable_functions_walker about why we treat
1032  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
1033  * SQLValueFunction is stable. Hence, none of them are of interest here.
1034  * Also, since we're intentionally ignoring nextval(), presumably we
1035  * should ignore NextValueExpr.
1036  */
1037 
1038  /* Recurse to check arguments */
1039  if (IsA(node, Query))
1040  {
1041  /* Recurse into subselects */
1042  return query_tree_walker((Query *) node,
1044  context, 0);
1045  }
1046  return expression_tree_walker(node,
1048  context);
1049 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2246
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:1020
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1651
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
static bool contain_volatile_functions_not_nextval_checker(Oid func_id, void *context)
Definition: clauses.c:1013
static bool contain_volatile_functions_walker ( Node node,
void *  context 
)
static

Definition at line 969 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().

970 {
971  if (node == NULL)
972  return false;
973  /* Check for volatile functions in node itself */
975  context))
976  return true;
977 
978  if (IsA(node, NextValueExpr))
979  {
980  /* NextValueExpr is volatile */
981  return true;
982  }
983 
984  /*
985  * See notes in contain_mutable_functions_walker about why we treat
986  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
987  * SQLValueFunction is stable. Hence, none of them are of interest here.
988  */
989 
990  /* Recurse to check arguments */
991  if (IsA(node, Query))
992  {
993  /* Recurse into subselects */
994  return query_tree_walker((Query *) node,
996  context, 0);
997  }
999  context);
1000 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2246
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1651
static bool contain_volatile_functions_walker(Node *node, void *context)
Definition: clauses.c:969
static bool contain_volatile_functions_checker(Oid func_id, void *context)
Definition: clauses.c:963
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
bool contain_window_function ( Node clause)

Definition at line 727 of file clauses.c.

References contain_windowfuncs().

Referenced by get_eclass_for_sort_expr(), and qual_is_pushdown_safe().

728 {
729  return contain_windowfuncs(clause);
730 }
bool contain_windowfuncs(Node *node)
Definition: rewriteManip.c:197
Node* estimate_expression_value ( PlannerInfo root,
Node node 
)

Definition at line 2454 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 bernoulli_samplescangetsamplesize(), clause_selectivity(), get_restriction_variable(), gincost_opexpr(), gincost_scalararrayopexpr(), preprocess_limit(), scalararraysel(), system_rows_samplescangetsamplesize(), system_samplescangetsamplesize(), and system_time_samplescangetsamplesize().

2455 {
2457 
2458  context.boundParams = root->glob->boundParams; /* bound Params */
2459  /* we do not need to mark the plan as depending on inlined functions */
2460  context.root = NULL;
2461  context.active_fns = NIL; /* nothing being recursively simplified */
2462  context.case_val = NULL; /* no CASE being examined */
2463  context.estimate = true; /* unsafe transformations OK */
2464  return eval_const_expressions_mutator(node, &context);
2465 }
#define NIL
Definition: pg_list.h:69
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2468
ParamListInfo boundParams
Definition: clauses.c:65
PlannerGlobal * glob
Definition: relation.h:157
ParamListInfo boundParams
Definition: relation.h:96
Node* eval_const_expressions ( PlannerInfo root,
Node node 
)

Definition at line 2421 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 ATExecAttachPartition(), convert_EXISTS_to_ANY(), expression_planner(), get_proposed_default_constraint(), get_relation_constraints(), inline_set_returning_function(), PartConstraintImpliedByRelConstraint(), preprocess_expression(), process_implied_equality(), RelationBuildPartitionKey(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), set_append_rel_size(), and simplify_EXISTS_query().

2422 {
2424 
2425  if (root)
2426  context.boundParams = root->glob->boundParams; /* bound Params */
2427  else
2428  context.boundParams = NULL;
2429  context.root = root; /* for inlined-function dependencies */
2430  context.active_fns = NIL; /* nothing being recursively simplified */
2431  context.case_val = NULL; /* no CASE being examined */
2432  context.estimate = false; /* safe transformations only */
2433  return eval_const_expressions_mutator(node, &context);
2434 }
#define NIL
Definition: pg_list.h:69
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2468
ParamListInfo boundParams
Definition: clauses.c:65
PlannerGlobal * glob
Definition: relation.h:157
ParamListInfo boundParams
Definition: relation.h:96
static Node * eval_const_expressions_mutator ( Node node,
eval_const_expressions_context context 
)
static

Definition at line 2468 of file clauses.c.

References WindowFunc::aggfilter, AND_EXPR, arg, FieldSelect::arg, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, CollateExpr::arg, CaseExpr::arg, NullTest::arg, BooleanTest::arg, NullTest::argisrow, generate_unaccent_rules::args, WindowFunc::args, FuncExpr::args, OpExpr::args, BoolExpr::args, CaseExpr::args, RowExpr::args, CoalesceExpr::args, ArrayExpr::array_collid, ArrayExpr::array_typeid, Assert, BooleanEqualOperator, BooleanNotEqualOperator, 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, ArrayCoerceExpr::coerceformat, CollateExpr::collOid, Const::constcollid, Const::constisnull, Const::consttype, Const::consttypmod, Const::constvalue, copyObject, CSTRINGOID, datumCopy(), DatumGetBool, CaseExpr::defresult, element(), ArrayExpr::element_typeid, ArrayExpr::elements, ArrayCoerceExpr::elemfuncid, elog, ERROR, eval_const_expressions_context::estimate, evaluate_expr(), expand_function_arguments(), CaseWhen::expr, exprCollation(), expression_tree_mutator(), exprType(), exprTypmod(), FieldSelect::fieldnum, func_volatile(), FuncExpr::funccollid, FuncExpr::funcformat, FuncExpr::funcid, FuncExpr::funcresulttype, FuncExpr::funcretset, FuncExpr::funcvariadic, get_typlenbyval(), getTypeInputInfo(), getTypeOutputInfo(), HeapTupleIsValid, WindowFunc::inputcollid, FuncExpr::inputcollid, OpExpr::inputcollid, Int32GetDatum, INT4OID, InvalidAttrNumber, InvalidOid, IS_FALSE, IS_NOT_FALSE, IS_NOT_NULL, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_NULL, IS_TRUE, IS_UNKNOWN, IsA, ArrayCoerceExpr::isExplicit, 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, ArrayCoerceExpr::location, CollateExpr::location, CaseExpr::location, CaseWhen::location, ArrayExpr::location, CoalesceExpr::location, NullTest::location, BooleanTest::location, make_andclause(), make_orclause(), makeBoolConst(), makeConst(), makeNode, makeNullConst(), makeVar(), ArrayExpr::multidims, negate_clause(), NIL, nodeTag, NOT_EXPR, NullTest::nulltesttype, ParamListInfoData::numParams, ObjectIdGetDatum, OidIsValid, OIDOID, OpExpr::opcollid, OpExpr::opfuncid, OpExpr::opno, OpExpr::opresulttype, OpExpr::opretset, OR_EXPR, PARAM_EXTERN, PARAM_FLAG_CONST, Param::paramcollid, Param::paramid, Param::paramkind, ParamListInfoData::params, Param::paramtype, Param::paramtypmod, ParamExternData::pflags, PlaceHolderVar::phexpr, PROCOID, PROVOLATILE_IMMUTABLE, ParamExternData::ptype, RelabelType::relabelformat, ReleaseSysCache(), CaseWhen::result, FieldSelect::resultcollid, RelabelType::resultcollid, CoerceViaIO::resultcollid, ArrayCoerceExpr::resultcollid, FieldSelect::resulttype, RelabelType::resulttype, CoerceViaIO::resulttype, ArrayCoerceExpr::resulttype, FieldSelect::resulttypmod, RelabelType::resulttypmod, ArrayCoerceExpr::resulttypmod, RowExpr::row_typeid, rowtype_field_matches(), SearchSysCache1, set_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_CoerceViaIO, T_CollateExpr, T_DistinctExpr, T_FieldSelect, T_FuncExpr, T_NullTest, T_OpExpr, T_Param, T_PlaceHolderVar, T_RelabelType, T_SQLValueFunction, T_SubPlan, T_WindowFunc, SQLValueFunction::type, SQLValueFunction::typmod, ParamExternData::value, WindowFunc::winagg, WindowFunc::wincollid, WindowFunc::winfnoid, WindowFunc::winref, WindowFunc::winstar, and WindowFunc::wintype.

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

2470 {
2471  if (node == NULL)
2472  return NULL;
2473  switch (nodeTag(node))
2474  {
2475  case T_Param:
2476  {
2477  Param *param = (Param *) node;
2478 
2479  /* Look to see if we've been given a value for this Param */
2480  if (param->paramkind == PARAM_EXTERN &&
2481  context->boundParams != NULL &&
2482  param->paramid > 0 &&
2483  param->paramid <= context->boundParams->numParams)
2484  {
2485  ParamExternData *prm = &context->boundParams->params[param->paramid - 1];
2486 
2487  if (OidIsValid(prm->ptype))
2488  {
2489  /* OK to substitute parameter value? */
2490  if (context->estimate ||
2491  (prm->pflags & PARAM_FLAG_CONST))
2492  {
2493  /*
2494  * Return a Const representing the param value.
2495  * Must copy pass-by-ref datatypes, since the
2496  * Param might be in a memory context
2497  * shorter-lived than our output plan should be.
2498  */
2499  int16 typLen;
2500  bool typByVal;
2501  Datum pval;
2502 
2503  Assert(prm->ptype == param->paramtype);
2504  get_typlenbyval(param->paramtype,
2505  &typLen, &typByVal);
2506  if (prm->isnull || typByVal)
2507  pval = prm->value;
2508  else
2509  pval = datumCopy(prm->value, typByVal, typLen);
2510  return (Node *) makeConst(param->paramtype,
2511  param->paramtypmod,
2512  param->paramcollid,
2513  (int) typLen,
2514  pval,
2515  prm->isnull,
2516  typByVal);
2517  }
2518  }
2519  }
2520 
2521  /*
2522  * Not replaceable, so just copy the Param (no need to
2523  * recurse)
2524  */
2525  return (Node *) copyObject(param);
2526  }
2527  case T_WindowFunc:
2528  {
2529  WindowFunc *expr = (WindowFunc *) node;
2530  Oid funcid = expr->winfnoid;
2531  List *args;
2532  Expr *aggfilter;
2533  HeapTuple func_tuple;
2534  WindowFunc *newexpr;
2535 
2536  /*
2537  * We can't really simplify a WindowFunc node, but we mustn't
2538  * just fall through to the default processing, because we
2539  * have to apply expand_function_arguments to its argument
2540  * list. That takes care of inserting default arguments and
2541  * expanding named-argument notation.
2542  */
2543  func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
2544  if (!HeapTupleIsValid(func_tuple))
2545  elog(ERROR, "cache lookup failed for function %u", funcid);
2546 
2547  args = expand_function_arguments(expr->args, expr->wintype,
2548  func_tuple);
2549 
2550  ReleaseSysCache(func_tuple);
2551 
2552  /* Now, recursively simplify the args (which are a List) */
2553  args = (List *)
2556  (void *) context);
2557  /* ... and the filter expression, which isn't */
2558  aggfilter = (Expr *)
2560  context);
2561 
2562  /* And build the replacement WindowFunc node */
2563  newexpr = makeNode(WindowFunc);
2564  newexpr->winfnoid = expr->winfnoid;
2565  newexpr->wintype = expr->wintype;
2566  newexpr->wincollid = expr->wincollid;
2567  newexpr->inputcollid = expr->inputcollid;
2568  newexpr->args = args;
2569  newexpr->aggfilter = aggfilter;
2570  newexpr->winref = expr->winref;
2571  newexpr->winstar = expr->winstar;
2572  newexpr->winagg = expr->winagg;
2573  newexpr->location = expr->location;
2574 
2575  return (Node *) newexpr;
2576  }
2577  case T_FuncExpr:
2578  {
2579  FuncExpr *expr = (FuncExpr *) node;
2580  List *args = expr->args;
2581  Expr *simple;
2582  FuncExpr *newexpr;
2583 
2584  /*
2585  * Code for op/func reduction is pretty bulky, so split it out
2586  * as a separate function. Note: exprTypmod normally returns
2587  * -1 for a FuncExpr, but not when the node is recognizably a
2588  * length coercion; we want to preserve the typmod in the
2589  * eventual Const if so.
2590  */
2591  simple = simplify_function(expr->funcid,
2592  expr->funcresulttype,
2593  exprTypmod(node),
2594  expr->funccollid,
2595  expr->inputcollid,
2596  &args,
2597  expr->funcvariadic,
2598  true,
2599  true,
2600  context);
2601  if (simple) /* successfully simplified it */
2602  return (Node *) simple;
2603 
2604  /*
2605  * The expression cannot be simplified any further, so build
2606  * and return a replacement FuncExpr node using the
2607  * possibly-simplified arguments. Note that we have also
2608  * converted the argument list to positional notation.
2609  */
2610  newexpr = makeNode(FuncExpr);
2611  newexpr->funcid = expr->funcid;
2612  newexpr->funcresulttype = expr->funcresulttype;
2613  newexpr->funcretset = expr->funcretset;
2614  newexpr->funcvariadic = expr->funcvariadic;
2615  newexpr->funcformat = expr->funcformat;
2616  newexpr->funccollid = expr->funccollid;
2617  newexpr->inputcollid = expr->inputcollid;
2618  newexpr->args = args;
2619  newexpr->location = expr->location;
2620  return (Node *) newexpr;
2621  }
2622  case T_OpExpr:
2623  {
2624  OpExpr *expr = (OpExpr *) node;
2625  List *args = expr->args;
2626  Expr *simple;
2627  OpExpr *newexpr;
2628 
2629  /*
2630  * Need to get OID of underlying function. Okay to scribble
2631  * on input to this extent.
2632  */
2633  set_opfuncid(expr);
2634 
2635  /*
2636  * Code for op/func reduction is pretty bulky, so split it out
2637  * as a separate function.
2638  */
2639  simple = simplify_function(expr->opfuncid,
2640  expr->opresulttype, -1,
2641  expr->opcollid,
2642  expr->inputcollid,
2643  &args,
2644  false,
2645  true,
2646  true,
2647  context);
2648  if (simple) /* successfully simplified it */
2649  return (Node *) simple;
2650 
2651  /*
2652  * If the operator is boolean equality or inequality, we know
2653  * how to simplify cases involving one constant and one
2654  * non-constant argument.
2655  */
2656  if (expr->opno == BooleanEqualOperator ||
2657  expr->opno == BooleanNotEqualOperator)
2658  {
2659  simple = (Expr *) simplify_boolean_equality(expr->opno,
2660  args);
2661  if (simple) /* successfully simplified it */
2662  return (Node *) simple;
2663  }
2664 
2665  /*
2666  * The expression cannot be simplified any further, so build
2667  * and return a replacement OpExpr node using the
2668  * possibly-simplified arguments.
2669  */
2670  newexpr = makeNode(OpExpr);
2671  newexpr->opno = expr->opno;
2672  newexpr->opfuncid = expr->opfuncid;
2673  newexpr->opresulttype = expr->opresulttype;
2674  newexpr->opretset = expr->opretset;
2675  newexpr->opcollid = expr->opcollid;
2676  newexpr->inputcollid = expr->inputcollid;
2677  newexpr->args = args;
2678  newexpr->location = expr->location;
2679  return (Node *) newexpr;
2680  }
2681  case T_DistinctExpr:
2682  {
2683  DistinctExpr *expr = (DistinctExpr *) node;
2684  List *args;
2685  ListCell *arg;
2686  bool has_null_input = false;
2687  bool all_null_input = true;
2688  bool has_nonconst_input = false;
2689  Expr *simple;
2690  DistinctExpr *newexpr;
2691 
2692  /*
2693  * Reduce constants in the DistinctExpr's arguments. We know
2694  * args is either NIL or a List node, so we can call
2695  * expression_tree_mutator directly rather than recursing to
2696  * self.
2697  */
2698  args = (List *) expression_tree_mutator((Node *) expr->args,
2700  (void *) context);
2701 
2702  /*
2703  * We must do our own check for NULLs because DistinctExpr has
2704  * different results for NULL input than the underlying
2705  * operator does.
2706  */
2707  foreach(arg, args)
2708  {
2709  if (IsA(lfirst(arg), Const))
2710  {
2711  has_null_input |= ((Const *) lfirst(arg))->constisnull;
2712  all_null_input &= ((Const *) lfirst(arg))->constisnull;
2713  }
2714  else
2715  has_nonconst_input = true;
2716  }
2717 
2718  /* all constants? then can optimize this out */
2719  if (!has_nonconst_input)
2720  {
2721  /* all nulls? then not distinct */
2722  if (all_null_input)
2723  return makeBoolConst(false, false);
2724 
2725  /* one null? then distinct */
2726  if (has_null_input)
2727  return makeBoolConst(true, false);
2728 
2729  /* otherwise try to evaluate the '=' operator */
2730  /* (NOT okay to try to inline it, though!) */
2731 
2732  /*
2733  * Need to get OID of underlying function. Okay to
2734  * scribble on input to this extent.
2735  */
2736  set_opfuncid((OpExpr *) expr); /* rely on struct
2737  * equivalence */
2738 
2739  /*
2740  * Code for op/func reduction is pretty bulky, so split it
2741  * out as a separate function.
2742  */
2743  simple = simplify_function(expr->opfuncid,
2744  expr->opresulttype, -1,
2745  expr->opcollid,
2746  expr->inputcollid,
2747  &args,
2748  false,
2749  false,
2750  false,
2751  context);
2752  if (simple) /* successfully simplified it */
2753  {
2754  /*
2755  * Since the underlying operator is "=", must negate
2756  * its result
2757  */
2758  Const *csimple = castNode(Const, simple);
2759 
2760  csimple->constvalue =
2761  BoolGetDatum(!DatumGetBool(csimple->constvalue));
2762  return (Node *) csimple;
2763  }
2764  }
2765 
2766  /*
2767  * The expression cannot be simplified any further, so build
2768  * and return a replacement DistinctExpr node using the
2769  * possibly-simplified arguments.
2770  */
2771  newexpr = makeNode(DistinctExpr);
2772  newexpr->opno = expr->opno;
2773  newexpr->opfuncid = expr->opfuncid;
2774  newexpr->opresulttype = expr->opresulttype;
2775  newexpr->opretset = expr->opretset;
2776  newexpr->opcollid = expr->opcollid;
2777  newexpr->inputcollid = expr->inputcollid;
2778  newexpr->args = args;
2779  newexpr->location = expr->location;
2780  return (Node *) newexpr;
2781  }
2782  case T_BoolExpr:
2783  {
2784  BoolExpr *expr = (BoolExpr *) node;
2785 
2786  switch (expr->boolop)
2787  {
2788  case OR_EXPR:
2789  {
2790  List *newargs;
2791  bool haveNull = false;
2792  bool forceTrue = false;
2793 
2794  newargs = simplify_or_arguments(expr->args,
2795  context,
2796  &haveNull,
2797  &forceTrue);
2798  if (forceTrue)
2799  return makeBoolConst(true, false);
2800  if (haveNull)
2801  newargs = lappend(newargs,
2802  makeBoolConst(false, true));
2803  /* If all the inputs are FALSE, result is FALSE */
2804  if (newargs == NIL)
2805  return makeBoolConst(false, false);
2806 
2807  /*
2808  * If only one nonconst-or-NULL input, it's the
2809  * result
2810  */
2811  if (list_length(newargs) == 1)
2812  return (Node *) linitial(newargs);
2813  /* Else we still need an OR node */
2814  return (Node *) make_orclause(newargs);
2815  }
2816  case AND_EXPR:
2817  {
2818  List *newargs;
2819  bool haveNull = false;
2820  bool forceFalse = false;
2821 
2822  newargs = simplify_and_arguments(expr->args,
2823  context,
2824  &haveNull,
2825  &forceFalse);
2826  if (forceFalse)
2827  return makeBoolConst(false, false);
2828  if (haveNull)
2829  newargs = lappend(newargs,
2830  makeBoolConst(false, true));
2831  /* If all the inputs are TRUE, result is TRUE */
2832  if (newargs == NIL)
2833  return makeBoolConst(true, false);
2834 
2835  /*
2836  * If only one nonconst-or-NULL input, it's the
2837  * result
2838  */
2839  if (list_length(newargs) == 1)
2840  return (Node *) linitial(newargs);
2841  /* Else we still need an AND node */
2842  return (Node *) make_andclause(newargs);
2843  }
2844  case NOT_EXPR:
2845  {
2846  Node *arg;
2847 
2848  Assert(list_length(expr->args) == 1);
2850  context);
2851 
2852  /*
2853  * Use negate_clause() to see if we can simplify
2854  * away the NOT.
2855  */
2856  return negate_clause(arg);
2857  }
2858  default:
2859  elog(ERROR, "unrecognized boolop: %d",
2860  (int) expr->boolop);
2861  break;
2862  }
2863  break;
2864  }
2865  case T_SubPlan:
2866  case T_AlternativeSubPlan:
2867 
2868  /*
2869  * Return a SubPlan unchanged --- too late to do anything with it.
2870  *
2871  * XXX should we ereport() here instead? Probably this routine
2872  * should never be invoked after SubPlan creation.
2873  */
2874  return node;
2875  case T_RelabelType:
2876  {
2877  /*
2878  * If we can simplify the input to a constant, then we don't
2879  * need the RelabelType node anymore: just change the type
2880  * field of the Const node. Otherwise, must copy the
2881  * RelabelType node.
2882  */
2883  RelabelType *relabel = (RelabelType *) node;
2884  Node *arg;
2885 
2886  arg = eval_const_expressions_mutator((Node *) relabel->arg,
2887  context);
2888 
2889  /*
2890  * If we find stacked RelabelTypes (eg, from foo :: int ::
2891  * oid) we can discard all but the top one.
2892  */
2893  while (arg && IsA(arg, RelabelType))
2894  arg = (Node *) ((RelabelType *) arg)->arg;
2895 
2896  if (arg && IsA(arg, Const))
2897  {
2898  Const *con = (Const *) arg;
2899 
2900  con->consttype = relabel->resulttype;
2901  con->consttypmod = relabel->resulttypmod;
2902  con->constcollid = relabel->resultcollid;
2903  return (Node *) con;
2904  }
2905  else
2906  {
2907  RelabelType *newrelabel = makeNode(RelabelType);
2908 
2909  newrelabel->arg = (Expr *) arg;
2910  newrelabel->resulttype = relabel->resulttype;
2911  newrelabel->resulttypmod = relabel->resulttypmod;
2912  newrelabel->resultcollid = relabel->resultcollid;
2913  newrelabel->relabelformat = relabel->relabelformat;
2914  newrelabel->location = relabel->location;
2915  return (Node *) newrelabel;
2916  }
2917  }
2918  case T_CoerceViaIO:
2919  {
2920  CoerceViaIO *expr = (CoerceViaIO *) node;
2921  List *args;
2922  Oid outfunc;
2923  bool outtypisvarlena;
2924  Oid infunc;
2925  Oid intypioparam;
2926  Expr *simple;
2927  CoerceViaIO *newexpr;
2928 
2929  /* Make a List so we can use simplify_function */
2930  args = list_make1(expr->arg);
2931 
2932  /*
2933  * CoerceViaIO represents calling the source type's output
2934  * function then the result type's input function. So, try to
2935  * simplify it as though it were a stack of two such function
2936  * calls. First we need to know what the functions are.
2937  *
2938  * Note that the coercion functions are assumed not to care
2939  * about input collation, so we just pass InvalidOid for that.
2940  */
2941  getTypeOutputInfo(exprType((Node *) expr->arg),
2942  &outfunc, &outtypisvarlena);
2944  &infunc, &intypioparam);
2945 
2946  simple = simplify_function(outfunc,
2947  CSTRINGOID, -1,
2948  InvalidOid,
2949  InvalidOid,
2950  &args,
2951  false,
2952  true,
2953  true,
2954  context);
2955  if (simple) /* successfully simplified output fn */
2956  {
2957  /*
2958  * Input functions may want 1 to 3 arguments. We always
2959  * supply all three, trusting that nothing downstream will
2960  * complain.
2961  */
2962  args = list_make3(simple,
2963  makeConst(OIDOID,
2964  -1,
2965  InvalidOid,
2966  sizeof(Oid),
2967  ObjectIdGetDatum(intypioparam),
2968  false,
2969  true),
2971  -1,
2972  InvalidOid,
2973  sizeof(int32),
2974  Int32GetDatum(-1),
2975  false,
2976  true));
2977 
2978  simple = simplify_function(infunc,
2979  expr->resulttype, -1,
2980  expr->resultcollid,
2981  InvalidOid,
2982  &args,
2983  false,
2984  false,
2985  true,
2986  context);
2987  if (simple) /* successfully simplified input fn */
2988  return (Node *) simple;
2989  }
2990 
2991  /*
2992  * The expression cannot be simplified any further, so build
2993  * and return a replacement CoerceViaIO node using the
2994  * possibly-simplified argument.
2995  */
2996  newexpr = makeNode(CoerceViaIO);
2997  newexpr->arg = (Expr *) linitial(args);
2998  newexpr->resulttype = expr->resulttype;
2999  newexpr->resultcollid = expr->resultcollid;
3000  newexpr->coerceformat = expr->coerceformat;
3001  newexpr->location = expr->location;
3002  return (Node *) newexpr;
3003  }
3004  case T_ArrayCoerceExpr:
3005  {
3006  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
3007  Expr *arg;
3008  ArrayCoerceExpr *newexpr;
3009 
3010  /*
3011  * Reduce constants in the ArrayCoerceExpr's argument, then
3012  * build a new ArrayCoerceExpr.
3013  */
3014  arg = (Expr *) eval_const_expressions_mutator((Node *) expr->arg,
3015  context);
3016 
3017  newexpr = makeNode(ArrayCoerceExpr);
3018  newexpr->arg = arg;
3019  newexpr->elemfuncid = expr->elemfuncid;
3020  newexpr->resulttype = expr->resulttype;
3021  newexpr->resulttypmod = expr->resulttypmod;
3022  newexpr->resultcollid = expr->resultcollid;
3023  newexpr->isExplicit = expr->isExplicit;
3024  newexpr->coerceformat = expr->coerceformat;
3025  newexpr->location = expr->location;
3026 
3027  /*
3028  * If constant argument and it's a binary-coercible or
3029  * immutable conversion, we can simplify it to a constant.
3030  */
3031  if (arg && IsA(arg, Const) &&
3032  (!OidIsValid(newexpr->elemfuncid) ||
3034  return (Node *) evaluate_expr((Expr *) newexpr,
3035  newexpr->resulttype,
3036  newexpr->resulttypmod,
3037  newexpr->resultcollid);
3038 
3039  /* Else we must return the partially-simplified node */
3040  return (Node *) newexpr;
3041  }
3042  case T_CollateExpr:
3043  {
3044  /*
3045  * If we can simplify the input to a constant, then we don't
3046  * need the CollateExpr node at all: just change the
3047  * constcollid field of the Const node. Otherwise, replace
3048  * the CollateExpr with a RelabelType. (We do that so as to
3049  * improve uniformity of expression representation and thus
3050  * simplify comparison of expressions.)
3051  */
3052  CollateExpr *collate = (CollateExpr *) node;
3053  Node *arg;
3054 
3055  arg = eval_const_expressions_mutator((Node *) collate->arg,
3056  context);
3057 
3058  if (arg && IsA(arg, Const))
3059  {
3060  Const *con = (Const *) arg;
3061 
3062  con->constcollid = collate->collOid;
3063  return (Node *) con;
3064  }
3065  else if (collate->collOid == exprCollation(arg))
3066  {
3067  /* Don't need a RelabelType either... */
3068  return arg;
3069  }
3070  else
3071  {
3072  RelabelType *relabel = makeNode(RelabelType);
3073 
3074  relabel->resulttype = exprType(arg);
3075  relabel->resulttypmod = exprTypmod(arg);
3076  relabel->resultcollid = collate->collOid;
3078  relabel->location = collate->location;
3079 
3080  /* Don't create stacked RelabelTypes */
3081  while (arg && IsA(arg, RelabelType))
3082  arg = (Node *) ((RelabelType *) arg)->arg;
3083  relabel->arg = (Expr *) arg;
3084 
3085  return (Node *) relabel;
3086  }
3087  }
3088  case T_CaseExpr:
3089  {
3090  /*----------
3091  * CASE expressions can be simplified if there are constant
3092  * condition clauses:
3093  * FALSE (or NULL): drop the alternative
3094  * TRUE: drop all remaining alternatives
3095  * If the first non-FALSE alternative is a constant TRUE,
3096  * we can simplify the entire CASE to that alternative's
3097  * expression. If there are no non-FALSE alternatives,
3098  * we simplify the entire CASE to the default result (ELSE).
3099  *
3100  * If we have a simple-form CASE with constant test
3101  * expression, we substitute the constant value for contained
3102  * CaseTestExpr placeholder nodes, so that we have the
3103  * opportunity to reduce constant test conditions. For
3104  * example this allows
3105  * CASE 0 WHEN 0 THEN 1 ELSE 1/0 END
3106  * to reduce to 1 rather than drawing a divide-by-0 error.
3107  * Note that when the test expression is constant, we don't
3108  * have to include it in the resulting CASE; for example
3109  * CASE 0 WHEN x THEN y ELSE z END
3110  * is transformed by the parser to
3111  * CASE 0 WHEN CaseTestExpr = x THEN y ELSE z END
3112  * which we can simplify to
3113  * CASE WHEN 0 = x THEN y ELSE z END
3114  * It is not necessary for the executor to evaluate the "arg"
3115  * expression when executing the CASE, since any contained
3116  * CaseTestExprs that might have referred to it will have been
3117  * replaced by the constant.
3118  *----------
3119  */
3120  CaseExpr *caseexpr = (CaseExpr *) node;
3121  CaseExpr *newcase;
3122  Node *save_case_val;
3123  Node *newarg;
3124  List *newargs;
3125  bool const_true_cond;
3126  Node *defresult = NULL;
3127  ListCell *arg;
3128 
3129  /* Simplify the test expression, if any */
3130  newarg = eval_const_expressions_mutator((Node *) caseexpr->arg,
3131  context);
3132 
3133  /* Set up for contained CaseTestExpr nodes */
3134  save_case_val = context->case_val;
3135  if (newarg && IsA(newarg, Const))
3136  {
3137  context->case_val = newarg;
3138  newarg = NULL; /* not needed anymore, see above */
3139  }
3140  else
3141  context->case_val = NULL;
3142 
3143  /* Simplify the WHEN clauses */
3144  newargs = NIL;
3145  const_true_cond = false;
3146  foreach(arg, caseexpr->args)
3147  {
3148  CaseWhen *oldcasewhen = lfirst_node(CaseWhen, arg);
3149  Node *casecond;
3150  Node *caseresult;
3151 
3152  /* Simplify this alternative's test condition */
3153  casecond = eval_const_expressions_mutator((Node *) oldcasewhen->expr,
3154  context);
3155 
3156  /*
3157  * If the test condition is constant FALSE (or NULL), then
3158  * drop this WHEN clause completely, without processing
3159  * the result.
3160  */
3161  if (casecond && IsA(casecond, Const))
3162  {
3163  Const *const_input = (Const *) casecond;
3164 
3165  if (const_input->constisnull ||
3166  !DatumGetBool(const_input->constvalue))
3167  continue; /* drop alternative with FALSE cond */
3168  /* Else it's constant TRUE */
3169  const_true_cond = true;
3170  }
3171 
3172  /* Simplify this alternative's result value */
3173  caseresult = eval_const_expressions_mutator((Node *) oldcasewhen->result,
3174  context);
3175 
3176  /* If non-constant test condition, emit a new WHEN node */
3177  if (!const_true_cond)
3178  {
3179  CaseWhen *newcasewhen = makeNode(CaseWhen);
3180 
3181  newcasewhen->expr = (Expr *) casecond;
3182  newcasewhen->result = (Expr *) caseresult;
3183  newcasewhen->location = oldcasewhen->location;
3184  newargs = lappend(newargs, newcasewhen);
3185  continue;
3186  }
3187 
3188  /*
3189  * Found a TRUE condition, so none of the remaining
3190  * alternatives can be reached. We treat the result as
3191  * the default result.
3192  */
3193  defresult = caseresult;
3194  break;
3195  }
3196 
3197  /* Simplify the default result, unless we replaced it above */
3198  if (!const_true_cond)
3199  defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult,
3200  context);
3201 
3202  context->case_val = save_case_val;
3203 
3204  /*
3205  * If no non-FALSE alternatives, CASE reduces to the default
3206  * result
3207  */
3208  if (newargs == NIL)
3209  return defresult;
3210  /* Otherwise we need a new CASE node */
3211  newcase = makeNode(CaseExpr);
3212  newcase->casetype = caseexpr->casetype;
3213  newcase->casecollid = caseexpr->casecollid;
3214  newcase->arg = (Expr *) newarg;
3215  newcase->args = newargs;
3216  newcase->defresult = (Expr *) defresult;
3217  newcase->location = caseexpr->location;
3218  return (Node *) newcase;
3219  }
3220  case T_CaseTestExpr:
3221  {
3222  /*
3223  * If we know a constant test value for the current CASE
3224  * construct, substitute it for the placeholder. Else just
3225  * return the placeholder as-is.
3226  */
3227  if (context->case_val)
3228  return copyObject(context->case_val);
3229  else
3230  return copyObject(node);
3231  }
3232  case T_ArrayExpr:
3233  {
3234  ArrayExpr *arrayexpr = (ArrayExpr *) node;
3235  ArrayExpr *newarray;
3236  bool all_const = true;
3237  List *newelems;
3238  ListCell *element;
3239 
3240  newelems = NIL;
3241  foreach(element, arrayexpr->elements)
3242  {
3243  Node *e;
3244 
3245  e = eval_const_expressions_mutator((Node *) lfirst(element),
3246  context);
3247  if (!IsA(e, Const))
3248  all_const = false;
3249  newelems = lappend(newelems, e);
3250  }
3251 
3252  newarray = makeNode(ArrayExpr);
3253  newarray->array_typeid = arrayexpr->array_typeid;
3254  newarray->array_collid = arrayexpr->array_collid;
3255  newarray->element_typeid = arrayexpr->element_typeid;
3256  newarray->elements = newelems;
3257  newarray->multidims = arrayexpr->multidims;
3258  newarray->location = arrayexpr->location;
3259 
3260  if (all_const)
3261  return (Node *) evaluate_expr((Expr *) newarray,
3262  newarray->array_typeid,
3263  exprTypmod(node),
3264  newarray->array_collid);
3265 
3266  return (Node *) newarray;
3267  }
3268  case T_CoalesceExpr:
3269  {
3270  CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
3271  CoalesceExpr *newcoalesce;
3272  List *newargs;
3273  ListCell *arg;
3274 
3275  newargs = NIL;
3276  foreach(arg, coalesceexpr->args)
3277  {
3278  Node *e;
3279 
3281  context);
3282 
3283  /*
3284  * We can remove null constants from the list. For a
3285  * non-null constant, if it has not been preceded by any
3286  * other non-null-constant expressions then it is the
3287  * result. Otherwise, it's the next argument, but we can
3288  * drop following arguments since they will never be
3289  * reached.
3290  */
3291  if (IsA(e, Const))
3292  {
3293  if (((Const *) e)->constisnull)
3294  continue; /* drop null constant */
3295  if (newargs == NIL)
3296  return e; /* first expr */
3297  newargs = lappend(newargs, e);
3298  break;
3299  }
3300  newargs = lappend(newargs, e);
3301  }
3302 
3303  /*
3304  * If all the arguments were constant null, the result is just
3305  * null
3306  */
3307  if (newargs == NIL)
3308  return (Node *) makeNullConst(coalesceexpr->coalescetype,
3309  -1,
3310  coalesceexpr->coalescecollid);
3311 
3312  newcoalesce = makeNode(CoalesceExpr);
3313  newcoalesce->coalescetype = coalesceexpr->coalescetype;
3314  newcoalesce->coalescecollid = coalesceexpr->coalescecollid;
3315  newcoalesce->args = newargs;
3316  newcoalesce->location = coalesceexpr->location;
3317  return (Node *) newcoalesce;
3318  }
3319  case T_SQLValueFunction:
3320  {
3321  /*
3322  * All variants of SQLValueFunction are stable, so if we are
3323  * estimating the expression's value, we should evaluate the
3324  * current function value. Otherwise just copy.
3325  */
3326  SQLValueFunction *svf = (SQLValueFunction *) node;
3327 
3328  if (context->estimate)
3329  return (Node *) evaluate_expr((Expr *) svf,
3330  svf->type,
3331  svf->typmod,
3332  InvalidOid);
3333  else
3334  return copyObject((Node *) svf);
3335  }
3336  case T_FieldSelect:
3337  {
3338  /*
3339  * We can optimize field selection from a whole-row Var into a
3340  * simple Var. (This case won't be generated directly by the
3341  * parser, because ParseComplexProjection short-circuits it.
3342  * But it can arise while simplifying functions.) Also, we
3343  * can optimize field selection from a RowExpr construct.
3344  *
3345  * However, replacing a whole-row Var in this way has a
3346  * pitfall: if we've already built the rel targetlist for the
3347  * source relation, then the whole-row Var is scheduled to be
3348  * produced by the relation scan, but the simple Var probably
3349  * isn't, which will lead to a failure in setrefs.c. This is
3350  * not a problem when handling simple single-level queries, in
3351  * which expression simplification always happens first. It
3352  * is a risk for lateral references from subqueries, though.
3353  * To avoid such failures, don't optimize uplevel references.
3354  *
3355  * We must also check that the declared type of the field is
3356  * still the same as when the FieldSelect was created --- this
3357  * can change if someone did ALTER COLUMN TYPE on the rowtype.
3358  */
3359  FieldSelect *fselect = (FieldSelect *) node;
3360  FieldSelect *newfselect;
3361  Node *arg;
3362 
3363  arg = eval_const_expressions_mutator((Node *) fselect->arg,
3364  context);
3365  if (arg && IsA(arg, Var) &&
3366  ((Var *) arg)->varattno == InvalidAttrNumber &&
3367  ((Var *) arg)->varlevelsup == 0)
3368  {
3369  if (rowtype_field_matches(((Var *) arg)->vartype,
3370  fselect->fieldnum,
3371  fselect->resulttype,
3372  fselect->resulttypmod,
3373  fselect->resultcollid))
3374  return (Node *) makeVar(((Var *) arg)->varno,
3375  fselect->fieldnum,
3376  fselect->resulttype,
3377  fselect->resulttypmod,
3378  fselect->resultcollid,
3379  ((Var *) arg)->varlevelsup);
3380  }
3381  if (arg && IsA(arg, RowExpr))
3382  {
3383  RowExpr *rowexpr = (RowExpr *) arg;
3384 
3385  if (fselect->fieldnum > 0 &&
3386  fselect->fieldnum <= list_length(rowexpr->args))
3387  {
3388  Node *fld = (Node *) list_nth(rowexpr->args,
3389  fselect->fieldnum - 1);
3390 
3391  if (rowtype_field_matches(rowexpr->row_typeid,
3392  fselect->fieldnum,
3393  fselect->resulttype,
3394  fselect->resulttypmod,
3395  fselect->resultcollid) &&
3396  fselect->resulttype == exprType(fld) &&
3397  fselect->resulttypmod == exprTypmod(fld) &&
3398  fselect->resultcollid == exprCollation(fld))
3399  return fld;
3400  }
3401  }
3402  newfselect = makeNode(FieldSelect);
3403  newfselect->arg = (Expr *) arg;
3404  newfselect->fieldnum = fselect->fieldnum;
3405  newfselect->resulttype = fselect->resulttype;
3406  newfselect->resulttypmod = fselect->resulttypmod;
3407  newfselect->resultcollid = fselect->resultcollid;
3408  return (Node *) newfselect;
3409  }
3410  case T_NullTest:
3411  {
3412  NullTest *ntest = (NullTest *) node;
3413  NullTest *newntest;
3414  Node *arg;
3415 
3416  arg = eval_const_expressions_mutator((Node *) ntest->arg,
3417  context);
3418  if (ntest->argisrow && arg && IsA(arg, RowExpr))
3419  {
3420  /*
3421  * We break ROW(...) IS [NOT] NULL into separate tests on
3422  * its component fields. This form is usually more
3423  * efficient to evaluate, as well as being more amenable
3424  * to optimization.
3425  */
3426  RowExpr *rarg = (RowExpr *) arg;
3427  List *newargs = NIL;
3428  ListCell *l;
3429 
3430  foreach(l, rarg->args)
3431  {
3432  Node *relem = (Node *) lfirst(l);
3433 
3434  /*
3435  * A constant field refutes the whole NullTest if it's
3436  * of the wrong nullness; else we can discard it.
3437  */
3438  if (relem && IsA(relem, Const))
3439  {
3440  Const *carg = (Const *) relem;
3441 
3442  if (carg->constisnull ?
3443  (ntest->nulltesttype == IS_NOT_NULL) :
3444  (ntest->nulltesttype == IS_NULL))
3445  return makeBoolConst(false, false);
3446  continue;
3447  }
3448 
3449  /*
3450  * Else, make a scalar (argisrow == false) NullTest
3451  * for this field. Scalar semantics are required
3452  * because IS [NOT] NULL doesn't recurse; see comments
3453  * in ExecEvalRowNullInt().
3454  */
3455  newntest = makeNode(NullTest);
3456  newntest->arg = (Expr *) relem;
3457  newntest->nulltesttype = ntest->nulltesttype;
3458  newntest->argisrow = false;
3459  newntest->location = ntest->location;
3460  newargs = lappend(newargs, newntest);
3461  }
3462  /* If all the inputs were constants, result is TRUE */
3463  if (newargs == NIL)
3464  return makeBoolConst(true, false);
3465  /* If only one nonconst input, it's the result */
3466  if (list_length(newargs) == 1)
3467  return (Node *) linitial(newargs);
3468  /* Else we need an AND node */
3469  return (Node *) make_andclause(newargs);
3470  }
3471  if (!ntest->argisrow && arg && IsA(arg, Const))
3472  {
3473  Const *carg = (Const *) arg;
3474  bool result;
3475 
3476  switch (ntest->nulltesttype)
3477  {
3478  case IS_NULL:
3479  result = carg->constisnull;
3480  break;
3481  case IS_NOT_NULL:
3482  result = !carg->constisnull;
3483  break;
3484  default:
3485  elog(ERROR, "unrecognized nulltesttype: %d",
3486  (int) ntest->nulltesttype);
3487  result = false; /* keep compiler quiet */
3488  break;
3489  }
3490 
3491  return makeBoolConst(result, false);
3492  }
3493 
3494  newntest = makeNode(NullTest);
3495  newntest->arg = (Expr *) arg;
3496  newntest->nulltesttype = ntest->nulltesttype;
3497  newntest->argisrow = ntest->argisrow;
3498  newntest->location = ntest->location;
3499  return (Node *) newntest;
3500  }
3501  case T_BooleanTest:
3502  {
3503  BooleanTest *btest = (BooleanTest *) node;
3504  BooleanTest *newbtest;
3505  Node *arg;
3506 
3507  arg = eval_const_expressions_mutator((Node *) btest->arg,
3508  context);
3509  if (arg && IsA(arg, Const))
3510  {
3511  Const *carg = (Const *) arg;
3512  bool result;
3513 
3514  switch (btest->booltesttype)
3515  {
3516  case IS_TRUE:
3517  result = (!carg->constisnull &&
3518  DatumGetBool(carg->constvalue));
3519  break;
3520  case IS_NOT_TRUE:
3521  result = (carg->constisnull ||
3522  !DatumGetBool(carg->constvalue));
3523  break;
3524  case IS_FALSE:
3525  result = (!carg->constisnull &&
3526  !DatumGetBool(carg->constvalue));
3527  break;
3528  case IS_NOT_FALSE:
3529  result = (carg->constisnull ||
3530  DatumGetBool(carg->constvalue));
3531  break;
3532  case IS_UNKNOWN:
3533  result = carg->constisnull;
3534  break;
3535  case IS_NOT_UNKNOWN:
3536  result = !carg->constisnull;
3537  break;
3538  default:
3539  elog(ERROR, "unrecognized booltesttype: %d",
3540  (int) btest->booltesttype);
3541  result = false; /* keep compiler quiet */
3542  break;
3543  }
3544 
3545  return makeBoolConst(result, false);
3546  }
3547 
3548  newbtest = makeNode(BooleanTest);
3549  newbtest->arg = (Expr *) arg;
3550  newbtest->booltesttype = btest->booltesttype;
3551  newbtest->location = btest->location;
3552  return (Node *) newbtest;
3553  }
3554  case T_PlaceHolderVar:
3555 
3556  /*
3557  * In estimation mode, just strip the PlaceHolderVar node
3558  * altogether; this amounts to estimating that the contained value
3559  * won't be forced to null by an outer join. In regular mode we
3560  * just use the default behavior (ie, simplify the expression but
3561  * leave the PlaceHolderVar node intact).
3562  */
3563  if (context->estimate)
3564  {
3565  PlaceHolderVar *phv = (PlaceHolderVar *) node;
3566 
3567  return eval_const_expressions_mutator((Node *) phv->phexpr,
3568  context);
3569  }
3570  break;
3571  default:
3572  break;
3573  }
3574 
3575  /*
3576  * For any node type not handled above, we recurse using
3577  * expression_tree_mutator, which will copy the node unchanged but try to
3578  * simplify its arguments (if any) using this routine. For example: we
3579  * cannot eliminate an ArrayRef node, but we might be able to simplify
3580  * constant expressions in its subscripts.
3581  */
3582  return expression_tree_mutator(node, eval_const_expressions_mutator,
3583  (void *) context);
3584 }
Datum constvalue
Definition: primnodes.h:196
#define list_make3(x1, x2, x3)
Definition: pg_list.h:141
signed short int16
Definition: c.h:245
Oid funcresulttype
Definition: primnodes.h:450
bool multidims
Definition: primnodes.h:956
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:76
#define NIL
Definition: pg_list.h:69
Datum value
Definition: params.h:56
List * args
Definition: primnodes.h:986
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
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:3887
Node * negate_clause(Node *node)
Definition: prepqual.c:73
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2410
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2632
static Expr * evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
Definition: clauses.c:4704
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5533
List * args
Definition: primnodes.h:359
List * args
Definition: primnodes.h:457
Oid wincollid
Definition: primnodes.h:357
Oid resulttype
Definition: primnodes.h:744
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
#define OIDOID
Definition: pg_type.h:328
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
Oid funccollid
Definition: primnodes.h:455
Oid resulttype
Definition: primnodes.h:812
Oid casecollid
Definition: primnodes.h:907
Expr * arg
Definition: primnodes.h:791
#define INT4OID
Definition: pg_type.h:316
ParamKind paramkind
Definition: primnodes.h:244
Definition: nodes.h:509
Oid array_typeid
Definition: primnodes.h:952
Expr * arg
Definition: primnodes.h:742
bool funcretset
Definition: primnodes.h:451
Oid casetype
Definition: primnodes.h:906
unsigned int Oid
Definition: postgres_ext.h:31
Index winref
Definition: primnodes.h:361
Definition: primnodes.h:163
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:296
#define OidIsValid(objectId)
Definition: c.h:532
#define BooleanEqualOperator
Definition: pg_operator.h:114
int location
Definition: primnodes.h:922
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:159
signed int int32
Definition: c.h:246
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:334
#define list_make1(x1)
Definition: pg_list.h:139
Oid consttype
Definition: primnodes.h:192
CoercionForm funcformat
Definition: primnodes.h:454
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2468
Oid opresulttype
Definition: primnodes.h:498
ParamListInfo boundParams
Definition: clauses.c:65
#define linitial(l)
Definition: pg_list.h:111
Oid funcid
Definition: primnodes.h:449
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Expr * phexpr
Definition: relation.h:1906
static bool rowtype_field_matches(Oid rowtypeid, int fieldnum, Oid expectedtype, int32 expectedtypmod, Oid expectedcollation)
Definition: clauses.c:2353
Oid paramcollid
Definition: primnodes.h:248
List * args
Definition: primnodes.h:1047
BoolExprType boolop
Definition: primnodes.h:562
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:354
Expr * arg
Definition: primnodes.h:1180
Oid constcollid
Definition: primnodes.h:194
Oid resultcollid
Definition: primnodes.h:747
#define lfirst_node(type, lc)
Definition: pg_list.h:109
struct Const Const
void * list_nth(const List *list, int n)
Definition: list.c:410
int location
Definition: primnodes.h:503
Expr * arg
Definition: primnodes.h:1203
#define DatumGetBool(X)
Definition: postgres.h:399
Oid winfnoid
Definition: primnodes.h:355
Expr * arg
Definition: primnodes.h:811
List * elements
Definition: primnodes.h:955
static List * expand_function_arguments(List *args, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:3984
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2599
Oid opcollid
Definition: primnodes.h:500
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:67
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
List * lappend(List *list, void *datum)
Definition: list.c:128
#define BooleanNotEqualOperator
Definition: pg_operator.h:111
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
List * args
Definition: primnodes.h:909
CoercionForm coerceformat
Definition: primnodes.h:840
int location
Definition: primnodes.h:957
BoolTestType booltesttype
Definition: primnodes.h:1204
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Oid resultcollid
Definition: primnodes.h:814
Oid opfuncid
Definition: primnodes.h:497
Oid resulttype
Definition: primnodes.h:792
NullTestType nulltesttype
Definition: primnodes.h:1181
#define BoolGetDatum(X)
Definition: postgres.h:408
Oid resultcollid
Definition: primnodes.h:794
#define InvalidOid
Definition: postgres_ext.h:36
int32 paramtypmod
Definition: primnodes.h:247
#define makeNode(_type_)
Definition: nodes.h:557
static Node * simplify_boolean_equality(Oid opno, List *args)
Definition: clauses.c:3818
int location
Definition: primnodes.h:816
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
int location
Definition: primnodes.h:364
Oid inputcollid
Definition: primnodes.h:456
#define CSTRINGOID
Definition: pg_type.h:684
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
Expr * aggfilter
Definition: primnodes.h:360
int paramid
Definition: primnodes.h:245
Oid array_collid
Definition: primnodes.h:953
uint16 pflags
Definition: params.h:58
int location
Definition: primnodes.h:1183
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static List * simplify_and_arguments(List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceFalse)
Definition: clauses.c:3718
Oid row_typeid
Definition: primnodes.h:987
static int list_length(const List *l)
Definition: pg_list.h:89
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
Expr * arg
Definition: primnodes.h:876
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2001
int location
Definition: primnodes.h:911
Oid inputcollid
Definition: primnodes.h:501
Oid inputcollid
Definition: primnodes.h:358
List * args
Definition: primnodes.h:563
#define InvalidAttrNumber
Definition: attnum.h:23
#define nodeTag(nodeptr)
Definition: nodes.h:514
int32 consttypmod
Definition: primnodes.h:193
Oid element_typeid
Definition: primnodes.h:954
Oid wintype
Definition: primnodes.h:356
CoercionForm coerceformat
Definition: primnodes.h:815
static List * simplify_or_arguments(List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceTrue)
Definition: clauses.c:3606
#define Int32GetDatum(X)
Definition: postgres.h:485
e
Definition: preproc-init.c:82
char func_volatile(Oid funcid)
Definition: lsyscache.c:1584
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1613
bool winagg
Definition: primnodes.h:363
Oid coalescetype
Definition: primnodes.h:1045
void * arg
bool argisrow
Definition: primnodes.h:1182
Expr * make_andclause(List *andclauses)
Definition: clauses.c:327
int32 resulttypmod
Definition: primnodes.h:793
Expr * arg
Definition: primnodes.h:908
int location
Definition: primnodes.h:458
Oid opno
Definition: primnodes.h:496
int32 resulttypmod
Definition: primnodes.h:837
#define elog
Definition: elog.h:219
Expr * result
Definition: primnodes.h:921
#define copyObject(obj)
Definition: nodes.h:622
List * args
Definition: primnodes.h:502
CoercionForm relabelformat
Definition: primnodes.h:795
Expr * defresult
Definition: primnodes.h:910
Expr * expr
Definition: primnodes.h:920
int location
Definition: primnodes.h:878
Definition: pg_list.h:45
bool isnull
Definition: params.h:57
Expr * make_orclause(List *orclauses)
Definition: clauses.c:293
Oid paramtype
Definition: primnodes.h:246
int location
Definition: primnodes.h:796
bool constisnull
Definition: primnodes.h:197
Oid coalescecollid
Definition: primnodes.h:1046
bool funcvariadic
Definition: primnodes.h:452
#define PARAM_FLAG_CONST
Definition: params.h:52
bool opretset
Definition: primnodes.h:499
int32 resulttypmod
Definition: primnodes.h:746
bool winstar
Definition: primnodes.h:362
Definition: nodes.h:148
AttrNumber fieldnum
Definition: primnodes.h:743
static Expr * evaluate_expr ( Expr expr,
Oid  result_type,
int32  result_typmod,
Oid  result_collation 
)
static

Definition at line 4704 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(), and evaluate_function().

4706 {
4707  EState *estate;
4708  ExprState *exprstate;
4709  MemoryContext oldcontext;
4710  Datum const_val;
4711  bool const_is_null;
4712  int16 resultTypLen;
4713  bool resultTypByVal;
4714 
4715  /*
4716  * To use the executor, we need an EState.
4717  */
4718  estate = CreateExecutorState();
4719 
4720  /* We can use the estate's working context to avoid memory leaks. */
4721  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
4722 
4723  /* Make sure any opfuncids are filled in. */
4724  fix_opfuncids((Node *) expr);
4725 
4726  /*
4727  * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
4728  * because it'd result in recursively invoking eval_const_expressions.)
4729  */
4730  exprstate = ExecInitExpr(expr, NULL);
4731 
4732  /*
4733  * And evaluate it.
4734  *
4735  * It is OK to use a default econtext because none of the ExecEvalExpr()
4736  * code used in this situation will use econtext. That might seem
4737  * fortuitous, but it's not so unreasonable --- a constant expression does
4738  * not depend on context, by definition, n'est ce pas?
4739  */
4740  const_val = ExecEvalExprSwitchContext(exprstate,
4741  GetPerTupleExprContext(estate),
4742  &const_is_null);
4743 
4744  /* Get info needed about result datatype */
4745  get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
4746 
4747  /* Get back to outer memory context */
4748  MemoryContextSwitchTo(oldcontext);
4749 
4750  /*
4751  * Must copy result out of sub-context used by expression eval.
4752  *
4753  * Also, if it's varlena, forcibly detoast it. This protects us against
4754  * storing TOAST pointers into plans that might outlive the referenced
4755  * data. (makeConst would handle detoasting anyway, but it's worth a few
4756  * extra lines here so that we can do the copy and detoast in one step.)
4757  */
4758  if (!const_is_null)
4759  {
4760  if (resultTypLen == -1)
4761  const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
4762  else
4763  const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
4764  }
4765 
4766  /* Release all the junk we just created */
4767  FreeExecutorState(estate);
4768 
4769  /*
4770  * Make the constant result node.
4771  */
4772  return (Expr *) makeConst(result_type, result_typmod, result_collation,
4773  resultTypLen,
4774  const_val, const_is_null,
4775  resultTypByVal);
4776 }
signed short int16
Definition: c.h:245
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:301
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:207
#define PointerGetDatum(X)
Definition: postgres.h:562
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1582
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:509
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:296
void FreeExecutorState(EState *estate)
Definition: execUtils.c:183
#define GetPerTupleExprContext(estate)
Definition: executor.h:476
MemoryContext es_query_cxt
Definition: execnodes.h:471
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
EState * CreateExecutorState(void)
Definition: execUtils.c:80
uintptr_t Datum
Definition: postgres.h:372
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2001
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:113
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 4201 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, makeNullConst(), PROVOLATILE_IMMUTABLE, PROVOLATILE_STABLE, and RECORDOID.

Referenced by simplify_function().

4206 {
4207  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4208  bool has_nonconst_input = false;
4209  bool has_null_input = false;
4210  ListCell *arg;
4211  FuncExpr *newexpr;
4212 
4213  /*
4214  * Can't simplify if it returns a set.
4215  */
4216  if (funcform->proretset)
4217  return NULL;
4218 
4219  /*
4220  * Can't simplify if it returns RECORD. The immediate problem is that it
4221  * will be needing an expected tupdesc which we can't supply here.
4222  *
4223  * In the case where it has OUT parameters, it could get by without an
4224  * expected tupdesc, but we still have issues: get_expr_result_type()
4225  * doesn't know how to extract type info from a RECORD constant, and in
4226  * the case of a NULL function result there doesn't seem to be any clean
4227  * way to fix that. In view of the likelihood of there being still other
4228  * gotchas, seems best to leave the function call unreduced.
4229  */
4230  if (funcform->prorettype == RECORDOID)
4231  return NULL;
4232 
4233  /*
4234  * Check for constant inputs and especially constant-NULL inputs.
4235  */
4236  foreach(arg, args)
4237  {
4238  if (IsA(lfirst(arg), Const))
4239  has_null_input |= ((Const *) lfirst(arg))->constisnull;
4240  else
4241  has_nonconst_input = true;
4242  }
4243 
4244  /*
4245  * If the function is strict and has a constant-NULL input, it will never
4246  * be called at all, so we can replace the call by a NULL constant, even
4247  * if there are other inputs that aren't constant, and even if the
4248  * function is not otherwise immutable.
4249  */
4250  if (funcform->proisstrict && has_null_input)
4251  return (Expr *) makeNullConst(result_type, result_typmod,
4252  result_collid);
4253 
4254  /*
4255  * Otherwise, can simplify only if all inputs are constants. (For a
4256  * non-strict function, constant NULL inputs are treated the same as
4257  * constant non-NULL inputs.)
4258  */
4259  if (has_nonconst_input)
4260  return NULL;
4261 
4262  /*
4263  * Ordinarily we are only allowed to simplify immutable functions. But for
4264  * purposes of estimation, we consider it okay to simplify functions that
4265  * are merely stable; the risk that the result might change from planning
4266  * time to execution time is worth taking in preference to not being able
4267  * to estimate the value at all.
4268  */
4269  if (funcform->provolatile == PROVOLATILE_IMMUTABLE)
4270  /* okay */ ;
4271  else if (context->estimate && funcform->provolatile == PROVOLATILE_STABLE)
4272  /* okay */ ;
4273  else
4274  return NULL;
4275 
4276  /*
4277  * OK, looks like we can simplify this operator/function.
4278  *
4279  * Build a new FuncExpr node containing the already-simplified arguments.
4280  */
4281  newexpr = makeNode(FuncExpr);
4282  newexpr->funcid = funcid;
4283  newexpr->funcresulttype = result_type;
4284  newexpr->funcretset = false;
4285  newexpr->funcvariadic = funcvariadic;
4286  newexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
4287  newexpr->funccollid = result_collid; /* doesn't matter */
4288  newexpr->inputcollid = input_collid;
4289  newexpr->args = args;
4290  newexpr->location = -1;
4291 
4292  return evaluate_expr((Expr *) newexpr, result_type, result_typmod,
4293  result_collid);
4294 }
Oid funcresulttype
Definition: primnodes.h:450
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static Expr * evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
Definition: clauses.c:4704
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5533
List * args
Definition: primnodes.h:457
Oid funccollid
Definition: primnodes.h:455
bool funcretset
Definition: primnodes.h:451
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:334
CoercionForm funcformat
Definition: primnodes.h:454
Oid funcid
Definition: primnodes.h:449
#define PROVOLATILE_STABLE
Definition: pg_proc.h:5534
#define RECORDOID
Definition: pg_type.h:680
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define makeNode(_type_)
Definition: nodes.h:557
Oid inputcollid
Definition: primnodes.h:456
#define lfirst(lc)
Definition: pg_list.h:106
void * arg
int location
Definition: primnodes.h:458
bool funcvariadic
Definition: primnodes.h:452
static List * expand_function_arguments ( List args,
Oid  result_type,
HeapTuple  func_tuple 
)
static

Definition at line 3984 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(), and simplify_function().

3985 {
3986  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
3987  bool has_named_args = false;
3988  ListCell *lc;
3989 
3990  /* Do we have any named arguments? */
3991  foreach(lc, args)
3992  {
3993  Node *arg = (Node *) lfirst(lc);
3994 
3995  if (IsA(arg, NamedArgExpr))
3996  {
3997  has_named_args = true;
3998  break;
3999  }
4000  }
4001 
4002  /* If so, we must apply reorder_function_arguments */
4003  if (has_named_args)
4004  {
4005  args = reorder_function_arguments(args, func_tuple);
4006  /* Recheck argument types and add casts if needed */
4007  recheck_cast_function_args(args, result_type, func_tuple);
4008  }
4009  else if (list_length(args) < funcform->pronargs)
4010  {
4011  /* No named args, but we seem to be short some defaults */
4012  args = add_function_defaults(args, func_tuple);
4013  /* Recheck argument types and add casts if needed */
4014  recheck_cast_function_args(args, result_type, func_tuple);
4015  }
4016 
4017  return args;
4018 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Definition: nodes.h:509
static void recheck_cast_function_args(List *args, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:4157
static List * add_function_defaults(List *args, HeapTuple func_tuple)
Definition: clauses.c:4097
static List * reorder_function_arguments(List *args, HeapTuple func_tuple)
Definition: clauses.c:4027
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
void * arg
double expression_returns_set_rows ( Node clause)

Definition at line 802 of file clauses.c.

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

Referenced by create_set_projection_path(), and set_function_size_estimates().

803 {
804  if (clause == NULL)
805  return 1.0;
806  if (IsA(clause, FuncExpr))
807  {
808  FuncExpr *expr = (FuncExpr *) clause;
809 
810  if (expr->funcretset)
811  return clamp_row_est(get_func_rows(expr->funcid));
812  }
813  if (IsA(clause, OpExpr))
814  {
815  OpExpr *expr = (OpExpr *) clause;
816 
817  if (expr->opretset)
818  {
819  set_opfuncid(expr);
820  return clamp_row_est(get_func_rows(expr->opfuncid));
821  }
822  }
823  return 1.0;
824 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
float4 get_func_rows(Oid funcid)
Definition: lsyscache.c:1660
bool funcretset
Definition: primnodes.h:451
Oid funcid
Definition: primnodes.h:449
Oid opfuncid
Definition: primnodes.h:497
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1613
double clamp_row_est(double nrows)
Definition: costsize.c:173
bool opretset
Definition: primnodes.h:499
static List * fetch_function_defaults ( HeapTuple  func_tuple)
static

Definition at line 4122 of file clauses.c.

References Anum_pg_proc_proargdefaults, castNode, elog, ERROR, pfree(), PROCOID, stringToNode(), SysCacheGetAttr(), and TextDatumGetCString.

Referenced by add_function_defaults(), and reorder_function_arguments().

4123 {
4124  List *defaults;
4125  Datum proargdefaults;
4126  bool isnull;
4127  char *str;
4128 
4129  /* The error cases here shouldn't happen, but check anyway */
4130  proargdefaults = SysCacheGetAttr(PROCOID, func_tuple,
4132  &isnull);
4133  if (isnull)
4134  elog(ERROR, "not enough default arguments");
4135  str = TextDatumGetCString(proargdefaults);
4136  defaults = castNode(List, stringToNode(str));
4137  pfree(str);
4138  return defaults;
4139 }
void * stringToNode(char *str)
Definition: read.c:38
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
#define Anum_pg_proc_proargdefaults
Definition: pg_proc.h:113
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1325
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Var* find_forced_null_var ( Node node)

Definition at line 2086 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().

2087 {
2088  if (node == NULL)
2089  return NULL;
2090  if (IsA(node, NullTest))
2091  {
2092  /* check for var IS NULL */
2093  NullTest *expr = (NullTest *) node;
2094 
2095  if (expr->nulltesttype == IS_NULL && !expr->argisrow)
2096  {
2097  Var *var = (Var *) expr->arg;
2098 
2099  if (var && IsA(var, Var) &&
2100  var->varlevelsup == 0)
2101  return var;
2102  }
2103  }
2104  else if (IsA(node, BooleanTest))
2105  {
2106  /* var IS UNKNOWN is equivalent to var IS NULL */
2107  BooleanTest *expr = (BooleanTest *) node;
2108 
2109  if (expr->booltesttype == IS_UNKNOWN)
2110  {
2111  Var *var = (Var *) expr->arg;
2112 
2113  if (var && IsA(var, Var) &&
2114  var->varlevelsup == 0)
2115  return var;
2116  }
2117  }
2118  return NULL;
2119 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Index varlevelsup
Definition: primnodes.h:173
Definition: primnodes.h:163
Expr * arg
Definition: primnodes.h:1180
Expr * arg
Definition: primnodes.h:1203
BoolTestType booltesttype
Definition: primnodes.h:1204
NullTestType nulltesttype
Definition: primnodes.h:1181
bool argisrow
Definition: primnodes.h:1182
List* find_forced_null_vars ( Node node)

Definition at line 2027 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().

2028 {
2029  List *result = NIL;
2030  Var *var;
2031  ListCell *l;
2032 
2033  if (node == NULL)
2034  return NIL;
2035  /* Check single-clause cases using subroutine */
2036  var = find_forced_null_var(node);
2037  if (var)
2038  {
2039  result = list_make1(var);
2040  }
2041  /* Otherwise, handle AND-conditions */
2042  else if (IsA(node, List))
2043  {
2044  /*
2045  * At top level, we are examining an implicit-AND list: if any of the
2046  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
2047  */
2048  foreach(l, (List *) node)
2049  {
2050  result = list_concat(result,
2052  }
2053  }
2054  else if (IsA(node, BoolExpr))
2055  {
2056  BoolExpr *expr = (BoolExpr *) node;
2057 
2058  /*
2059  * We don't bother considering the OR case, because it's fairly
2060  * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
2061  * the NOT case isn't worth expending code on.
2062  */
2063  if (expr->boolop == AND_EXPR)
2064  {
2065  /* At top level we can just recurse (to the List case) */
2066  result = find_forced_null_vars((Node *) expr->args);
2067  }
2068  }
2069  return result;
2070 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Definition: nodes.h:509
List * list_concat(List *list1, List *list2)
Definition: list.c:321
Definition: primnodes.h:163
List * find_forced_null_vars(Node *node)
Definition: clauses.c:2027
#define list_make1(x1)
Definition: pg_list.h:139
BoolExprType boolop
Definition: primnodes.h:562
#define lfirst(lc)
Definition: pg_list.h:106
List * args
Definition: primnodes.h:563
Definition: pg_list.h:45
Var * find_forced_null_var(Node *node)
Definition: clauses.c:2086
Relids find_nonnullable_rels ( Node clause)

Definition at line 1626 of file clauses.c.

References find_nonnullable_rels_walker().

Referenced by make_outerjoininfo(), and reduce_outer_joins_pass2().

1627 {
1628  return find_nonnullable_rels_walker(clause, true);
1629 }
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1632
static Relids find_nonnullable_rels_walker ( Node node,
bool  top_level 
)
static

Definition at line 1632 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_int_members(), bms_is_empty(), bms_join(), bms_make_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, set_opfuncid(), Var::varlevelsup, and Var::varno.

Referenced by find_nonnullable_rels().

1633 {
1634  Relids result = NULL;
1635  ListCell *l;
1636 
1637  if (node == NULL)
1638  return NULL;
1639  if (IsA(node, Var))
1640  {
1641  Var *var = (Var *) node;
1642 
1643  if (var->varlevelsup == 0)
1644  result = bms_make_singleton(var->varno);
1645  }
1646  else if (IsA(node, List))
1647  {
1648  /*
1649  * At top level, we are examining an implicit-AND list: if any of the
1650  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1651  * not at top level, we are examining the arguments of a strict
1652  * function: if any of them produce NULL then the result of the
1653  * function must be NULL. So in both cases, the set of nonnullable
1654  * rels is the union of those found in the arms, and we pass down the
1655  * top_level flag unmodified.
1656  */
1657  foreach(l, (List *) node)
1658  {
1659  result = bms_join(result,
1661  top_level));
1662  }
1663  }
1664  else if (IsA(node, FuncExpr))
1665  {
1666  FuncExpr *expr = (FuncExpr *) node;
1667 
1668  if (func_strict(expr->funcid))
1669  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1670  }
1671  else if (IsA(node, OpExpr))
1672  {
1673  OpExpr *expr = (OpExpr *) node;
1674 
1675  set_opfuncid(expr);
1676  if (func_strict(expr->opfuncid))
1677  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1678  }
1679  else if (IsA(node, ScalarArrayOpExpr))
1680  {
1681  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1682 
1683  if (is_strict_saop(expr, true))
1684  result = find_nonnullable_rels_walker((Node *) expr->args, false);
1685  }
1686  else if (IsA(node, BoolExpr))
1687  {
1688  BoolExpr *expr = (BoolExpr *) node;
1689 
1690  switch (expr->boolop)
1691  {
1692  case AND_EXPR:
1693  /* At top level we can just recurse (to the List case) */
1694  if (top_level)
1695  {
1696  result = find_nonnullable_rels_walker((Node *) expr->args,
1697  top_level);
1698  break;
1699  }
1700 
1701  /*
1702  * Below top level, even if one arm produces NULL, the result
1703  * could be FALSE (hence not NULL). However, if *all* the
1704  * arms produce NULL then the result is NULL, so we can take
1705  * the intersection of the sets of nonnullable rels, just as
1706  * for OR. Fall through to share code.
1707  */
1708  /* FALL THRU */
1709  case OR_EXPR:
1710 
1711  /*
1712  * OR is strict if all of its arms are, so we can take the
1713  * intersection of the sets of nonnullable rels for each arm.
1714  * This works for both values of top_level.
1715  */
1716  foreach(l, expr->args)
1717  {
1718  Relids subresult;
1719 
1720  subresult = find_nonnullable_rels_walker(lfirst(l),
1721  top_level);
1722  if (result == NULL) /* first subresult? */
1723  result = subresult;
1724  else
1725  result = bms_int_members(result, subresult);
1726 
1727  /*
1728  * If the intersection is empty, we can stop looking. This
1729  * also justifies the test for first-subresult above.
1730  */
1731  if (bms_is_empty(result))
1732  break;
1733  }
1734  break;
1735  case NOT_EXPR:
1736  /* NOT will return null if its arg is null */
1737  result = find_nonnullable_rels_walker((Node *) expr->args,
1738  false);
1739  break;
1740  default:
1741  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1742  break;
1743  }
1744  }
1745  else if (IsA(node, RelabelType))
1746  {
1747  RelabelType *expr = (RelabelType *) node;
1748 
1749  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1750  }
1751  else if (IsA(node, CoerceViaIO))
1752  {
1753  /* not clear this is useful, but it can't hurt */
1754  CoerceViaIO *expr = (CoerceViaIO *) node;
1755 
1756  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1757  }
1758  else if (IsA(node, ArrayCoerceExpr))
1759  {
1760  /* ArrayCoerceExpr is strict at the array level */
1761  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1762 
1763  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1764  }
1765  else if (IsA(node, ConvertRowtypeExpr))
1766  {
1767  /* not clear this is useful, but it can't hurt */
1768  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1769 
1770  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1771  }
1772  else if (IsA(node, CollateExpr))
1773  {
1774  CollateExpr *expr = (CollateExpr *) node;
1775 
1776  result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1777  }
1778  else if (IsA(node, NullTest))
1779  {
1780  /* IS NOT NULL can be considered strict, but only at top level */
1781  NullTest *expr = (NullTest *) node;
1782 
1783  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1784  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1785  }
1786  else if (IsA(node, BooleanTest))
1787  {
1788  /* Boolean tests that reject NULL are strict at top level */
1789  BooleanTest *expr = (BooleanTest *) node;
1790 
1791  if (top_level &&
1792  (expr->booltesttype == IS_TRUE ||
1793  expr->booltesttype == IS_FALSE ||
1794  expr->booltesttype == IS_NOT_UNKNOWN))
1795  result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1796  }
1797  else if (IsA(node, PlaceHolderVar))
1798  {
1799  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1800 
1801  result = find_nonnullable_rels_walker((Node *) phv->phexpr, top_level);
1802  }
1803  return result;
1804 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Index varlevelsup
Definition: primnodes.h:173
List * args
Definition: primnodes.h:457
Expr * arg
Definition: primnodes.h:791
Definition: nodes.h:509
Definition: primnodes.h:163
Oid funcid
Definition: primnodes.h:449
#define ERROR
Definition: elog.h:43
Expr * phexpr
Definition: relation.h:1906
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:838
BoolExprType boolop
Definition: primnodes.h:562
Expr * arg
Definition: primnodes.h:1180
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:179
Expr * arg
Definition: primnodes.h:1203
Expr * arg
Definition: primnodes.h:811
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
Index varno
Definition: primnodes.h:166
BoolTestType booltesttype
Definition: primnodes.h:1204
Oid opfuncid
Definition: primnodes.h:497
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1632
NullTestType nulltesttype
Definition: primnodes.h:1181
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition: clauses.c:2135
#define lfirst(lc)
Definition: pg_list.h:106
Expr * arg
Definition: primnodes.h:876
List * args
Definition: primnodes.h:563
bool func_strict(Oid funcid)
Definition: lsyscache.c:1565
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1613
bool argisrow
Definition: primnodes.h:1182
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:502
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:791
Definition: pg_list.h:45
List* find_nonnullable_vars ( Node clause)

Definition at line 1834 of file clauses.c.

References find_nonnullable_vars_walker().

Referenced by reduce_outer_joins_pass2().

1835 {
1836  return find_nonnullable_vars_walker(clause, true);
1837 }
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1840
static List * find_nonnullable_vars_walker ( Node node,
bool  top_level 
)
static

Definition at line 1840 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().

1841 {
1842  List *result = NIL;
1843  ListCell *l;
1844 
1845  if (node == NULL)
1846  return NIL;
1847  if (IsA(node, Var))
1848  {
1849  Var *var = (Var *) node;
1850 
1851  if (var->varlevelsup == 0)
1852  result = list_make1(var);
1853  }
1854  else if (IsA(node, List))
1855  {
1856  /*
1857  * At top level, we are examining an implicit-AND list: if any of the
1858  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1859  * not at top level, we are examining the arguments of a strict
1860  * function: if any of them produce NULL then the result of the
1861  * function must be NULL. So in both cases, the set of nonnullable
1862  * vars is the union of those found in the arms, and we pass down the
1863  * top_level flag unmodified.
1864  */
1865  foreach(l, (List *) node)
1866  {
1867  result = list_concat(result,
1869  top_level));
1870  }
1871  }
1872  else if (IsA(node, FuncExpr))
1873  {
1874  FuncExpr *expr = (FuncExpr *) node;
1875 
1876  if (func_strict(expr->funcid))
1877  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1878  }
1879  else if (IsA(node, OpExpr))
1880  {
1881  OpExpr *expr = (OpExpr *) node;
1882 
1883  set_opfuncid(expr);
1884  if (func_strict(expr->opfuncid))
1885  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1886  }
1887  else if (IsA(node, ScalarArrayOpExpr))
1888  {
1889  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1890 
1891  if (is_strict_saop(expr, true))
1892  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1893  }
1894  else if (IsA(node, BoolExpr))
1895  {
1896  BoolExpr *expr = (BoolExpr *) node;
1897 
1898  switch (expr->boolop)
1899  {
1900  case AND_EXPR:
1901  /* At top level we can just recurse (to the List case) */
1902  if (top_level)
1903  {
1904  result = find_nonnullable_vars_walker((Node *) expr->args,
1905  top_level);
1906  break;
1907  }
1908 
1909  /*
1910  * Below top level, even if one arm produces NULL, the result
1911  * could be FALSE (hence not NULL). However, if *all* the
1912  * arms produce NULL then the result is NULL, so we can take
1913  * the intersection of the sets of nonnullable vars, just as
1914  * for OR. Fall through to share code.
1915  */
1916  /* FALL THRU */
1917  case OR_EXPR:
1918 
1919  /*
1920  * OR is strict if all of its arms are, so we can take the
1921  * intersection of the sets of nonnullable vars for each arm.
1922  * This works for both values of top_level.
1923  */
1924  foreach(l, expr->args)
1925  {
1926  List *subresult;
1927 
1928  subresult = find_nonnullable_vars_walker(lfirst(l),
1929  top_level);
1930  if (result == NIL) /* first subresult? */
1931  result = subresult;
1932  else
1933  result = list_intersection(result, subresult);
1934 
1935  /*
1936  * If the intersection is empty, we can stop looking. This
1937  * also justifies the test for first-subresult above.
1938  */
1939  if (result == NIL)
1940  break;
1941  }
1942  break;
1943  case NOT_EXPR:
1944  /* NOT will return null if its arg is null */
1945  result = find_nonnullable_vars_walker((Node *) expr->args,
1946  false);
1947  break;
1948  default:
1949  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1950  break;
1951  }
1952  }
1953  else if (IsA(node, RelabelType))
1954  {
1955  RelabelType *expr = (RelabelType *) node;
1956 
1957  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1958  }
1959  else if (IsA(node, CoerceViaIO))
1960  {
1961  /* not clear this is useful, but it can't hurt */
1962  CoerceViaIO *expr = (CoerceViaIO *) node;
1963 
1964  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1965  }
1966  else if (IsA(node, ArrayCoerceExpr))
1967  {
1968  /* ArrayCoerceExpr is strict at the array level */
1969  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1970 
1971  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1972  }
1973  else if (IsA(node, ConvertRowtypeExpr))
1974  {
1975  /* not clear this is useful, but it can't hurt */
1976  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1977 
1978  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1979  }
1980  else if (IsA(node, CollateExpr))
1981  {
1982  CollateExpr *expr = (CollateExpr *) node;
1983 
1984  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1985  }
1986  else if (IsA(node, NullTest))
1987  {
1988  /* IS NOT NULL can be considered strict, but only at top level */
1989  NullTest *expr = (NullTest *) node;
1990 
1991  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1992  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1993  }
1994  else if (IsA(node, BooleanTest))
1995  {
1996  /* Boolean tests that reject NULL are strict at top level */
1997  BooleanTest *expr = (BooleanTest *) node;
1998 
1999  if (top_level &&
2000  (expr->booltesttype == IS_TRUE ||
2001  expr->booltesttype == IS_FALSE ||
2002  expr->booltesttype == IS_NOT_UNKNOWN))
2003  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
2004  }
2005  else if (IsA(node, PlaceHolderVar))
2006  {
2007  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2008 
2009  result = find_nonnullable_vars_walker((Node *) phv->phexpr, top_level);
2010  }
2011  return result;
2012 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Index varlevelsup
Definition: primnodes.h:173
List * args
Definition: primnodes.h:457
Expr * arg
Definition: primnodes.h:791
Definition: nodes.h:509
List * list_concat(List *list1, List *list2)
Definition: list.c:321
Definition: primnodes.h:163
#define list_make1(x1)
Definition: pg_list.h:139
Oid funcid
Definition: primnodes.h:449
#define ERROR
Definition: elog.h:43
Expr * phexpr
Definition: relation.h:1906
BoolExprType boolop
Definition: primnodes.h:562
Expr * arg
Definition: primnodes.h:1180
Expr * arg
Definition: primnodes.h:1203
List * list_intersection(const List *list1, const List *list2)
Definition: list.c:800
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1840
Expr * arg
Definition: primnodes.h:811
BoolTestType booltesttype
Definition: primnodes.h:1204
Oid opfuncid
Definition: primnodes.h:497
NullTestType nulltesttype
Definition: primnodes.h:1181
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition: clauses.c:2135
#define lfirst(lc)
Definition: pg_list.h:106
Expr * arg
Definition: primnodes.h:876
List * args
Definition: primnodes.h:563
bool func_strict(Oid funcid)
Definition: lsyscache.c:1565
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1613
bool argisrow
Definition: primnodes.h:1182
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:502
Definition: pg_list.h:45
WindowFuncLists* find_window_functions ( Node clause,
Index  maxWinRef 
)

Definition at line 740 of file clauses.c.

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

Referenced by grouping_planner().

741 {
742  WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
743 
744  lists->numWindowFuncs = 0;
745  lists->maxWinRef = maxWinRef;
746  lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
747  (void) find_window_functions_walker(clause, lists);
748  return lists;
749 }
Index maxWinRef
Definition: clauses.h:26
int numWindowFuncs
Definition: clauses.h:25
void * palloc0(Size size)
Definition: mcxt.c:877
void * palloc(Size size)
Definition: mcxt.c:848
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:752
Definition: pg_list.h:45
List ** windowFuncs
Definition: clauses.h:27
static bool find_window_functions_walker ( Node node,
WindowFuncLists lists 
)
static

Definition at line 752 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().

753 {
754  if (node == NULL)
755  return false;
756  if (IsA(node, WindowFunc))
757  {
758  WindowFunc *wfunc = (WindowFunc *) node;
759 
760  /* winref is unsigned, so one-sided test is OK */
761  if (wfunc->winref > lists->maxWinRef)
762  elog(ERROR, "WindowFunc contains out-of-range winref %u",
763  wfunc->winref);
764  /* eliminate duplicates, so that we avoid repeated computation */
765  if (!list_member(lists->windowFuncs[wfunc->winref], wfunc))
766  {
767  lists->windowFuncs[wfunc->winref] =
768  lappend(lists->windowFuncs[wfunc->winref], wfunc);
769  lists->numWindowFuncs++;
770  }
771 
772  /*
773  * We assume that the parser checked that there are no window
774  * functions in the arguments or filter clause. Hence, we need not
775  * recurse into them. (If either the parser or the planner screws up
776  * on this point, the executor will still catch it; see ExecInitExpr.)
777  */
778  return false;
779  }
780  Assert(!IsA(node, SubLink));
782  (void *) lists);
783 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Index maxWinRef
Definition: clauses.h:26
int numWindowFuncs
Definition: clauses.h:25
Index winref
Definition: primnodes.h:361
#define ERROR
Definition: elog.h:43
bool list_member(const List *list, const void *datum)
Definition: list.c:444
List * lappend(List *list, void *datum)
Definition: list.c:128
#define Assert(condition)
Definition: c.h:664
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:752
#define elog
Definition: elog.h:219
List ** windowFuncs
Definition: clauses.h:27
void get_agg_clause_costs ( PlannerInfo root,
Node clause,
AggSplit  aggsplit,
AggClauseCosts costs 
)

Definition at line 467 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_grouping_paths(), estimate_path_cost_size(), and grouping_planner().

469 {
471 
472  context.root = root;
473  context.aggsplit = aggsplit;
474  context.costs = costs;
475  (void) get_agg_clause_costs_walker(clause, &context);
476 }
AggClauseCosts * costs
Definition: clauses.c:60
static bool get_agg_clause_costs_walker(Node *node, get_agg_clause_costs_context *context)
Definition: clauses.c:479
static bool get_agg_clause_costs_walker ( Node node,
get_agg_clause_costs_context context 
)
static

Definition at line 479 of file clauses.c.

References 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, cpu_operator_cost, 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_func_cost(), get_typavgwidth(), get_typbyval(), GETSTRUCT, AggClauseCosts::hasNonPartial, AggClauseCosts::hasNonSerial, HeapTupleIsValid, INTERNALOID, 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().

480 {
481  if (node == NULL)
482  return false;
483  if (IsA(node, Aggref))
484  {
485  Aggref *aggref = (Aggref *) node;
486  AggClauseCosts *costs = context->costs;
487  HeapTuple aggTuple;
488  Form_pg_aggregate aggform;
489  Oid aggtransfn;
490  Oid aggfinalfn;
491  Oid aggcombinefn;
492  Oid aggserialfn;
493  Oid aggdeserialfn;
494  Oid aggtranstype;
495  int32 aggtransspace;
496  QualCost argcosts;
497 
498  Assert(aggref->agglevelsup == 0);
499 
500  /*
501  * Fetch info about aggregate from pg_aggregate. Note it's correct to
502  * ignore the moving-aggregate variant, since what we're concerned
503  * with here is aggregates not window functions.
504  */
505  aggTuple = SearchSysCache1(AGGFNOID,
506  ObjectIdGetDatum(aggref->aggfnoid));
507  if (!HeapTupleIsValid(aggTuple))
508  elog(ERROR, "cache lookup failed for aggregate %u",
509  aggref->aggfnoid);
510  aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
511  aggtransfn = aggform->aggtransfn;
512  aggfinalfn = aggform->aggfinalfn;
513  aggcombinefn = aggform->aggcombinefn;
514  aggserialfn = aggform->aggserialfn;
515  aggdeserialfn = aggform->aggdeserialfn;
516  aggtranstype = aggform->aggtranstype;
517  aggtransspace = aggform->aggtransspace;
518  ReleaseSysCache(aggTuple);
519 
520  /*
521  * Resolve the possibly-polymorphic aggregate transition type, unless
522  * already done in a previous pass over the expression.
523  */
524  if (OidIsValid(aggref->aggtranstype))
525  aggtranstype = aggref->aggtranstype;
526  else
527  {
528  Oid inputTypes[FUNC_MAX_ARGS];
529  int numArguments;
530 
531  /* extract argument types (ignoring any ORDER BY expressions) */
532  numArguments = get_aggregate_argtypes(aggref, inputTypes);
533 
534  /* resolve actual type of transition state, if polymorphic */
535  aggtranstype = resolve_aggregate_transtype(aggref->aggfnoid,
536  aggtranstype,
537  inputTypes,
538  numArguments);
539  aggref->aggtranstype = aggtranstype;
540  }
541 
542  /*
543  * Count it, and check for cases requiring ordered input. Note that
544  * ordered-set aggs always have nonempty aggorder. Any ordered-input
545  * case also defeats partial aggregation.
546  */
547  costs->numAggs++;
548  if (aggref->aggorder != NIL || aggref->aggdistinct != NIL)
549  {
550  costs->numOrderedAggs++;
551  costs->hasNonPartial = true;
552  }
553 
554  /*
555  * Check whether partial aggregation is feasible, unless we already
556  * found out that we can't do it.
557  */
558  if (!costs->hasNonPartial)
559  {
560  /*
561  * If there is no combine function, then partial aggregation is
562  * not possible.
563  */
564  if (!OidIsValid(aggcombinefn))
565  costs->hasNonPartial = true;
566 
567  /*
568  * If we have any aggs with transtype INTERNAL then we must check
569  * whether they have serialization/deserialization functions; if
570  * not, we can't serialize partial-aggregation results.
571  */
572  else if (aggtranstype == INTERNALOID &&
573  (!OidIsValid(aggserialfn) || !OidIsValid(aggdeserialfn)))
574  costs->hasNonSerial = true;
575  }
576 
577  /*
578  * Add the appropriate component function execution costs to
579  * appropriate totals.
580  */
581  if (DO_AGGSPLIT_COMBINE(context->aggsplit))
582  {
583  /* charge for combining previously aggregated states */
584  costs->transCost.per_tuple += get_func_cost(aggcombinefn) * cpu_operator_cost;
585  }
586  else
587  costs->transCost.per_tuple += get_func_cost(aggtransfn) * cpu_operator_cost;
588  if (DO_AGGSPLIT_DESERIALIZE(context->aggsplit) &&
589  OidIsValid(aggdeserialfn))
590  costs->transCost.per_tuple += get_func_cost(aggdeserialfn) * cpu_operator_cost;
591  if (DO_AGGSPLIT_SERIALIZE(context->aggsplit) &&
592  OidIsValid(aggserialfn))
593  costs->finalCost += get_func_cost(aggserialfn) * cpu_operator_cost;
594  if (!DO_AGGSPLIT_SKIPFINAL(context->aggsplit) &&
595  OidIsValid(aggfinalfn))
596  costs->finalCost += get_func_cost(aggfinalfn) * cpu_operator_cost;
597 
598  /*
599  * These costs are incurred only by the initial aggregate node, so we
600  * mustn't include them again at upper levels.
601  */
602  if (!DO_AGGSPLIT_COMBINE(context->aggsplit))
603  {
604  /* add the input expressions' cost to per-input-row costs */
605  cost_qual_eval_node(&argcosts, (Node *) aggref->args, context->root);
606  costs->transCost.startup += argcosts.startup;
607  costs->transCost.per_tuple += argcosts.per_tuple;
608 
609  /*
610  * Add any filter's cost to per-input-row costs.
611  *
612  * XXX Ideally we should reduce input expression costs according
613  * to filter selectivity, but it's not clear it's worth the
614  * trouble.
615  */
616  if (aggref->aggfilter)
617  {
618  cost_qual_eval_node(&argcosts, (Node *) aggref->aggfilter,
619  context->root);
620  costs->transCost.startup += argcosts.startup;
621  costs->transCost.per_tuple += argcosts.per_tuple;
622  }
623  }
624 
625  /*
626  * If there are direct arguments, treat their evaluation cost like the
627  * cost of the finalfn.
628  */
629  if (aggref->aggdirectargs)
630  {
631  cost_qual_eval_node(&argcosts, (Node *) aggref->aggdirectargs,
632  context->root);
633  costs->transCost.startup += argcosts.startup;
634  costs->finalCost += argcosts.per_tuple;
635  }
636 
637  /*
638  * If the transition type is pass-by-value then it doesn't add
639  * anything to the required size of the hashtable. If it is
640  * pass-by-reference then we have to add the estimated size of the
641  * value itself, plus palloc overhead.
642  */
643  if (!get_typbyval(aggtranstype))
644  {
645  int32 avgwidth;
646 
647  /* Use average width if aggregate definition gave one */
648  if (aggtransspace > 0)
649  avgwidth = aggtransspace;
650  else if (aggtransfn == F_ARRAY_APPEND)
651  {
652  /*
653  * If the transition function is array_append(), it'll use an
654  * expanded array as transvalue, which will occupy at least
655  * ALLOCSET_SMALL_INITSIZE and possibly more. Use that as the
656  * estimate for lack of a better idea.
657  */
658  avgwidth = ALLOCSET_SMALL_INITSIZE;
659  }
660  else
661  {
662  /*
663  * If transition state is of same type as first aggregated
664  * input, assume it's the same typmod (same width) as well.
665  * This works for cases like MAX/MIN and is probably somewhat
666  * reasonable otherwise.
667  */
668  int32 aggtranstypmod = -1;
669 
670  if (aggref->args)
671  {
672  TargetEntry *tle = (TargetEntry *) linitial(aggref->args);
673 
674  if (aggtranstype == exprType((Node *) tle->expr))
675  aggtranstypmod = exprTypmod((Node *) tle->expr);
676  }
677 
678  avgwidth = get_typavgwidth(aggtranstype, aggtranstypmod);
679  }
680 
681  avgwidth = MAXALIGN(avgwidth);
682  costs->transitionSpace += avgwidth + 2 * sizeof(void *);
683  }
684  else if (aggtranstype == INTERNALOID)
685  {
686  /*
687  * INTERNAL transition type is a special case: although INTERNAL
688  * is pass-by-value, it's almost certainly being used as a pointer
689  * to some large data structure. The aggregate definition can
690  * provide an estimate of the size. If it doesn't, then we assume
691  * ALLOCSET_DEFAULT_INITSIZE, which is a good guess if the data is
692  * being kept in a private memory context, as is done by
693  * array_agg() for instance.
694  */
695  if (aggtransspace > 0)
696  costs->transitionSpace += aggtransspace;
697  else
699  }
700 
701  /*
702  * We assume that the parser checked that there are no aggregates (of
703  * this level anyway) in the aggregated arguments, direct arguments,
704  * or filter clause. Hence, we need not recurse into any of them.
705  */
706  return false;
707  }
708  Assert(!IsA(node, SubLink));
710  (void *) context);
711 }
List * aggdistinct
Definition: primnodes.h:303
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition: costsize.c:3489
#define NIL
Definition: pg_list.h:69
AggClauseCosts * costs
Definition: clauses.c:60
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
Definition: nodes.h:509
List * args
Definition: primnodes.h:301
bool hasNonSerial
Definition: relation.h:61
bool hasNonPartial
Definition: relation.h:60
QualCost transCost
Definition: relation.h:62
float4 get_func_cost(Oid funcid)
Definition: lsyscache.c:1641
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:768
Cost startup
Definition: relation.h:45
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:159
static bool get_agg_clause_costs_walker(Node *node, get_agg_clause_costs_context *context)
Definition: clauses.c:479
signed int int32
Definition: c.h:246
#define FUNC_MAX_ARGS
bool get_typbyval(Oid typid)
Definition: lsyscache.c:1972
Cost per_tuple
Definition: relation.h:46
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:770
#define linitial(l)
Definition: pg_list.h:111
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
List * aggorder
Definition: primnodes.h:302
Index agglevelsup
Definition: primnodes.h:309
List * aggdirectargs
Definition: primnodes.h:300
double cpu_operator_cost
Definition: costsize.c:108
int numOrderedAggs
Definition: relation.h:59
#define ALLOCSET_SMALL_INITSIZE
Definition: memutils.h:173
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
int32 get_typavgwidth(Oid typid, int32 typmod)
Definition: lsyscache.c:2328
Cost finalCost
Definition: relation.h:63
Oid aggfnoid
Definition: primnodes.h:294
#define INTERNALOID
Definition: pg_type.h:698
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:664
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:87
Expr * expr
Definition: primnodes.h:1368
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1843
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:769
Expr * aggfilter
Definition: primnodes.h:304
#define MAXALIGN(LEN)
Definition: c.h:576
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:771
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:163
Oid aggtranstype
Definition: primnodes.h:298
Size transitionSpace
Definition: relation.h:64
#define elog
Definition: elog.h:219
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1801
Oid resolve_aggregate_transtype(Oid aggfuncid, Oid aggtranstype, Oid *inputTypes, int numArguments)
Definition: parse_agg.c:1827
Expr* get_notclausearg ( Expr notclause)

Definition at line 265 of file clauses.c.

References generate_unaccent_rules::args, and linitial.

Referenced by clause_selectivity(), expand_boolean_index_clause(), match_boolean_index_clause(), and pull_up_sublinks_qual_recurse().

266 {
267  return linitial(((BoolExpr *) notclause)->args);
268 }
#define linitial(l)
Definition: pg_list.h:111
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 4328 of file clauses.c.

References ACL_EXECUTE, ACLCHECK_OK, eval_const_expressions_context::active_fns, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Anum_pg_proc_proconfig, Anum_pg_proc_prosrc, arg, ErrorContextCallback::arg, CollateExpr::arg, generate_unaccent_rules::args, FuncExpr::args, Assert, 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, GETSTRUCT, GetUserId(), Query::groupClause, Query::groupingSets, Query::hasAggs, Query::hasSubLinks, Query::hasTargetSRFs, Query::hasWindowFuncs, Query::havingQual, heap_attisnull(), i, FuncExpr::inputcollid, IsA, Query::jointree, lcons_oid(), lfirst, Query::limitCount, Query::limitOffset, linitial, list_delete_first(), 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, PROVOLATILE_IMMUTABLE, PROVOLATILE_STABLE, FromExpr::quals, querytree(), record_plan_function_dependency(), RECORDOID, eval_const_expressions_context::root, Query::rtable, Query::setOperations, Query::sortClause, sql_fn_parser_setup(), sql_inline_error_callback(), SQLlanguageId, QualCost::startup, substitute_actual_parameters(), SysCacheGetAttr(), Query::targetList, TextDatumGetCString, transformTopLevelStmt(), and Query::windowClause.

Referenced by simplify_function().

4333 {
4334  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4335  char *src;
4336  Datum tmp;
4337  bool isNull;
4338  bool modifyTargetList;
4339  MemoryContext oldcxt;
4340  MemoryContext mycxt;
4341  inline_error_callback_arg callback_arg;
4342  ErrorContextCallback sqlerrcontext;
4343  FuncExpr *fexpr;
4345  ParseState *pstate;
4346  List *raw_parsetree_list;
4347  Query *querytree;
4348  Node *newexpr;
4349  int *usecounts;
4350  ListCell *arg;
4351  int i;
4352 
4353  /*
4354  * Forget it if the function is not SQL-language or has other showstopper
4355  * properties. (The nargs check is just paranoia.)
4356  */
4357  if (funcform->prolang != SQLlanguageId ||
4358  funcform->prosecdef ||
4359  funcform->proretset ||
4360  funcform->prorettype == RECORDOID ||
4361  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig) ||
4362  funcform->pronargs != list_length(args))
4363  return NULL;
4364 
4365  /* Check for recursive function, and give up trying to expand if so */
4366  if (list_member_oid(context->active_fns, funcid))
4367  return NULL;
4368 
4369  /* Check permission to call function (fail later, if not) */
4371  return NULL;
4372 
4373  /* Check whether a plugin wants to hook function entry/exit */
4374  if (FmgrHookIsNeeded(funcid))
4375  return NULL;
4376 
4377  /*
4378  * Make a temporary memory context, so that we don't leak all the stuff
4379  * that parsing might create.
4380  */
4382  "inline_function",
4384  oldcxt = MemoryContextSwitchTo(mycxt);
4385 
4386  /* Fetch the function body */
4387  tmp = SysCacheGetAttr(PROCOID,
4388  func_tuple,
4390  &isNull);
4391  if (isNull)
4392  elog(ERROR, "null prosrc for function %u", funcid);
4393  src = TextDatumGetCString(tmp);
4394 
4395  /*
4396  * Setup error traceback support for ereport(). This is so that we can
4397  * finger the function that bad information came from.
4398  */
4399  callback_arg.proname = NameStr(funcform->proname);
4400  callback_arg.prosrc = src;
4401 
4402  sqlerrcontext.callback = sql_inline_error_callback;
4403  sqlerrcontext.arg = (void *) &callback_arg;
4404  sqlerrcontext.previous = error_context_stack;
4405  error_context_stack = &sqlerrcontext;
4406 
4407  /*
4408  * Set up to handle parameters while parsing the function body. We need a
4409  * dummy FuncExpr node containing the already-simplified arguments to pass
4410  * to prepare_sql_fn_parse_info. (It is really only needed if there are
4411  * some polymorphic arguments, but for simplicity we always build it.)
4412  */
4413  fexpr = makeNode(FuncExpr);
4414  fexpr->funcid = funcid;
4415  fexpr->funcresulttype = result_type;
4416  fexpr->funcretset = false;
4417  fexpr->funcvariadic = funcvariadic;
4418  fexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
4419  fexpr->funccollid = result_collid; /* doesn't matter */
4420  fexpr->inputcollid = input_collid;
4421  fexpr->args = args;
4422  fexpr->location = -1;
4423 
4424  pinfo = prepare_sql_fn_parse_info(func_tuple,
4425  (Node *) fexpr,
4426  input_collid);
4427 
4428  /*
4429  * We just do parsing and parse analysis, not rewriting, because rewriting
4430  * will not affect table-free-SELECT-only queries, which is all that we
4431  * care about. Also, we can punt as soon as we detect more than one
4432  * command in the function body.
4433  */
4434  raw_parsetree_list = pg_parse_query(src);
4435  if (list_length(raw_parsetree_list) != 1)
4436  goto fail;
4437 
4438  pstate = make_parsestate(NULL);
4439  pstate->p_sourcetext = src;
4440  sql_fn_parser_setup(pstate, pinfo);
4441 
4442  querytree = transformTopLevelStmt(pstate, linitial(raw_parsetree_list));
4443 
4444  free_parsestate(pstate);
4445 
4446  /*
4447  * The single command must be a simple "SELECT expression".
4448  *
4449  * Note: if you change the tests involved in this, see also plpgsql's
4450  * exec_simple_check_plan(). That generally needs to have the same idea
4451  * of what's a "simple expression", so that inlining a function that
4452  * previously wasn't inlined won't change plpgsql's conclusion.
4453  */
4454  if (!IsA(querytree, Query) ||
4455  querytree->commandType != CMD_SELECT ||
4456  querytree->hasAggs ||
4457  querytree->hasWindowFuncs ||
4458  querytree->hasTargetSRFs ||
4459  querytree->hasSubLinks ||
4460  querytree->cteList ||
4461  querytree->rtable ||
4462  querytree->jointree->fromlist ||
4463  querytree->jointree->quals ||
4464  querytree->groupClause ||
4465  querytree->groupingSets ||
4466  querytree->havingQual ||
4467  querytree->windowClause ||
4468  querytree->distinctClause ||
4469  querytree->sortClause ||
4470  querytree->limitOffset ||
4471  querytree->limitCount ||
4472  querytree->setOperations ||
4473  list_length(querytree->targetList) != 1)
4474  goto fail;
4475 
4476  /*
4477  * Make sure the function (still) returns what it's declared to. This
4478  * will raise an error if wrong, but that's okay since the function would
4479  * fail at runtime anyway. Note that check_sql_fn_retval will also insert
4480  * a RelabelType if needed to make the tlist expression match the declared
4481  * type of the function.
4482  *
4483  * Note: we do not try this until we have verified that no rewriting was
4484  * needed; that's probably not important, but let's be careful.
4485  */
4486  if (check_sql_fn_retval(funcid, result_type, list_make1(querytree),
4487  &modifyTargetList, NULL))
4488  goto fail; /* reject whole-tuple-result cases */
4489 
4490  /* Now we can grab the tlist expression */
4491  newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr;
4492 
4493  /* Assert that check_sql_fn_retval did the right thing */
4494  Assert(exprType(newexpr) == result_type);
4495  /* It couldn't have made any dangerous tlist changes, either */
4496  Assert(!modifyTargetList);
4497 
4498  /*
4499  * Additional validity checks on the expression. It mustn't be more
4500  * volatile than the surrounding function (this is to avoid breaking hacks
4501  * that involve pretending a function is immutable when it really ain't).
4502  * If the surrounding function is declared strict, then the expression
4503  * must contain only strict constructs and must use all of the function
4504  * parameters (this is overkill, but an exact analysis is hard).
4505  */
4506  if (funcform->provolatile == PROVOLATILE_IMMUTABLE &&
4507  contain_mutable_functions(newexpr))
4508  goto fail;
4509  else if (funcform->provolatile == PROVOLATILE_STABLE &&
4510  contain_volatile_functions(newexpr))
4511  goto fail;
4512 
4513  if (funcform->proisstrict &&
4514  contain_nonstrict_functions(newexpr))
4515  goto fail;
4516 
4517  /*
4518  * If any parameter expression contains a context-dependent node, we can't
4519  * inline, for fear of putting such a node into the wrong context.
4520  */
4521  if (contain_context_dependent_node((Node *) args))
4522  goto fail;
4523 
4524  /*
4525  * We may be able to do it; there are still checks on parameter usage to
4526  * make, but those are most easily done in combination with the actual
4527  * substitution of the inputs. So start building expression with inputs
4528  * substituted.
4529  */
4530  usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
4531  newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
4532  args, usecounts);
4533 
4534  /* Now check for parameter usage */
4535  i = 0;
4536  foreach(arg, args)
4537  {
4538  Node *param = lfirst(arg);
4539 
4540  if (usecounts[i] == 0)
4541  {
4542  /* Param not used at all: uncool if func is strict */
4543  if (funcform->proisstrict)
4544  goto fail;
4545  }
4546  else if (usecounts[i] != 1)
4547  {
4548  /* Param used multiple times: uncool if expensive or volatile */
4549  QualCost eval_cost;
4550 
4551  /*
4552  * We define "expensive" as "contains any subplan or more than 10
4553  * operators". Note that the subplan search has to be done
4554  * explicitly, since cost_qual_eval() will barf on unplanned
4555  * subselects.
4556  */
4557  if (contain_subplans(param))
4558  goto fail;
4559  cost_qual_eval(&eval_cost, list_make1(param), NULL);
4560  if (eval_cost.startup + eval_cost.per_tuple >
4561  10 * cpu_operator_cost)
4562  goto fail;
4563 
4564  /*
4565  * Check volatility last since this is more expensive than the
4566  * above tests
4567  */
4568  if (contain_volatile_functions(param))
4569  goto fail;
4570  }
4571  i++;
4572  }
4573 
4574  /*
4575  * Whew --- we can make the substitution. Copy the modified expression
4576  * out of the temporary memory context, and clean up.
4577  */
4578  MemoryContextSwitchTo(oldcxt);
4579 
4580  newexpr = copyObject(newexpr);
4581 
4582  MemoryContextDelete(mycxt);
4583 
4584  /*
4585  * If the result is of a collatable type, force the result to expose the
4586  * correct collation. In most cases this does not matter, but it's
4587  * possible that the function result is used directly as a sort key or in
4588  * other places where we expect exprCollation() to tell the truth.
4589  */
4590  if (OidIsValid(result_collid))
4591  {
4592  Oid exprcoll = exprCollation(newexpr);
4593 
4594  if (OidIsValid(exprcoll) && exprcoll != result_collid)
4595  {
4596  CollateExpr *newnode = makeNode(CollateExpr);
4597 
4598  newnode->arg = (Expr *) newexpr;
4599  newnode->collOid = result_collid;
4600  newnode->location = -1;
4601 
4602  newexpr = (Node *) newnode;
4603  }
4604  }
4605 
4606  /*
4607  * Since there is now no trace of the function in the plan tree, we must
4608  * explicitly record the plan's dependency on the function.
4609  */
4610  if (context->root)
4611  record_plan_function_dependency(context->root, funcid);
4612 
4613  /*
4614  * Recursively try to simplify the modified expression. Here we must add
4615  * the current function to the context list of active functions.
4616  */
4617  context->active_fns = lcons_oid(funcid, context->active_fns);
4618  newexpr = eval_const_expressions_mutator(newexpr, context);
4619  context->active_fns = list_delete_first(context->active_fns);
4620 
4621  error_context_stack = sqlerrcontext.previous;
4622 
4623  return (Expr *) newexpr;
4624 
4625  /* Here if func is not inlinable: release temp memory and return NULL */
4626 fail:
4627  MemoryContextSwitchTo(oldcxt);
4628  MemoryContextDelete(mycxt);
4629  error_context_stack = sqlerrcontext.previous;
4630 
4631  return NULL;
4632 }
Node * limitOffset
Definition: parsenodes.h:158
Oid funcresulttype
Definition: primnodes.h:450
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5533
List * sortClause
Definition: parsenodes.h:156
List * args
Definition: primnodes.h:457
FromExpr * jointree
Definition: parsenodes.h:136
Oid GetUserId(void)
Definition: miscinit.c:284
Oid funccollid
Definition: primnodes.h:455
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition: functions.c:273
bool hasAggs
Definition: parsenodes.h:123
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Anum_pg_proc_prosrc
Definition: pg_proc.h:115
List * groupingSets
Definition: parsenodes.h:148
Definition: nodes.h:509
bool check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, bool *modifyTargetList, JunkFilter **junkFilter)
Definition: functions.c:1532
bool funcretset
Definition: primnodes.h:451
List * lcons_oid(Oid datum, List *list)
Definition: list.c:295
List * fromlist
Definition: primnodes.h:1471
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:957
unsigned int Oid
Definition: postgres_ext.h:31
struct ErrorContextCallback * previous
Definition: elog.h:238
#define OidIsValid(objectId)
Definition: c.h:532
#define FmgrHookIsNeeded(fn_oid)
Definition: fmgr.h:729
Node * quals
Definition: primnodes.h:1472
Cost startup
Definition: relation.h:45
#define Anum_pg_proc_proconfig
Definition: pg_proc.h:117
List * windowClause
Definition: parsenodes.h:152
List * targetList
Definition: parsenodes.h:138
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
ErrorContextCallback * error_context_stack
Definition: elog.c:88
#define list_make1(x1)
Definition: pg_list.h:139
bool contain_subplans(Node *clause)
Definition: clauses.c:843
CoercionForm funcformat
Definition: primnodes.h:454
Cost per_tuple
Definition: relation.h:46
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2468
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
List * distinctClause
Definition: parsenodes.h:154
Oid funcid
Definition: primnodes.h:449
#define ERROR
Definition: elog.h:43
#define SQLlanguageId
Definition: pg_language.h:80
#define PROVOLATILE_STABLE
Definition: pg_proc.h:5534
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:3463
List * pg_parse_query(const char *query_string)
Definition: postgres.c:603
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
Node * limitCount
Definition: parsenodes.h:159
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:296
double cpu_operator_cost
Definition: costsize.c:108
#define RECORDOID
Definition: pg_type.h:680
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
const char * p_sourcetext
Definition: parse_node.h:171
static Node * substitute_actual_parameters(Node *expr, int nargs, List *args, int *usecounts)
Definition: clauses.c:4638
static void sql_inline_error_callback(void *arg)
Definition: clauses.c:4680
#define TextDatumGetCString(d)
Definition: builtins.h:92
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1325
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2496
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
CmdType commandType
Definition: parsenodes.h:110
bool hasTargetSRFs
Definition: parsenodes.h:125
#define makeNode(_type_)
Definition: nodes.h:557
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
Oid inputcollid
Definition: primnodes.h:456
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
bool hasWindowFuncs
Definition: parsenodes.h:124
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:187
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
Expr * arg
Definition: primnodes.h:876
Datum querytree(PG_FUNCTION_ARGS)
Definition: _int_bool.c:665
static bool contain_context_dependent_node(Node *clause)
Definition: clauses.c:1415
List * cteList
Definition: parsenodes.h:133
Node * setOperations
Definition: parsenodes.h:163
List * groupClause
Definition: parsenodes.h:146
void(* callback)(void *arg)
Definition: elog.h:239
bool hasSubLinks
Definition: parsenodes.h:126
#define ACL_EXECUTE
Definition: parsenodes.h:79
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4446
int i
#define NameStr(name)
Definition: c.h:493
void * arg
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:878
int location
Definition: primnodes.h:458
#define elog
Definition: elog.h:219
bool contain_nonstrict_functions(Node *clause)
Definition: clauses.c:1288
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
Definition: functions.c:184
#define copyObject(obj)
Definition: nodes.h:622
Node * havingQual
Definition: parsenodes.h:150
int location
Definition: primnodes.h:878
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
Definition: pg_list.h:45
bool funcvariadic
Definition: primnodes.h:452
List * list_delete_first(List *list)
Definition: list.c:666
Query* inline_set_returning_function ( PlannerInfo root,
RangeTblEntry rte 
)

Definition at line 4792 of file clauses.c.

References ACL_EXECUTE, ACLCHECK_OK, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Anum_pg_proc_proconfig, Anum_pg_proc_prosrc, ErrorContextCallback::arg, FuncExpr::args, Assert, ErrorContextCallback::callback, check_sql_fn_retval(), check_stack_depth(), CMD_SELECT, Query::commandType, contain_subplans(), contain_volatile_functions(), copyObject, CurrentMemoryContext, elog, ERROR, error_context_stack, eval_const_expressions(), FmgrHookIsNeeded, RangeTblFunction::funccoltypes, RangeTblFunction::funcexpr, FuncExpr::funcid, RangeTblEntry::funcordinality, FuncExpr::funcresulttype, FuncExpr::funcretset, RangeTblEntry::functions, get_func_result_type(), get_typtype(), GETSTRUCT, GetUserId(), PlannerInfo::glob, heap_attisnull(), HeapTupleIsValid, FuncExpr::inputcollid, PlannerGlobal::invalItems, IsA, linitial, list_concat(), list_length(), MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, NIL, ObjectIdGetDatum, pg_analyze_and_rewrite_params(), pg_parse_query(), pg_proc_aclcheck(), prepare_sql_fn_parse_info(), ErrorContextCallback::previous, PROCOID, inline_error_callback_arg::proname, inline_error_callback_arg::prosrc, PROVOLATILE_VOLATILE, querytree(), record_plan_function_dependency(), RECORDOID, ReleaseSysCache(), RTE_FUNCTION, RangeTblEntry::rtekind, SearchSysCache1, sql_fn_parser_setup(), sql_inline_error_callback(), SQLlanguageId, substitute_actual_srf_parameters(), SysCacheGetAttr(), Query::targetList, TextDatumGetCString, tlist_matches_coltypelist(), TYPEFUNC_RECORD, and TYPTYPE_COMPOSITE.

Referenced by inline_set_returning_functions().

4793 {
4794  RangeTblFunction *rtfunc;
4795  FuncExpr *fexpr;
4796  Oid func_oid;
4797  HeapTuple func_tuple;
4798  Form_pg_proc funcform;
4799  char *src;
4800  Datum tmp;
4801  bool isNull;
4802  bool modifyTargetList;
4803  MemoryContext oldcxt;
4804  MemoryContext mycxt;
4805  List *saveInvalItems;
4806  inline_error_callback_arg callback_arg;
4807  ErrorContextCallback sqlerrcontext;
4809  List *raw_parsetree_list;
4810  List *querytree_list;
4811  Query *querytree;
4812 
4813  Assert(rte->rtekind == RTE_FUNCTION);
4814 
4815  /*
4816  * It doesn't make a lot of sense for a SQL SRF to refer to itself in its
4817  * own FROM clause, since that must cause infinite recursion at runtime.
4818  * It will cause this code to recurse too, so check for stack overflow.
4819  * (There's no need to do more.)
4820  */
4822 
4823  /* Fail if the RTE has ORDINALITY - we don't implement that here. */
4824  if (rte->funcordinality)
4825  return NULL;
4826 
4827  /* Fail if RTE isn't a single, simple FuncExpr */
4828  if (list_length(rte->functions) != 1)
4829  return NULL;
4830  rtfunc = (RangeTblFunction *) linitial(rte->functions);
4831 
4832  if (!IsA(rtfunc->funcexpr, FuncExpr))
4833  return NULL;
4834  fexpr = (FuncExpr *) rtfunc->funcexpr;
4835 
4836  func_oid = fexpr->funcid;
4837 
4838  /*
4839  * The function must be declared to return a set, else inlining would
4840  * change the results if the contained SELECT didn't return exactly one
4841  * row.
4842  */
4843  if (!fexpr->funcretset)
4844  return NULL;
4845 
4846  /*
4847  * Refuse to inline if the arguments contain any volatile functions or
4848  * sub-selects. Volatile functions are rejected because inlining may
4849  * result in the arguments being evaluated multiple times, risking a
4850  * change in behavior. Sub-selects are rejected partly for implementation
4851  * reasons (pushing them down another level might change their behavior)
4852  * and partly because they're likely to be expensive and so multiple
4853  * evaluation would be bad.
4854  */
4855  if (contain_volatile_functions((Node *) fexpr->args) ||
4856  contain_subplans((Node *) fexpr->args))
4857  return NULL;
4858 
4859  /* Check permission to call function (fail later, if not) */
4860  if (pg_proc_aclcheck(func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
4861  return NULL;
4862 
4863  /* Check whether a plugin wants to hook function entry/exit */
4864  if (FmgrHookIsNeeded(func_oid))
4865  return NULL;
4866 
4867  /*
4868  * OK, let's take a look at the function's pg_proc entry.
4869  */
4870  func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid));
4871  if (!HeapTupleIsValid(func_tuple))
4872  elog(ERROR, "cache lookup failed for function %u", func_oid);
4873  funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4874 
4875  /*
4876  * Forget it if the function is not SQL-language or has other showstopper
4877  * properties. In particular it mustn't be declared STRICT, since we
4878  * couldn't enforce that. It also mustn't be VOLATILE, because that is
4879  * supposed to cause it to be executed with its own snapshot, rather than
4880  * sharing the snapshot of the calling query. (Rechecking proretset is
4881  * just paranoia.)
4882  */
4883  if (funcform->prolang != SQLlanguageId ||
4884  funcform->proisstrict ||
4885  funcform->provolatile == PROVOLATILE_VOLATILE ||
4886  funcform->prosecdef ||
4887  !funcform->proretset ||
4888  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig))
4889  {
4890