Header And Logo

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

Typedefs | Functions

parse_oper.h File Reference

#include "access/htup.h"
#include "parser/parse_node.h"
Include dependency graph for parse_oper.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef HeapTuple Operator

Functions

Oid LookupOperName (ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Oid LookupOperNameTypeNames (ParseState *pstate, List *opername, TypeName *oprleft, TypeName *oprright, bool noError, int location)
Operator oper (ParseState *pstate, List *op, Oid arg1, Oid arg2, bool noError, int location)
Operator right_oper (ParseState *pstate, List *op, Oid arg, bool noError, int location)
Operator left_oper (ParseState *pstate, List *op, Oid arg, bool noError, int location)
Operator compatible_oper (ParseState *pstate, List *op, Oid arg1, Oid arg2, bool noError, int location)
void get_sort_group_operators (Oid argtype, bool needLT, bool needEQ, bool needGT, Oid *ltOpr, Oid *eqOpr, Oid *gtOpr, bool *isHashable)
Oid compatible_oper_opid (List *op, Oid arg1, Oid arg2, bool noError)
Oid oprid (Operator op)
Oid oprfuncid (Operator op)
Exprmake_op (ParseState *pstate, List *opname, Node *ltree, Node *rtree, int location)
Exprmake_scalar_array_op (ParseState *pstate, List *opname, bool useOr, Node *ltree, Node *rtree, int location)

Typedef Documentation

Definition at line 21 of file parse_oper.h.


Function Documentation

Operator compatible_oper ( ParseState pstate,
List op,
Oid  arg1,
Oid  arg2,
bool  noError,
int  location 
)

Definition at line 453 of file parse_oper.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, IsBinaryCoercible(), NULL, op_signature_string(), oper(), parser_errposition(), and ReleaseSysCache().

Referenced by compatible_oper_opid().

{
    Operator    optup;
    Form_pg_operator opform;

    /* oper() will find the best available match */
    optup = oper(pstate, op, arg1, arg2, noError, location);
    if (optup == (Operator) NULL)
        return (Operator) NULL; /* must be noError case */

    /* but is it good enough? */
    opform = (Form_pg_operator) GETSTRUCT(optup);
    if (IsBinaryCoercible(arg1, opform->oprleft) &&
        IsBinaryCoercible(arg2, opform->oprright))
        return optup;

    /* nope... */
    ReleaseSysCache(optup);

    if (!noError)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("operator requires run-time type coercion: %s",
                        op_signature_string(op, 'b', arg1, arg2)),
                 parser_errposition(pstate, location)));

    return (Operator) NULL;
}

Oid compatible_oper_opid ( List op,
Oid  arg1,
Oid  arg2,
bool  noError 
)

Definition at line 490 of file parse_oper.c.

References compatible_oper(), NULL, oprid(), and ReleaseSysCache().

Referenced by addTargetToSortList(), and ComputeIndexAttrs().

{
    Operator    optup;
    Oid         result;

    optup = compatible_oper(NULL, op, arg1, arg2, noError, -1);
    if (optup != NULL)
    {
        result = oprid(optup);
        ReleaseSysCache(optup);
        return result;
    }
    return InvalidOid;
}

void get_sort_group_operators ( Oid  argtype,
bool  needLT,
bool  needEQ,
bool  needGT,
Oid ltOpr,
Oid eqOpr,
Oid gtOpr,
bool isHashable 
)

Definition at line 184 of file parse_oper.c.

References TypeCacheEntry::eq_opr, ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), TypeCacheEntry::gt_opr, TypeCacheEntry::hash_proc, lookup_type_cache(), TypeCacheEntry::lt_opr, NULL, OidIsValid, TYPECACHE_EQ_OPR, TYPECACHE_GT_OPR, and TYPECACHE_LT_OPR.

Referenced by addTargetToGroupList(), addTargetToSortList(), std_typanalyze(), and transformSetOperationTree().

