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

2155{
2156 Oid opoid;
2157 Node *temp;
2158
2159 /* Sanity checks: caller is at fault if these fail */
2160 if (!is_opclause(clause) ||
2161 list_length(clause->args) != 2)
2162 elog(ERROR, "cannot commute non-binary-operator clause");
2163
2164 opoid = get_commutator(clause->opno);
2165
2166 if (!OidIsValid(opoid))
2167 elog(ERROR, "could not find commutator for operator %u",
2168 clause->opno);
2169
2170 /*
2171 * modify the clause in-place!
2172 */
2173 clause->opno = opoid;
2174 clause->opfuncid = InvalidOid;
2175 /* opresulttype, opretset, opcollid, inputcollid need not change */
2176
2177 temp = linitial(clause->args);
2178 linitial(clause->args) = lsecond(clause->args);
2179 lsecond(clause->args) = temp;
2180}
#define OidIsValid(objectId)
Definition: c.h:774
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1676
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:37
unsigned int Oid
Definition: postgres_ext.h:32
Definition: nodes.h:135
Oid opno
Definition: primnodes.h:850
List * args
Definition: primnodes.h:868

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

183{
184 return contain_agg_clause_walker(clause, NULL);
185}
static bool contain_agg_clause_walker(Node *node, void *context)
Definition: clauses.c:188

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

1144{
1145 return contain_exec_param_walker(clause, param_ids);
1146}
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition: clauses.c:1149

References contain_exec_param_walker().

Referenced by test_opexpr_is_hashable().

◆ contain_leaked_vars()

bool contain_leaked_vars ( Node clause)

Definition at line 1269 of file clauses.c.

1270{
1271 return contain_leaked_vars_walker(clause, NULL);
1272}
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition: clauses.c:1281

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

998{
999 return contain_nonstrict_functions_walker(clause, NULL);
1000}
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition: clauses.c:1009

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

220{
221 return contain_windowfuncs(clause);
222}
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 293 of file clauses.c.

294{
295 if (clause == NULL)
296 return 1.0;
297 if (IsA(clause, FuncExpr))
298 {
299 FuncExpr *expr = (FuncExpr *) clause;
300
301 if (expr->funcretset)
302 return clamp_row_est(get_function_rows(root, expr->funcid, clause));
303 }
304 if (IsA(clause, OpExpr))
305 {
306 OpExpr *expr = (OpExpr *) clause;
307
308 if (expr->opretset)
309 {
310 set_opfuncid(expr);
311 return clamp_row_est(get_function_rows(root, expr->opfuncid, clause));
312 }
313 }
314 return 1.0;
315}
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:2267
tree ctl root
Definition: radixtree.h:1857
Oid funcid
Definition: primnodes.h:782

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

1985{
1986 if (node == NULL)
1987 return NULL;
1988 if (IsA(node, NullTest))
1989 {
1990 /* check for var IS NULL */
1991 NullTest *expr = (NullTest *) node;
1992
1993 if (expr->nulltesttype == IS_NULL && !expr->argisrow)
1994 {
1995 Var *var = (Var *) expr->arg;
1996
1997 if (var && IsA(var, Var) &&
1998 var->varlevelsup == 0)
1999 return var;
2000 }
2001 }
2002 else if (IsA(node, BooleanTest))
2003 {
2004 /* var IS UNKNOWN is equivalent to var IS NULL */
2005 BooleanTest *expr = (BooleanTest *) node;
2006
2007 if (expr->booltesttype == IS_UNKNOWN)
2008 {
2009 Var *var = (Var *) expr->arg;
2010
2011 if (var && IsA(var, Var) &&
2012 var->varlevelsup == 0)
2013 return var;
2014 }
2015 }
2016 return NULL;
2017}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
@ IS_UNKNOWN
Definition: primnodes.h:2001
@ IS_NULL
Definition: primnodes.h:1977
BoolTestType booltesttype
Definition: primnodes.h:2008
Expr * arg
Definition: primnodes.h:2007
NullTestType nulltesttype
Definition: primnodes.h:1984
Expr * arg
Definition: primnodes.h:1983
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 1923 of file clauses.c.

