From: Tom Lane Date: Thu, 26 Aug 1999 04:59:15 +0000 (+0000) Subject: Clean up some bugs in oper_select_candidate(), notably the X-Git-Tag: REL7_0~1569 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5adebf83b6cffbf4133ff97dbe6d5da0ff59bff1;p=postgresql Clean up some bugs in oper_select_candidate(), notably the 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'. --- diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 529663b6ce..8f82e58517 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -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)