{
    TypeCacheEntry *typentry;
    int         cache_flags;
    Oid         lt_opr;
    Oid         eq_opr;
    Oid         gt_opr;
    bool        hashable;

    /*
     * Look up the operators using the type cache.
     *
     * Note: the search algorithm used by typcache.c ensures that the results
     * are consistent, ie all from matching opclasses.
     */
    if (isHashable != NULL)
        cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR |
            TYPECACHE_HASH_PROC;
    else
        cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR;

    typentry = lookup_type_cache(argtype, cache_flags);
    lt_opr = typentry->lt_opr;
    eq_opr = typentry->eq_opr;
    gt_opr = typentry->gt_opr;
    hashable = OidIsValid(typentry->hash_proc);

    /* Report errors if needed */
    if ((needLT && !OidIsValid(lt_opr)) ||
        (needGT && !OidIsValid(gt_opr)))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("could not identify an ordering operator for type %s",
                        format_type_be(argtype)),
         errhint("Use an explicit ordering operator or modify the query.")));
    if (needEQ && !OidIsValid(eq_opr))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("could not identify an equality operator for type %s",
                        format_type_be(argtype))));

    /* Return results as needed */
    if (ltOpr)
        *ltOpr = lt_opr;
    if (eqOpr)
        *eqOpr = eq_opr;
    if (gtOpr)
        *gtOpr = gt_opr;
    if (isHashable)
        *isHashable = hashable;
}

Operator left_oper ( ParseState pstate,
List op,
Oid  arg,
bool  noError,
int  location 
)

Definition at line 599 of file parse_oper.c.

References _FuncCandidateList::args, find_oper_cache_entry(), HeapTupleIsValid, InvalidOid, make_oper_cache_entry(), make_oper_cache_key(), _FuncCandidateList::next, NULL, ObjectIdGetDatum, OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), OpernameGetOprid(), OPEROID, and SearchSysCache1.

Referenced by generate_operator_name(), and make_op().

{
    Oid         operOid;
    OprCacheKey key;
    bool        key_ok;
    FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
    HeapTuple   tup = NULL;

    /*
     * Try to find the mapping in the lookaside cache.
     */
    key_ok = make_oper_cache_key(&key, op, InvalidOid, arg);
    if (key_ok)
    {
        operOid = find_oper_cache_entry(&key);
        if (OidIsValid(operOid))
        {
            tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
            if (HeapTupleIsValid(tup))
                return (Operator) tup;
        }
    }

    /*
     * First try for an "exact" match.
     */
    operOid = OpernameGetOprid(op, InvalidOid, arg);
    if (!OidIsValid(operOid))
    {
        /*
         * Otherwise, search for the most suitable candidate.
         */
        FuncCandidateList clist;

        /* Get prefix operators of given name */
        clist = OpernameGetCandidates(op, 'l');

        /* No operators found? Then fail... */
        if (clist != NULL)
        {
            /*
             * The returned list has args in the form (0, oprright). Move the
             * useful data into args[0] to keep oper_select_candidate simple.
             * XXX we are assuming here that we may scribble on the list!
             */
            FuncCandidateList clisti;

            for (clisti = clist; clisti != NULL; clisti = clisti->next)
            {
                clisti->args[0] = clisti->args[1];
            }

            /*
             * We must run oper_select_candidate even if only one candidate,
             * otherwise we may falsely return a non-type-compatible operator.
             */
            fdresult = oper_select_candidate(1, &arg, clist, &operOid);
        }
    }

    if (OidIsValid(operOid))
        tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));

    if (HeapTupleIsValid(tup))
    {
        if (key_ok)
            make_oper_cache_entry(&key, operOid);
    }
    else if (!noError)
        op_error(pstate, op, 'l', InvalidOid, arg, fdresult, location);

    return (Operator) tup;
}

Oid LookupOperName ( ParseState pstate,
List opername,
Oid  oprleft,
Oid  oprright,
bool  noError,
int  location 
)

Definition at line 101 of file parse_oper.c.

References ereport, errcode(), errmsg(), ERROR, OidIsValid, op_signature_string(), OpernameGetOprid(), and parser_errposition().

Referenced by AggregateCreate(), DefineOpClass(), and LookupOperNameTypeNames().

{
    Oid         result;

    result = OpernameGetOprid(opername, oprleft, oprright);
    if (OidIsValid(result))
        return result;

    /* we don't use op_error here because only an exact match is wanted */
    if (!noError)
    {
        char        oprkind;

        if (!OidIsValid(oprleft))
            oprkind = 'l';
        else if (!OidIsValid(oprright))
            oprkind = 'r';
        else
            oprkind = 'b';

        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("operator does not exist: %s",
                        op_signature_string(opername, oprkind,
                                            oprleft, oprright)),
                 parser_errposition(pstate, location)));
    }

    return InvalidOid;
}

Oid LookupOperNameTypeNames ( ParseState pstate,
List opername,
TypeName oprleft,
TypeName oprright,
bool  noError,
int  location 
)

