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