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

4077 {
4078  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4079  int nargsprovided = list_length(args);
4080  List *defaults;
4081  int ndelete;
4082 
4083  /* Get all the default expressions from the pg_proc tuple */
4084  defaults = fetch_function_defaults(func_tuple);
4085 
4086  /* Delete any unused defaults from the list */
4087  ndelete = nargsprovided + list_length(defaults) - funcform->pronargs;
4088  if (ndelete < 0)
4089  elog(ERROR, "not enough default arguments");
4090  while (ndelete-- > 0)
4091  defaults = list_delete_first(defaults);
4092 
4093  /* And form the combined argument list, not modifying the input list */
4094  return list_concat(list_copy(args), defaults);
4095 }
#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:4101
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 2232 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().

2233 {
2234  Oid opoid;
2235  Node *temp;
2236 
2237  /* Sanity checks: caller is at fault if these fail */
2238  if (!is_opclause(clause) ||
2239  list_length(clause->args) != 2)
2240  elog(ERROR, "cannot commute non-binary-operator clause");
2241 
2242  opoid = get_commutator(clause->opno);
2243 
2244  if (!OidIsValid(opoid))
2245  elog(ERROR, "could not find commutator for operator %u",
2246  clause->opno);
2247 
2248  /*
2249  * modify the clause in-place!
2250  */
2251  clause->opno = opoid;
2252  clause->opfuncid = InvalidOid;
2253  /* opresulttype, opretset, opcollid, inputcollid need not change */
2254 
2255  temp = linitial(clause->args);
2256  linitial(clause->args) = lsecond(clause->args);
2257  lsecond(clause->args) = temp;
2258 }
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:538
#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:496
#define InvalidOid
Definition: postgres_ext.h:36
static int list_length(const List *l)
Definition: pg_list.h:89
Oid opno
Definition: primnodes.h:495
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:501
void CommuteRowCompareExpr ( RowCompareExpr clause)

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

2267 {
2268  List *newops;
2269  List *temp;
2270  ListCell *l;
2271 
2272  /* Sanity checks: caller is at fault if these fail */
2273  if (!IsA(clause, RowCompareExpr))
2274  elog(ERROR, "expected a RowCompareExpr");
2275 
2276  /* Build list of commuted operators */
2277  newops = NIL;
2278  foreach(l, clause->opnos)
2279  {
2280  Oid opoid = lfirst_oid(l);
2281 
2282  opoid = get_commutator(opoid);
2283  if (!OidIsValid(opoid))
2284  elog(ERROR, "could not find commutator for operator %u",
2285  lfirst_oid(l));
2286  newops = lappend_oid(newops, opoid);
2287  }
2288 
2289  /*
2290  * modify the clause in-place!
2291  */
2292  switch (clause->rctype)
2293  {
2294  case ROWCOMPARE_LT:
2295  clause->rctype = ROWCOMPARE_GT;
2296  break;
2297  case ROWCOMPARE_LE:
2298  clause->rctype = ROWCOMPARE_GE;
2299  break;
2300  case ROWCOMPARE_GE:
2301  clause->rctype = ROWCOMPARE_LE;
2302  break;
2303  case ROWCOMPARE_GT:
2304  clause->rctype = ROWCOMPARE_LT;
2305  break;
2306  default:
2307  elog(ERROR, "unexpected RowCompare type: %d",
2308  (int) clause->rctype);
2309  break;
2310  }
2311 
2312  clause->opnos = newops;
2313 
2314  /*
2315  * Note: we need not change the opfamilies list; we assume any btree
2316  * opfamily containing an operator will also contain its commutator.
2317  * Collations don't change either.
2318  */
2319 
2320  temp = clause->largs;
2321  clause->largs = clause->rargs;
2322  clause->rargs = temp;
2323 }
#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:1030
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:538
#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(), and NULL.

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
#define NULL
Definition: c.h:229
static bool contain_agg_clause_walker ( Node node,
void *  context 
)
static

Definition at line 423 of file clauses.c.

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

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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1865
static bool contain_context_dependent_node ( Node clause)
static

Definition at line 1395 of file clauses.c.

References contain_context_dependent_node_walker().

Referenced by inline_function().

1396 {
1397  int flags = 0;
1398 
1399  return contain_context_dependent_node_walker(clause, &flags);
1400 }
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:1405
static bool contain_context_dependent_node_walker ( Node node,
int *  flags 
)
static

Definition at line 1405 of file clauses.c.

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

Referenced by contain_context_dependent_node().

1406 {
1407  if (node == NULL)
1408  return false;
1409  if (IsA(node, CaseTestExpr))
1410  return !(*flags & CCDN_IN_CASEEXPR);
1411  if (IsA(node, CaseExpr))
1412  {
1413  CaseExpr *caseexpr = (CaseExpr *) node;
1414 
1415  /*
1416  * If this CASE doesn't have a test expression, then it doesn't create
1417  * a context in which CaseTestExprs should appear, so just fall
1418  * through and treat it as a generic expression node.
1419  */
1420  if (caseexpr->arg)
1421  {
1422  int save_flags = *flags;
1423  bool res;
1424 
1425  /*
1426  * Note: in principle, we could distinguish the various sub-parts
1427  * of a CASE construct and set the flag bit only for some of them,
1428  * since we are only expecting CaseTestExprs to appear in the
1429  * "expr" subtree of the CaseWhen nodes. But it doesn't really
1430  * seem worth any extra code. If there are any bare CaseTestExprs
1431  * elsewhere in the CASE, something's wrong already.
1432  */
1433  *flags |= CCDN_IN_CASEEXPR;
1434  res = expression_tree_walker(node,
1436  (void *) flags);
1437  *flags = save_flags;
1438  return res;
1439  }
1440  }
1442  (void *) flags);
1443 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define CCDN_IN_CASEEXPR
Definition: clauses.c:1402
#define NULL
Definition: c.h:229
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1865
Expr * arg
Definition: primnodes.h:907
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition: clauses.c:1405
bool contain_leaked_vars ( Node clause)

