PostgreSQL Source Code  git master
clauses.h File Reference
#include "nodes/pathnodes.h"
Include dependency graph for clauses.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  WindowFuncLists
 

Functions

bool contain_agg_clause (Node *clause)
 
bool contain_window_function (Node *clause)
 
WindowFuncListsfind_window_functions (Node *clause, Index maxWinRef)
 
double expression_returns_set_rows (PlannerInfo *root, Node *clause)
 
bool contain_subplans (Node *clause)
 
char max_parallel_hazard (Query *parse)
 
bool is_parallel_safe (PlannerInfo *root, Node *node)
 
bool contain_nonstrict_functions (Node *clause)
 
bool contain_exec_param (Node *clause, List *param_ids)
 
bool contain_leaked_vars (Node *clause)
 
Relids find_nonnullable_rels (Node *clause)
 
Listfind_nonnullable_vars (Node *clause)
 
Listfind_forced_null_vars (Node *clause)
 
Varfind_forced_null_var (Node *clause)
 
bool is_pseudo_constant_clause (Node *clause)
 
bool is_pseudo_constant_clause_relids (Node *clause, Relids relids)
 
int NumRelids (PlannerInfo *root, Node *clause)
 
void CommuteOpExpr (OpExpr *clause)
 
Queryinline_set_returning_function (PlannerInfo *root, RangeTblEntry *rte)
 

Function Documentation

◆ CommuteOpExpr()

void CommuteOpExpr ( OpExpr clause)

Definition at line 1915 of file clauses.c.

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

Referenced by get_switched_clauses().

1916 {
1917  Oid opoid;
1918  Node *temp;
1919 
1920  /* Sanity checks: caller is at fault if these fail */
1921  if (!is_opclause(clause) ||
1922  list_length(clause->args) != 2)
1923  elog(ERROR, "cannot commute non-binary-operator clause");
1924 
1925  opoid = get_commutator(clause->opno);
1926 
1927  if (!OidIsValid(opoid))
1928  elog(ERROR, "could not find commutator for operator %u",
1929  clause->opno);
1930 
1931  /*
1932  * modify the clause in-place!
1933  */
1934  clause->opno = opoid;
1935  clause->opfuncid = InvalidOid;
1936  /* opresulttype, opretset, opcollid, inputcollid need not change */
1937 
1938  temp = linitial(clause->args);
1939  linitial(clause->args) = lsecond(clause->args);
1940  lsecond(clause->args) = temp;
1941 }
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1480
Definition: nodes.h:530
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define lsecond(l)
Definition: pg_list.h:179
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:45
Oid opfuncid
Definition: primnodes.h:538
#define InvalidOid
Definition: postgres_ext.h:36
static int list_length(const List *l)
Definition: pg_list.h:149
#define elog(elevel,...)
Definition: elog.h:228
Oid opno
Definition: primnodes.h:537
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:66
List * args
Definition: primnodes.h:543

◆ contain_agg_clause()

bool contain_agg_clause ( Node clause)

Definition at line 170 of file clauses.c.

References contain_agg_clause_walker().

Referenced by get_eclass_for_sort_expr(), and subquery_planner().

171 {
172  return contain_agg_clause_walker(clause, NULL);
173 }
static bool contain_agg_clause_walker(Node *node, void *context)
Definition: clauses.c:176

◆ contain_exec_param()

bool contain_exec_param ( Node clause,
List param_ids 
)

Definition at line 951 of file clauses.c.

References contain_exec_param_walker().

Referenced by test_opexpr_is_hashable().

952 {
953  return contain_exec_param_walker(clause, param_ids);
954 }
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition: clauses.c:957

◆ contain_leaked_vars()

bool contain_leaked_vars ( Node clause)

Definition at line 1077 of file clauses.c.

References contain_leaked_vars_walker().

Referenced by make_restrictinfo_internal(), and qual_is_pushdown_safe().

1078 {
1079  return contain_leaked_vars_walker(clause, NULL);
1080 }
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1089

◆ contain_nonstrict_functions()

bool contain_nonstrict_functions ( Node clause)

Definition at line 807 of file clauses.c.

