PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 *node)
 
Varfind_forced_null_var (Node *node)
 
bool is_pseudo_constant_clause (Node *clause)
 
bool is_pseudo_constant_clause_relids (Node *clause, Relids relids)
 
int NumRelids (PlannerInfo *root, Node *clause)
 
void CommuteOpExpr (OpExpr *clause)
 
Queryinline_set_returning_function (PlannerInfo *root, RangeTblEntry *rte)
 
Bitmapsetpull_paramids (Expr *expr)
 

Function Documentation

◆ CommuteOpExpr()

void CommuteOpExpr ( OpExpr clause)

Definition at line 2149 of file clauses.c.

2150{
2151 Oid opoid;
2152 Node *temp;
2153
2154 /* Sanity checks: caller is at fault if these fail */
2155 if (!is_opclause(clause) ||
2156 list_length(clause->args) != 2)
2157 elog(ERROR, "cannot commute non-binary-operator clause");
2158
2159 opoid = get_commutator(clause->opno);
2160
2161 if (!OidIsValid(opoid))
2162 elog(ERROR, "could not find commutator for operator %u",
2163 clause->opno);
2164
2165 /*
2166 * modify the clause in-place!
2167 */
2168 clause->opno = opoid;
2169 clause->opfuncid = InvalidOid;
2170 /* opresulttype, opretset, opcollid, inputcollid need not change */
2171
2172 temp = linitial(clause->args);
2173 linitial(clause->args) = lsecond(clause->args);
2174 lsecond(clause->args) = temp;
2175}
#define OidIsValid(objectId)
Definition: c.h:746
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1649
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:76
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
Definition: nodes.h:135
Oid opno
Definition: primnodes.h:835
List * args
Definition: primnodes.h:853

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

Referenced by get_switched_clauses().

◆ contain_agg_clause()

bool contain_agg_clause ( Node clause)

Definition at line 179 of file clauses.c.

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

References contain_agg_clause_walker().

Referenced by get_eclass_for_sort_expr(), mark_nullable_by_grouping(), and subquery_planner().

◆ contain_exec_param()

bool contain_exec_param ( Node clause,
List param_ids 
)

Definition at line 1138 of file clauses.c.

1139{
1140 return contain_exec_param_walker(clause, param_ids);
1141}
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition: clauses.c:1144

References contain_exec_param_walker().

Referenced by test_opexpr_is_hashable().

◆ contain_leaked_vars()

bool contain_leaked_vars ( Node clause)

Definition at line 1264 of file clauses.c.

1265{
1266 return contain_leaked_vars_walker(clause, NULL);
1267}
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1276

References contain_leaked_vars_walker().

Referenced by make_plain_restrictinfo(), and qual_is_pushdown_safe().

◆ contain_nonstrict_functions()

bool contain_nonstrict_functions ( Node clause)

Definition at line 994 of file clauses.c.

995{
996 return contain_nonstrict_functions_walker(clause, NULL);
997}
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:1006

References contain_nonstrict_functions_walker().

Referenced by inline_function(), and pullup_replace_vars_callback().

◆ contain_subplans()

bool contain_subplans ( Node clause)

◆ contain_window_function()

bool contain_window_function ( Node clause)

Definition at line 216 of file clauses.c.

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

References contain_windowfuncs().

Referenced by get_eclass_for_sort_expr(), and mark_nullable_by_grouping().

◆ expression_returns_set_rows()

double expression_returns_set_rows ( PlannerInfo root,
Node clause 
)

Definition at line 290 of file clauses.c.

291{
292 if (clause == NULL)
293 return 1.0;
294 if (IsA(clause, FuncExpr))
295 {
296 FuncExpr *expr = (FuncExpr *) clause;
297
298 if (expr->funcretset)
299 return clamp_row_est(get_function_rows(root, expr->funcid, clause));
300 }
301 if (IsA(clause, OpExpr))
302 {
303 OpExpr *expr = (OpExpr *) clause;
304
305 if (expr->opretset)
306 {
307 set_opfuncid(expr);
308 return clamp_row_est(get_function_rows(root, expr->opfuncid, clause));
309 }
310 }
311 return 1.0;
312}
double clamp_row_est(double nrows)
Definition: costsize.c:213
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1872
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
double get_function_rows(PlannerInfo *root, Oid funcid, Node *node)
Definition: plancat.c:2172
tree ctl root
Definition: radixtree.h:1857
Oid funcid
Definition: primnodes.h:767

