Index: parse_oper.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_oper.c,v retrieving revision 1.86 diff -c -r1.86 parse_oper.c *** parse_oper.c 14 Mar 2006 22:48:21 -0000 1.86 --- parse_oper.c 24 Mar 2006 18:59:58 -0000 *************** *** 43,48 **** --- 43,49 ---- static Expr *make_op_expr(ParseState *pstate, Operator op, Node *ltree, Node *rtree, Oid ltypeId, Oid rtypeId); + static List * mk_oper_arg_list( Oid arg); /* *************** *** 388,431 **** */ static Oid binary_oper_exact(Oid arg1, Oid arg2, ! FuncCandidateList candidates) { ! FuncCandidateList cand; ! bool was_unknown = false; /* Unspecified type for one of the arguments? then use the other */ if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid)) { arg1 = arg2; ! was_unknown = true; } else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid)) { arg2 = arg1; ! was_unknown = true; } ! for (cand = candidates; cand != NULL; cand = cand->next) ! { ! if (arg1 == cand->args[0] && arg2 == cand->args[1]) ! return cand->oid; ! } ! if (was_unknown) { ! /* arg1 and arg2 are the same here, need only look at arg1 */ ! Oid basetype = getBaseType(arg1); ! ! if (basetype != arg1) { for (cand = candidates; cand != NULL; cand = cand->next) { ! if (basetype == cand->args[0] && basetype == cand->args[1]) return cand->oid; } } } return InvalidOid; } --- 389,455 ---- */ static Oid binary_oper_exact(Oid arg1, Oid arg2, ! FuncCandidateList candidates) { ! FuncCandidateList cand; ! int was_unknown = 0; ! List * larglist=NIL; ! List * rarglist=NIL; ! ListCell * larg_cell; ! ListCell * rarg_cell; ! Oid larg = InvalidOid; ! Oid rarg = InvalidOid; + + /* Check for both args == UNKNOWNOID is in oper() */ /* Unspecified type for one of the arguments? then use the other */ if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid)) { arg1 = arg2; ! was_unknown = 1; } else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid)) { arg2 = arg1; ! was_unknown = 2; } ! /* ! * create argument list of type + basetypes ! */ ! larglist = mk_oper_arg_list( arg1); ! rarglist = mk_oper_arg_list( arg2); ! /* ! * Check each basetype combination for exact match ! * This favors current types and basetypes for matches ! */ ! foreach ( larg_cell, larglist ) { ! larg = lfirst_oid( larg_cell ); ! foreach ( rarg_cell, rarglist ) { + rarg = lfirst_oid( rarg_cell ); for (cand = candidates; cand != NULL; cand = cand->next) { ! if (larg == cand->args[0] && rarg == cand->args[1]) return cand->oid; } } } + /* + * Put back the unknownid to let func sel handle it + */ + if (was_unknown == 1) + { + arg1 = UNKNOWNOID; + } + else if (was_unknown == 2) + { + arg2 = UNKNOWNOID; + } + return InvalidOid; } *************** *** 518,531 **** /* * Check for an "exact" match. */ ! operOid = binary_oper_exact(ltypeId, rtypeId, clist); if (!OidIsValid(operOid)) { /* - * Otherwise, search for the most suitable candidate. - */ - - /* * Unspecified type for one of the arguments? then use the other * (XXX this is probably dead code?) */ --- 542,554 ---- /* * Check for an "exact" match. */ ! if ( ltypeId == UNKNOWNOID && rtypeId == UNKNOWNOID ) ! operOid = InvalidOid; ! else ! operOid = binary_oper_exact(ltypeId, rtypeId, clist); if (!OidIsValid(operOid)) { /* * Unspecified type for one of the arguments? then use the other * (XXX this is probably dead code?) */ *************** *** 533,538 **** --- 556,565 ---- rtypeId = ltypeId; else if (ltypeId == InvalidOid) ltypeId = rtypeId; + + /* + * search for the most suitable candidate. + */ inputOids[0] = ltypeId; inputOids[1] = rtypeId; fdresult = oper_select_candidate(2, inputOids, clist, &operOid); *************** *** 1017,1019 **** --- 1044,1074 ---- return (Expr *) result; } + + /* + * mk_oper_arg_list() + * Build type argument list of current type and basetypes. + * + * Order of list is important. Current type has precedence, + * then parent types in order of distance from current type. + * + * Called by binary_oper_exact to find operators for domains. + */ + List * + mk_oper_arg_list( Oid arg) + { + List *arglist = NIL; + Oid basetype = InvalidOid; + Oid prevtype = arg; + + + arglist = lappend_oid( arglist, prevtype ); + basetype = getBaseType(prevtype); + while ( basetype != prevtype ){ + arglist = lappend_oid( arglist, basetype ); + prevtype = basetype; + basetype = getBaseType(prevtype); + } + return arglist; + } +