#include "nodes/relation.h"

Go to the source code of this file.
| #define is_funcclause | ( | clause | ) | ((clause) != NULL && IsA(clause, FuncExpr)) |
Definition at line 21 of file clauses.h.
Referenced by clause_selectivity(), predicate_implied_by_simple_clause(), and predicate_refuted_by_simple_clause().
| #define is_opclause | ( | clause | ) | ((clause) != NULL && IsA(clause, OpExpr)) |
Definition at line 20 of file clauses.h.
Referenced by btree_predicate_proof(), check_hashjoinable(), check_mergejoinable(), clause_selectivity(), clauselist_selectivity(), CommuteOpExpr(), create_hashjoin_plan(), expand_indexqual_conditions(), get_switched_clauses(), make_restrictinfo_internal(), match_clause_to_indexcol(), match_clause_to_ordering_op(), mergejoinscansel(), predicate_implied_by_simple_clause(), predicate_refuted_by_simple_clause(), process_equivalence(), reconsider_full_join_clause(), reconsider_outer_join_clause(), TidListCreate(), and TidQualFromExpr().
Definition at line 299 of file clauses.c.
References AND_EXPR, boolop(), IsA, and NULL.
Referenced by clause_selectivity(), ExecInitSubPlan(), find_duplicate_ors(), generate_bitmap_or_paths(), make_ands_implicit(), make_restrictinfo(), make_sub_restrictinfos(), predicate_classify(), process_duplicate_ors(), process_sublinks_mutator(), pull_ands(), pull_up_sublinks_qual_recurse(), simplify_and_arguments(), testexpr_is_hashable(), and TidQualFromExpr().
| void CommuteOpExpr | ( | OpExpr * | clause | ) |
Definition at line 1969 of file clauses.c.
References OpExpr::args, elog, ERROR, get_commutator(), is_opclause, linitial, list_length(), lsecond, OidIsValid, OpExpr::opfuncid, and OpExpr::opno.
Referenced by fix_indexqual_references(), and get_switched_clauses().
{
Oid opoid;
Node *temp;
/* Sanity checks: caller is at fault if these fail */
if (!is_opclause(clause) ||
list_length(clause->args) != 2)
elog(ERROR, "cannot commute non-binary-operator clause");
opoid = get_commutator(clause->opno);
if (!OidIsValid(opoid))
elog(ERROR, "could not find commutator for operator %u",
clause->opno);
/*
* modify the clause in-place!
*/
clause->opno = opoid;
clause->opfuncid = InvalidOid;
/* opresulttype, opretset, opcollid, inputcollid need not change */
temp = linitial(clause->args);
linitial(clause->args) = lsecond(clause->args);
lsecond(clause->args) = temp;
}
| void CommuteRowCompareExpr | ( | RowCompareExpr * | clause | ) |
Definition at line 2003 of file clauses.c.
References elog, ERROR, get_commutator(), IsA, lappend_oid(), RowCompareExpr::largs, lfirst_oid, OidIsValid, RowCompareExpr::opnos, RowCompareExpr::rargs, RowCompareExpr::rctype, ROWCOMPARE_GE, ROWCOMPARE_GT, ROWCOMPARE_LE, and ROWCOMPARE_LT.
Referenced by fix_indexqual_references().
{
List *newops;
List *temp;
ListCell *l;
/* Sanity checks: caller is at fault if these fail */
if (!IsA(clause, RowCompareExpr))
elog(ERROR, "expected a RowCompareExpr");
/* Build list of commuted operators */
newops = NIL;
foreach(l, clause->opnos)
{
Oid opoid = lfirst_oid(l);
opoid = get_commutator(opoid);
if (!OidIsValid(opoid))
elog(ERROR, "could not find commutator for operator %u",
lfirst_oid(l));
newops = lappend_oid(newops, opoid);
}
/*
* modify the clause in-place!
*/
switch (clause->rctype)
{
case ROWCOMPARE_LT:
clause->rctype = ROWCOMPARE_GT;
break;
case ROWCOMPARE_LE:
clause->rctype = ROWCOMPARE_GE;
break;
case ROWCOMPARE_GE:
clause->rctype = ROWCOMPARE_LE;
break;
case ROWCOMPARE_GT:
clause->rctype = ROWCOMPARE_LT;
break;
default:
elog(ERROR, "unexpected RowCompare type: %d",
(int) clause->rctype);
break;
}
clause->opnos = newops;
/*
* Note: we need not change the opfamilies list; we assume any btree
* opfamily containing an operator will also contain its commutator.
* Collations don't change either.
*/
temp = clause->largs;
clause->largs = clause->rargs;
clause->rargs = temp;
}
Definition at line 402 of file clauses.c.
References contain_agg_clause_walker(), and NULL.
Referenced by count_agg_clauses_walker(), get_eclass_for_sort_expr(), and subquery_planner().
{
return contain_agg_clause_walker(clause, NULL);
}
Definition at line 1182 of file clauses.c.
References contain_leaky_functions_walker(), and NULL.
Referenced by set_subquery_pathlist().
{
return contain_leaky_functions_walker(clause, NULL);
}
Definition at line 829 of file clauses.c.
References contain_mutable_functions_walker(), and NULL.
Referenced by CheckMutability(), create_bitmap_scan_plan(), create_indexscan_plan(), find_minmax_aggs_walker(), inline_function(), is_foreign_expr(), and relation_excluded_by_constraints().
{
return contain_mutable_functions_walker(clause, NULL);
}
Definition at line 1061 of file clauses.c.
References contain_nonstrict_functions_walker(), and NULL.
Referenced by inline_function(), process_equivalence(), and pullup_replace_vars_callback().
{
return contain_nonstrict_functions_walker(clause, NULL);
}
Definition at line 794 of file clauses.c.
References contain_subplans_walker(), and NULL.
Referenced by convert_EXISTS_to_ANY(), inline_function(), inline_set_returning_function(), qual_is_pushdown_safe(), and subquery_planner().
{
return contain_subplans_walker(clause, NULL);
}
Definition at line 944 of file clauses.c.
References contain_volatile_functions_walker(), and NULL.
Referenced by adjust_rowcompare_for_index(), BeginCopyFrom(), check_hashjoinable(), check_mergejoinable(), convert_ANY_sublink_to_join(), convert_EXISTS_sublink_to_join(), convert_EXISTS_to_ANY(), create_unique_path(), distribute_qual_to_rels(), estimate_num_groups(), ExecInitAgg(), ExecInitWindowAgg(), get_eclass_for_sort_expr(), inline_function(), inline_set_returning_function(), is_pseudo_constant_clause(), is_pseudo_constant_clause_relids(), is_simple_subquery(), make_restrictinfos_from_actual_clauses(), match_clause_to_indexcol(), match_clause_to_ordering_op(), match_rowcompare_to_indexcol(), qual_is_pushdown_safe(), and subquery_planner().
{
return contain_volatile_functions_walker(clause, NULL);
}
Definition at line 599 of file clauses.c.
References contain_windowfuncs().
Referenced by find_window_functions_walker(), get_eclass_for_sort_expr(), and qual_is_pushdown_safe().
{
return contain_windowfuncs(clause);
}
| void count_agg_clauses | ( | PlannerInfo * | root, | |
| Node * | clause, | |||
| AggClauseCosts * | costs | |||
| ) |
Definition at line 441 of file clauses.c.
References count_agg_clauses_context::costs, count_agg_clauses_walker(), and count_agg_clauses_context::root.
Referenced by grouping_planner().
{
count_agg_clauses_context context;
context.root = root;
context.costs = costs;
(void) count_agg_clauses_walker(clause, &context);
}
| Node* estimate_expression_value | ( | PlannerInfo * | root, | |
| Node * | node | |||
| ) |
Definition at line 2226 of file clauses.c.
References eval_const_expressions_context::active_fns, PlannerGlobal::boundParams, eval_const_expressions_context::boundParams, eval_const_expressions_context::case_val, eval_const_expressions_context::estimate, eval_const_expressions_mutator(), PlannerInfo::glob, and eval_const_expressions_context::root.
Referenced by clause_selectivity(), get_restriction_variable(), preprocess_limit(), and scalararraysel_containment().
{
eval_const_expressions_context context;
context.boundParams = root->glob->boundParams; /* bound Params */
/* we do not need to mark the plan as depending on inlined functions */
context.root = NULL;
context.active_fns = NIL; /* nothing being recursively simplified */
context.case_val = NULL; /* no CASE being examined */
context.estimate = true; /* unsafe transformations OK */
return eval_const_expressions_mutator(node, &context);
}
| Node* eval_const_expressions | ( | PlannerInfo * | root, | |
| Node * | node | |||
| ) |
Definition at line 2193 of file clauses.c.
References eval_const_expressions_context::active_fns, PlannerGlobal::boundParams, eval_const_expressions_context::boundParams, eval_const_expressions_context::case_val, eval_const_expressions_context::estimate, eval_const_expressions_mutator(), PlannerInfo::glob, and eval_const_expressions_context::root.
Referenced by convert_EXISTS_to_ANY(), expression_planner(), get_relation_constraints(), inline_set_returning_function(), preprocess_expression(), process_implied_equality(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), and set_append_rel_size().
{
eval_const_expressions_context context;
if (root)
context.boundParams = root->glob->boundParams; /* bound Params */
else
context.boundParams = NULL;
context.root = root; /* for inlined-function dependencies */
context.active_fns = NIL; /* nothing being recursively simplified */
context.case_val = NULL; /* no CASE being examined */
context.estimate = false; /* safe transformations only */
return eval_const_expressions_mutator(node, &context);
}
| double expression_returns_set_rows | ( | Node * | clause | ) |
Definition at line 676 of file clauses.c.
References clamp_row_est(), and expression_returns_set_rows_walker().
Referenced by set_function_size_estimates(), and tlist_returns_set_rows().
{
double result = 1;
(void) expression_returns_set_rows_walker(clause, &result);
return clamp_row_est(result);
}
Definition at line 1802 of file clauses.c.
References BooleanTest::arg, NullTest::arg, NullTest::argisrow, BooleanTest::booltesttype, IS_NULL, IS_UNKNOWN, IsA, NULL, NullTest::nulltesttype, and Var::varlevelsup.
Referenced by check_redundant_nullability_qual(), and find_forced_null_vars().
{
if (node == NULL)
return NULL;
if (IsA(node, NullTest))
{
/* check for var IS NULL */
NullTest *expr = (NullTest *) node;
if (expr->nulltesttype == IS_NULL && !expr->argisrow)
{
Var *var = (Var *) expr->arg;
if (var && IsA(var, Var) &&
var->varlevelsup == 0)
return var;
}
}
else if (IsA(node, BooleanTest))
{
/* var IS UNKNOWN is equivalent to var IS NULL */
BooleanTest *expr = (BooleanTest *) node;
if (expr->booltesttype == IS_UNKNOWN)
{
Var *var = (Var *) expr->arg;
if (var && IsA(var, Var) &&
var->varlevelsup == 0)
return var;
}
}
return NULL;
}
Definition at line 1743 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 NULL.
Referenced by find_forced_null_vars(), and reduce_outer_joins_pass2().
{
List *result = NIL;
Var *var;
ListCell *l;
if (node == NULL)
return NIL;
/* Check single-clause cases using subroutine */
var = find_forced_null_var(node);
if (var)
{
result = list_make1(var);
}
/* Otherwise, handle AND-conditions */
else if (IsA(node, List))
{
/*
* At top level, we are examining an implicit-AND list: if any of the
* arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
*/
foreach(l, (List *) node)
{
result = list_concat(result,
find_forced_null_vars(lfirst(l)));
}
}
else if (IsA(node, BoolExpr))
{
BoolExpr *expr = (BoolExpr *) node;
/*
* We don't bother considering the OR case, because it's fairly
* unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
* the NOT case isn't worth expending code on.
*/
if (expr->boolop == AND_EXPR)
{
/* At top level we can just recurse (to the List case) */
result = find_forced_null_vars((Node *) expr->args);
}
}
return result;
}
Definition at line 1342 of file clauses.c.
References find_nonnullable_rels_walker().
Referenced by make_outerjoininfo(), and reduce_outer_joins_pass2().
{
return find_nonnullable_rels_walker(clause, true);
}
Definition at line 1550 of file clauses.c.
References find_nonnullable_vars_walker().
Referenced by reduce_outer_joins_pass2().
{
return find_nonnullable_vars_walker(clause, true);
}
| WindowFuncLists* find_window_functions | ( | Node * | clause, | |
| Index | maxWinRef | |||
| ) |
Definition at line 612 of file clauses.c.
References find_window_functions_walker(), WindowFuncLists::maxWinRef, WindowFuncLists::numWindowFuncs, palloc(), palloc0(), and WindowFuncLists::windowFuncs.
Referenced by grouping_planner().
{
WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
lists->numWindowFuncs = 0;
lists->maxWinRef = maxWinRef;
lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
(void) find_window_functions_walker(clause, lists);
return lists;
}
Definition at line 184 of file clauses.c.
References OpExpr::args, linitial, and NIL.
Referenced by addRangeClause(), btcostestimate(), btree_predicate_proof(), ExecIndexBuildScanKeys(), expand_indexqual_opclause(), final_cost_hashjoin(), gincost_opexpr(), initialize_mergeclause_eclasses(), make_restrictinfo_internal(), match_clause_to_indexcol(), match_clause_to_ordering_op(), mergejoinscansel(), print_expr(), process_equivalence(), reconsider_full_join_clause(), reconsider_outer_join_clause(), relation_has_unique_index_for(), and TidListCreate().
Definition at line 250 of file clauses.c.
References linitial.
Referenced by clause_selectivity(), expand_boolean_index_clause(), match_boolean_index_clause(), and pull_up_sublinks_qual_recurse().
Definition at line 201 of file clauses.c.
References OpExpr::args, list_length(), and lsecond.
Referenced by addRangeClause(), btcostestimate(), btree_predicate_proof(), ExecIndexBuildScanKeys(), expand_indexqual_opclause(), final_cost_hashjoin(), gincost_opexpr(), initialize_mergeclause_eclasses(), make_restrictinfo_internal(), match_clause_to_indexcol(), match_clause_to_ordering_op(), match_special_index_operator(), mergejoinscansel(), print_expr(), process_equivalence(), reconsider_full_join_clause(), reconsider_outer_join_clause(), relation_has_unique_index_for(), and TidListCreate().
| Query* inline_set_returning_function | ( | PlannerInfo * | root, | |
| RangeTblEntry * | rte | |||
| ) |
Definition at line 4470 of file clauses.c.
References ACL_EXECUTE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), Anum_pg_proc_proconfig, Anum_pg_proc_prosrc, ErrorContextCallback::arg, FuncExpr::args, Assert, ErrorContextCallback::callback, check_sql_fn_retval(), check_stack_depth(), CMD_SELECT, Query::commandType, contain_subplans(), contain_volatile_functions(), copyObject(), CurrentMemoryContext, elog, ERROR, error_context_stack, eval_const_expressions(), FmgrHookIsNeeded, RangeTblEntry::funccoltypes, RangeTblEntry::funcexpr, FuncExpr::funcid, FuncExpr::funcretset, get_func_result_type(), get_typtype(), GETSTRUCT, GetUserId(), PlannerInfo::glob, heap_attisnull(), HeapTupleIsValid, PlannerGlobal::invalItems, IsA, linitial, list_concat(), list_length(), MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, NULL, ObjectIdGetDatum, pg_analyze_and_rewrite_params(), pg_parse_query(), pg_proc_aclcheck(), prepare_sql_fn_parse_info(), ErrorContextCallback::previous, PROCOID, inline_error_callback_arg::proname, inline_error_callback_arg::prosrc, PROVOLATILE_VOLATILE, record_plan_function_dependency(), RECORDOID, ReleaseSysCache(), RTE_FUNCTION, RangeTblEntry::rtekind, SearchSysCache1, sql_fn_parser_setup(), SQLlanguageId, substitute_actual_srf_parameters(), SysCacheGetAttr(), Query::targetList, TextDatumGetCString, tlist_matches_coltypelist(), TYPEFUNC_RECORD, TYPTYPE_COMPOSITE, and Query::utilityStmt.
Referenced by inline_set_returning_functions().
{
FuncExpr *fexpr;
Oid func_oid;
HeapTuple func_tuple;
Form_pg_proc funcform;
char *src;
Datum tmp;
bool isNull;
bool modifyTargetList;
MemoryContext oldcxt;
MemoryContext mycxt;
List *saveInvalItems;
inline_error_callback_arg callback_arg;
ErrorContextCallback sqlerrcontext;
SQLFunctionParseInfoPtr pinfo;
List *raw_parsetree_list;
List *querytree_list;
Query *querytree;
Assert(rte->rtekind == RTE_FUNCTION);
/*
* It doesn't make a lot of sense for a SQL SRF to refer to itself in its
* own FROM clause, since that must cause infinite recursion at runtime.
* It will cause this code to recurse too, so check for stack overflow.
* (There's no need to do more.)
*/
check_stack_depth();
/* Fail if FROM item isn't a simple FuncExpr */
fexpr = (FuncExpr *) rte->funcexpr;
if (fexpr == NULL || !IsA(fexpr, FuncExpr))
return NULL;
func_oid = fexpr->funcid;
/*
* The function must be declared to return a set, else inlining would
* change the results if the contained SELECT didn't return exactly one
* row.
*/
if (!fexpr->funcretset)
return NULL;
/*
* Refuse to inline if the arguments contain any volatile functions or
* sub-selects. Volatile functions are rejected because inlining may
* result in the arguments being evaluated multiple times, risking a
* change in behavior. Sub-selects are rejected partly for implementation
* reasons (pushing them down another level might change their behavior)
* and partly because they're likely to be expensive and so multiple
* evaluation would be bad.
*/
if (contain_volatile_functions((Node *) fexpr->args) ||
contain_subplans((Node *) fexpr->args))
return NULL;
/* Check permission to call function (fail later, if not) */
if (pg_proc_aclcheck(func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
return NULL;
/* Check whether a plugin wants to hook function entry/exit */
if (FmgrHookIsNeeded(func_oid))
return NULL;
/*
* OK, let's take a look at the function's pg_proc entry.
*/
func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid));
if (!HeapTupleIsValid(func_tuple))
elog(ERROR, "cache lookup failed for function %u", func_oid);
funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
/*
* Forget it if the function is not SQL-language or has other showstopper
* properties. In particular it mustn't be declared STRICT, since we
* couldn't enforce that. It also mustn't be VOLATILE, because that is
* supposed to cause it to be executed with its own snapshot, rather than
* sharing the snapshot of the calling query. (Rechecking proretset is
* just paranoia.)
*/
if (funcform->prolang != SQLlanguageId ||
funcform->proisstrict ||
funcform->provolatile == PROVOLATILE_VOLATILE ||
funcform->prosecdef ||
!funcform->proretset ||
!heap_attisnull(func_tuple, Anum_pg_proc_proconfig))
{
ReleaseSysCache(func_tuple);
return NULL;
}
/*
* Make a temporary memory context, so that we don't leak all the stuff
* that parsing might create.
*/
mycxt = AllocSetContextCreate(CurrentMemoryContext,
"inline_set_returning_function",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
oldcxt = MemoryContextSwitchTo(mycxt);
/*
* When we call eval_const_expressions below, it might try to add items to
* root->glob->invalItems. Since it is running in the temp context, those
* items will be in that context, and will need to be copied out if we're
* successful. Temporarily reset the list so that we can keep those items
* separate from the pre-existing list contents.
*/
saveInvalItems = root->glob->invalItems;
root->glob->invalItems = NIL;
/* Fetch the function body */
tmp = SysCacheGetAttr(PROCOID,
func_tuple,
Anum_pg_proc_prosrc,
&isNull);
if (isNull)
elog(ERROR, "null prosrc for function %u", func_oid);
src = TextDatumGetCString(tmp);
/*
* Setup error traceback support for ereport(). This is so that we can
* finger the function that bad information came from.
*/
callback_arg.proname = NameStr(funcform->proname);
callback_arg.prosrc = src;
sqlerrcontext.callback = sql_inline_error_callback;
sqlerrcontext.arg = (void *) &callback_arg;
sqlerrcontext.previous = error_context_stack;
error_context_stack = &sqlerrcontext;
/*
* Run eval_const_expressions on the function call. This is necessary to
* ensure that named-argument notation is converted to positional notation
* and any default arguments are inserted. It's a bit of overkill for the
* arguments, since they'll get processed again later, but no harm will be
* done.
*/
fexpr = (FuncExpr *) eval_const_expressions(root, (Node *) fexpr);
/* It should still be a call of the same function, but let's check */
if (!IsA(fexpr, FuncExpr) ||
fexpr->funcid != func_oid)
goto fail;
/* Arg list length should now match the function */
if (list_length(fexpr->args) != funcform->pronargs)
goto fail;
/*
* Set up to handle parameters while parsing the function body. We can
* use the FuncExpr just created as the input for
* prepare_sql_fn_parse_info.
*/
pinfo = prepare_sql_fn_parse_info(func_tuple,
(Node *) fexpr,
fexpr->inputcollid);
/*
* Parse, analyze, and rewrite (unlike inline_function(), we can't skip
* rewriting here). We can fail as soon as we find more than one query,
* though.
*/
raw_parsetree_list = pg_parse_query(src);
if (list_length(raw_parsetree_list) != 1)
goto fail;
querytree_list = pg_analyze_and_rewrite_params(linitial(raw_parsetree_list),
src,
(ParserSetupHook) sql_fn_parser_setup,
pinfo);
if (list_length(querytree_list) != 1)
goto fail;
querytree = linitial(querytree_list);
/*
* The single command must be a plain SELECT.
*/
if (!IsA(querytree, Query) ||
querytree->commandType != CMD_SELECT ||
querytree->utilityStmt)
goto fail;
/*
* Make sure the function (still) returns what it's declared to. This
* will raise an error if wrong, but that's okay since the function would
* fail at runtime anyway. Note that check_sql_fn_retval will also insert
* RelabelType(s) and/or NULL columns if needed to make the tlist
* expression(s) match the declared type of the function.
*
* If the function returns a composite type, don't inline unless the check
* shows it's returning a whole tuple result; otherwise what it's
* returning is a single composite column which is not what we need.
*/
if (!check_sql_fn_retval(func_oid, fexpr->funcresulttype,
querytree_list,
&modifyTargetList, NULL) &&
(get_typtype(fexpr->funcresulttype) == TYPTYPE_COMPOSITE ||
fexpr->funcresulttype == RECORDOID))
goto fail; /* reject not-whole-tuple-result cases */
/*
* If we had to modify the tlist to make it match, and the statement is
* one in which changing the tlist contents could change semantics, we
* have to punt and not inline.
*/
if (modifyTargetList)
goto fail;
/*
* If it returns RECORD, we have to check against the column type list
* provided in the RTE; check_sql_fn_retval can't do that. (If no match,
* we just fail to inline, rather than complaining; see notes for
* tlist_matches_coltypelist.) We don't have to do this for functions
* with declared OUT parameters, even though their funcresulttype is
* RECORDOID, so check get_func_result_type too.
*/
if (fexpr->funcresulttype == RECORDOID &&
get_func_result_type(func_oid, NULL, NULL) == TYPEFUNC_RECORD &&
!tlist_matches_coltypelist(querytree->targetList, rte->funccoltypes))
goto fail;
/*
* Looks good --- substitute parameters into the query.
*/
querytree = substitute_actual_srf_parameters(querytree,
funcform->pronargs,
fexpr->args);
/*
* Copy the modified query out of the temporary memory context, and clean
* up.
*/
MemoryContextSwitchTo(oldcxt);
querytree = copyObject(querytree);
/* copy up any new invalItems, too */
root->glob->invalItems = list_concat(saveInvalItems,
copyObject(root->glob->invalItems));
MemoryContextDelete(mycxt);
error_context_stack = sqlerrcontext.previous;
ReleaseSysCache(func_tuple);
/*
* We don't have to fix collations here because the upper query is already
* parsed, ie, the collations in the RTE are what count.
*/
/*
* Since there is now no trace of the function in the plan tree, we must
* explicitly record the plan's dependency on the function.
*/
record_plan_function_dependency(root, func_oid);
return querytree;
/* Here if func is not inlinable: release temp memory and return NULL */
fail:
MemoryContextSwitchTo(oldcxt);
root->glob->invalItems = saveInvalItems;
MemoryContextDelete(mycxt);
error_context_stack = sqlerrcontext.previous;
ReleaseSysCache(func_tuple);
return NULL;
}
Definition at line 1912 of file clauses.c.
References contain_var_clause(), and contain_volatile_functions().
Referenced by clauselist_selectivity(), IsTidEqualAnyClause(), and IsTidEqualClause().
{
/*
* We could implement this check in one recursive scan. But since the
* check for volatile functions is both moderately expensive and unlikely
* to fail, it seems better to look for Vars first and only check for
* volatile functions if we find no Vars.
*/
if (!contain_var_clause(clause) &&
!contain_volatile_functions(clause))
return true;
return false;
}
Definition at line 1932 of file clauses.c.
References bms_is_empty(), and contain_volatile_functions().
Referenced by clauselist_selectivity().
{
if (bms_is_empty(relids) &&
!contain_volatile_functions(clause))
return true;
return false;
}
Definition at line 333 of file clauses.c.
References list_make2, make_andclause(), and NULL.
Referenced by AddQual(), and subquery_push_qual().
{
if (qual1 == NULL)
return qual2;
if (qual2 == NULL)
return qual1;
return (Node *) make_andclause(list_make2(qual1, qual2));
}
Definition at line 312 of file clauses.c.
References BoolExpr::args, BoolExpr::boolop, BoolExpr::location, and makeNode.
Referenced by eval_const_expressions_mutator(), find_duplicate_ors(), make_and_qual(), make_ands_explicit(), make_restrictinfo_from_bitmapqual(), make_sub_restrictinfos(), negate_clause(), process_duplicate_ors(), process_sublinks_mutator(), and pull_up_sublinks_qual_recurse().
Definition at line 352 of file clauses.c.
References linitial, list_length(), make_andclause(), makeBoolConst(), and NIL.
Referenced by convert_EXISTS_to_ANY(), create_bitmap_subplan(), set_append_rel_size(), show_qual(), and UpdateIndexRelation().
{
if (andclauses == NIL)
return (Expr *) makeBoolConst(true, false);
else if (list_length(andclauses) == 1)
return (Expr *) linitial(andclauses);
else
return make_andclause(andclauses);
}
Definition at line 363 of file clauses.c.
References and_clause(), DatumGetBool, IsA, list_make1, and NULL.
Referenced by ATAddCheckConstraint(), convert_EXISTS_to_ANY(), cost_subplan(), DefineIndex(), ExecRelCheck(), get_relation_constraints(), preprocess_expression(), RelationGetIndexPredicate(), set_append_rel_size(), TriggerEnabled(), and validateCheckConstraint().
{
/*
* NB: because the parser sets the qual field to NULL in a query that has
* no WHERE clause, we must consider a NULL input clause as TRUE, even
* though one might more reasonably think it FALSE. Grumble. If this
* causes trouble, consider changing the parser's behavior.
*/
if (clause == NULL)
return NIL; /* NULL -> NIL list == TRUE */
else if (and_clause((Node *) clause))
return ((BoolExpr *) clause)->args;
else if (IsA(clause, Const) &&
!((Const *) clause)->constisnull &&
DatumGetBool(((Const *) clause)->constvalue))
return NIL; /* constant TRUE input -> NIL list */
else
return list_make1(clause);
}
Definition at line 234 of file clauses.c.
References BoolExpr::args, BoolExpr::boolop, list_make1, BoolExpr::location, and makeNode.
Referenced by negate_clause().
| Expr* make_opclause | ( | Oid | opno, | |
| Oid | opresulttype, | |||
| bool | opretset, | |||
| Expr * | leftop, | |||
| Expr * | rightop, | |||
| Oid | opcollid, | |||
| Oid | inputcollid | |||
| ) |
Definition at line 157 of file clauses.c.
References OpExpr::args, OpExpr::inputcollid, list_make1, list_make2, OpExpr::location, makeNode, OpExpr::opcollid, OpExpr::opfuncid, OpExpr::opno, OpExpr::opresulttype, and OpExpr::opretset.
Referenced by adjust_rowcompare_for_index(), btree_predicate_proof(), build_implied_join_equality(), convert_EXISTS_to_ANY(), expand_boolean_index_clause(), network_prefix_quals(), prefix_quals(), and process_implied_equality().
{
OpExpr *expr = makeNode(OpExpr);
expr->opno = opno;
expr->opfuncid = InvalidOid;
expr->opresulttype = opresulttype;
expr->opretset = opretset;
expr->opcollid = opcollid;
expr->inputcollid = inputcollid;
if (rightop)
expr->args = list_make2(leftop, rightop);
else
expr->args = list_make1(leftop);
expr->location = -1;
return (Expr *) expr;
}
Definition at line 278 of file clauses.c.
References BoolExpr::args, BoolExpr::boolop, BoolExpr::location, and makeNode.
Referenced by create_bitmap_subplan(), create_tidscan_plan(), eval_const_expressions_mutator(), ExplainNode(), make_restrictinfo_from_bitmapqual(), make_sub_restrictinfos(), negate_clause(), process_duplicate_ors(), and process_sublinks_mutator().
Definition at line 221 of file clauses.c.
References boolop(), IsA, NOT_EXPR, and NULL.
Referenced by clause_selectivity(), expand_boolean_index_clause(), match_boolean_index_clause(), and pull_up_sublinks_qual_recurse().
| int NumRelids | ( | Node * | clause | ) |
Definition at line 1954 of file clauses.c.
References bms_free(), bms_num_members(), and pull_varnos().
Referenced by clauselist_selectivity(), rowcomparesel(), and treat_as_join_clause().
{
Relids varnos = pull_varnos(clause);
int result = bms_num_members(varnos);
bms_free(varnos);
return result;
}
Definition at line 265 of file clauses.c.
References boolop(), IsA, NULL, and OR_EXPR.
Referenced by clause_selectivity(), find_duplicate_ors(), make_restrictinfo(), make_restrictinfo_from_bitmapqual(), make_sub_restrictinfos(), predicate_classify(), process_sublinks_mutator(), pull_ors(), simplify_or_arguments(), and TidQualFromExpr().
Definition at line 2069 of file clauses.c.
References CoerceToDomain::arg, ConvertRowtypeExpr::arg, ArrayCoerceExpr::arg, CoerceViaIO::arg, RelabelType::arg, FuncExpr::args, COERCE_IMPLICIT_CAST, ArrayCoerceExpr::coerceformat, CoerceViaIO::coerceformat, CoerceToDomain::coercionformat, ConvertRowtypeExpr::convertformat, FuncExpr::funcformat, IsA, linitial, NULL, RelabelType::relabelformat, and strip_implicit_coercions().
Referenced by ATExecAlterColumnType(), findTargetlistEntrySQL99(), flatten_join_using_qual(), get_rule_expr(), and strip_implicit_coercions().
{
if (node == NULL)
return NULL;
if (IsA(node, FuncExpr))
{
FuncExpr *f = (FuncExpr *) node;
if (f->funcformat == COERCE_IMPLICIT_CAST)
return strip_implicit_coercions(linitial(f->args));
}
else if (IsA(node, RelabelType))
{
RelabelType *r = (RelabelType *) node;
if (r->relabelformat == COERCE_IMPLICIT_CAST)
return strip_implicit_coercions((Node *) r->arg);
}
else if (IsA(node, CoerceViaIO))
{
CoerceViaIO *c = (CoerceViaIO *) node;
if (c->coerceformat == COERCE_IMPLICIT_CAST)
return strip_implicit_coercions((Node *) c->arg);
}
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *c = (ArrayCoerceExpr *) node;
if (c->coerceformat == COERCE_IMPLICIT_CAST)
return strip_implicit_coercions((Node *) c->arg);
}
else if (IsA(node, ConvertRowtypeExpr))
{
ConvertRowtypeExpr *c = (ConvertRowtypeExpr *) node;
if (c->convertformat == COERCE_IMPLICIT_CAST)
return strip_implicit_coercions((Node *) c->arg);
}
else if (IsA(node, CoerceToDomain))
{
CoerceToDomain *c = (CoerceToDomain *) node;
if (c->coercionformat == COERCE_IMPLICIT_CAST)
return strip_implicit_coercions((Node *) c->arg);
}
return node;
}
| double tlist_returns_set_rows | ( | List * | tlist | ) |
Definition at line 760 of file clauses.c.
References TargetEntry::expr, expression_returns_set_rows(), and lfirst.
Referenced by add_tlist_costs_to_plan().
{
double result = 1;
ListCell *lc;
foreach(lc, tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(lc);
double colresult;
colresult = expression_returns_set_rows((Node *) tle->expr);
if (result < colresult)
result = colresult;
}
return result;
}
1.7.1