References clamp_row_est(), FuncExpr::funcid, get_function_rows(), IsA, root, and set_opfuncid().

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

◆ find_forced_null_var()

Var * find_forced_null_var ( Node node)

Definition at line 1979 of file clauses.c.

1980{
1981 if (node == NULL)
1982 return NULL;
1983 if (IsA(node, NullTest))
1984 {
1985 /* check for var IS NULL */
1986 NullTest *expr = (NullTest *) node;
1987
1988 if (expr->nulltesttype == IS_NULL && !expr->argisrow)
1989 {
1990 Var *var = (Var *) expr->arg;
1991
1992 if (var && IsA(var, Var) &&
1993 var->varlevelsup == 0)
1994 return var;
1995 }
1996 }
1997 else if (IsA(node, BooleanTest))
1998 {
1999 /* var IS UNKNOWN is equivalent to var IS NULL */
2000 BooleanTest *expr = (BooleanTest *) node;
2001
2002 if (expr->booltesttype == IS_UNKNOWN)
2003 {
2004 Var *var = (Var *) expr->arg;
2005
2006 if (var && IsA(var, Var) &&
2007 var->varlevelsup == 0)
2008 return var;
2009 }
2010 }
2011 return NULL;
2012}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
@ IS_UNKNOWN
Definition: primnodes.h:1981
@ IS_NULL
Definition: primnodes.h:1957
BoolTestType booltesttype
Definition: primnodes.h:1988
Expr * arg
Definition: primnodes.h:1987
NullTestType nulltesttype
Definition: primnodes.h:1964
Expr * arg
Definition: primnodes.h:1963
Definition: primnodes.h:262
Index varlevelsup
Definition: primnodes.h:294

References NullTest::arg, BooleanTest::arg, BooleanTest::booltesttype, if(), IS_NULL, IS_UNKNOWN, IsA, NullTest::nulltesttype, and Var::varlevelsup.

Referenced by check_redundant_nullability_qual(), and find_forced_null_vars().

◆ find_forced_null_vars()

List * find_forced_null_vars ( Node node)

Definition at line 1918 of file clauses.c.