Definition at line 141 of file parse_oper.c.

References LookupOperName(), NULL, and typenameTypeId().

Referenced by AlterOpFamilyAdd(), DefineOpClass(), and get_object_address().

{
    Oid         leftoid,
                rightoid;

    if (oprleft == NULL)
        leftoid = InvalidOid;
    else
        leftoid = typenameTypeId(pstate, oprleft);

    if (oprright == NULL)
        rightoid = InvalidOid;
    else
        rightoid = typenameTypeId(pstate, oprright);

    return LookupOperName(pstate, opername, leftoid, rightoid,
                          noError, location);
}

Expr* make_op ( ParseState pstate,
List opname,
Node ltree,
Node rtree,
int  location 
)

Definition at line 736 of file parse_oper.c.

References OpExpr::args, enforce_generic_type_consistency(), ereport, errcode(), errmsg(), ERROR, exprType(), get_func_retset(), GETSTRUCT, left_oper(), list_make1, list_make2, OpExpr::location, make_fn_arguments(), makeNode, NULL, op_signature_string(), oper(), OpExpr::opfuncid, OpExpr::opno, OpExpr::opresulttype, OpExpr::opretset, oprid(), parser_errposition(), RegProcedureIsValid, ReleaseSysCache(), and right_oper().

Referenced by make_distinct_op(), make_row_comparison_op(), transformAExprIn(), transformAExprNullIf(), and transformAExprOp().

{
    Oid         ltypeId,
                rtypeId;
    Operator    tup;
    Form_pg_operator opform;
    Oid         actual_arg_types[2];
    Oid         declared_arg_types[2];
    int         nargs;
    List       *args;
    Oid         rettype;
    OpExpr     *result;

    /* Select the operator */
    if (rtree == NULL)
    {
        /* right operator */
        ltypeId = exprType(ltree);
        rtypeId = InvalidOid;
        tup = right_oper(pstate, opname, ltypeId, false, location);
    }
    else if (ltree == NULL)
    {
        /* left operator */
        rtypeId = exprType(rtree);
        ltypeId = InvalidOid;
        tup = left_oper(pstate, opname, rtypeId, false, location);
    }
    else
    {
        /* otherwise, binary operator */
        ltypeId = exprType(ltree);
        rtypeId = exprType(rtree);
        tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
    }

    opform = (Form_pg_operator) GETSTRUCT(tup);

    /* Check it's not a shell */
    if (!RegProcedureIsValid(opform->oprcode))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("operator is only a shell: %s",
                        op_signature_string(opname,
                                            opform->oprkind,
                                            opform->oprleft,
                                            opform->oprright)),
                 parser_errposition(pstate, location)));

    /* Do typecasting and build the expression tree */
    if (rtree == NULL)
    {
        /* right operator */
        args = list_make1(ltree);
        actual_arg_types[0] = ltypeId;
        declared_arg_types[0] = opform->oprleft;
        nargs = 1;
    }
    else if (ltree == NULL)
    {
        /* left operator */
        args = list_make1(rtree);
        actual_arg_types[0] = rtypeId;
        declared_arg_types[0] = opform->oprright;
        nargs = 1;
    }
    else
    {
        /* otherwise, binary operator */
        args = list_make2(ltree, rtree);
        actual_arg_types[0] = ltypeId;
        actual_arg_types[1] = rtypeId;
        declared_arg_types[0] = opform->oprleft;
        declared_arg_types[1] = opform->oprright;
        nargs = 2;
    }

    /*
     * enforce consistency with polymorphic argument and return types,
     * possibly adjusting return type or declared_arg_types (which will be
     * used as the cast destination by make_fn_arguments)
     */
    rettype = enforce_generic_type_consistency(actual_arg_types,
                                               declared_arg_types,
                                               nargs,
                                               opform->oprresult,
                                               false);

    /* perform the necessary typecasting of arguments */
    make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);

    /* and build the expression node */
    result = makeNode(OpExpr);
    result->opno = oprid(tup);
    result->opfuncid = opform->oprcode;
    result->opresulttype = rettype;
    result->opretset = get_func_retset(opform->oprcode);
    /* opcollid and inputcollid will be set by parse_collate.c */
    result->args = args;
    result->location = location;

    ReleaseSysCache(tup);

    return (Expr *) result;
}

Expr* make_scalar_array_op ( ParseState pstate,
List opname,
bool  useOr,
Node ltree,
Node rtree,
int  location 
)

