1 /*-------------------------------------------------------------------------
4 * handle operator things for parser
6 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.77 2003/11/29 19:51:52 pgsql Exp $
13 *-------------------------------------------------------------------------
18 #include "catalog/pg_operator.h"
19 #include "lib/stringinfo.h"
20 #include "parser/parse_coerce.h"
21 #include "parser/parse_expr.h"
22 #include "parser/parse_func.h"
23 #include "parser/parse_oper.h"
24 #include "parser/parse_type.h"
25 #include "utils/builtins.h"
26 #include "utils/fmgroids.h"
27 #include "utils/lsyscache.h"
28 #include "utils/syscache.h"
29 #include "utils/typcache.h"
32 static Oid binary_oper_exact(Oid arg1, Oid arg2,
33 FuncCandidateList candidates);
34 static FuncDetailCode oper_select_candidate(int nargs,
36 FuncCandidateList candidates,
38 static const char *op_signature_string(List *op, char oprkind,
40 static void op_error(List *op, char oprkind, Oid arg1, Oid arg2,
41 FuncDetailCode fdresult);
46 * Given a possibly-qualified operator name and exact input datatypes,
47 * look up the operator.
49 * Pass oprleft = InvalidOid for a prefix op, oprright = InvalidOid for
52 * If the operator name is not schema-qualified, it is sought in the current
53 * namespace search path.
55 * If the operator is not found, we return InvalidOid if noError is true,
56 * else raise an error.
59 LookupOperName(List *opername, Oid oprleft, Oid oprright, bool noError)
61 FuncCandidateList clist;
64 if (!OidIsValid(oprleft))
66 else if (!OidIsValid(oprright))
71 clist = OpernameGetCandidates(opername, oprkind);
75 if (clist->args[0] == oprleft && clist->args[1] == oprright)
80 /* we don't use op_error here because only an exact match is wanted */
83 (errcode(ERRCODE_UNDEFINED_FUNCTION),
84 errmsg("operator does not exist: %s",
85 op_signature_string(opername, oprkind,
86 oprleft, oprright))));
92 * LookupOperNameTypeNames
93 * Like LookupOperName, but the argument types are specified by
96 * Pass oprleft = NULL for a prefix op, oprright = NULL for a postfix op.
99 LookupOperNameTypeNames(List *opername, TypeName *oprleft,
100 TypeName *oprright, bool noError)
106 leftoid = InvalidOid;
109 leftoid = LookupTypeName(oprleft);
110 if (!OidIsValid(leftoid))
112 (errcode(ERRCODE_UNDEFINED_OBJECT),
113 errmsg("type %s does not exist",
114 TypeNameToString(oprleft))));
116 if (oprright == NULL)
117 rightoid = InvalidOid;
120 rightoid = LookupTypeName(oprright);
121 if (!OidIsValid(rightoid))
123 (errcode(ERRCODE_UNDEFINED_OBJECT),
124 errmsg("type %s does not exist",
125 TypeNameToString(oprright))));
128 return LookupOperName(opername, leftoid, rightoid, noError);
132 * equality_oper - identify a suitable equality operator for a datatype
134 * On failure, return NULL if noError, else report a standard error
137 equality_oper(Oid argtype, bool noError)
139 TypeCacheEntry *typentry;
144 * Look for an "=" operator for the datatype. We require it to be
145 * an exact or binary-compatible match, since most callers are not
146 * prepared to cope with adding any run-time type coercion steps.
148 typentry = lookup_type_cache(argtype, TYPECACHE_EQ_OPR);
149 oproid = typentry->eq_opr;
152 * If the datatype is an array, then we can use array_eq ... but only
153 * if there is a suitable equality operator for the element type.
154 * (This check is not in the raw typcache.c code ... should it be?)
156 if (oproid == ARRAY_EQ_OP)
158 Oid elem_type = get_element_type(argtype);
160 if (OidIsValid(elem_type))
162 optup = equality_oper(elem_type, true);
164 ReleaseSysCache(optup);
166 oproid = InvalidOid; /* element type has no "=" */
169 oproid = InvalidOid; /* bogus array type? */
172 if (OidIsValid(oproid))
174 optup = SearchSysCache(OPEROID,
175 ObjectIdGetDatum(oproid),
177 if (optup == NULL) /* should not fail */
178 elog(ERROR, "cache lookup failed for operator %u", oproid);
184 (errcode(ERRCODE_UNDEFINED_FUNCTION),
185 errmsg("could not identify an equality operator for type %s",
186 format_type_be(argtype))));
191 * ordering_oper - identify a suitable sorting operator ("<") for a datatype
193 * On failure, return NULL if noError, else report a standard error
196 ordering_oper(Oid argtype, bool noError)
198 TypeCacheEntry *typentry;
203 * Look for a "<" operator for the datatype. We require it to be
204 * an exact or binary-compatible match, since most callers are not
205 * prepared to cope with adding any run-time type coercion steps.
207 * Note: the search algorithm used by typcache.c ensures that if a "<"
208 * operator is returned, it will be consistent with the "=" operator
209 * returned by equality_oper. This is critical for sorting and grouping
212 typentry = lookup_type_cache(argtype, TYPECACHE_LT_OPR);
213 oproid = typentry->lt_opr;
216 * If the datatype is an array, then we can use array_lt ... but only
217 * if there is a suitable less-than operator for the element type.
218 * (This check is not in the raw typcache.c code ... should it be?)
220 if (oproid == ARRAY_LT_OP)
222 Oid elem_type = get_element_type(argtype);
224 if (OidIsValid(elem_type))
226 optup = ordering_oper(elem_type, true);
228 ReleaseSysCache(optup);
230 oproid = InvalidOid; /* element type has no "<" */
233 oproid = InvalidOid; /* bogus array type? */
236 if (OidIsValid(oproid))
238 optup = SearchSysCache(OPEROID,
239 ObjectIdGetDatum(oproid),
241 if (optup == NULL) /* should not fail */
242 elog(ERROR, "cache lookup failed for operator %u", oproid);
248 (errcode(ERRCODE_UNDEFINED_FUNCTION),
249 errmsg("could not identify an ordering operator for type %s",
250 format_type_be(argtype)),
251 errhint("Use an explicit ordering operator or modify the query.")));
256 * reverse_ordering_oper - identify DESC sort operator (">") for a datatype
258 * On failure, return NULL if noError, else report a standard error
261 reverse_ordering_oper(Oid argtype, bool noError)
263 TypeCacheEntry *typentry;
268 * Look for a ">" operator for the datatype. We require it to be
269 * an exact or binary-compatible match, since most callers are not
270 * prepared to cope with adding any run-time type coercion steps.
272 * Note: the search algorithm used by typcache.c ensures that if a ">"
273 * operator is returned, it will be consistent with the "=" operator
274 * returned by equality_oper. This is critical for sorting and grouping
277 typentry = lookup_type_cache(argtype, TYPECACHE_GT_OPR);
278 oproid = typentry->gt_opr;
281 * If the datatype is an array, then we can use array_gt ... but only
282 * if there is a suitable greater-than operator for the element type.
283 * (This check is not in the raw typcache.c code ... should it be?)
285 if (oproid == ARRAY_GT_OP)
287 Oid elem_type = get_element_type(argtype);
289 if (OidIsValid(elem_type))
291 optup = reverse_ordering_oper(elem_type, true);
293 ReleaseSysCache(optup);
295 oproid = InvalidOid; /* element type has no ">" */
298 oproid = InvalidOid; /* bogus array type? */
301 if (OidIsValid(oproid))
303 optup = SearchSysCache(OPEROID,
304 ObjectIdGetDatum(oproid),
306 if (optup == NULL) /* should not fail */
307 elog(ERROR, "cache lookup failed for operator %u", oproid);
313 (errcode(ERRCODE_UNDEFINED_FUNCTION),
314 errmsg("could not identify an ordering operator for type %s",
315 format_type_be(argtype)),
316 errhint("Use an explicit ordering operator or modify the query.")));
321 * equality_oper_funcid - convenience routine for oprfuncid(equality_oper())
324 equality_oper_funcid(Oid argtype)
329 optup = equality_oper(argtype, false);
330 result = oprfuncid(optup);
331 ReleaseSysCache(optup);
336 * ordering_oper_opid - convenience routine for oprid(ordering_oper())
338 * This was formerly called any_ordering_op()
341 ordering_oper_opid(Oid argtype)
346 optup = ordering_oper(argtype, false);
347 result = oprid(optup);
348 ReleaseSysCache(optup);
353 * reverse_ordering_oper_opid - convenience routine for oprid(reverse_ordering_oper())
356 reverse_ordering_oper_opid(Oid argtype)
361 optup = reverse_ordering_oper(argtype, false);
362 result = oprid(optup);
363 ReleaseSysCache(optup);
368 /* given operator tuple, return the operator OID */
372 return HeapTupleGetOid(op);
375 /* given operator tuple, return the underlying function's OID */
377 oprfuncid(Operator op)
379 Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(op);
381 return pgopform->oprcode;
385 /* binary_oper_exact()
386 * Check for an "exact" match to the specified operand types.
388 * If one operand is an unknown literal, assume it should be taken to be
389 * the same type as the other operand for this purpose. Also, consider
390 * the possibility that the other operand is a domain type that needs to
391 * be reduced to its base type to find an "exact" match.
394 binary_oper_exact(Oid arg1, Oid arg2,
395 FuncCandidateList candidates)
397 FuncCandidateList cand;
398 bool was_unknown = false;
400 /* Unspecified type for one of the arguments? then use the other */
401 if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
406 else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
412 for (cand = candidates; cand != NULL; cand = cand->next)
414 if (arg1 == cand->args[0] && arg2 == cand->args[1])
420 /* arg1 and arg2 are the same here, need only look at arg1 */
421 Oid basetype = getBaseType(arg1);
423 if (basetype != arg1)
425 for (cand = candidates; cand != NULL; cand = cand->next)
427 if (basetype == cand->args[0] && basetype == cand->args[1])
437 /* oper_select_candidate()
438 * Given the input argtype array and one or more candidates
439 * for the operator, attempt to resolve the conflict.
441 * Returns FUNCDETAIL_NOTFOUND, FUNCDETAIL_MULTIPLE, or FUNCDETAIL_NORMAL.
442 * In the success case the Oid of the best candidate is stored in *operOid.
444 * Note that the caller has already determined that there is no candidate
445 * exactly matching the input argtype(s). Incompatible candidates are not yet
446 * pruned away, however.
448 static FuncDetailCode
449 oper_select_candidate(int nargs,
451 FuncCandidateList candidates,
452 Oid *operOid) /* output argument */
457 * Delete any candidates that cannot actually accept the given input
458 * types, whether directly or by coercion.
460 ncandidates = func_match_argtypes(nargs, input_typeids,
461 candidates, &candidates);
463 /* Done if no candidate or only one candidate survives */
464 if (ncandidates == 0)
466 *operOid = InvalidOid;
467 return FUNCDETAIL_NOTFOUND;
469 if (ncandidates == 1)
471 *operOid = candidates->oid;
472 return FUNCDETAIL_NORMAL;
476 * Use the same heuristics as for ambiguous functions to resolve the
479 candidates = func_select_candidate(nargs, input_typeids, candidates);
483 *operOid = candidates->oid;
484 return FUNCDETAIL_NORMAL;
487 *operOid = InvalidOid;
488 return FUNCDETAIL_MULTIPLE; /* failed to select a best candidate */
492 /* oper() -- search for a binary operator
493 * Given operator name, types of arg1 and arg2, return oper struct.
495 * IMPORTANT: the returned operator (if any) is only promised to be
496 * coercion-compatible with the input datatypes. Do not use this if
497 * you need an exact- or binary-compatible match; see compatible_oper.
499 * If no matching operator found, return NULL if noError is true,
500 * raise an error if it is false.
502 * NOTE: on success, the returned object is a syscache entry. The caller
503 * must ReleaseSysCache() the entry when done with it.
506 oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError)
508 FuncCandidateList clist;
511 FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
512 HeapTuple tup = NULL;
514 /* Get binary operators of given name */
515 clist = OpernameGetCandidates(opname, 'b');
517 /* No operators found? Then fail... */
521 * Check for an "exact" match.
523 operOid = binary_oper_exact(ltypeId, rtypeId, clist);
524 if (!OidIsValid(operOid))
527 * Otherwise, search for the most suitable candidate.
531 * Unspecified type for one of the arguments? then use the
532 * other (XXX this is probably dead code?)
534 if (rtypeId == InvalidOid)
536 else if (ltypeId == InvalidOid)
538 inputOids[0] = ltypeId;
539 inputOids[1] = rtypeId;
540 fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
542 if (OidIsValid(operOid))
543 tup = SearchSysCache(OPEROID,
544 ObjectIdGetDatum(operOid),
548 if (!HeapTupleIsValid(tup) && !noError)
549 op_error(opname, 'b', ltypeId, rtypeId, fdresult);
551 return (Operator) tup;
555 * given an opname and input datatypes, find a compatible binary operator
557 * This is tighter than oper() because it will not return an operator that
558 * requires coercion of the input datatypes (but binary-compatible operators
559 * are accepted). Otherwise, the semantics are the same.
562 compatible_oper(List *op, Oid arg1, Oid arg2, bool noError)
565 Form_pg_operator opform;
567 /* oper() will find the best available match */
568 optup = oper(op, arg1, arg2, noError);
569 if (optup == (Operator) NULL)
570 return (Operator) NULL; /* must be noError case */
572 /* but is it good enough? */
573 opform = (Form_pg_operator) GETSTRUCT(optup);
574 if (IsBinaryCoercible(arg1, opform->oprleft) &&
575 IsBinaryCoercible(arg2, opform->oprright))
579 ReleaseSysCache(optup);
583 (errcode(ERRCODE_UNDEFINED_FUNCTION),
584 errmsg("operator requires run-time type coercion: %s",
585 op_signature_string(op, 'b', arg1, arg2))));
587 return (Operator) NULL;
590 /* compatible_oper_opid() -- get OID of a binary operator
592 * This is a convenience routine that extracts only the operator OID
593 * from the result of compatible_oper(). InvalidOid is returned if the
594 * lookup fails and noError is true.
597 compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
602 optup = compatible_oper(op, arg1, arg2, noError);
605 result = oprid(optup);
606 ReleaseSysCache(optup);
613 /* right_oper() -- search for a unary right operator (postfix operator)
614 * Given operator name and type of arg, return oper struct.
616 * IMPORTANT: the returned operator (if any) is only promised to be
617 * coercion-compatible with the input datatype. Do not use this if
618 * you need an exact- or binary-compatible match.
620 * If no matching operator found, return NULL if noError is true,
621 * raise an error if it is false.
623 * NOTE: on success, the returned object is a syscache entry. The caller
624 * must ReleaseSysCache() the entry when done with it.
627 right_oper(List *op, Oid arg, bool noError)
629 FuncCandidateList clist;
630 Oid operOid = InvalidOid;
631 FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
632 HeapTuple tup = NULL;
634 /* Find candidates */
635 clist = OpernameGetCandidates(op, 'r');
640 * First, quickly check to see if there is an exactly matching
641 * operator (there can be only one such entry in the list).
643 FuncCandidateList clisti;
645 for (clisti = clist; clisti != NULL; clisti = clisti->next)
647 if (arg == clisti->args[0])
649 operOid = clisti->oid;
654 if (!OidIsValid(operOid))
657 * We must run oper_select_candidate even if only one
658 * candidate, otherwise we may falsely return a
659 * non-type-compatible operator.
661 fdresult = oper_select_candidate(1, &arg, clist, &operOid);
663 if (OidIsValid(operOid))
664 tup = SearchSysCache(OPEROID,
665 ObjectIdGetDatum(operOid),
669 if (!HeapTupleIsValid(tup) && !noError)
670 op_error(op, 'r', arg, InvalidOid, fdresult);
672 return (Operator) tup;
676 /* left_oper() -- search for a unary left operator (prefix operator)
677 * Given operator name and type of arg, return oper struct.
679 * IMPORTANT: the returned operator (if any) is only promised to be
680 * coercion-compatible with the input datatype. Do not use this if
681 * you need an exact- or binary-compatible match.
683 * If no matching operator found, return NULL if noError is true,
684 * raise an error if it is false.
686 * NOTE: on success, the returned object is a syscache entry. The caller
687 * must ReleaseSysCache() the entry when done with it.
690 left_oper(List *op, Oid arg, bool noError)
692 FuncCandidateList clist;
693 Oid operOid = InvalidOid;
694 FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
695 HeapTuple tup = NULL;
697 /* Find candidates */
698 clist = OpernameGetCandidates(op, 'l');
703 * First, quickly check to see if there is an exactly matching
704 * operator (there can be only one such entry in the list).
706 * The returned list has args in the form (0, oprright). Move the
707 * useful data into args[0] to keep oper_select_candidate simple.
708 * XXX we are assuming here that we may scribble on the list!
710 FuncCandidateList clisti;
712 for (clisti = clist; clisti != NULL; clisti = clisti->next)
714 clisti->args[0] = clisti->args[1];
715 if (arg == clisti->args[0])
717 operOid = clisti->oid;
722 if (!OidIsValid(operOid))
725 * We must run oper_select_candidate even if only one
726 * candidate, otherwise we may falsely return a
727 * non-type-compatible operator.
729 fdresult = oper_select_candidate(1, &arg, clist, &operOid);
731 if (OidIsValid(operOid))
732 tup = SearchSysCache(OPEROID,
733 ObjectIdGetDatum(operOid),
737 if (!HeapTupleIsValid(tup) && !noError)
738 op_error(op, 'l', InvalidOid, arg, fdresult);
740 return (Operator) tup;
744 * op_signature_string
745 * Build a string representing an operator name, including arg type(s).
746 * The result is something like "integer + integer".
748 * This is typically used in the construction of operator-not-found error
752 op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2)
754 StringInfoData argbuf;
756 initStringInfo(&argbuf);
759 appendStringInfo(&argbuf, "%s ", format_type_be(arg1));
761 appendStringInfoString(&argbuf, NameListToString(op));
764 appendStringInfo(&argbuf, " %s", format_type_be(arg2));
766 return argbuf.data; /* return palloc'd string buffer */
770 * op_error - utility routine to complain about an unresolvable operator
773 op_error(List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult)
775 if (fdresult == FUNCDETAIL_MULTIPLE)
777 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
778 errmsg("operator is not unique: %s",
779 op_signature_string(op, oprkind, arg1, arg2)),
780 errhint("Could not choose a best candidate operator. "
781 "You may need to add explicit type casts.")));
784 (errcode(ERRCODE_UNDEFINED_FUNCTION),
785 errmsg("operator does not exist: %s",
786 op_signature_string(op, oprkind, arg1, arg2)),
787 errhint("No operator matches the given name and argument type(s). "
788 "You may need to add explicit type casts.")));
793 * Operator expression construction.
795 * Transform operator expression ensuring type compatibility.
796 * This is where some type conversion happens.
798 * As with coerce_type, pstate may be NULL if no special unknown-Param
799 * processing is wanted.
802 make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree)
809 /* Select the operator */
813 ltypeId = exprType(ltree);
814 rtypeId = InvalidOid;
815 tup = right_oper(opname, ltypeId, false);
817 else if (ltree == NULL)
820 rtypeId = exprType(rtree);
821 ltypeId = InvalidOid;
822 tup = left_oper(opname, rtypeId, false);
826 /* otherwise, binary operator */
827 ltypeId = exprType(ltree);
828 rtypeId = exprType(rtree);
829 tup = oper(opname, ltypeId, rtypeId, false);
832 /* Do typecasting and build the expression tree */
833 result = make_op_expr(pstate, tup, ltree, rtree, ltypeId, rtypeId);
835 ReleaseSysCache(tup);
841 * make_scalar_array_op()
842 * Build expression tree for "scalar op ANY/ALL (array)" construct.
845 make_scalar_array_op(ParseState *pstate, List *opname,
847 Node *ltree, Node *rtree)
854 Form_pg_operator opform;
855 Oid actual_arg_types[2];
856 Oid declared_arg_types[2];
859 ScalarArrayOpExpr *result;
861 ltypeId = exprType(ltree);
862 atypeId = exprType(rtree);
865 * The right-hand input of the operator will be the element type of
866 * the array. However, if we currently have just an untyped literal
867 * on the right, stay with that and hope we can resolve the operator.
869 if (atypeId == UNKNOWNOID)
870 rtypeId = UNKNOWNOID;
873 rtypeId = get_element_type(atypeId);
874 if (!OidIsValid(rtypeId))
876 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
877 errmsg("op ANY/ALL (array) requires array on right side")));
880 /* Now resolve the operator */
881 tup = oper(opname, ltypeId, rtypeId, false);
882 opform = (Form_pg_operator) GETSTRUCT(tup);
884 args = makeList2(ltree, rtree);
885 actual_arg_types[0] = ltypeId;
886 actual_arg_types[1] = rtypeId;
887 declared_arg_types[0] = opform->oprleft;
888 declared_arg_types[1] = opform->oprright;
891 * enforce consistency with ANYARRAY and ANYELEMENT argument and
892 * return types, possibly adjusting return type or declared_arg_types
893 * (which will be used as the cast destination by make_fn_arguments)
895 rettype = enforce_generic_type_consistency(actual_arg_types,
901 * Check that operator result is boolean
903 if (rettype != BOOLOID)
905 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
906 errmsg("op ANY/ALL (array) requires operator to yield boolean")));
907 if (get_func_retset(opform->oprcode))
909 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
910 errmsg("op ANY/ALL (array) requires operator not to return a set")));
913 * Now switch back to the array type on the right, arranging for any
914 * needed cast to be applied.
916 res_atypeId = get_array_type(declared_arg_types[1]);
917 if (!OidIsValid(res_atypeId))
919 (errcode(ERRCODE_UNDEFINED_OBJECT),
920 errmsg("could not find array type for data type %s",
921 format_type_be(declared_arg_types[1]))));
922 actual_arg_types[1] = atypeId;
923 declared_arg_types[1] = res_atypeId;
925 /* perform the necessary typecasting of arguments */
926 make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
928 /* and build the expression node */
929 result = makeNode(ScalarArrayOpExpr);
930 result->opno = oprid(tup);
931 result->opfuncid = InvalidOid;
932 result->useOr = useOr;
935 ReleaseSysCache(tup);
937 return (Expr *) result;
942 * Build operator expression using an already-looked-up operator.
944 * As with coerce_type, pstate may be NULL if no special unknown-Param
945 * processing is wanted.
948 make_op_expr(ParseState *pstate, Operator op,
949 Node *ltree, Node *rtree,
950 Oid ltypeId, Oid rtypeId)
952 Form_pg_operator opform = (Form_pg_operator) GETSTRUCT(op);
953 Oid actual_arg_types[2];
954 Oid declared_arg_types[2];
963 args = makeList1(ltree);
964 actual_arg_types[0] = ltypeId;
965 declared_arg_types[0] = opform->oprleft;
968 else if (ltree == NULL)
971 args = makeList1(rtree);
972 actual_arg_types[0] = rtypeId;
973 declared_arg_types[0] = opform->oprright;
978 /* otherwise, binary operator */
979 args = makeList2(ltree, rtree);
980 actual_arg_types[0] = ltypeId;
981 actual_arg_types[1] = rtypeId;
982 declared_arg_types[0] = opform->oprleft;
983 declared_arg_types[1] = opform->oprright;
988 * enforce consistency with ANYARRAY and ANYELEMENT argument and
989 * return types, possibly adjusting return type or declared_arg_types
990 * (which will be used as the cast destination by make_fn_arguments)
992 rettype = enforce_generic_type_consistency(actual_arg_types,
997 /* perform the necessary typecasting of arguments */
998 make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
1000 /* and build the expression node */
1001 result = makeNode(OpExpr);
1002 result->opno = oprid(op);
1003 result->opfuncid = InvalidOid;
1004 result->opresulttype = rettype;
1005 result->opretset = get_func_retset(opform->oprcode);
1006 result->args = args;
1008 return (Expr *) result;