1919{
1920 List *result = NIL;
1921 Var *var;
1922 ListCell *l;
1923
1924 if (node == NULL)
1925 return NIL;
1926 /* Check single-clause cases using subroutine */
1927 var = find_forced_null_var(node);
1928 if (var)
1929 {
1930 result = mbms_add_member(result,
1931 var->varno,
1933 }
1934 /* Otherwise, handle AND-conditions */
1935 else if (IsA(node, List))
1936 {
1937 /*
1938 * At top level, we are examining an implicit-AND list: if any of the
1939 * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1940 */
1941 foreach(l, (List *) node)
1942 {
1943 result = mbms_add_members(result,
1945 }
1946 }
1947 else if (IsA(node, BoolExpr))
1948 {
1949 BoolExpr *expr = (BoolExpr *) node;
1950
1951 /*
1952 * We don't bother considering the OR case, because it's fairly
1953 * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
1954 * the NOT case isn't worth expending code on.
1955 */
1956 if (expr->boolop == AND_EXPR)
1957 {
1958 /* At top level we can just recurse (to the List case) */
1959 result = find_forced_null_vars((Node *) expr->args);
1960 }
1961 }
1962 return result;
1963}
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1918
Var * find_forced_null_var(Node *node)
Definition: clauses.c:1979
List * mbms_add_members(List *a, const List *b)
List * mbms_add_member(List *a, int listidx, int bitidx)
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
@ AND_EXPR
Definition: primnodes.h:948
BoolExprType boolop
Definition: primnodes.h:956
List * args
Definition: primnodes.h:957
Definition: pg_list.h:54
AttrNumber varattno
Definition: primnodes.h:274
int varno
Definition: primnodes.h:269
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27

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

Referenced by find_forced_null_vars(), and reduce_outer_joins_pass2().

◆ find_nonnullable_rels()

Relids find_nonnullable_rels ( Node clause)

Definition at line 1458 of file clauses.c.

1459{
1460 return find_nonnullable_rels_walker(clause, true);
1461}
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1464

References find_nonnullable_rels_walker().

Referenced by make_outerjoininfo(), and reduce_outer_joins_pass2().

◆ find_nonnullable_vars()

List * find_nonnullable_vars ( Node clause)

Definition at line 1709 of file clauses.c.

1710{
1711 return find_nonnullable_vars_walker(clause, true);
1712}
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1715

References find_nonnullable_vars_walker().

Referenced by reduce_outer_joins_pass2().

◆ find_window_functions()

WindowFuncLists * find_window_functions ( Node clause,
Index  maxWinRef 
)

Definition at line 229 of file clauses.c.

230{
231 WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
232
233 lists->numWindowFuncs = 0;
234 lists->maxWinRef = maxWinRef;
235 lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
236 (void) find_window_functions_walker(clause, lists);
237 return lists;
238}
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:241
void * palloc0(Size size)
Definition: mcxt.c:1970
void * palloc(Size size)
Definition: mcxt.c:1940
List ** windowFuncs
Definition: clauses.h:23
Index maxWinRef
Definition: clauses.h:22
int numWindowFuncs
Definition: clauses.h:21

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

Referenced by grouping_planner().

◆ inline_set_returning_function()

Query * inline_set_returning_function ( PlannerInfo root,
RangeTblEntry rte 
)

Definition at line 5068 of file clauses.c.

5069{
5070 RangeTblFunction *rtfunc;
5071 FuncExpr *fexpr;
5072 Oid func_oid;
5073 HeapTuple func_tuple;
5074 Form_pg_proc funcform;
5075 char *src;
5076 Datum tmp;
5077 bool isNull;
5078 MemoryContext oldcxt;
5079 MemoryContext mycxt;
5080 inline_error_callback_arg callback_arg;
5081 ErrorContextCallback sqlerrcontext;
5083 TypeFuncClass functypclass;
5084 TupleDesc rettupdesc;
5085 List *raw_parsetree_list;
5086 List *querytree_list;
5088
5089 Assert(rte->rtekind == RTE_FUNCTION);
5090
5091 /*
5092 * It doesn't make a lot of sense for a SQL SRF to refer to itself in its
5093 * own FROM clause, since that must cause infinite recursion at runtime.
5094 * It will cause this code to recurse too, so check for stack overflow.
5095 * (There's no need to do more.)
5096 */
5098
5099 /* Fail if the RTE has ORDINALITY - we don't implement that here. */
5100 if (rte->funcordinality)
5101 return NULL;
5102
5103 /* Fail if RTE isn't a single, simple FuncExpr */
5104 if (list_length(rte->functions) != 1)
5105 return NULL;
5106 rtfunc = (RangeTblFunction *) linitial(rte->functions);
5107
5108 if (!IsA(rtfunc->funcexpr, FuncExpr))
5109 return NULL;
5110 fexpr = (FuncExpr *) rtfunc->funcexpr;
5111
5112 func_oid = fexpr->funcid;
5113
5114 /*
5115 * The function must be declared to return a set, else inlining would
5116 * change the results if the contained SELECT didn't return exactly one
5117 * row.
5118 */
5119 if (!fexpr->funcretset)
5120 return NULL;
5121
5122 /*
5123 * Refuse to inline if the arguments contain any volatile functions or
5124 * sub-selects. Volatile functions are rejected because inlining may
5125 * result in the arguments being evaluated multiple times, risking a
5126 * change in behavior. Sub-selects are rejected partly for implementation
5127 * reasons (pushing them down another level might change their behavior)
5128 * and partly because they're likely to be expensive and so multiple
5129 * evaluation would be bad.
5130 */
5131 if (contain_volatile_functions((Node *) fexpr->args) ||
5132 contain_subplans((Node *) fexpr->args))
5133 return NULL;
5134
5135 /* Check permission to call function (fail later, if not) */
5136 if (object_aclcheck(ProcedureRelationId, func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
5137 return NULL;
5138
5139 /* Check whether a plugin wants to hook function entry/exit */
5140 if (FmgrHookIsNeeded(func_oid))
5141 return NULL;
5142
5143 /*
5144 * OK, let's take a look at the function's pg_proc entry.
5145 */
5146 func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid));
5147 if (!HeapTupleIsValid(func_tuple))
5148 elog(ERROR, "cache lookup failed for function %u", func_oid);
5149 funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
5150
5151 /*
5152 * Forget it if the function is not SQL-language or has other showstopper
5153 * properties. In particular it mustn't be declared STRICT, since we
5154 * couldn't enforce that. It also mustn't be VOLATILE, because that is
5155 * supposed to cause it to be executed with its own snapshot, rather than
5156 * sharing the snapshot of the calling query. We also disallow returning
5157 * SETOF VOID, because inlining would result in exposing the actual result
5158 * of the function's last SELECT, which should not happen in that case.
5159 * (Rechecking prokind, proretset, and pronargs is just paranoia.)
5160 */
5161 if (funcform->prolang != SQLlanguageId ||
5162 funcform->prokind != PROKIND_FUNCTION ||
5163 funcform->proisstrict ||
5164 funcform->provolatile == PROVOLATILE_VOLATILE ||
5165 funcform->prorettype == VOIDOID ||
5166 funcform->prosecdef ||
5167 !funcform->proretset ||
5168 list_length(fexpr->args) != funcform->pronargs ||
5169 !heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL))
5170 {
5171 ReleaseSysCache(func_tuple);
5172 return NULL;
5173 }
5174
5175 /*
5176 * Make a temporary memory context, so that we don't leak all the stuff
5177 * that parsing might create.
5178 */
5180 "inline_set_returning_function",
5182 oldcxt = MemoryContextSwitchTo(mycxt);
5183
5184 /* Fetch the function body */
5185 tmp = SysCacheGetAttrNotNull(PROCOID, func_tuple, Anum_pg_proc_prosrc);
5186 src = TextDatumGetCString(tmp);
5187
5188 /*
5189 * Setup error traceback support for ereport(). This is so that we can
5190 * finger the function that bad information came from.
5191 */
5192 callback_arg.proname = NameStr(funcform->proname);
5193 callback_arg.prosrc = src;
5194
5195 sqlerrcontext.callback = sql_inline_error_callback;
5196 sqlerrcontext.arg = &callback_arg;
5197 sqlerrcontext.previous = error_context_stack;
5198 error_context_stack = &sqlerrcontext;
5199
5200 /* If we have prosqlbody, pay attention to that not prosrc */
5201 tmp = SysCacheGetAttr(PROCOID,
5202 func_tuple,
5203 Anum_pg_proc_prosqlbody,
5204 &isNull);
5205 if (!isNull)
5206 {
5207 Node *n;
5208
5210 if (IsA(n, List))
5211 querytree_list = linitial_node(List, castNode(List, n));
5212 else
5213 querytree_list = list_make1(n);
5214 if (list_length(querytree_list) != 1)
5215 goto fail;
5216 querytree = linitial(querytree_list);
5217
5218 /* Acquire necessary locks, then apply rewriter. */
5219 AcquireRewriteLocks(querytree, true, false);
5220 querytree_list = pg_rewrite_query(querytree);
5221 if (list_length(querytree_list) != 1)
5222 goto fail;
5223 querytree = linitial(querytree_list);
5224 }
5225 else
5226 {
5227 /*
5228 * Set up to handle parameters while parsing the function body. We
5229 * can use the FuncExpr just created as the input for
5230 * prepare_sql_fn_parse_info.
5231 */
5232 pinfo = prepare_sql_fn_parse_info(func_tuple,
5233 (Node *) fexpr,
5234 fexpr->inputcollid);
5235
5236 /*
5237 * Parse, analyze, and rewrite (unlike inline_function(), we can't
5238 * skip rewriting here). We can fail as soon as we find more than one
5239 * query, though.
5240 */
5241 raw_parsetree_list = pg_parse_query(src);
5242 if (list_length(raw_parsetree_list) != 1)
5243 goto fail;
5244
5245 querytree_list = pg_analyze_and_rewrite_withcb(linitial(raw_parsetree_list),
5246 src,
5248 pinfo, NULL);
5249 if (list_length(querytree_list) != 1)
5250 goto fail;
5251 querytree = linitial(querytree_list);
5252 }
5253
5254 /*
5255 * Also resolve the actual function result tupdesc, if composite. If we
5256 * have a coldeflist, believe that; otherwise use get_expr_result_type.
5257 * (This logic should match ExecInitFunctionScan.)
5258 */
5259 if (rtfunc->funccolnames != NIL)
5260 {
5261 functypclass = TYPEFUNC_RECORD;
5262 rettupdesc = BuildDescFromLists(rtfunc->funccolnames,
5263 rtfunc->funccoltypes,
5264 rtfunc->funccoltypmods,
5265 rtfunc->funccolcollations);
5266 }
5267 else
5268 functypclass = get_expr_result_type((Node *) fexpr, NULL, &rettupdesc);
5269
5270 /*
5271 * The single command must be a plain SELECT.
5272 */
5273 if (!IsA(querytree, Query) ||
5274 querytree->commandType != CMD_SELECT)
5275 goto fail;
5276
5277 /*
5278 * Make sure the function (still) returns what it's declared to. This
5279 * will raise an error if wrong, but that's okay since the function would
5280 * fail at runtime anyway. Note that check_sql_fn_retval will also insert
5281 * coercions if needed to make the tlist expression(s) match the declared
5282 * type of the function. We also ask it to insert dummy NULL columns for
5283 * any dropped columns in rettupdesc, so that the elements of the modified
5284 * tlist match up to the attribute numbers.
5285 *
5286 * If the function returns a composite type, don't inline unless the check
5287 * shows it's returning a whole tuple result; otherwise what it's
5288 * returning is a single composite column which is not what we need.
5289 */
5290 if (!check_sql_fn_retval(list_make1(querytree_list),
5291 fexpr->funcresulttype, rettupdesc,
5292 funcform->prokind,
5293 true) &&
5294 (functypclass == TYPEFUNC_COMPOSITE ||
5295 functypclass == TYPEFUNC_COMPOSITE_DOMAIN ||
5296 functypclass == TYPEFUNC_RECORD))
5297 goto fail; /* reject not-whole-tuple-result cases */
5298
5299 /*
5300 * check_sql_fn_retval might've inserted a projection step, but that's
5301 * fine; just make sure we use the upper Query.
5302 */
5303 querytree = linitial_node(Query, querytree_list);
5304
5305 /*
5306 * Looks good --- substitute parameters into the query.
5307 */
5309 funcform->pronargs,
5310 fexpr->args);
5311
5312 /*
5313 * Copy the modified query out of the temporary memory context, and clean
5314 * up.
5315 */
5316 MemoryContextSwitchTo(oldcxt);
5317
5319
5320 MemoryContextDelete(mycxt);
5321 error_context_stack = sqlerrcontext.previous;
5322 ReleaseSysCache(func_tuple);
5323
5324 /*
5325 * We don't have to fix collations here because the upper query is already
5326 * parsed, ie, the collations in the RTE are what count.
5327 */
5328
5329 /*
5330 * Since there is now no trace of the function in the plan tree, we must
5331 * explicitly record the plan's dependency on the function.
5332 */
5334
5335 /*
5336 * We must also notice if the inserted query adds a dependency on the
5337 * calling role due to RLS quals.
5338 */
5339 if (querytree->hasRowSecurity)
5340 root->glob->dependsOnRole = true;
5341
5342 return querytree;
5343
5344 /* Here if func is not inlinable: release temp memory and return NULL */
5345fail:
5346 MemoryContextSwitchTo(oldcxt);
5347 MemoryContextDelete(mycxt);
5348 error_context_stack = sqlerrcontext.previous;
5349 ReleaseSysCache(func_tuple);
5350
5351 return NULL;
5352}
Datum querytree(PG_FUNCTION_ARGS)
Definition: _int_bool.c:665
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3821
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:717
static Query * substitute_actual_srf_parameters(Query *expr, int nargs, List *args)
Definition: clauses.c:5361
static void sql_inline_error_callback(void *arg)
Definition: clauses.c:4952
bool contain_subplans(Node *clause)
Definition: clauses.c:331
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:539
ErrorContextCallback * error_context_stack
Definition: elog.c:95
#define FmgrHookIsNeeded(fn_oid)
Definition: fmgr.h:848
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:299
TypeFuncClass
Definition: funcapi.h:147
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
@ TYPEFUNC_RECORD
Definition: funcapi.h:151
@ TYPEFUNC_COMPOSITE_DOMAIN
Definition: funcapi.h:150
bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols)
Definition: functions.c:2021
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition: functions.c:341
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
Definition: functions.c:252
Assert(PointerIsAligned(start, uint64))
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:456
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:485
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180
Oid GetUserId(void)
Definition: miscinit.c:520
#define copyObject(obj)
Definition: nodes.h:230
@ CMD_SELECT
Definition: nodes.h:271
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
Definition: params.h:108
@ RTE_FUNCTION
Definition: parsenodes.h:1029
#define ACL_EXECUTE
Definition: parsenodes.h:83
#define linitial_node(type, l)
Definition: pg_list.h:181
#define list_make1(x1)
Definition: pg_list.h:212
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
List * pg_analyze_and_rewrite_withcb(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:758
List * pg_parse_query(const char *query_string)
Definition: postgres.c:603
List * pg_rewrite_query(Query *query)
Definition: postgres.c:798
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
void * stringToNode(const char *str)
Definition: read.c:90
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:3552
void check_stack_depth(void)
Definition: stack_depth.c:95
struct ErrorContextCallback * previous
Definition: elog.h:297
void(* callback)(void *arg)
Definition: elog.h:298
List * args
Definition: primnodes.h:785
bool funcordinality
Definition: parsenodes.h:1193
List * functions
Definition: parsenodes.h:1191
RTEKind rtekind
Definition: parsenodes.h:1061
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:631
TupleDesc BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations)
Definition: tupdesc.c:1044