1924{
1925 List *result = NIL;
1926 Var *var;
1927 ListCell *l;
1928
1929 if (node == NULL)
1930 return NIL;
1931 /* Check single-clause cases using subroutine */
1932 var = find_forced_null_var(node);
1933 if (var)
1934 {
1935 result = mbms_add_member(result,
1936 var->varno,
1938 }
1939 /* Otherwise, handle AND-conditions */
1940 else if (IsA(node, List))
1941 {
1942 /*
1943 * At top level, we are examining an implicit-AND list: if any of the
1944 * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1945 */
1946 foreach(l, (List *) node)
1947 {
1948 result = mbms_add_members(result,
1950 }
1951 }
1952 else if (IsA(node, BoolExpr))
1953 {
1954 BoolExpr *expr = (BoolExpr *) node;
1955
1956 /*
1957 * We don't bother considering the OR case, because it's fairly
1958 * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
1959 * the NOT case isn't worth expending code on.
1960 */
1961 if (expr->boolop == AND_EXPR)
1962 {
1963 /* At top level we can just recurse (to the List case) */
1964 result = find_forced_null_vars((Node *) expr->args);
1965 }
1966 }
1967 return result;
1968}
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1923
Var * find_forced_null_var(Node *node)
Definition: clauses.c:1984
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:963
BoolExprType boolop
Definition: primnodes.h:971
List * args
Definition: primnodes.h:972
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 1463 of file clauses.c.

1464{
1465 return find_nonnullable_rels_walker(clause, true);
1466}
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition: clauses.c:1469

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

1715{
1716 return find_nonnullable_vars_walker(clause, true);
1717}
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition: clauses.c:1720

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

233{
234 WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
235
236 lists->numWindowFuncs = 0;
237 lists->maxWinRef = maxWinRef;
238 lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
239 (void) find_window_functions_walker(clause, lists);
240 return lists;
241}
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition: clauses.c:244
void * palloc0(Size size)
Definition: mcxt.c:1395
void * palloc(Size size)
Definition: mcxt.c:1365
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 5168 of file clauses.c.

5169{
5170 RangeTblFunction *rtfunc;
5171 FuncExpr *fexpr;
5172 Oid func_oid;
5173 HeapTuple func_tuple;
5174 Form_pg_proc funcform;
5175 char *src;
5176 Datum tmp;
5177 bool isNull;
5178 MemoryContext oldcxt;
5179 MemoryContext mycxt;
5180 inline_error_callback_arg callback_arg;
5181 ErrorContextCallback sqlerrcontext;
5183 TypeFuncClass functypclass;
5184 TupleDesc rettupdesc;
5185 List *raw_parsetree_list;
5186 List *querytree_list;
5188
5189 Assert(rte->rtekind == RTE_FUNCTION);
5190
5191 /*
5192 * It doesn't make a lot of sense for a SQL SRF to refer to itself in its
5193 * own FROM clause, since that must cause infinite recursion at runtime.
5194 * It will cause this code to recurse too, so check for stack overflow.
5195 * (There's no need to do more.)
5196 */
5198
5199 /* Fail if the RTE has ORDINALITY - we don't implement that here. */
5200 if (rte->funcordinality)
5201 return NULL;
5202
5203 /* Fail if RTE isn't a single, simple FuncExpr */
5204 if (list_length(rte->functions) != 1)
5205 return NULL;
5206 rtfunc = (RangeTblFunction *) linitial(rte->functions);
5207
5208 if (!IsA(rtfunc->funcexpr, FuncExpr))
5209 return NULL;
5210 fexpr = (FuncExpr *) rtfunc->funcexpr;
5211
5212 func_oid = fexpr->funcid;
5213
5214 /*
5215 * The function must be declared to return a set, else inlining would
5216 * change the results if the contained SELECT didn't return exactly one
5217 * row.
5218 */
5219 if (!fexpr->funcretset)
5220 return NULL;
5221
5222 /*
5223 * Refuse to inline if the arguments contain any volatile functions or
5224 * sub-selects. Volatile functions are rejected because inlining may
5225 * result in the arguments being evaluated multiple times, risking a
5226 * change in behavior. Sub-selects are rejected partly for implementation
5227 * reasons (pushing them down another level might change their behavior)
5228 * and partly because they're likely to be expensive and so multiple
5229 * evaluation would be bad.
5230 */
5231 if (contain_volatile_functions((Node *) fexpr->args) ||
5232 contain_subplans((Node *) fexpr->args))
5233 return NULL;
5234
5235 /* Check permission to call function (fail later, if not) */
5236 if (object_aclcheck(ProcedureRelationId, func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
5237 return NULL;
5238
5239 /* Check whether a plugin wants to hook function entry/exit */
5240 if (FmgrHookIsNeeded(func_oid))
5241 return NULL;
5242
5243 /*
5244 * OK, let's take a look at the function's pg_proc entry.
5245 */
5246 func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid));
5247 if (!HeapTupleIsValid(func_tuple))
5248 elog(ERROR, "cache lookup failed for function %u", func_oid);
5249 funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
5250
5251 /*
5252 * Forget it if the function is not SQL-language or has other showstopper
5253 * properties. In particular it mustn't be declared STRICT, since we
5254 * couldn't enforce that. It also mustn't be VOLATILE, because that is
5255 * supposed to cause it to be executed with its own snapshot, rather than
5256 * sharing the snapshot of the calling query. We also disallow returning
5257 * SETOF VOID, because inlining would result in exposing the actual result
5258 * of the function's last SELECT, which should not happen in that case.
5259 * (Rechecking prokind, proretset, and pronargs is just paranoia.)
5260 */
5261 if (funcform->prolang != SQLlanguageId ||
5262 funcform->prokind != PROKIND_FUNCTION ||
5263 funcform->proisstrict ||
5264 funcform->provolatile == PROVOLATILE_VOLATILE ||
5265 funcform->prorettype == VOIDOID ||
5266 funcform->prosecdef ||
5267 !funcform->proretset ||
5268 list_length(fexpr->args) != funcform->pronargs ||
5269 !heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL))
5270 {
5271 ReleaseSysCache(func_tuple);
5272 return NULL;
5273 }
5274
5275 /*
5276 * Make a temporary memory context, so that we don't leak all the stuff
5277 * that parsing might create.
5278 */
5280 "inline_set_returning_function",
5282 oldcxt = MemoryContextSwitchTo(mycxt);
5283
5284 /* Fetch the function body */
5285 tmp = SysCacheGetAttrNotNull(PROCOID, func_tuple, Anum_pg_proc_prosrc);
5286 src = TextDatumGetCString(tmp);
5287
5288 /*
5289 * Setup error traceback support for ereport(). This is so that we can
5290 * finger the function that bad information came from.
5291 */
5292 callback_arg.proname = NameStr(funcform->proname);
5293 callback_arg.prosrc = src;
5294
5295 sqlerrcontext.callback = sql_inline_error_callback;
5296 sqlerrcontext.arg = &callback_arg;
5297 sqlerrcontext.previous = error_context_stack;
5298 error_context_stack = &sqlerrcontext;
5299
5300 /* If we have prosqlbody, pay attention to that not prosrc */
5301 tmp = SysCacheGetAttr(PROCOID,
5302 func_tuple,
5303 Anum_pg_proc_prosqlbody,
5304 &isNull);
5305 if (!isNull)
5306 {
5307 Node *n;
5308
5310 if (IsA(n, List))
5311 querytree_list = linitial_node(List, castNode(List, n));
5312 else
5313 querytree_list = list_make1(n);
5314 if (list_length(querytree_list) != 1)
5315 goto fail;
5316 querytree = linitial(querytree_list);
5317
5318 /* Acquire necessary locks, then apply rewriter. */
5319 AcquireRewriteLocks(querytree, true, false);
5320 querytree_list = pg_rewrite_query(querytree);
5321 if (list_length(querytree_list) != 1)
5322 goto fail;
5323 querytree = linitial(querytree_list);
5324 }
5325 else
5326 {
5327 /*
5328 * Set up to handle parameters while parsing the function body. We
5329 * can use the FuncExpr just created as the input for
5330 * prepare_sql_fn_parse_info.
5331 */
5332 pinfo = prepare_sql_fn_parse_info(func_tuple,
5333 (Node *) fexpr,
5334 fexpr->inputcollid);
5335
5336 /*
5337 * Parse, analyze, and rewrite (unlike inline_function(), we can't
5338 * skip rewriting here). We can fail as soon as we find more than one
5339 * query, though.
5340 */
5341 raw_parsetree_list = pg_parse_query(src);
5342 if (list_length(raw_parsetree_list) != 1)
5343 goto fail;
5344
5345 querytree_list = pg_analyze_and_rewrite_withcb(linitial(raw_parsetree_list),
5346 src,
5348 pinfo, NULL);
5349 if (list_length(querytree_list) != 1)
5350 goto fail;
5351 querytree = linitial(querytree_list);
5352 }
5353
5354 /*
5355 * Also resolve the actual function result tupdesc, if composite. If we
5356 * have a coldeflist, believe that; otherwise use get_expr_result_type.
5357 * (This logic should match ExecInitFunctionScan.)
5358 */
5359 if (rtfunc->funccolnames != NIL)
5360 {
5361 functypclass = TYPEFUNC_RECORD;
5362 rettupdesc = BuildDescFromLists(rtfunc->funccolnames,
5363 rtfunc->funccoltypes,
5364 rtfunc->funccoltypmods,
5365 rtfunc->funccolcollations);
5366 }
5367 else
5368 functypclass = get_expr_result_type((Node *) fexpr, NULL, &rettupdesc);
5369
5370 /*
5371 * The single command must be a plain SELECT.
5372 */
5373 if (!IsA(querytree, Query) ||
5374 querytree->commandType != CMD_SELECT)
5375 goto fail;
5376
5377 /*
5378 * Make sure the function (still) returns what it's declared to. This
5379 * will raise an error if wrong, but that's okay since the function would
5380 * fail at runtime anyway. Note that check_sql_fn_retval will also insert
5381 * coercions if needed to make the tlist expression(s) match the declared
5382 * type of the function. We also ask it to insert dummy NULL columns for
5383 * any dropped columns in rettupdesc, so that the elements of the modified
5384 * tlist match up to the attribute numbers.
5385 *
5386 * If the function returns a composite type, don't inline unless the check
5387 * shows it's returning a whole tuple result; otherwise what it's
5388 * returning is a single composite column which is not what we need.
5389 */
5390 if (!check_sql_fn_retval(list_make1(querytree_list),
5391 fexpr->funcresulttype, rettupdesc,
5392 funcform->prokind,
5393 true) &&
5394 (functypclass == TYPEFUNC_COMPOSITE ||
5395 functypclass == TYPEFUNC_COMPOSITE_DOMAIN ||
5396 functypclass == TYPEFUNC_RECORD))
5397 goto fail; /* reject not-whole-tuple-result cases */
5398
5399 /*
5400 * check_sql_fn_retval might've inserted a projection step, but that's
5401 * fine; just make sure we use the upper Query.
5402 */
5403 querytree = linitial_node(Query, querytree_list);
5404
5405 /*
5406 * Looks good --- substitute parameters into the query.
5407 */
5409 funcform->pronargs,
5410 fexpr->args);
5411
5412 /*
5413 * Copy the modified query out of the temporary memory context, and clean
5414 * up.
5415 */
5416 MemoryContextSwitchTo(oldcxt);
5417
5419
5420 MemoryContextDelete(mycxt);
5421 error_context_stack = sqlerrcontext.previous;
5422 ReleaseSysCache(func_tuple);
5423
5424 /*
5425 * We don't have to fix collations here because the upper query is already
5426 * parsed, ie, the collations in the RTE are what count.
5427 */
5428
5429 /*
5430 * Since there is now no trace of the function in the plan tree, we must
5431 * explicitly record the plan's dependency on the function.
5432 */
5434
5435 /*
5436 * We must also notice if the inserted query adds a dependency on the
5437 * calling role due to RLS quals.
5438 */
5439 if (querytree->hasRowSecurity)
5440 root->glob->dependsOnRole = true;
5441
5442 return querytree;
5443
5444 /* Here if func is not inlinable: release temp memory and return NULL */
5445fail:
5446 MemoryContextSwitchTo(oldcxt);
5447 MemoryContextDelete(mycxt);
5448 error_context_stack = sqlerrcontext.previous;
5449 ReleaseSysCache(func_tuple);
5450
5451 return NULL;
5452}
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:3834
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:751
static Query * substitute_actual_srf_parameters(Query *expr, int nargs, List *args)
Definition: clauses.c:5461
static void sql_inline_error_callback(void *arg)
Definition: clauses.c:5052
bool contain_subplans(Node *clause)
Definition: clauses.c:334
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:542
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:2116
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition: functions.c:340
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
Definition: functions.c:251
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:160
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:469
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
Oid GetUserId(void)
Definition: miscinit.c:469
#define copyObject(obj)
Definition: nodes.h:232
@ CMD_SELECT
Definition: nodes.h:275
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
void(* ParserSetupHook)(ParseState *pstate, void *arg)
Definition: params.h:107
@ RTE_FUNCTION
Definition: parsenodes.h:1046
#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:763
List * pg_parse_query(const char *query_string)
Definition: postgres.c:604
List * pg_rewrite_query(Query *query)
Definition: postgres.c:803
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
uint64_t Datum
Definition: postgres.h:70
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:3575
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:800
bool funcordinality
Definition: parsenodes.h:1210
List * functions
Definition: parsenodes.h:1208
RTEKind rtekind
Definition: parsenodes.h:1078
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:595
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:625
TupleDesc BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations)
Definition: tupdesc.c:1051

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

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

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_nestloop_plan(), create_partial_unique_paths(), 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 2095 of file clauses.c.

