Fix poorly worded error messages for unary operator type resolution

failures.  Fix some outright bugs too, including a reference to
uninitialized memory that would cause failures like this one:
select -('1234567890.1234567'::text);
ERROR:  Unable to locate type oid 2139062143 in catalog
This commit is contained in:
Tom Lane 2000-02-27 02:48:15 +00:00
parent ed0e292354
commit 66fe0fc87e

View File

@ -1,6 +1,6 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* parse_oper.h * parse_oper.c
* handle operator things for parser * handle operator things for parser
* *
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, CandidateList *candidates,
char rightleft); char rightleft);
static void op_error(char *op, Oid arg1, Oid arg2); static void op_error(char *op, Oid arg1, Oid arg2);
static void unary_op_error(char *op, Oid arg, bool is_left_op);
Oid Oid
any_ordering_op(Oid restype) any_ordering_op(Oid restype)
@ -224,11 +226,11 @@ oper_select_candidate(int nargs,
if (ncandidates <= 1) if (ncandidates <= 1)
{ {
if (ncandidates > 0 && if (ncandidates > 0)
(!can_coerce_type(1, &input_typeids[0], &candidates->args[0]) || {
(nargs > 1 && if (!can_coerce_type(nargs, input_typeids, candidates->args))
!can_coerce_type(1, &input_typeids[1], &candidates->args[1]))))
ncandidates = 0; ncandidates = 0;
}
return (ncandidates == 1) ? candidates->args : NULL; return (ncandidates == 1) ? candidates->args : NULL;
} }
@ -279,11 +281,11 @@ oper_select_candidate(int nargs,
if (ncandidates <= 1) if (ncandidates <= 1)
{ {
if (ncandidates > 0 && if (ncandidates > 0)
(!can_coerce_type(1, &input_typeids[0], &candidates->args[0]) || {
(nargs > 1 && if (!can_coerce_type(nargs, input_typeids, candidates->args))
!can_coerce_type(1, &input_typeids[1], &candidates->args[1]))))
ncandidates = 0; ncandidates = 0;
}
return (ncandidates == 1) ? candidates->args : NULL; return (ncandidates == 1) ? candidates->args : NULL;
} }
@ -368,8 +370,7 @@ oper_select_candidate(int nargs,
current_candidate != NULL; current_candidate != NULL;
current_candidate = current_candidate->next) current_candidate = current_candidate->next)
{ {
if (can_coerce_type(1, &input_typeids[0], &current_candidate->args[0]) if (can_coerce_type(nargs, input_typeids, current_candidate->args))
&& can_coerce_type(1, &input_typeids[1], &current_candidate->args[1]))
{ {
ncandidates++; ncandidates++;
last_candidate = current_candidate; last_candidate = current_candidate;
@ -559,6 +560,7 @@ right_oper(char *op, Oid arg)
int ncandidates; int ncandidates;
Oid *targetOid; Oid *targetOid;
/* Try for exact match */
tup = SearchSysCacheTuple(OPERNAME, tup = SearchSysCacheTuple(OPERNAME,
PointerGetDatum(op), PointerGetDatum(op),
ObjectIdGetDatum(arg), ObjectIdGetDatum(arg),
@ -567,11 +569,11 @@ right_oper(char *op, Oid arg)
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
/* Try for inexact matches */
ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r'); ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r');
if (ncandidates == 0) if (ncandidates == 0)
{ {
elog(ERROR, "Can't find right op '%s' for type %u", op, arg); unary_op_error(op, arg, FALSE);
return NULL;
} }
else if (ncandidates == 1) else if (ncandidates == 1)
{ {
@ -580,31 +582,22 @@ right_oper(char *op, Oid arg)
ObjectIdGetDatum(candidates->args[0]), ObjectIdGetDatum(candidates->args[0]),
ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(InvalidOid),
CharGetDatum('r')); CharGetDatum('r'));
Assert(HeapTupleIsValid(tup));
} }
else else
{ {
targetOid = oper_select_candidate(1, &arg, candidates); targetOid = oper_select_candidate(1, &arg, candidates);
if (targetOid != NULL) if (targetOid != NULL)
{
tup = SearchSysCacheTuple(OPERNAME, tup = SearchSysCacheTuple(OPERNAME,
PointerGetDatum(op), PointerGetDatum(op),
ObjectIdGetDatum(targetOid[0]),
ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(InvalidOid),
ObjectIdGetDatum(*targetOid),
CharGetDatum('r')); CharGetDatum('r'));
} }
else
tup = NULL;
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ unary_op_error(op, arg, FALSE);
elog(ERROR, "Unable to convert right operator '%s' from type '%s'",
op, typeidTypeName(arg));
return NULL;
}
}
} }
return (Operator) tup; return (Operator) tup;
} /* right_oper() */ } /* right_oper() */
@ -619,6 +612,7 @@ left_oper(char *op, Oid arg)
int ncandidates; int ncandidates;
Oid *targetOid; Oid *targetOid;
/* Try for exact match */
tup = SearchSysCacheTuple(OPERNAME, tup = SearchSysCacheTuple(OPERNAME,
PointerGetDatum(op), PointerGetDatum(op),
ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(InvalidOid),
@ -627,11 +621,11 @@ left_oper(char *op, Oid arg)
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
/* Try for inexact matches */
ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l'); ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l');
if (ncandidates == 0) if (ncandidates == 0)
{ {
elog(ERROR, "Can't find left op '%s' for type %u", op, arg); unary_op_error(op, arg, TRUE);
return NULL;
} }
else if (ncandidates == 1) else if (ncandidates == 1)
{ {
@ -640,30 +634,22 @@ left_oper(char *op, Oid arg)
ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(InvalidOid),
ObjectIdGetDatum(candidates->args[0]), ObjectIdGetDatum(candidates->args[0]),
CharGetDatum('l')); CharGetDatum('l'));
Assert(HeapTupleIsValid(tup));
} }
else else
{ {
targetOid = oper_select_candidate(1, &arg, candidates); targetOid = oper_select_candidate(1, &arg, candidates);
if (targetOid != NULL) if (targetOid != NULL)
{
tup = SearchSysCacheTuple(OPERNAME, tup = SearchSysCacheTuple(OPERNAME,
PointerGetDatum(op), PointerGetDatum(op),
ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(InvalidOid),
ObjectIdGetDatum(*targetOid), ObjectIdGetDatum(targetOid[0]),
CharGetDatum('l')); CharGetDatum('l'));
} }
else
tup = NULL;
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ unary_op_error(op, arg, TRUE);
elog(ERROR, "Unable to convert left operator '%s' from type '%s'",
op, typeidTypeName(arg));
return NULL;
}
}
} }
return (Operator) tup; return (Operator) tup;
} /* left_oper() */ } /* 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", "\n\tYou will have to retype this query using an explicit cast",
op, typeTypeName(tp1), typeTypeName(tp2)); 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));
}