Definition at line 1461 of file clauses.c.

References contain_leaked_vars_walker(), and NULL.

Referenced by make_restrictinfo_internal(), and qual_is_pushdown_safe().

1462 {
1463  return contain_leaked_vars_walker(clause, NULL);
1464 }
#define NULL
Definition: c.h:229
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1473
static bool contain_leaked_vars_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 1467 of file clauses.c.

References get_func_leakproof().

Referenced by contain_leaked_vars_walker().

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

Definition at line 1473 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, NULL, 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_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().

1474 {
1475  if (node == NULL)
1476  return false;
1477 
1478  switch (nodeTag(node))
1479  {
1480  case T_Var:
1481  case T_Const:
1482  case T_Param:
1483  case T_ArrayRef:
1484  case T_ArrayExpr:
1485  case T_FieldSelect:
1486  case T_FieldStore:
1487  case T_NamedArgExpr:
1488  case T_BoolExpr:
1489  case T_RelabelType:
1490  case T_CollateExpr:
1491  case T_CaseExpr:
1492  case T_CaseTestExpr:
1493  case T_RowExpr:
1494  case T_MinMaxExpr:
1495  case T_SQLValueFunction:
1496  case T_NullTest:
1497  case T_BooleanTest:
1498  case T_List:
1499 
1500  /*
1501  * We know these node types don't contain function calls; but
1502  * something further down in the node tree might.
1503  */
1504  break;
1505 
1506  case T_FuncExpr:
1507  case T_OpExpr:
1508  case T_DistinctExpr:
1509  case T_NullIfExpr:
1510  case T_ScalarArrayOpExpr:
1511  case T_CoerceViaIO:
1512  case T_ArrayCoerceExpr:
1513 
1514  /*
1515  * If node contains a leaky function call, and there's any Var
1516  * underneath it, reject.
1517  */
1519  context) &&
1520  contain_var_clause(node))
1521  return true;
1522  break;
1523 
1524  case T_RowCompareExpr:
1525  {
1526  /*
1527  * It's worth special-casing this because a leaky comparison
1528  * function only compromises one pair of row elements, which
1529  * might not contain Vars while others do.
1530  */
1531  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1532  ListCell *opid;
1533  ListCell *larg;
1534  ListCell *rarg;
1535 
1536  forthree(opid, rcexpr->opnos,
1537  larg, rcexpr->largs,
1538  rarg, rcexpr->rargs)
1539  {
1540  Oid funcid = get_opcode(lfirst_oid(opid));
1541 
1542  if (!get_func_leakproof(funcid) &&
1543  (contain_var_clause((Node *) lfirst(larg)) ||
1544  contain_var_clause((Node *) lfirst(rarg))))
1545  return true;
1546  }
1547  }
1548  break;
1549 
1550  case T_CurrentOfExpr:
1551 
1552  /*
1553  * WHERE CURRENT OF doesn't contain leaky function calls.
1554  * Moreover, it is essential that this is considered non-leaky,
1555  * since the planner must always generate a TID scan when CURRENT
1556  * OF is present -- c.f. cost_tidscan.
1557  */
1558  return false;
1559 
1560  default:
1561 
1562  /*
1563  * If we don't recognize the node tag, assume it might be leaky.
1564  * This prevents an unexpected security hole if someone adds a new
1565  * node type that can call a function.
1566  */
1567  return true;
1568  }
1570  context);
1571 }
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:1673
Definition: nodes.h:291
Definition: nodes.h:147
Definition: nodes.h:146
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1865
#define nodeTag(nodeptr)
Definition: nodes.h:514
static bool contain_leaked_vars_checker(Oid func_id, void *context)
Definition: clauses.c:1467
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1473
#define lfirst_oid(lc)
Definition: pg_list.h:108
Definition: nodes.h:148
bool contain_mutable_functions ( Node clause)

Definition at line 878 of file clauses.c.

References contain_mutable_functions_walker(), and NULL.

Referenced by check_index_predicates(), CheckMutability(), ComputePartitionAttrs(), create_bitmap_scan_plan(), create_indexscan_plan(), find_minmax_aggs_walker(), inline_function(), is_foreign_expr(), and relation_excluded_by_constraints().

879 {
880  return contain_mutable_functions_walker(clause, NULL);
881 }
static bool contain_mutable_functions_walker(Node *node, void *context)
Definition: clauses.c:890
#define NULL
Definition: c.h:229
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:5483
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, NULL, 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  /*
906  * It should be safe to treat MinMaxExpr as immutable, because it will
907  * depend on a non-cross-type btree comparison function, and those should
908  * always be immutable. Treating XmlExpr as immutable is more dubious,
909  * and treating CoerceToDomain as immutable is outright dangerous. But we
910  * have done so historically, and changing this would probably cause more
911  * problems than it would fix. In practice, if you have a non-immutable
912  * domain constraint you are in for pain anyhow.
913  */
914 
915  /* Recurse to check arguments */
916  if (IsA(node, Query))
917  {
918  /* Recurse into subselects */
919  return query_tree_walker((Query *) node,
921  context, 0);
922  }
924  context);
925 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2268
#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:1673
#define NULL
Definition: c.h:229
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1865
bool contain_nonstrict_functions ( Node clause)

Definition at line 1268 of file clauses.c.

References contain_nonstrict_functions_walker(), and NULL.

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

1269 {
1270  return contain_nonstrict_functions_walker(clause, NULL);
1271 }
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:1280
#define NULL
Definition: c.h:229
static bool contain_nonstrict_functions_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 1274 of file clauses.c.

References func_strict().

Referenced by contain_nonstrict_functions_walker().

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

Definition at line 1280 of file clauses.c.

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

Referenced by contain_nonstrict_functions().

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

Definition at line 843 of file clauses.c.

References contain_subplans_walker(), and NULL.

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 }
#define NULL
Definition: c.h:229
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(), IsA, and NULL.

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
#define NULL
Definition: c.h:229
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1865
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 957 of file clauses.c.