References ACL_EXECUTE, ACLCHECK_OK, AcquireRewriteLocks(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, FuncExpr::args, Assert(), BuildDescFromLists(), ErrorContextCallback::callback, castNode, check_sql_fn_retval(), check_stack_depth(), CMD_SELECT, contain_subplans(), contain_volatile_functions(), copyObject, CurrentMemoryContext, elog, ERROR, error_context_stack, FmgrHookIsNeeded, RangeTblFunction::funcexpr, FuncExpr::funcid, RangeTblEntry::funcordinality, RangeTblEntry::functions, get_expr_result_type(), GETSTRUCT(), GetUserId(), heap_attisnull(), HeapTupleIsValid, if(), IsA, linitial, linitial_node, list_length(), list_make1, MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, NIL, object_aclcheck(), ObjectIdGetDatum(), pg_analyze_and_rewrite_withcb(), pg_parse_query(), pg_rewrite_query(), prepare_sql_fn_parse_info(), ErrorContextCallback::previous, inline_error_callback_arg::proname, inline_error_callback_arg::prosrc, querytree(), record_plan_function_dependency(), ReleaseSysCache(), root, RTE_FUNCTION, RangeTblEntry::rtekind, SearchSysCache1(), sql_fn_parser_setup(), sql_inline_error_callback(), stringToNode(), substitute_actual_srf_parameters(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), TextDatumGetCString, TYPEFUNC_COMPOSITE, TYPEFUNC_COMPOSITE_DOMAIN, and TYPEFUNC_RECORD.

Referenced by preprocess_function_rtes().

◆ is_parallel_safe()

bool is_parallel_safe ( PlannerInfo root,
Node node 
)

Definition at line 754 of file clauses.c.

755{
757 PlannerInfo *proot;
758 ListCell *l;
759
760 /*
761 * Even if the original querytree contained nothing unsafe, we need to
762 * search the expression if we have generated any PARAM_EXEC Params while
763 * planning, because those are parallel-restricted and there might be one
764 * in this expression. But otherwise we don't need to look.
765 */
766 if (root->glob->maxParallelHazard == PROPARALLEL_SAFE &&
767 root->glob->paramExecTypes == NIL)
768 return true;
769 /* Else use max_parallel_hazard's search logic, but stop on RESTRICTED */
770 context.max_hazard = PROPARALLEL_SAFE;
771 context.max_interesting = PROPARALLEL_RESTRICTED;
772 context.safe_param_ids = NIL;
773
774 /*
775 * The params that refer to the same or parent query level are considered
776 * parallel-safe. The idea is that we compute such params at Gather or
777 * Gather Merge node and pass their value to workers.
778 */
779 for (proot = root; proot != NULL; proot = proot->parent_root)
780 {
781 foreach(l, proot->init_plans)
782 {
783 SubPlan *initsubplan = (SubPlan *) lfirst(l);
784
785 context.safe_param_ids = list_concat(context.safe_param_ids,
786 initsubplan->setParam);
787 }
788 }
789
790 return !max_parallel_hazard_walker(node, &context);
791}
static bool max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
Definition: clauses.c:830
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
List * init_plans
Definition: pathnodes.h:323
List * setParam
Definition: primnodes.h:1105

References PlannerInfo::init_plans, lfirst, list_concat(), max_parallel_hazard_context::max_hazard, max_parallel_hazard_context::max_interesting, max_parallel_hazard_walker(), NIL, root, max_parallel_hazard_context::safe_param_ids, and SubPlan::setParam.

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

◆ is_pseudo_constant_clause()

bool is_pseudo_constant_clause ( Node clause)

Definition at line 2090 of file clauses.c.

2091{
2092 /*
2093 * We could implement this check in one recursive scan. But since the
2094 * check for volatile functions is both moderately expensive and unlikely
2095 * to fail, it seems better to look for Vars first and only check for
2096 * volatile functions if we find no Vars.
2097 */
2098 if (!contain_var_clause(clause) &&
2100 return true;
2101 return false;
2102}
bool contain_var_clause(Node *node)
Definition: var.c:406

References contain_var_clause(), and contain_volatile_functions().

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

◆ is_pseudo_constant_clause_relids()

bool is_pseudo_constant_clause_relids ( Node clause,
Relids  relids 
)

Definition at line 2110 of file clauses.c.

2111{
2112 if (bms_is_empty(relids) &&
2114 return true;
2115 return false;
2116}
#define bms_is_empty(a)
Definition: bitmapset.h:118

References bms_is_empty, and contain_volatile_functions().

Referenced by clauselist_selectivity_ext().

◆ max_parallel_hazard()

char max_parallel_hazard ( Query parse)

Definition at line 735 of file clauses.c.

736{
738
739 context.max_hazard = PROPARALLEL_SAFE;
740 context.max_interesting = PROPARALLEL_UNSAFE;
741 context.safe_param_ids = NIL;
742 (void) max_parallel_hazard_walker((Node *) parse, &context);
743 return context.max_hazard;
744}
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717

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

Referenced by standard_planner().

◆ NumRelids()

int NumRelids ( PlannerInfo root,
Node clause 
)

Definition at line 2132 of file clauses.c.

2133{
2134 int result;
2135 Relids varnos = pull_varnos(root, clause);
2136
2137 varnos = bms_del_members(varnos, root->outer_join_rels);
2138 result = bms_num_members(varnos);
2139 bms_free(varnos);
2140 return result;
2141}
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:1161
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:751
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:114

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

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

◆ pull_paramids()

Bitmapset * pull_paramids ( Expr expr)

Definition at line 5421 of file clauses.c.

5422{
5423 Bitmapset *result = NULL;
5424
5425 (void) pull_paramids_walker((Node *) expr, &result);
5426
5427 return result;
5428}
static bool pull_paramids_walker(Node *node, Bitmapset **context)
Definition: clauses.c:5431

References pull_paramids_walker().

Referenced by create_memoize_plan().