#include "access/htup.h"#include "parser/parse_node.h"

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) |
| Expr * | make_op (ParseState *pstate, List *opname, Node *ltree, Node *rtree, int location) |
| Expr * | make_scalar_array_op (ParseState *pstate, List *opname, bool useOr, Node *ltree, Node *rtree, int location) |
Definition at line 21 of file parse_oper.h.
| 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;
}
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;
}
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;
}
Definition at line 249 of file parse_oper.c.
References GETSTRUCT.
{
Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(op);
return pgopform->oprcode;
}
Definition at line 242 of file parse_oper.c.
References HeapTupleGetOid.
Referenced by compatible_oper_opid(), generate_operator_name(), make_op(), make_scalar_array_op(), regoperatorout(), and regoperout().
{
return HeapTupleGetOid(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;
}
1.7.1