Definition at line 848 of file parse_oper.c.

References ScalarArrayOpExpr::args, BOOLOID, enforce_generic_type_consistency(), ereport, errcode(), errmsg(), ERROR, exprType(), format_type_be(), get_array_type(), get_base_element_type(), get_func_retset(), GETSTRUCT, IsPolymorphicType, list_make2, ScalarArrayOpExpr::location, make_fn_arguments(), makeNode, OidIsValid, op_signature_string(), oper(), ScalarArrayOpExpr::opfuncid, ScalarArrayOpExpr::opno, oprid(), parser_errposition(), RegProcedureIsValid, ReleaseSysCache(), UNKNOWNOID, and ScalarArrayOpExpr::useOr.

Referenced by transformAExprIn(), transformAExprOpAll(), and transformAExprOpAny().

{
    Oid         ltypeId,
                rtypeId,
                atypeId,
                res_atypeId;
    Operator    tup;
    Form_pg_operator opform;
    Oid         actual_arg_types[2];
    Oid         declared_arg_types[2];
    List       *args;
    Oid         rettype;
    ScalarArrayOpExpr *result;

    ltypeId = exprType(ltree);
    atypeId = exprType(rtree);

    /*
     * The right-hand input of the operator will be the element type of the
     * array.  However, if we currently have just an untyped literal on the
     * right, stay with that and hope we can resolve the operator.
     */
    if (atypeId == UNKNOWNOID)
        rtypeId = UNKNOWNOID;
    else
    {
        rtypeId = get_base_element_type(atypeId);
        if (!OidIsValid(rtypeId))
            ereport(ERROR,
                    (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                   errmsg("op ANY/ALL (array) requires array on right side"),
                     parser_errposition(pstate, location)));
    }

    /* Now resolve the operator */
    tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
    opform = (Form_pg_operator) GETSTRUCT(tup);

    /* Check it's not a shell */
    if (!RegProcedureIsValid(opform->oprcode))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("operator is only a shell: %s",
                        op_signature_string(opname,
                                            opform->oprkind,
                                            opform->oprleft,
                                            opform->oprright)),
                 parser_errposition(pstate, location)));

    args = list_make2(ltree, rtree);
    actual_arg_types[0] = ltypeId;
    actual_arg_types[1] = rtypeId;
    declared_arg_types[0] = opform->oprleft;
    declared_arg_types[1] = opform->oprright;

    /*
     * enforce consistency with polymorphic argument and return types,
     * possibly adjusting return type or declared_arg_types (which will be
     * used as the cast destination by make_fn_arguments)
     */
    rettype = enforce_generic_type_consistency(actual_arg_types,
                                               declared_arg_types,
                                               2,
                                               opform->oprresult,
                                               false);

    /*
     * Check that operator result is boolean
     */
    if (rettype != BOOLOID)
        ereport(ERROR,
                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
             errmsg("op ANY/ALL (array) requires operator to yield boolean"),
                 parser_errposition(pstate, location)));
    if (get_func_retset(opform->oprcode))
        ereport(ERROR,
                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
          errmsg("op ANY/ALL (array) requires operator not to return a set"),
                 parser_errposition(pstate, location)));

    /*
     * Now switch back to the array type on the right, arranging for any
     * needed cast to be applied.  Beware of polymorphic operators here;
     * enforce_generic_type_consistency may or may not have replaced a
     * polymorphic type with a real one.
     */
    if (IsPolymorphicType(declared_arg_types[1]))
    {
        /* assume the actual array type is OK */
        res_atypeId = atypeId;
    }
    else
    {
        res_atypeId = get_array_type(declared_arg_types[1]);
        if (!OidIsValid(res_atypeId))
            ereport(ERROR,
                    (errcode(ERRCODE_UNDEFINED_OBJECT),
                     errmsg("could not find array type for data type %s",
                            format_type_be(declared_arg_types[1])),
                     parser_errposition(pstate, location)));
    }
    actual_arg_types[1] = atypeId;
    declared_arg_types[1] = res_atypeId;

    /* perform the necessary typecasting of arguments */
    make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);

    /* and build the expression node */
    result = makeNode(ScalarArrayOpExpr);
    result->opno = oprid(tup);
    result->opfuncid = opform->oprcode;
    result->useOr = useOr;
    /* inputcollid will be set by parse_collate.c */
    result->args = args;
    result->location = location;

    ReleaseSysCache(tup);

    return (Expr *) result;
}

