diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-02-20 21:32:16 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-02-20 21:32:16 +0000 |
commit | 57b30e8e226014c8d06bae0158e0c7fc679f700b (patch) | |
tree | 172a3052e6c88922d63726bacd092afac6bf053c /src/backend/parser/parse_func.c | |
parent | bd8e071482e3c33876295aae5523fe57ce35025b (diff) | |
download | postgresql-57b30e8e226014c8d06bae0158e0c7fc679f700b.tar.gz postgresql-57b30e8e226014c8d06bae0158e0c7fc679f700b.zip |
Create a new expression node type RelabelType, which exists solely to
represent the result of a binary-compatible type coercion. At runtime
it just evaluates its argument --- but during type resolution, exprType
will pick up the output type of the RelabelType node instead of the type
of the argument. This solves some longstanding problems with dropped
type coercions, an example being 'select now()::abstime::int4' which
used to produce date-formatted output, not an integer, because the
coercion to int4 was dropped on the floor.
Diffstat (limited to 'src/backend/parser/parse_func.c')
-rw-r--r-- | src/backend/parser/parse_func.c | 58 |
1 files changed, 36 insertions, 22 deletions
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 939d7a91ec3..71cda760874 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.70 2000/02/20 06:35:08 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.71 2000/02/20 21:32:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -163,7 +163,10 @@ agg_get_candidates(char *aggname, } /* agg_get_candidates() */ /* agg_select_candidate() - * Try to choose only one candidate aggregate function from a list of possibles. + * + * Try to choose only one candidate aggregate function from a list of + * possible matches. Return value is Oid of input type of aggregate + * if successful, else InvalidOid. */ static Oid agg_select_candidate(Oid typeid, CandidateList candidates) @@ -175,10 +178,12 @@ agg_select_candidate(Oid typeid, CandidateList candidates) CATEGORY category, current_category; -/* - * First look for exact matches or binary compatible matches. - * (Of course exact matches shouldn't even get here, but anyway.) - */ + /* + * First look for exact matches or binary compatible matches. + * (Of course exact matches shouldn't even get here, but anyway.) + */ + ncandidates = 0; + last_candidate = NULL; for (current_candidate = candidates; current_candidate != NULL; current_candidate = current_candidate->next) @@ -188,15 +193,17 @@ agg_select_candidate(Oid typeid, CandidateList candidates) if (current_typeid == typeid || IS_BINARY_COMPATIBLE(current_typeid, typeid)) { - /* we're home free */ - return current_typeid; + last_candidate = current_candidate; + ncandidates++; } } + if (ncandidates == 1) + return last_candidate->args[0]; -/* - * If no luck that way, look for candidates which allow coersion - * and have a preferred type. Keep all candidates if none match. - */ + /* + * If no luck that way, look for candidates which allow coercion + * and have a preferred type. Keep all candidates if none match. + */ category = TypeCategory(typeid); ncandidates = 0; last_candidate = NULL; @@ -232,7 +239,10 @@ agg_select_candidate(Oid typeid, CandidateList candidates) if (last_candidate) /* terminate rebuilt list */ last_candidate->next = NULL; - return ((ncandidates == 1) ? candidates->args[0] : 0); + if (ncandidates == 1) + return candidates->args[0]; + + return InvalidOid; } /* agg_select_candidate() */ @@ -471,10 +481,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, /* * See if this is a single argument function with the function * name also a type name and the input argument and type name - * binary compatible... This means that you are trying for a - * type conversion which does not need to take place, so we'll - * just pass through the argument itself. (make this clearer - * with some extra brackets - thomas 1998-12-05) + * binary compatible. If so, we do not need to do any real + * conversion, but we do need to build a RelabelType node + * so that exprType() sees the result as being of the output type. */ if (nargs == 1) { @@ -486,8 +495,13 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, if (HeapTupleIsValid(tp) && IS_BINARY_COMPATIBLE(typeTypeId(tp), exprType(lfirst(fargs)))) { - /* XXX FIXME: probably need to change expression's marked type? */ - return (Node *) lfirst(fargs); + RelabelType *relabel = makeNode(RelabelType); + + relabel->arg = (Node *) lfirst(fargs); + relabel->resulttype = typeTypeId(tp); + relabel->resulttypmod = -1; + + return (Node *) relabel; } } @@ -1128,7 +1142,7 @@ func_get_detail(char *funcname, * inheritance properties of the supplied argv. * * This function is used to disambiguate among functions with the - * same name but different signatures. It takes an array of eight + * same name but different signatures. It takes an array of input * type ids. For each type id in the array that's a complex type * (a class), it walks up the inheritance tree, finding all * superclasses of that type. A vector of new Oid type arrays @@ -1342,7 +1356,7 @@ gen_cross_product(InhPaths *arginh, int nargs) * 2) the input type can be typecast into the function type * Right now, we only typecast unknowns, and that is all we check for. * - * func_get_detail() now can find coersions for function arguments which + * func_get_detail() now can find coercions for function arguments which * will make this function executable. So, we need to recover these * results here too. * - thomas 1998-03-25 @@ -1361,7 +1375,7 @@ make_arguments(ParseState *pstate, i < nargs; i++, current_fargs = lnext(current_fargs)) { - /* types don't match? then force coersion using a function call... */ + /* types don't match? then force coercion using a function call... */ if (input_typeids[i] != function_typeids[i]) { lfirst(current_fargs) = coerce_type(pstate, |