References contain_nonstrict_functions_walker().

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

808 {
809  return contain_nonstrict_functions_walker(clause, NULL);
810 }
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:819

◆ contain_subplans()

bool contain_subplans ( Node clause)

Definition at line 323 of file clauses.c.

References contain_subplans_walker().

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

324 {
325  return contain_subplans_walker(clause, NULL);
326 }
static bool contain_subplans_walker(Node *node, void *context)
Definition: clauses.c:329

◆ contain_window_function()

bool contain_window_function ( Node clause)

Definition at line 207 of file clauses.c.

References contain_windowfuncs().

Referenced by get_eclass_for_sort_expr(), and qual_is_pushdown_safe().

208 {
209  return contain_windowfuncs(clause);
210 }
bool contain_windowfuncs(Node *node)
Definition: rewriteManip.c:197

◆ expression_returns_set_rows()

double expression_returns_set_rows ( PlannerInfo root,
Node clause 
)

Definition at line 282 of file clauses.c.

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

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

283 {
284  if (clause == NULL)
285  return 1.0;
286  if (IsA(clause, FuncExpr))
287  {
288  FuncExpr *expr = (FuncExpr *) clause;
289 
290  if (expr->funcretset)
291  return clamp_row_est(get_function_rows(root, expr->funcid, clause));
292  }
293  if (IsA(clause, OpExpr))
294  {
295  OpExpr *expr = (OpExpr *) clause;
296 
297  if (expr->opretset)
298  {
299  set_opfuncid(expr);
300  return clamp_row_est(get_function_rows(root, expr->opfuncid, clause));
301  }
302  }
303  return 1.0;
304 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:581
bool funcretset
Definition: primnodes.h:492
Oid funcid
Definition: primnodes.h:490
Oid opfuncid
Definition: primnodes.h:538
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1664
double clamp_row_est(double nrows)
Definition: costsize.c:196
bool opretset
Definition: primnodes.h:540
double get_function_rows(PlannerInfo *root, Oid funcid, Node *node)
Definition: plancat.c:1979

◆ find_forced_null_var()

Var* find_forced_null_var ( Node clause)

Definition at line 1747 of file clauses.c.

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

Referenced by check_redundant_nullability_qual(), and find_forced_null_vars().

1748 {
1749  if (node == NULL)
1750  return NULL;
1751  if (IsA(node, NullTest))
1752  {
1753  /* check for var IS NULL */
1754  NullTest *expr = (NullTest *) node;
1755 
1756  if (expr->nulltesttype == IS_NULL && !expr->argisrow)
1757  {
1758  Var *var = (Var *) expr->arg;
1759 
1760  if (var && IsA(var, Var) &&
1761  var->varlevelsup == 0)
1762  return var;
1763  }
1764  }
1765  else if (IsA(node, BooleanTest))
1766  {
1767  /* var IS UNKNOWN is equivalent to var IS NULL */
1768  BooleanTest *expr = (BooleanTest *) node;
1769 
1770  if (expr->booltesttype == IS_UNKNOWN)
1771  {
1772  Var *var = (Var *) expr->arg;
1773 
1774  if (var && IsA(var, Var) &&
1775  var->varlevelsup == 0)
1776  return var;
1777  }
1778  }
1779  return NULL;
1780 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:581
Index varlevelsup
Definition: primnodes.h:191
Definition: primnodes.h:181
Expr * arg
Definition: primnodes.h:1243
Expr * arg
Definition: primnodes.h:1266
BoolTestType booltesttype
Definition: primnodes.h:1267
NullTestType nulltesttype
Definition: primnodes.h:1244
bool argisrow
Definition: primnodes.h:1245

◆ find_forced_null_vars()

List* find_forced_null_vars ( Node clause)

Definition at line 1688 of file clauses.c.

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

Referenced by find_forced_null_vars(), and reduce_outer_joins_pass2().

1689 {
1690  List *result = NIL;
1691  Var *var;
1692  ListCell *l;
1693 
1694  if (node == NULL)
1695  return NIL;
1696  /* Check single-clause cases using subroutine */
1697  var = find_forced_null_var(node);
1698  if (var)
1699  {
1700  result = list_make1(var);
1701  }
1702  /* Otherwise, handle AND-conditions */
1703  else if (IsA(node, List))
1704  {
1705  /*
1706  * At top level, we are examining an implicit-AND list: if any of the
1707  * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1708  */
1709  foreach(l, (List *) node)
1710  {
1711  result = list_concat(result,
1713  }
1714  }
1715  else if (IsA(node, BoolExpr))
1716  {
1717  BoolExpr *expr = (BoolExpr *) node;
1718 
1719  /*
1720  * We don't bother considering the OR case, because it's fairly
1721  * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
1722  * the NOT case isn't worth expending code on.
1723  */
1724  if (expr->boolop == AND_EXPR)
1725  {
1726  /* At top level we can just recurse (to the List case) */
1727  result = find_forced_null_vars((Node *) expr->args);
1728  }
1729  }
1730  return result;
1731 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:581
Definition: nodes.h:530
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
Definition: primnodes.h:181
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1688
#define list_make1(x1)
Definition: pg_list.h:206
BoolExprType boolop
Definition: primnodes.h:603
#define lfirst(lc)
Definition: pg_list.h:169
List * args
Definition: primnodes.h:604
Definition: pg_list.h:50
Var * find_forced_null_var(Node *node)
Definition: clauses.c:1747

◆ find_nonnullable_rels()

Relids find_nonnullable_rels ( Node clause)

Definition at line 1270 of file clauses.c.

References find_nonnullable_rels_walker().

Referenced by make_outerjoininfo(), and reduce_outer_joins_pass2().

1271 {
1272  return find_nonnullable_rels_walker(clause, true);
1273 }
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1276

◆ find_nonnullable_vars()

List* find_nonnullable_vars ( Node clause)

Definition at line 1495 of file clauses.c.

References find_nonnullable_vars_walker().

Referenced by reduce_outer_joins_pass2().

1496 {
1497  return find_nonnullable_vars_walker(clause, true);
1498 }
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1501

◆ find_window_functions()

WindowFuncLists* find_window_functions ( Node clause,
Index  maxWinRef 
)

Definition at line 220 of file clauses.c.

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

Referenced by grouping_planner().

221 {
222  WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
223 
224  lists->numWindowFuncs = 0;
225  lists->maxWinRef = maxWinRef;
226  lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
227  (void) find_window_functions_walker(clause, lists);
228  return lists;
229 }
Index maxWinRef
Definition: clauses.h:22
int numWindowFuncs
Definition: clauses.h:21
void * palloc0(Size size)
Definition: mcxt.c:981
void * palloc(Size size)
Definition: mcxt.c:950
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:232
Definition: pg_list.h:50
List ** windowFuncs
Definition: clauses.h:23

◆ inline_set_returning_function()

Query* inline_set_returning_function ( PlannerInfo root,
RangeTblEntry rte 
)

Definition at line 4589 of file clauses.c.

References ACL_EXECUTE, ACLCHECK_OK, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, FuncExpr::args, Assert, BuildDescFromLists(), 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, FmgrHookIsNeeded, RangeTblFunction::funccolcollations, RangeTblFunction::funccolnames, RangeTblFunction::funccoltypes, RangeTblFunction::funccoltypmods, RangeTblFunction::funcexpr, FuncExpr::funcid, RangeTblEntry::funcordinality, FuncExpr::funcretset, RangeTblEntry::functions, get_expr_result_type(), GETSTRUCT, GetUserId(), heap_attisnull(), HeapTupleIsValid, IsA, linitial, linitial_node, list_length(), list_make1, MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, 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, querytree(), record_plan_function_dependency(), ReleaseSysCache(), RTE_FUNCTION, RangeTblEntry::rtekind, SearchSysCache1(), sql_fn_parser_setup(), sql_inline_error_callback(), substitute_actual_srf_parameters(), SysCacheGetAttr(), TextDatumGetCString, TYPEFUNC_COMPOSITE, TYPEFUNC_COMPOSITE_DOMAIN, and TYPEFUNC_RECORD.

Referenced by preprocess_function_rtes().

4590 {
4591  RangeTblFunction *rtfunc;
4592  FuncExpr *fexpr;
4593  Oid func_oid;
4594  HeapTuple func_tuple;
4595  Form_pg_proc funcform;
4596  char *src;
4597  Datum tmp;
4598  bool isNull;
4599  MemoryContext oldcxt;
4600  MemoryContext mycxt;
4601  inline_error_callback_arg callback_arg;
4602  ErrorContextCallback sqlerrcontext;
4604  TypeFuncClass functypclass;
4605  TupleDesc rettupdesc;
4606  List *raw_parsetree_list;
4607  List *querytree_list;
4608  Query *querytree;
4609 
4610  Assert(rte->rtekind == RTE_FUNCTION);
4611 
4612  /*
4613  * It doesn't make a lot of sense for a SQL SRF to refer to itself in its
4614  * own FROM clause, since that must cause infinite recursion at runtime.
4615  * It will cause this code to recurse too, so check for stack overflow.
4616  * (There's no need to do more.)
4617  */
4619 
4620  /* Fail if the RTE has ORDINALITY - we don't implement that here. */
4621  if (rte->funcordinality)
4622  return NULL;
4623 
4624  /* Fail if RTE isn't a single, simple FuncExpr */
4625  if (list_length(rte->functions) != 1)
4626  return NULL;
4627  rtfunc = (RangeTblFunction *) linitial(rte->functions);
4628 
4629  if (!IsA(rtfunc->funcexpr, FuncExpr))
4630  return NULL;
4631  fexpr = (FuncExpr *) rtfunc->funcexpr;
4632 
4633  func_oid = fexpr->funcid;
4634 
4635  /*
4636  * The function must be declared to return a set, else inlining would
4637  * change the results if the contained SELECT didn't return exactly one
4638  * row.
4639  */
4640  if (!fexpr->funcretset)
4641  return NULL;
4642 
4643  /*
4644  * Refuse to inline if the arguments contain any volatile functions or
4645  * sub-selects. Volatile functions are rejected because inlining may
4646  * result in the arguments being evaluated multiple times, risking a
4647  * change in behavior. Sub-selects are rejected partly for implementation
4648  * reasons (pushing them down another level might change their behavior)
4649  * and partly because they're likely to be expensive and so multiple
4650  * evaluation would be bad.
4651  */
4652  if (contain_volatile_functions((Node *) fexpr->args) ||
4653  contain_subplans((Node *) fexpr->args))
4654  return NULL;
4655 
4656  /* Check permission to call function (fail later, if not) */
4657  if (pg_proc_aclcheck(func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
4658  return NULL;
4659 
4660  /* Check whether a plugin wants to hook function entry/exit */
4661  if (FmgrHookIsNeeded(func_oid))
4662  return NULL;
4663 
4664  /*
4665  * OK, let's take a look at the function's pg_proc entry.
4666  */
4667  func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid));
4668  if (!HeapTupleIsValid(func_tuple))
4669  elog(ERROR, "cache lookup failed for function %u", func_oid);
4670  funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
4671 
4672  /*
4673  * Forget it if the function is not SQL-language or has other showstopper
4674  * properties. In particular it mustn't be declared STRICT, since we
4675  * couldn't enforce that. It also mustn't be VOLATILE, because that is
4676  * supposed to cause it to be executed with its own snapshot, rather than
4677  * sharing the snapshot of the calling query. We also disallow returning
4678  * SETOF VOID, because inlining would result in exposing the actual result
4679  * of the function's last SELECT, which should not happen in that case.
4680  * (Rechecking prokind, proretset, and pronargs is just paranoia.)
4681  */
4682  if (funcform->prolang != SQLlanguageId ||
4683  funcform->prokind != PROKIND_FUNCTION ||
4684  funcform->proisstrict ||
4685  funcform->provolatile == PROVOLATILE_VOLATILE ||
4686  funcform->prorettype == VOIDOID ||
4687  funcform->prosecdef ||
4688  !funcform->proretset ||
4689  list_length(fexpr->args) != funcform->pronargs ||
4690  !heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL))
4691  {
4692  ReleaseSysCache(func_tuple);
4693  return NULL;
4694  }
4695 
4696  /*
4697  * Make a temporary memory context, so that we don't leak all the stuff
4698  * that parsing might create.
4699  */
4701  "inline_set_returning_function",
4703  oldcxt = MemoryContextSwitchTo(mycxt);
4704 
4705  /* Fetch the function body */
4706  tmp = SysCacheGetAttr(PROCOID,
4707  func_tuple,
4708  Anum_pg_proc_prosrc,
4709  &isNull);
4710  if (isNull)
4711  elog(ERROR, "null prosrc for function %u", func_oid);
4712  src = TextDatumGetCString(tmp);
4713 
4714  /*
4715  * Setup error traceback support for ereport(). This is so that we can
4716  * finger the function that bad information came from.
4717  */
4718  callback_arg.proname = NameStr(funcform->proname);
4719  callback_arg.prosrc = src;
4720 
4721  sqlerrcontext.callback = sql_inline_error_callback;
4722  sqlerrcontext.arg = (void *) &callback_arg;
4723  sqlerrcontext.previous = error_context_stack;
4724  error_context_stack = &sqlerrcontext;
4725 
4726  /*
4727  * Set up to handle parameters while parsing the function body. We can
4728  * use the FuncExpr just created as the input for
4729  * prepare_sql_fn_parse_info.
4730  */
4731  pinfo = prepare_sql_fn_parse_info(func_tuple,
4732  (Node *) fexpr,
4733  fexpr->inputcollid);
4734 
4735  /*
4736  * Also resolve the actual function result tupdesc, if composite. If the
4737  * function is just declared to return RECORD, dig the info out of the AS
4738  * clause.
4739  */
4740  functypclass = get_expr_result_type((Node *) fexpr, NULL, &rettupdesc);
4741  if (functypclass == TYPEFUNC_RECORD)
4742  rettupdesc = BuildDescFromLists(rtfunc->funccolnames,
4743  rtfunc->funccoltypes,
4744  rtfunc->funccoltypmods,
4745  rtfunc->funccolcollations);
4746 
4747  /*
4748  * Parse, analyze, and rewrite (unlike inline_function(), we can't skip
4749  * rewriting here). We can fail as soon as we find more than one query,
4750  * though.
4751  */
4752  raw_parsetree_list = pg_parse_query(src);
4753  if (list_length(raw_parsetree_list) != 1)
4754  goto fail;
4755 
4756  querytree_list = pg_analyze_and_rewrite_params(linitial(raw_parsetree_list),
4757  src,
4759  pinfo, NULL);
4760  if (list_length(querytree_list) != 1)
4761  goto fail;
4762  querytree = linitial(querytree_list);
4763 
4764  /*
4765  * The single command must be a plain SELECT.
4766  */
4767  if (!IsA(querytree, Query) ||
4768  querytree->commandType != CMD_SELECT)
4769  goto fail;
4770 
4771  /*
4772  * Make sure the function (still) returns what it's declared to. This
4773  * will raise an error if wrong, but that's okay since the function would
4774  * fail at runtime anyway. Note that check_sql_fn_retval will also insert
4775  * coercions if needed to make the tlist expression(s) match the declared
4776  * type of the function. We also ask it to insert dummy NULL columns for
4777  * any dropped columns in rettupdesc, so that the elements of the modified
4778  * tlist match up to the attribute numbers.
4779  *
4780  * If the function returns a composite type, don't inline unless the check
4781  * shows it's returning a whole tuple result; otherwise what it's
4782  * returning is a single composite column which is not what we need.
4783  */
4784  if (!check_sql_fn_retval(list_make1(querytree_list),
4785  fexpr->funcresulttype, rettupdesc,
4786  true, NULL) &&
4787  (functypclass == TYPEFUNC_COMPOSITE ||
4788  functypclass == TYPEFUNC_COMPOSITE_DOMAIN ||
4789  functypclass == TYPEFUNC_RECORD))
4790  goto fail; /* reject not-whole-tuple-result cases */
4791 
4792  /*
4793  * check_sql_fn_retval might've inserted a projection step, but that's
4794  * fine; just make sure we use the upper Query.
4795  */
4796  querytree = linitial_node(Query, querytree_list);
4797 
4798  /*
4799  * Looks good --- substitute parameters into the query.
4800  */
4801  querytree = substitute_actual_srf_parameters(querytree,
4802  funcform->pronargs,
4803  fexpr->args);
4804 
4805  /*
4806  * Copy the modified query out of the temporary memory context, and clean
4807  * up.
4808  */
4809  MemoryContextSwitchTo(oldcxt);
4810 
4811  querytree = copyObject(querytree);
4812 
4813  MemoryContextDelete(mycxt);
4814  error_context_stack = sqlerrcontext.previous;
4815  ReleaseSysCache(func_tuple);
4816 
4817  /*
4818  * We don't have to fix collations here because the upper query is already
4819  * parsed, ie, the collations in the RTE are what count.
4820  */
4821 
4822  /*
4823  * Since there is now no trace of the function in the plan tree, we must
4824  * explicitly record the plan's dependency on the function.
4825  */
4826  record_plan_function_dependency(root, func_oid);
4827 
4828  return querytree;
4829 
4830  /* Here if func is not inlinable: release temp memory and return NULL */
4831 fail:
4832  MemoryContextSwitchTo(oldcxt);
4833  MemoryContextDelete(mycxt);
4834  error_context_stack = sqlerrcontext.previous;
4835  ReleaseSysCache(func_tuple);
4836 
4837  return NULL;
4838 }
Oid funcresulttype
Definition: primnodes.h:491
bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, bool insertDroppedCols, List **resultTargetList)
Definition: functions.c:1601
#define IsA(nodeptr, _type_)
Definition: nodes.h:581
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
#define AllocSetContextCreate
Definition: memutils.h:170
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
TupleDesc BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
Definition: tupdesc.c:892
List * args
Definition: primnodes.h:498
Oid GetUserId(void)
Definition: miscinit.c:476
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition: functions.c:280
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:530
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
bool funcretset
Definition: primnodes.h:492
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:437
bool funcordinality
Definition: parsenodes.h:1069
unsigned int Oid
Definition: postgres_ext.h:31
#define linitial_node(type, l)
Definition: pg_list.h:177
void(* callback)(void *arg)
Definition: elog.h:243
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:223
struct ErrorContextCallback * previous
Definition: elog.h:242
#define FmgrHookIsNeeded(fn_oid)
Definition: fmgr.h:774
ErrorContextCallback * error_context_stack
Definition: elog.c:93
#define list_make1(x1)
Definition: pg_list.h:206
bool contain_subplans(Node *clause)
Definition: clauses.c:323
#define linitial(l)
Definition: pg_list.h:174
Oid funcid
Definition: primnodes.h:490
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
List * pg_parse_query(const char *query_string)
Definition: postgres.c:629
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
Definition: params.h:108
void check_stack_depth(void)
Definition: postgres.c:3377
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
TypeFuncClass
Definition: funcapi.h:146
static void sql_inline_error_callback(void *arg)
Definition: clauses.c:4473
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2889
static Query * substitute_actual_srf_parameters(Query *expr, int nargs, List *args)
Definition: clauses.c:4847
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
List * funccoltypmods
Definition: parsenodes.h:1158
CmdType commandType
Definition: parsenodes.h:112
List * funccolcollations
Definition: parsenodes.h:1159
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
List * functions
Definition: parsenodes.h:1068
static int list_length(const List *l)
Definition: pg_list.h:149
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:714
Datum querytree(PG_FUNCTION_ARGS)
Definition: _int_bool.c:664
RTEKind rtekind
Definition: parsenodes.h:981
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:228
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4606
#define NameStr(name)
Definition: c.h:681
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
Definition: functions.c:190
#define copyObject(obj)
Definition: nodes.h:646
Definition: pg_list.h:50

◆ is_parallel_safe()

bool is_parallel_safe ( PlannerInfo root,
Node node 
)

Definition at line 567 of file clauses.c.

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

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

568 {
570  PlannerInfo *proot;
571  ListCell *l;
572 
573  /*
574  * Even if the original querytree contained nothing unsafe, we need to
575  * search the expression if we have generated any PARAM_EXEC Params while
576  * planning, because those are parallel-restricted and there might be one
577  * in this expression. But otherwise we don't need to look.
578  */
579  if (root->glob->maxParallelHazard == PROPARALLEL_SAFE &&
580  root->glob->paramExecTypes == NIL)
581  return true;
582  /* Else use max_parallel_hazard's search logic, but stop on RESTRICTED */
583  context.max_hazard = PROPARALLEL_SAFE;
584  context.max_interesting = PROPARALLEL_RESTRICTED;
585  context.safe_param_ids = NIL;
586 
587  /*
588  * The params that refer to the same or parent query level are considered
589  * parallel-safe. The idea is that we compute such params at Gather or
590  * Gather Merge node and pass their value to workers.
591  */
592  for (proot = root; proot != NULL; proot = proot->parent_root)
593  {
594  foreach(l, proot->init_plans)
595  {
596  SubPlan *initsubplan = (SubPlan *) lfirst(l);
597 
598  context.safe_param_ids = list_concat(context.safe_param_ids,
599  initsubplan->setParam);
600  }
601  }
602 
603  return !max_parallel_hazard_walker(node, &context);
604 }
char maxParallelHazard
Definition: pathnodes.h:141
#define NIL
Definition: pg_list.h:65
PlannerInfo * parent_root
Definition: pathnodes.h:179
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
List * paramExecTypes
Definition: pathnodes.h:125
static bool max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
Definition: clauses.c:643
PlannerGlobal * glob
Definition: pathnodes.h:175
List * init_plans
Definition: pathnodes.h:253
#define lfirst(lc)
Definition: pg_list.h:169
List * setParam
Definition: primnodes.h:748

◆ is_pseudo_constant_clause()

bool is_pseudo_constant_clause ( Node clause)

Definition at line 1858 of file clauses.c.

References contain_var_clause(), and contain_volatile_functions().

Referenced by clauselist_selectivity_ext(), and dependency_is_compatible_clause().

1859 {
1860  /*
1861  * We could implement this check in one recursive scan. But since the
1862  * check for volatile functions is both moderately expensive and unlikely
1863  * to fail, it seems better to look for Vars first and only check for
1864  * volatile functions if we find no Vars.
1865  */
1866  if (!contain_var_clause(clause) &&
1867  !contain_volatile_functions(clause))
1868  return true;
1869  return false;
1870 }
bool contain_var_clause(Node *node)
Definition: var.c:358
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:437

◆ is_pseudo_constant_clause_relids()

bool is_pseudo_constant_clause_relids ( Node clause,
Relids  relids 
)

Definition at line 1878 of file clauses.c.

References bms_is_empty(), and contain_volatile_functions().

Referenced by clauselist_selectivity_ext().

1879 {
1880  if (bms_is_empty(relids) &&
1881  !contain_volatile_functions(clause))
1882  return true;
1883  return false;
1884 }
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:437
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701

◆ max_parallel_hazard()

char max_parallel_hazard ( Query parse)

Definition at line 548 of file clauses.c.

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

Referenced by standard_planner().

549 {
551 
552  context.max_hazard = PROPARALLEL_SAFE;
553  context.max_interesting = PROPARALLEL_UNSAFE;
554  context.safe_param_ids = NIL;
555  (void) max_parallel_hazard_walker((Node *) parse, &context);
556  return context.max_hazard;
557 }
#define NIL
Definition: pg_list.h:65
Definition: nodes.h:530
static bool max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
Definition: clauses.c:643
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:664

◆ NumRelids()

int NumRelids ( PlannerInfo root,
Node clause 
)

Definition at line 1900 of file clauses.c.

References bms_free(), bms_num_members(), and pull_varnos().

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

1901 {
1902  Relids varnos = pull_varnos(root, clause);
1903  int result = bms_num_members(varnos);
1904 
1905  bms_free(varnos);
1906  return result;
1907 }
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:97
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208