]> granicus.if.org Git - postgresql/commitdiff
Fix poorly worded error messages for unary operator type resolution
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 27 Feb 2000 02:48:15 +0000 (02:48 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 27 Feb 2000 02:48:15 +0000 (02:48 +0000)
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

src/backend/parser/parse_oper.c

index 21fdb2203245e4361f7e5b53639c4e8a1304e28b..426c61887e6099842aae8543dc720fc48154a583 100644 (file)
@@ -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], &current_candidate->args[0])
-                       && can_coerce_type(1, &input_typeids[1], &current_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));
+}