2096{
2097 /*
2098 * We could implement this check in one recursive scan. But since the
2099 * check for volatile functions is both moderately expensive and unlikely
2100 * to fail, it seems better to look for Vars first and only check for
2101 * volatile functions if we find no Vars.
2102 */
2103 if (!contain_var_clause(clause) &&
2105 return true;
2106 return false;
2107}
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 2115 of file clauses.c.

2116{
2117 if (bms_is_empty(relids) &&
2119 return true;
2120 return false;
2121}
#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 738 of file clauses.c.

739{
741
742 context.max_hazard = PROPARALLEL_SAFE;
743 context.max_interesting = PROPARALLEL_UNSAFE;
744 context.safe_param_ids = NIL;
745 (void) max_parallel_hazard_walker((Node *) parse, &context);
746 return context.max_hazard;
747}
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 2137 of file clauses.c.

2138{
2139 int result;
2140 Relids varnos = pull_varnos(root, clause);
2141
2142 varnos = bms_del_members(varnos, root->outer_join_rels);
2143 result = bms_num_members(varnos);
2144 bms_free(varnos);
2145 return result;
2146}
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 5521 of file clauses.c.

5522{
5523 Bitmapset *result = NULL;
5524
5525 (void) pull_paramids_walker((Node *) expr, &result);
5526
5527 return result;
5528}
static bool pull_paramids_walker(Node *node, Bitmapset **context)
Definition: clauses.c:5531

References pull_paramids_walker().

Referenced by create_memoize_plan().