References func_volatile(), and PROVOLATILE_VOLATILE.

Referenced by contain_volatile_functions_walker().

958 {
959  return (func_volatile(func_id) == PROVOLATILE_VOLATILE);
960 }
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5485
char func_volatile(Oid funcid)
Definition: lsyscache.c:1584
bool contain_volatile_functions_not_nextval ( Node clause)

Definition at line 995 of file clauses.c.

References contain_volatile_functions_not_nextval_walker(), and NULL.

Referenced by BeginCopyFrom().

996 {
998 }
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:1008
#define NULL
Definition: c.h:229
static bool contain_volatile_functions_not_nextval_checker ( Oid  func_id,
void *  context 
)
static

Definition at line 1001 of file clauses.c.

References func_volatile(), and PROVOLATILE_VOLATILE.

Referenced by contain_volatile_functions_not_nextval_walker().

1002 {
1003  return (func_id != F_NEXTVAL_OID &&
1004  func_volatile(func_id) == PROVOLATILE_VOLATILE);
1005 }
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5485
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 1008 of file clauses.c.

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

Referenced by contain_volatile_functions_not_nextval().

1009 {
1010  if (node == NULL)
1011  return false;
1012  /* Check for volatile functions in node itself */
1013  if (check_functions_in_node(node,
1015  context))
1016  return true;
1017 
1018  /*
1019  * See notes in contain_mutable_functions_walker about why we treat
1020  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
1021  * SQLValueFunction is stable. Hence, none of them are of interest here.
1022  */
1023 
1024  /* Recurse to check arguments */
1025  if (IsA(node, Query))
1026  {
1027  /* Recurse into subselects */
1028  return query_tree_walker((Query *) node,
1030  context, 0);
1031  }
1032  return expression_tree_walker(node,
1034  context);
1035 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2268
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition: clauses.c:1008
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1673
#define NULL
Definition: c.h:229
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1865
static bool contain_volatile_functions_not_nextval_checker(Oid func_id, void *context)
Definition: clauses.c:1001
static bool contain_volatile_functions_walker ( Node node,
void *  context 
)
static

Definition at line 963 of file clauses.c.

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

Referenced by contain_volatile_functions().

964 {
965  if (node == NULL)
966  return false;
967  /* Check for volatile functions in node itself */
969  context))
970  return true;
971 
972  /*
973  * See notes in contain_mutable_functions_walker about why we treat
974  * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
975  * SQLValueFunction is stable. Hence, none of them are of interest here.
976  */
977 
978  /* Recurse to check arguments */
979  if (IsA(node, Query))
980  {
981  /* Recurse into subselects */
982  return query_tree_walker((Query *) node,
984  context, 0);
985  }
987  context);
988 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2268
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition: nodeFuncs.c:1673
static bool contain_volatile_functions_walker(Node *node, void *context)
Definition: clauses.c:963
#define NULL
Definition: c.h:229
static bool contain_volatile_functions_checker(Oid func_id, void *context)
Definition: clauses.c:957
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1865
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 2433 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, NULL, 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().

2434 {
2436 
2437  context.boundParams = root->glob->boundParams; /* bound Params */
2438  /* we do not need to mark the plan as depending on inlined functions */
2439  context.root = NULL;
2440  context.active_fns = NIL; /* nothing being recursively simplified */
2441  context.case_val = NULL; /* no CASE being examined */
2442  context.estimate = true; /* unsafe transformations OK */
2443  return eval_const_expressions_mutator(node, &context);
2444 }
#define NIL
Definition: pg_list.h:69
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2447
ParamListInfo boundParams
Definition: clauses.c:65
PlannerGlobal * glob
Definition: relation.h:157
#define NULL
Definition: c.h:229
ParamListInfo boundParams
Definition: relation.h:96
Node* eval_const_expressions ( PlannerInfo root,
Node node 
)

Definition at line 2400 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, NULL, and eval_const_expressions_context::root.

Referenced by ATExecAttachPartition(), convert_EXISTS_to_ANY(), expression_planner(), get_relation_constraints(), inline_set_returning_function(), preprocess_expression(), process_implied_equality(), RelationBuildPartitionKey(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), set_append_rel_size(), and simplify_EXISTS_query().

2401 {
2403 
2404  if (root)
2405  context.boundParams = root->glob->boundParams; /* bound Params */
2406  else
2407  context.boundParams = NULL;
2408  context.root = root; /* for inlined-function dependencies */
2409  context.active_fns = NIL; /* nothing being recursively simplified */
2410  context.case_val = NULL; /* no CASE being examined */
2411  context.estimate = false; /* safe transformations only */
2412  return eval_const_expressions_mutator(node, &context);
2413 }
#define NIL
Definition: pg_list.h:69
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2447
ParamListInfo boundParams
Definition: clauses.c:65
PlannerGlobal * glob
Definition: relation.h:157
#define NULL
Definition: c.h:229
ParamListInfo boundParams
Definition: relation.h:96
static Node * eval_const_expressions_mutator ( Node node,
eval_const_expressions_context context 
)
static

Definition at line 2447 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, NULL, 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, 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().

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

Definition at line 4678 of file clauses.c.

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

Referenced by eval_const_expressions_mutator(), and evaluate_function().

