diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 21fdb22032..426c61887e 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * parse_oper.h + * parse_oper.c * handle operator things for parser * * Portions Copyright (c) 1996-2000, PostgreSQL, Inc @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.35 2000/01/26 05:56:42 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.36 2000/02/27 02:48:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,6 +35,8 @@ static int unary_oper_get_candidates(char *op, CandidateList *candidates, char rightleft); static void op_error(char *op, Oid arg1, Oid arg2); +static void unary_op_error(char *op, Oid arg, bool is_left_op); + Oid any_ordering_op(Oid restype) @@ -224,11 +226,11 @@ oper_select_candidate(int nargs, if (ncandidates <= 1) { - if (ncandidates > 0 && - (!can_coerce_type(1, &input_typeids[0], &candidates->args[0]) || - (nargs > 1 && - !can_coerce_type(1, &input_typeids[1], &candidates->args[1])))) - ncandidates = 0; + if (ncandidates > 0) + { + if (!can_coerce_type(nargs, input_typeids, candidates->args)) + ncandidates = 0; + } return (ncandidates == 1) ? candidates->args : NULL; } @@ -279,11 +281,11 @@ oper_select_candidate(int nargs, if (ncandidates <= 1) { - if (ncandidates > 0 && - (!can_coerce_type(1, &input_typeids[0], &candidates->args[0]) || - (nargs > 1 && - !can_coerce_type(1, &input_typeids[1], &candidates->args[1])))) - ncandidates = 0; + if (ncandidates > 0) + { + if (!can_coerce_type(nargs, input_typeids, candidates->args)) + ncandidates = 0; + } return (ncandidates == 1) ? candidates->args : NULL; } @@ -368,8 +370,7 @@ oper_select_candidate(int nargs, current_candidate != NULL; current_candidate = current_candidate->next) { - if (can_coerce_type(1, &input_typeids[0], ¤t_candidate->args[0]) - && can_coerce_type(1, &input_typeids[1], ¤t_candidate->args[1])) + if (can_coerce_type(nargs, input_typeids, current_candidate->args)) { ncandidates++; last_candidate = current_candidate; @@ -559,6 +560,7 @@ right_oper(char *op, Oid arg) int ncandidates; Oid *targetOid; + /* Try for exact match */ tup = SearchSysCacheTuple(OPERNAME, PointerGetDatum(op), ObjectIdGetDatum(arg), @@ -567,44 +569,35 @@ right_oper(char *op, Oid arg) if (!HeapTupleIsValid(tup)) { + /* Try for inexact matches */ ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r'); if (ncandidates == 0) { - elog(ERROR, "Can't find right op '%s' for type %u", op, arg); - return NULL; + unary_op_error(op, arg, FALSE); } else if (ncandidates == 1) { tup = SearchSysCacheTuple(OPERNAME, PointerGetDatum(op), - ObjectIdGetDatum(candidates->args[0]), + ObjectIdGetDatum(candidates->args[0]), ObjectIdGetDatum(InvalidOid), CharGetDatum('r')); - Assert(HeapTupleIsValid(tup)); } else { targetOid = oper_select_candidate(1, &arg, candidates); - if (targetOid != NULL) - { tup = SearchSysCacheTuple(OPERNAME, PointerGetDatum(op), + ObjectIdGetDatum(targetOid[0]), ObjectIdGetDatum(InvalidOid), - ObjectIdGetDatum(*targetOid), CharGetDatum('r')); - } - else - tup = NULL; - - if (!HeapTupleIsValid(tup)) - { - elog(ERROR, "Unable to convert right operator '%s' from type '%s'", - op, typeidTypeName(arg)); - return NULL; - } } + + if (!HeapTupleIsValid(tup)) + unary_op_error(op, arg, FALSE); } + return (Operator) tup; } /* right_oper() */ @@ -619,6 +612,7 @@ left_oper(char *op, Oid arg) int ncandidates; Oid *targetOid; + /* Try for exact match */ tup = SearchSysCacheTuple(OPERNAME, PointerGetDatum(op), ObjectIdGetDatum(InvalidOid), @@ -627,43 +621,35 @@ left_oper(char *op, Oid arg) if (!HeapTupleIsValid(tup)) { + /* Try for inexact matches */ ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l'); if (ncandidates == 0) { - elog(ERROR, "Can't find left op '%s' for type %u", op, arg); - return NULL; + unary_op_error(op, arg, TRUE); } else if (ncandidates == 1) { tup = SearchSysCacheTuple(OPERNAME, PointerGetDatum(op), ObjectIdGetDatum(InvalidOid), - ObjectIdGetDatum(candidates->args[0]), + ObjectIdGetDatum(candidates->args[0]), CharGetDatum('l')); - Assert(HeapTupleIsValid(tup)); } else { targetOid = oper_select_candidate(1, &arg, candidates); if (targetOid != NULL) - { tup = SearchSysCacheTuple(OPERNAME, PointerGetDatum(op), ObjectIdGetDatum(InvalidOid), - ObjectIdGetDatum(*targetOid), + ObjectIdGetDatum(targetOid[0]), CharGetDatum('l')); - } - else - tup = NULL; - - if (!HeapTupleIsValid(tup)) - { - elog(ERROR, "Unable to convert left operator '%s' from type '%s'", - op, typeidTypeName(arg)); - return NULL; - } } + + if (!HeapTupleIsValid(tup)) + unary_op_error(op, arg, TRUE); } + return (Operator) tup; } /* left_oper() */ @@ -698,3 +684,28 @@ op_error(char *op, Oid arg1, Oid arg2) "\n\tYou will have to retype this query using an explicit cast", op, typeTypeName(tp1), typeTypeName(tp2)); } + +/* unary_op_error() + * Give a somewhat useful error message when the operator for one type + * is not found. + */ +static void +unary_op_error(char *op, Oid arg, bool is_left_op) +{ + Type tp1 = NULL; + + if (typeidIsValid(arg)) + tp1 = typeidType(arg); + else + { + elog(ERROR, "Argument of %s operator '%s' has an unknown type" + "\n\tProbably a bad attribute name", + (is_left_op ? "left" : "right"), + op); + } + + elog(ERROR, "Unable to identify a %s operator '%s' for type '%s'" + "\n\tYou will have to retype this query using an explicit cast", + (is_left_op ? "left" : "right"), + op, typeTypeName(tp1)); +}