Clean up some bugs in oper_select_candidate(), notably the
authorTom Lane
Thu, 26 Aug 1999 04:59:15 +0000 (04:59 +0000)
committerTom Lane
Thu, 26 Aug 1999 04:59:15 +0000 (04:59 +0000)
last loop which would return the *first* surviving-to-that-point candidate
regardless of which one actually passed the test.  This was producing
such curious results as 'oid % 2' getting translated to 'int2(oid) % 2'.

src/backend/parser/parse_oper.c

index 529663b6ce5acae6a00719aadbb44ad0bfe06b95..8f82e58517d748728586d18cc61278eac4a98b9e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.30 1999/08/23 23:48:39 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.31 1999/08/26 04:59:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,9 +28,7 @@ static Oid *oper_select_candidate(int nargs, Oid *input_typeids,
 static Operator oper_exact(char *op, Oid arg1, Oid arg2);
 static Operator oper_inexact(char *op, Oid arg1, Oid arg2);
 static int binary_oper_get_candidates(char *opname,
-                          Oid leftTypeId,
-                          Oid rightTypeId,
-                          CandidateList *candidates);
+                                     CandidateList *candidates);
 static int unary_oper_get_candidates(char *op,
                          Oid typeId,
                          CandidateList *candidates,
@@ -64,15 +62,12 @@ oprid(Operator op)
 
 
 /* binary_oper_get_candidates()
- * given opname, leftTypeId and rightTypeId,
- * find all possible (arg1, arg2) pairs for which an operator named
- * opname exists, such that leftTypeId can be coerced to arg1 and
- * rightTypeId can be coerced to arg2
+ * given opname, find all possible input type pairs for which an operator
+ * named opname exists.  Build a list of the candidate input types.
+ * Returns number of candidates found.
  */
 static int
 binary_oper_get_candidates(char *opname,
-                          Oid leftTypeId,
-                          Oid rightTypeId,
                           CandidateList *candidates)
 {
    CandidateList current_candidate;
@@ -224,14 +219,17 @@ oper_select_candidate(int nargs,
            ncandidates++;
        }
        /* otherwise, don't bother keeping this one... */
-       else
-           last_candidate->next = NULL;
    }
 
+   if (last_candidate)         /* terminate rebuilt list */
+       last_candidate->next = NULL;
+
    if (ncandidates <= 1)
    {
-       if (!can_coerce_type(1, &input_typeids[0], &candidates->args[0])
-        || !can_coerce_type(1, &input_typeids[1], &candidates->args[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;
        return (ncandidates == 1) ? candidates->args : NULL;
    }
@@ -252,9 +250,9 @@ oper_select_candidate(int nargs,
        nmatch = 0;
        for (i = 0; i < nargs; i++)
        {
-           current_category = TypeCategory(current_typeids[i]);
            if (input_typeids[i] != UNKNOWNOID)
            {
+               current_category = TypeCategory(current_typeids[i]);
                if (current_typeids[i] == input_typeids[i])
                    nmatch++;
                else if (IsPreferredType(current_category, current_typeids[i])
@@ -276,14 +274,17 @@ oper_select_candidate(int nargs,
            last_candidate = current_candidate;
            ncandidates++;
        }
-       else
-           last_candidate->next = NULL;
    }
 
+   if (last_candidate)         /* terminate rebuilt list */
+       last_candidate->next = NULL;
+
    if (ncandidates <= 1)
    {
-       if (!can_coerce_type(1, &input_typeids[0], &candidates->args[0])
-           || ((nargs > 1) && !can_coerce_type(1, &input_typeids[1], &candidates->args[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;
        return (ncandidates == 1) ? candidates->args : NULL;
    }
@@ -309,12 +310,12 @@ oper_select_candidate(int nargs,
             current_candidate != NULL;
             current_candidate = current_candidate->next)
        {
+           current_typeids = current_candidate->args;
            nmatch = 0;
            for (i = 0; i < nargs; i++)
            {
-               current_typeids = current_candidate->args;
-               if ((current_type == current_typeids[i])
-               || IS_BINARY_COMPATIBLE(current_type, current_typeids[i]))
+               if (current_type == current_typeids[i] ||
+                   IS_BINARY_COMPATIBLE(current_type, current_typeids[i]))
                    nmatch++;
            }
            if (nmatch == nargs)
@@ -364,16 +365,20 @@ oper_select_candidate(int nargs,
    }
 
    ncandidates = 0;
+   last_candidate = NULL;
    for (current_candidate = candidates;
         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]))
+       {
            ncandidates++;
+           last_candidate = current_candidate;
+       }
    }
 
-   return (ncandidates == 1) ? candidates->args : NULL;
+   return (ncandidates == 1) ? last_candidate->args : NULL;
 }  /* oper_select_candidate() */
 
 
@@ -423,7 +428,7 @@ oper_inexact(char *op, Oid arg1, Oid arg2)
    if (arg1 == InvalidOid)
        arg1 = arg2;
 
-   ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates);
+   ncandidates = binary_oper_get_candidates(op, &candidates);
 
    /* No operators found? Then return null... */
    if (ncandidates == 0)