Operator oper ( ParseState pstate,
List op,
Oid  arg1,
Oid  arg2,
bool  noError,
int  location 
)

Definition at line 374 of file parse_oper.c.

References binary_oper_exact(), find_oper_cache_entry(), HeapTupleIsValid, InvalidOid, make_oper_cache_entry(), make_oper_cache_key(), NULL, ObjectIdGetDatum, OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), OPEROID, and SearchSysCache1.

Referenced by compatible_oper(), generate_operator_name(), make_op(), make_scalar_array_op(), makeOperatorDependencies(), and tsquery_opr_selec().

{
    Oid         operOid;
    OprCacheKey key;
    bool        key_ok;
    FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
    HeapTuple   tup = NULL;

    /*
     * Try to find the mapping in the lookaside cache.
     */
    key_ok = make_oper_cache_key(&key, opname, ltypeId, rtypeId);
    if (key_ok)
    {
        operOid = find_oper_cache_entry(&key);
        if (OidIsValid(operOid))
        {
            tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
            if (HeapTupleIsValid(tup))
                return (Operator) tup;
        }
    }

    /*
     * First try for an "exact" match.
     */
    operOid = binary_oper_exact(opname, ltypeId, rtypeId);
    if (!OidIsValid(operOid))
    {
        /*
         * Otherwise, search for the most suitable candidate.
         */
        FuncCandidateList clist;

        /* Get binary operators of given name */
        clist = OpernameGetCandidates(opname, 'b');

        /* No operators found? Then fail... */
        if (clist != NULL)
        {
            /*
             * Unspecified type for one of the arguments? then use the other
             * (XXX this is probably dead code?)
             */
            Oid         inputOids[2];

            if (rtypeId == InvalidOid)
                rtypeId = ltypeId;
            else if (ltypeId == InvalidOid)
                ltypeId = rtypeId;
            inputOids[0] = ltypeId;
            inputOids[1] = rtypeId;
            fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
        }
    }

    if (OidIsValid(operOid))
        tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));

    if (HeapTupleIsValid(tup))
    {
        if (key_ok)
            make_oper_cache_entry(&key, operOid);
    }
    else if (!noError)
        op_error(pstate, opname, 'b', ltypeId, rtypeId, fdresult, location);

    return (Operator) tup;
}

Oid oprfuncid ( Operator  op  ) 

Definition at line 249 of file parse_oper.c.

References GETSTRUCT.

{
    Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(op);

    return pgopform->oprcode;
}

Oid oprid ( Operator  op  ) 
Operator right_oper ( ParseState pstate,
List op,
Oid  arg,
bool  noError,
int  location 
)

Definition at line 521 of file parse_oper.c.

References find_oper_cache_entry(), HeapTupleIsValid, InvalidOid, make_oper_cache_entry(), make_oper_cache_key(), NULL, ObjectIdGetDatum, OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), OpernameGetOprid(), OPEROID, and SearchSysCache1.

Referenced by generate_operator_name(), and make_op().

{
    Oid         operOid;
    OprCacheKey key;
    bool        key_ok;
    FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
    HeapTuple   tup = NULL;

    /*
     * Try to find the mapping in the lookaside cache.
     */
    key_ok = make_oper_cache_key(&key, op, arg, InvalidOid);
    if (key_ok)
    {
        operOid = find_oper_cache_entry(&key);
        if (OidIsValid(operOid))
        {
            tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
            if (HeapTupleIsValid(tup))
                return (Operator) tup;
        }
    }

    /*
     * First try for an "exact" match.
     */
    operOid = OpernameGetOprid(op, arg, InvalidOid);
    if (!OidIsValid(operOid))
    {
        /*
         * Otherwise, search for the most suitable candidate.
         */
        FuncCandidateList clist;

        /* Get postfix operators of given name */
        clist = OpernameGetCandidates(op, 'r');

        /* No operators found? Then fail... */
        if (clist != NULL)
        {
            /*
             * We must run oper_select_candidate even if only one candidate,
             * otherwise we may falsely return a non-type-compatible operator.
             */
            fdresult = oper_select_candidate(1, &arg, clist, &operOid);
        }
    }

    if (OidIsValid(operOid))
        tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));

    if (HeapTupleIsValid(tup))
    {
        if (key_ok)
            make_oper_cache_entry(&key, operOid);
    }
    else if (!noError)
        op_error(pstate, op, 'r', arg, InvalidOid, fdresult, location);

    return (Operator) tup;
}