Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Functions

clauses.h File Reference

#include "nodes/relation.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

Defines

#define is_opclause(clause)   ((clause) != NULL && IsA(clause, OpExpr))
#define is_funcclause(clause)   ((clause) != NULL && IsA(clause, FuncExpr))

Functions

Exprmake_opclause (Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Nodeget_leftop (const Expr *clause)
Nodeget_rightop (const Expr *clause)
bool not_clause (Node *clause)
Exprmake_notclause (Expr *notclause)
Exprget_notclausearg (Expr *notclause)
bool or_clause (Node *clause)
Exprmake_orclause (List *orclauses)
bool and_clause (Node *clause)
Exprmake_andclause (List *andclauses)
Nodemake_and_qual (Node *qual1, Node *qual2)
Exprmake_ands_explicit (List *andclauses)
Listmake_ands_implicit (Expr *clause)
bool contain_agg_clause (Node *clause)
void count_agg_clauses (PlannerInfo *root, Node *clause, AggClauseCosts *costs)
bool contain_window_function (Node *clause)
WindowFuncListsfind_window_functions (Node *clause, Index maxWinRef)
double expression_returns_set_rows (Node *clause)
double tlist_returns_set_rows (List *tlist)
bool contain_subplans (Node *clause)
bool contain_mutable_functions (Node *clause)
bool contain_volatile_functions (Node *clause)
bool contain_nonstrict_functions (Node *clause)
bool contain_leaky_functions (Node *clause)
Relids find_nonnullable_rels (Node *clause)
Listfind_nonnullable_vars (Node *clause)
Listfind_forced_null_vars (Node *clause)
Varfind_forced_null_var (Node *clause)
bool is_pseudo_constant_clause (Node *clause)
bool is_pseudo_constant_clause_relids (Node *clause, Relids relids)
int NumRelids (Node *clause)
void CommuteOpExpr (OpExpr *clause)
void CommuteRowCompareExpr (RowCompareExpr *clause)
Nodestrip_implicit_coercions (Node *node)
Nodeeval_const_expressions (PlannerInfo *root, Node *node)
Nodeestimate_expression_value (PlannerInfo *root, Node *node)
Queryinline_set_returning_function (PlannerInfo *root, RangeTblEntry *rte)

Define Documentation

#define is_funcclause (   clause  )     ((clause) != NULL && IsA(clause, FuncExpr))
#define is_opclause (   clause  )     ((clause) != NULL && IsA(clause, OpExpr))

Function Documentation

bool and_clause ( Node clause  ) 
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;
}

bool contain_agg_clause ( Node clause  ) 

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);
}

bool contain_leaky_functions ( Node clause  ) 

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);
}

bool contain_mutable_functions ( Node clause  ) 
bool contain_nonstrict_functions ( Node clause  ) 
bool contain_subplans ( Node clause  ) 
bool contain_volatile_functions ( Node clause  ) 
bool contain_window_function ( Node clause  ) 

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 
)
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);
}

Var* find_forced_null_var ( Node clause  ) 

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;
}

List* find_forced_null_vars ( Node clause  ) 

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;
}

Relids find_nonnullable_rels ( Node clause  ) 

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);
}

List* find_nonnullable_vars ( Node clause  ) 

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;
}

Node* get_leftop ( const Expr clause  ) 
Expr* get_notclausearg ( Expr notclause  ) 

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

{
    return linitial(((BoolExpr *) notclause)->args);
}

Node* get_rightop ( const Expr clause  ) 
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;
}

bool is_pseudo_constant_clause ( Node clause  ) 

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;
}

bool is_pseudo_constant_clause_relids ( Node clause,
Relids  relids 
)

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;
}

Node* make_and_qual ( Node qual1,
Node qual2 
)

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));
}

Expr* make_andclause ( List andclauses  ) 
Expr* make_ands_explicit ( List andclauses  ) 

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);
}

List* make_ands_implicit ( Expr clause  ) 

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);
}

Expr* make_notclause ( Expr notclause  ) 

Definition at line 234 of file clauses.c.

References BoolExpr::args, BoolExpr::boolop, list_make1, BoolExpr::location, and makeNode.

Referenced by negate_clause().

{
    BoolExpr   *expr = makeNode(BoolExpr);

    expr->boolop = NOT_EXPR;
    expr->args = list_make1(notclause);
    expr->location = -1;
    return (Expr *) expr;
}

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;
}

Expr* make_orclause ( List orclauses  ) 
bool not_clause ( Node clause  ) 

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

{
    return (clause != NULL &&
            IsA(clause, BoolExpr) &&
            ((BoolExpr *) clause)->boolop == NOT_EXPR);
}

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;
}

bool or_clause ( Node clause  ) 
Node* strip_implicit_coercions ( Node node  ) 

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;
}