4680 {
4681  EState *estate;
4682  ExprState *exprstate;
4683  MemoryContext oldcontext;
4684  Datum const_val;
4685  bool const_is_null;
4686  int16 resultTypLen;
4687  bool resultTypByVal;
4688 
4689  /*
4690  * To use the executor, we need an EState.
4691  */
4692  estate = CreateExecutorState();
4693 
4694  /* We can use the estate's working context to avoid memory leaks. */
4695  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
4696 
4697  /* Make sure any opfuncids are filled in. */
4698  fix_opfuncids((Node *) expr);
4699 
4700  /*
4701  * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
4702  * because it'd result in recursively invoking eval_const_expressions.)
4703  */
4704  exprstate = ExecInitExpr(expr, NULL);
4705 
4706  /*
4707  * And evaluate it.
4708  *
4709  * It is OK to use a default econtext because none of the ExecEvalExpr()
4710  * code used in this situation will use econtext. That might seem
4711  * fortuitous, but it's not so unreasonable --- a constant expression does
4712  * not depend on context, by definition, n'est ce pas?
4713  */
4714  const_val = ExecEvalExprSwitchContext(exprstate,
4715  GetPerTupleExprContext(estate),
4716  &const_is_null);
4717 
4718  /* Get info needed about result datatype */
4719  get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
4720 
4721  /* Get back to outer memory context */
4722  MemoryContextSwitchTo(oldcontext);
4723 
4724  /*
4725  * Must copy result out of sub-context used by expression eval.
4726  *
4727  * Also, if it's varlena, forcibly detoast it. This protects us against
4728  * storing TOAST pointers into plans that might outlive the referenced
4729  * data. (makeConst would handle detoasting anyway, but it's worth a few
4730  * extra lines here so that we can do the copy and detoast in one step.)
4731  */
4732  if (!const_is_null)
4733  {
4734  if (resultTypLen == -1)
4735  const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
4736  else
4737  const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
4738  }
4739 
4740  /* Release all the junk we just created */
4741  FreeExecutorState(estate);
4742 
4743  /*
4744  * Make the constant result node.
4745  */
4746  return (Expr *) makeConst(result_type, result_typmod, result_collation,
4747  resultTypLen,
4748  const_val, const_is_null,
4749  resultTypByVal);
4750 }
signed short int16
Definition: c.h:255
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:281
#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:1604
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:178
#define GetPerTupleExprContext(estate)
Definition: executor.h:456
MemoryContext es_query_cxt
Definition: execnodes.h:448
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
#define NULL
Definition: c.h:229
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 4180 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(), NULL, PROVOLATILE_IMMUTABLE, PROVOLATILE_STABLE, and RECORDOID.

Referenced by simplify_function().

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

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

3964 {
3965  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
3966  bool has_named_args = false;
3967  ListCell *lc;
3968 
3969  /* Do we have any named arguments? */
3970  foreach(lc, args)
3971  {
3972  Node *arg = (Node *) lfirst(lc);
3973 
3974  if (IsA(arg, NamedArgExpr))
3975  {
3976  has_named_args = true;
3977  break;
3978  }
3979  }
3980 
3981  /* If so, we must apply reorder_function_arguments */
3982  if (has_named_args)
3983  {
3984  args = reorder_function_arguments(args, func_tuple);
3985  /* Recheck argument types and add casts if needed */
3986  recheck_cast_function_args(args, result_type, func_tuple);
3987  }
3988  else if (list_length(args) < funcform->pronargs)
3989  {
3990  /* No named args, but we seem to be short some defaults */
3991  args = add_function_defaults(args, func_tuple);
3992  /* Recheck argument types and add casts if needed */
3993  recheck_cast_function_args(args, result_type, func_tuple);
3994  }
3995 
3996  return args;
3997 }
#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:4136
static List * add_function_defaults(List *args, HeapTuple func_tuple)
Definition: clauses.c:4076
static List * reorder_function_arguments(List *args, HeapTuple func_tuple)
Definition: clauses.c:4006
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, NULL, 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:450
Oid funcid
Definition: primnodes.h:448
Oid opfuncid
Definition: primnodes.h:496
#define NULL
Definition: c.h:229
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1635
double clamp_row_est(double nrows)
Definition: costsize.c:173
bool opretset
Definition: primnodes.h:498
static List * fetch_function_defaults ( HeapTuple  func_tuple)
static

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

4102 {
4103  List *defaults;
4104  Datum proargdefaults;
4105  bool isnull;
4106  char *str;
4107 
4108  /* The error cases here shouldn't happen, but check anyway */
4109  proargdefaults = SysCacheGetAttr(PROCOID, func_tuple,
4111  &isnull);
4112  if (isnull)
4113  elog(ERROR, "not enough default arguments");
4114  str = TextDatumGetCString(proargdefaults);
4115  defaults = castNode(List, stringToNode(str));
4116  pfree(str);
4117  return defaults;
4118 }
void * stringToNode(char *str)
Definition: read.c:38
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
void pfree(void *pointer)
Definition: mcxt.c:950
#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:1279
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Var* find_forced_null_var ( Node node)

Definition at line 2065 of file clauses.c.

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

Referenced by check_redundant_nullability_qual(), and find_forced_null_vars().

2066 {
2067  if (node == NULL)
2068  return NULL;
2069  if (IsA(node, NullTest))
2070  {
2071  /* check for var IS NULL */
2072  NullTest *expr = (NullTest *) node;
2073 
2074  if (expr->nulltesttype == IS_NULL && !expr->argisrow)
2075  {
2076  Var *var = (Var *) expr->arg;
2077 
2078  if (var && IsA(var, Var) &&
2079  var->varlevelsup == 0)
2080  return var;
2081  }
2082  }
2083  else if (IsA(node, BooleanTest))
2084  {
2085  /* var IS UNKNOWN is equivalent to var IS NULL */
2086  BooleanTest *expr = (BooleanTest *) node;
2087 
2088  if (expr->booltesttype == IS_UNKNOWN)
2089  {
2090  Var *var = (Var *) expr->arg;
2091 
2092  if (var && IsA(var, Var) &&
2093  var->varlevelsup == 0)
2094  return var;
2095  }
2096  }
2097  return NULL;
2098 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Index varlevelsup
Definition: primnodes.h:173
Definition: primnodes.h:163
Expr * arg
Definition: primnodes.h:1179
Expr * arg
Definition: primnodes.h:1202
BoolTestType booltesttype
Definition: primnodes.h:1203
NullTestType nulltesttype
Definition: primnodes.h:1180
#define NULL
Definition: c.h:229
bool argisrow
Definition: primnodes.h:1181
List* find_forced_null_vars ( Node node)

Definition at line 2006 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, NIL, NULL, and result.

Referenced by find_forced_null_vars(), and reduce_outer_joins_pass2().

2007 {
2008  List *result = NIL;
2009  Var *var;
2010  ListCell *l;
2011 
2012  if (node == NULL)
2013  return NIL;
2014  /* Check single-clause cases using subroutine */
2015  var = find_forced_null_var(node);
2016  if (var)
2017  {
2018  result = list_make1(var);
2019  }
2020  /* Otherwise, handle AND-conditions */
2021  else if (IsA(node, List))
2022  {
2023  /*
2024  * At top level, we are examining an implicit-AND list: if any of the
2025  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
2026  */
2027  foreach(l, (List *) node)
2028  {
2029  result = list_concat(result,
2031  }
2032  }
2033  else if (IsA(node, BoolExpr))
2034  {
2035  BoolExpr *expr = (BoolExpr *) node;
2036 
2037  /*
2038  * We don't bother considering the OR case, because it's fairly
2039  * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
2040  * the NOT case isn't worth expending code on.
2041  */
2042  if (expr->boolop == AND_EXPR)
2043  {
2044  /* At top level we can just recurse (to the List case) */
2045  result = find_forced_null_vars((Node *) expr->args);
2046  }
2047  }
2048  return result;
2049 }
#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
return result
Definition: formatting.c:1632
Definition: primnodes.h:163
List * find_forced_null_vars(Node *node)
Definition: clauses.c:2006
#define list_make1(x1)
Definition: pg_list.h:139
BoolExprType boolop
Definition: primnodes.h:561
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
List * args
Definition: primnodes.h:562
Definition: pg_list.h:45
Var * find_forced_null_var(Node *node)
Definition: clauses.c:2065
Relids find_nonnullable_rels ( Node clause)

Definition at line 1605 of file clauses.c.

References find_nonnullable_rels_walker().

Referenced by make_outerjoininfo(), and reduce_outer_joins_pass2().

1606 {
1607  return find_nonnullable_rels_walker(clause, true);
1608 }
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1611
static Relids find_nonnullable_rels_walker ( Node node,
bool  top_level 
)
static

Definition at line 1611 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, NULL, NullTest::nulltesttype, OpExpr::opfuncid, OR_EXPR, PlaceHolderVar::phexpr, result, set_opfuncid(), Var::varlevelsup, and Var::varno.

Referenced by find_nonnullable_rels().

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

References find_nonnullable_vars_walker().

Referenced by reduce_outer_joins_pass2().

1814 {
1815  return find_nonnullable_vars_walker(clause, true);
1816 }
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1819
static List * find_nonnullable_vars_walker ( Node node,
bool  top_level 
)
static

Definition at line 1819 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, NULL, NullTest::nulltesttype, OpExpr::opfuncid, OR_EXPR, PlaceHolderVar::phexpr, result, set_opfuncid(), and Var::varlevelsup.

Referenced by find_nonnullable_vars().

1820 {
1821  List *result = NIL;
1822  ListCell *l;
1823 
1824  if (node == NULL)
1825  return NIL;
1826  if (IsA(node, Var))
1827  {
1828  Var *var = (Var *) node;
1829 
1830  if (var->varlevelsup == 0)
1831  result = list_make1(var);
1832  }
1833  else if (IsA(node, List))
1834  {
1835  /*
1836  * At top level, we are examining an implicit-AND list: if any of the
1837  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1838  * not at top level, we are examining the arguments of a strict
1839  * function: if any of them produce NULL then the result of the
1840  * function must be NULL. So in both cases, the set of nonnullable
1841  * vars is the union of those found in the arms, and we pass down the
1842  * top_level flag unmodified.
1843  */
1844  foreach(l, (List *) node)
1845  {
1846  result = list_concat(result,
1848  top_level));
1849  }
1850  }
1851  else if (IsA(node, FuncExpr))
1852  {
1853  FuncExpr *expr = (FuncExpr *) node;
1854 
1855  if (func_strict(expr->funcid))
1856  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1857  }
1858  else if (IsA(node, OpExpr))
1859  {
1860  OpExpr *expr = (OpExpr *) node;
1861 
1862  set_opfuncid(expr);
1863  if (func_strict(expr->opfuncid))
1864  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1865  }
1866  else if (IsA(node, ScalarArrayOpExpr))
1867  {
1868  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1869 
1870  if (is_strict_saop(expr, true))
1871  result = find_nonnullable_vars_walker((Node *) expr->args, false);
1872  }
1873  else if (IsA(node, BoolExpr))
1874  {
1875  BoolExpr *expr = (BoolExpr *) node;
1876 
1877  switch (expr->boolop)
1878  {
1879  case AND_EXPR:
1880  /* At top level we can just recurse (to the List case) */
1881  if (top_level)
1882  {
1883  result = find_nonnullable_vars_walker((Node *) expr->args,
1884  top_level);
1885  break;
1886  }
1887 
1888  /*
1889  * Below top level, even if one arm produces NULL, the result
1890  * could be FALSE (hence not NULL). However, if *all* the
1891  * arms produce NULL then the result is NULL, so we can take
1892  * the intersection of the sets of nonnullable vars, just as
1893  * for OR. Fall through to share code.
1894  */
1895  /* FALL THRU */
1896  case OR_EXPR:
1897 
1898  /*
1899  * OR is strict if all of its arms are, so we can take the
1900  * intersection of the sets of nonnullable vars for each arm.
1901  * This works for both values of top_level.
1902  */
1903  foreach(l, expr->args)
1904  {
1905  List *subresult;
1906 
1907  subresult = find_nonnullable_vars_walker(lfirst(l),
1908  top_level);
1909  if (result == NIL) /* first subresult? */
1910  result = subresult;
1911  else
1912  result = list_intersection(result, subresult);
1913 
1914  /*
1915  * If the intersection is empty, we can stop looking. This
1916  * also justifies the test for first-subresult above.
1917  */
1918  if (result == NIL)
1919  break;
1920  }
1921  break;
1922  case NOT_EXPR:
1923  /* NOT will return null if its arg is null */
1924  result = find_nonnullable_vars_walker((Node *) expr->args,
1925  false);
1926  break;
1927  default:
1928  elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1929  break;
1930  }
1931  }
1932  else if (IsA(node, RelabelType))
1933  {
1934  RelabelType *expr = (RelabelType *) node;
1935 
1936  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1937  }
1938  else if (IsA(node, CoerceViaIO))
1939  {
1940  /* not clear this is useful, but it can't hurt */
1941  CoerceViaIO *expr = (CoerceViaIO *) node;
1942 
1943  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1944  }
1945  else if (IsA(node, ArrayCoerceExpr))
1946  {
1947  /* ArrayCoerceExpr is strict at the array level */
1948  ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1949 
1950  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1951  }
1952  else if (IsA(node, ConvertRowtypeExpr))
1953  {
1954  /* not clear this is useful, but it can't hurt */
1955  ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1956 
1957  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1958  }
1959  else if (IsA(node, CollateExpr))
1960  {
1961  CollateExpr *expr = (CollateExpr *) node;
1962 
1963  result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1964  }
1965  else if (IsA(node, NullTest))
1966  {
1967  /* IS NOT NULL can be considered strict, but only at top level */
1968  NullTest *expr = (NullTest *) node;
1969 
1970  if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1971  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1972  }
1973  else if (IsA(node, BooleanTest))
1974  {
1975  /* Boolean tests that reject NULL are strict at top level */
1976  BooleanTest *expr = (BooleanTest *) node;
1977 
1978  if (top_level &&
1979  (expr->booltesttype == IS_TRUE ||
1980  expr->booltesttype == IS_FALSE ||
1981  expr->booltesttype == IS_NOT_UNKNOWN))
1982  result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1983  }
1984  else if (IsA(node, PlaceHolderVar))
1985  {
1986  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1987 
1988  result = find_nonnullable_vars_walker((Node *) phv->phexpr, top_level);
1989  }
1990  return result;
1991 }
#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:456
Expr * arg
Definition: primnodes.h:790
Definition: nodes.h:509
List * list_concat(List *list1, List *list2)
Definition: list.c:321
return result
Definition: formatting.c:1632
Definition: primnodes.h:163
#define list_make1(x1)
Definition: pg_list.h:139
Oid funcid
Definition: primnodes.h:448
#define ERROR
Definition: elog.h:43
Expr * phexpr
Definition: relation.h:1850
BoolExprType boolop
Definition: primnodes.h:561
Expr * arg
Definition: primnodes.h:1179
Expr * arg
Definition: primnodes.h:1202
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:1819
Expr * arg
Definition: primnodes.h:810
BoolTestType booltesttype
Definition: primnodes.h:1203
Oid opfuncid
Definition: primnodes.h:496
NullTestType nulltesttype
Definition: primnodes.h:1180
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition: clauses.c:2114
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Expr * arg
Definition: primnodes.h:875
List * args
Definition: primnodes.h:562
bool func_strict(Oid funcid)
Definition: lsyscache.c:1565
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1635
bool argisrow
Definition: primnodes.h:1181
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:501
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:878
void * palloc(Size size)
Definition: mcxt.c:849
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, NULL, 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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1865
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, NULL, 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:3454
#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:538
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:767
Cost startup
Definition: relation.h:45
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
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:256
#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:769
#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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:87
Expr * expr
Definition: primnodes.h:1367
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1865
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:768
Expr * aggfilter
Definition: primnodes.h:304
#define MAXALIGN(LEN)
Definition: c.h:588
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:770
#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:1786
Oid resolve_aggregate_transtype(Oid aggfuncid, Oid aggtranstype, Oid *inputTypes, int numArguments)
Definition: parse_agg.c:1812
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 4307 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, NULL, 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().

4312 {
4313  Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4314  char *src;
4315  Datum tmp;
4316  bool isNull;
4317  bool modifyTargetList;
4318  MemoryContext oldcxt;
4319  MemoryContext mycxt;
4320  inline_error_callback_arg callback_arg;
4321  ErrorContextCallback sqlerrcontext;
4322  FuncExpr *fexpr;
4324  ParseState *pstate;
4325  List *raw_parsetree_list;
4326  Query *querytree;
4327  Node *newexpr;
4328  int *usecounts;
4329  ListCell *arg;
4330  int i;
4331 
4332  /*
4333  * Forget it if the function is not SQL-language or has other showstopper
4334  * properties. (The nargs check is just paranoia.)
4335  */
4336  if (funcform->prolang != SQLlanguageId ||
4337  funcform->prosecdef ||
4338  funcform->proretset ||
4339  funcform->prorettype == RECORDOID ||
4340  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig) ||
4341  funcform->pronargs != list_length(args))
4342  return NULL;
4343 
4344  /* Check for recursive function, and give up trying to expand if so */
4345  if (list_member_oid(context->active_fns, funcid))
4346  return NULL;
4347 
4348  /* Check permission to call function (fail later, if not) */
4350  return NULL;
4351 
4352  /* Check whether a plugin wants to hook function entry/exit */
4353  if (FmgrHookIsNeeded(funcid))
4354  return NULL;
4355 
4356  /*
4357  * Make a temporary memory context, so that we don't leak all the stuff
4358  * that parsing might create.
4359  */
4361  "inline_function",
4363  oldcxt = MemoryContextSwitchTo(mycxt);
4364 
4365  /* Fetch the function body */
4366  tmp = SysCacheGetAttr(PROCOID,
4367  func_tuple,
4369  &isNull);
4370  if (isNull)
4371  elog(ERROR, "null prosrc for function %u", funcid);
4372  src = TextDatumGetCString(tmp);
4373 
4374  /*
4375  * Setup error traceback support for ereport(). This is so that we can
4376  * finger the function that bad information came from.
4377  */
4378  callback_arg.proname = NameStr(funcform->proname);
4379  callback_arg.prosrc = src;
4380 
4381  sqlerrcontext.callback = sql_inline_error_callback;
4382  sqlerrcontext.arg = (void *) &callback_arg;
4383  sqlerrcontext.previous = error_context_stack;
4384  error_context_stack = &sqlerrcontext;
4385 
4386  /*
4387  * Set up to handle parameters while parsing the function body. We need a
4388  * dummy FuncExpr node containing the already-simplified arguments to pass
4389  * to prepare_sql_fn_parse_info. (It is really only needed if there are
4390  * some polymorphic arguments, but for simplicity we always build it.)
4391  */
4392  fexpr = makeNode(FuncExpr);
4393  fexpr->funcid = funcid;
4394  fexpr->funcresulttype = result_type;
4395  fexpr->funcretset = false;
4396  fexpr->funcvariadic = funcvariadic;
4397  fexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
4398  fexpr->funccollid = result_collid; /* doesn't matter */
4399  fexpr->inputcollid = input_collid;
4400  fexpr->args = args;
4401  fexpr->location = -1;
4402 
4403  pinfo = prepare_sql_fn_parse_info(func_tuple,
4404  (Node *) fexpr,
4405  input_collid);
4406 
4407  /*
4408  * We just do parsing and parse analysis, not rewriting, because rewriting
4409  * will not affect table-free-SELECT-only queries, which is all that we
4410  * care about. Also, we can punt as soon as we detect more than one
4411  * command in the function body.
4412  */
4413  raw_parsetree_list = pg_parse_query(src);
4414  if (list_length(raw_parsetree_list) != 1)
4415  goto fail;
4416 
4417  pstate = make_parsestate(NULL);
4418  pstate->p_sourcetext = src;
4419  sql_fn_parser_setup(pstate, pinfo);
4420 
4421  querytree = transformTopLevelStmt(pstate, linitial(raw_parsetree_list));
4422 
4423  free_parsestate(pstate);
4424 
4425  /*
4426  * The single command must be a simple "SELECT expression".
4427  */
4428  if (!IsA(querytree, Query) ||
4429  querytree->commandType != CMD_SELECT ||
4430  querytree->hasAggs ||
4431  querytree->hasWindowFuncs ||
4432  querytree->hasTargetSRFs ||
4433  querytree->hasSubLinks ||
4434  querytree->cteList ||
4435  querytree->rtable ||
4436  querytree->jointree->fromlist ||
4437  querytree->jointree->quals ||
4438  querytree->groupClause ||
4439  querytree->groupingSets ||
4440  querytree->havingQual ||
4441  querytree->windowClause ||
4442  querytree->distinctClause ||
4443  querytree->sortClause ||
4444  querytree->limitOffset ||
4445  querytree->limitCount ||
4446  querytree->setOperations ||
4447  list_length(querytree->targetList) != 1)
4448  goto fail;
4449 
4450  /*
4451  * Make sure the function (still) returns what it's declared to. This
4452  * will raise an error if wrong, but that's okay since the function would
4453  * fail at runtime anyway. Note that check_sql_fn_retval will also insert
4454  * a RelabelType if needed to make the tlist expression match the declared
4455  * type of the function.
4456  *
4457  * Note: we do not try this until we have verified that no rewriting was
4458  * needed; that's probably not important, but let's be careful.
4459  */
4460  if (check_sql_fn_retval(funcid, result_type, list_make1(querytree),
4461  &modifyTargetList, NULL))
4462  goto fail; /* reject whole-tuple-result cases */
4463 
4464  /* Now we can grab the tlist expression */
4465  newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr;
4466 
4467  /* Assert that check_sql_fn_retval did the right thing */
4468  Assert(exprType(newexpr) == result_type);
4469  /* It couldn't have made any dangerous tlist changes, either */
4470  Assert(!modifyTargetList);
4471 
4472  /*
4473  * Additional validity checks on the expression. It mustn't be more
4474  * volatile than the surrounding function (this is to avoid breaking hacks
4475  * that involve pretending a function is immutable when it really ain't).
4476  * If the surrounding function is declared strict, then the expression
4477  * must contain only strict constructs and must use all of the function
4478  * parameters (this is overkill, but an exact analysis is hard).
4479  */
4480  if (funcform->provolatile == PROVOLATILE_IMMUTABLE &&
4481  contain_mutable_functions(newexpr))
4482  goto fail;
4483  else if (funcform->provolatile == PROVOLATILE_STABLE &&
4484  contain_volatile_functions(newexpr))
4485  goto fail;
4486 
4487  if (funcform->proisstrict &&
4488  contain_nonstrict_functions(newexpr))
4489  goto fail;
4490 
4491  /*
4492  * If any parameter expression contains a context-dependent node, we can't
4493  * inline, for fear of putting such a node into the wrong context.
4494  */
4495  if (contain_context_dependent_node((Node *) args))
4496  goto fail;
4497 
4498  /*
4499  * We may be able to do it; there are still checks on parameter usage to
4500  * make, but those are most easily done in combination with the actual
4501  * substitution of the inputs. So start building expression with inputs
4502  * substituted.
4503  */
4504  usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
4505  newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
4506  args, usecounts);
4507 
4508  /* Now check for parameter usage */
4509  i = 0;
4510  foreach(arg, args)
4511  {
4512  Node *param = lfirst(arg);
4513 
4514  if (usecounts[i] == 0)
4515  {
4516  /* Param not used at all: uncool if func is strict */
4517  if (funcform->proisstrict)
4518  goto fail;
4519  }
4520  else if (usecounts[i] != 1)
4521  {
4522  /* Param used multiple times: uncool if expensive or volatile */
4523  QualCost eval_cost;
4524 
4525  /*
4526  * We define "expensive" as "contains any subplan or more than 10
4527  * operators". Note that the subplan search has to be done
4528  * explicitly, since cost_qual_eval() will barf on unplanned
4529  * subselects.
4530  */
4531  if (contain_subplans(param))
4532  goto fail;
4533  cost_qual_eval(&eval_cost, list_make1(param), NULL);
4534  if (eval_cost.startup + eval_cost.per_tuple >
4535  10 * cpu_operator_cost)
4536  goto fail;
4537 
4538  /*
4539  * Check volatility last since this is more expensive than the
4540  * above tests
4541  */
4542  if (contain_volatile_functions(param))
4543  goto fail;
4544  }
4545  i++;
4546  }
4547 
4548  /*
4549  * Whew --- we can make the substitution. Copy the modified expression
4550  * out of the temporary memory context, and clean up.
4551  */
4552  MemoryContextSwitchTo(oldcxt);
4553 
4554  newexpr = copyObject(newexpr);
4555 
4556  MemoryContextDelete(mycxt);
4557 
4558  /*
4559  * If the result is of a collatable type, force the result to expose the
4560  * correct collation. In most cases this does not matter, but it's
4561  * possible that the function result is used directly as a sort key or in
4562  * other places where we expect exprCollation() to tell the truth.
4563  */
4564  if (OidIsValid(result_collid))
4565  {
4566  Oid exprcoll = exprCollation(newexpr);
4567 
4568  if (OidIsValid(exprcoll) && exprcoll != result_collid)
4569  {
4570  CollateExpr *newnode = makeNode(CollateExpr);
4571 
4572  newnode->arg = (Expr *) newexpr;
4573  newnode->collOid = result_collid;
4574  newnode->location = -1;
4575 
4576  newexpr = (Node *) newnode;
4577  }
4578  }
4579 
4580  /*
4581  * Since there is now no trace of the function in the plan tree, we must
4582  * explicitly record the plan's dependency on the function.
4583  */
4584  if (context->root)
4585  record_plan_function_dependency(context->root, funcid);
4586 
4587  /*
4588  * Recursively try to simplify the modified expression. Here we must add
4589  * the current function to the context list of active functions.
4590  */
4591  context->active_fns = lcons_oid(funcid, context->active_fns);
4592  newexpr = eval_const_expressions_mutator(newexpr, context);
4593  context->active_fns = list_delete_first(context->active_fns);
4594 
4595  error_context_stack = sqlerrcontext.previous;
4596 
4597  return (Expr *) newexpr;
4598 
4599  /* Here if func is not inlinable: release temp memory and return NULL */
4600 fail:
4601  MemoryContextSwitchTo(oldcxt);
4602  MemoryContextDelete(mycxt);
4603  error_context_stack = sqlerrcontext.previous;
4604 
4605  return NULL;
4606 }
Node * limitOffset
Definition: parsenodes.h:158
Oid funcresulttype
Definition: primnodes.h:449
#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:5483
List * sortClause
Definition: parsenodes.h:156
List * args
Definition: primnodes.h:456
FromExpr * jointree
Definition: parsenodes.h:136
Oid GetUserId(void)
Definition: miscinit.c:283
Oid funccollid
Definition: primnodes.h:454
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:1531
bool funcretset
Definition: primnodes.h:450
List * lcons_oid(Oid datum, List *list)
Definition: list.c:295
List * fromlist
Definition: primnodes.h:1470
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:951
unsigned int Oid
Definition: postgres_ext.h:31
struct ErrorContextCallback * previous
Definition: elog.h:238
#define OidIsValid(objectId)
Definition: c.h:538
#define FmgrHookIsNeeded(fn_oid)
Definition: fmgr.h:728
Node * quals
Definition: primnodes.h:1471
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:453
Cost per_tuple
Definition: relation.h:46
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition: clauses.c:2447
#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:448
#define ERROR
Definition: elog.h:43
#define SQLlanguageId
Definition: pg_language.h:80
#define PROVOLATILE_STABLE
Definition: pg_proc.h:5484
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:3428
List * pg_parse_query(const char *query_string)
Definition: postgres.c:602
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
Node * limitCount
Definition: parsenodes.h:159
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:297
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:168
static Node * substitute_actual_parameters(Node *expr, int nargs, List *args, int *usecounts)
Definition: clauses.c:4612
static void sql_inline_error_callback(void *arg)
Definition: clauses.c:4654
#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:878
uintptr_t Datum
Definition: postgres.h:372
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
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:455
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#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:748
Expr * arg
Definition: primnodes.h:875
Datum querytree(PG_FUNCTION_ARGS)
Definition: _int_bool.c:665
static bool contain_context_dependent_node(Node *clause)
Definition: clauses.c:1395
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:499
void * arg
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:878
int location
Definition: primnodes.h:457
#define elog
Definition: elog.h:219
bool contain_nonstrict_functions(Node *clause)
Definition: clauses.c:1268
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
Definition: functions.c:184
#define copyObject(obj)
Definition: nodes.h:621
Node * havingQual
Definition: parsenodes.h:150
int location
Definition: primnodes.h:877
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
Definition: pg_list.h:45
bool funcvariadic
Definition: primnodes.h:451
List * list_delete_first(List *list)
Definition: list.c:666
Query* inline_set_returning_function ( PlannerInfo root,
RangeTblEntry rte 
)

Definition at line 4766 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, NULL, 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().

4767 {
4768  RangeTblFunction *rtfunc;
4769  FuncExpr *fexpr;
4770  Oid func_oid;
4771  HeapTuple func_tuple;
4772  Form_pg_proc funcform;
4773  char *src;
4774  Datum tmp;
4775  bool isNull;
4776  bool modifyTargetList;
4777  MemoryContext oldcxt;
4778  MemoryContext mycxt;
4779  List *saveInvalItems;
4780  inline_error_callback_arg callback_arg;
4781  ErrorContextCallback sqlerrcontext;
4783  List *raw_parsetree_list;
4784  List *querytree_list;
4785  Query *querytree;
4786 
4787  Assert(rte->rtekind == RTE_FUNCTION);
4788 
4789  /*
4790  * It doesn't make a lot of sense for a SQL SRF to refer to itself in its
4791  * own FROM clause, since that must cause infinite recursion at runtime.
4792  * It will cause this code to recurse too, so check for stack overflow.
4793  * (There's no need to do more.)
4794  */
4796 
4797  /* Fail if the RTE has ORDINALITY - we don't implement that here. */
4798