aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/parse_coerce.c32
-rw-r--r--src/backend/parser/parse_expr.c9
-rw-r--r--src/backend/parser/parse_func.c58
3 files changed, 68 insertions, 31 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index dbb6cbc5816..646f1a046b3 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* parse_coerce.c
- * handle type coersions/conversions for parser
+ * handle type coercions/conversions for parser
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.31 2000/02/20 06:28:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.32 2000/02/20 21:32:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,7 +36,7 @@ Node *
coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
Oid targetTypeId, int32 atttypmod)
{
- Node *result = NULL;
+ Node *result;
if (targetTypeId == InvalidOid ||
targetTypeId == inputTypeId)
@@ -44,11 +44,6 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
/* no conversion needed */
result = node;
}
- else if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
- {
- /* no work if one of the known-good transparent conversions */
- result = node;
- }
else if (inputTypeId == UNKNOWNOID && IsA(node, Const))
{
/*
@@ -87,6 +82,27 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
result = (Node *) newcon;
}
+ else if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
+ {
+ /*
+ * We don't really need to do a conversion, but we do need to attach
+ * a RelabelType node so that the expression will be seen to have
+ * the intended type when inspected by higher-level code.
+ */
+ RelabelType *relabel = makeNode(RelabelType);
+
+ relabel->arg = node;
+ relabel->resulttype = targetTypeId;
+ /*
+ * XXX could we label result with exprTypmod(node) instead of
+ * default -1 typmod, to save a possible length-coercion later?
+ * Would work if both types have same interpretation of typmod,
+ * which is likely but not certain.
+ */
+ relabel->resulttypmod = -1;
+
+ result = (Node *) relabel;
+ }
else
{
/*
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 365378f4072..3fd3370672f 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.68 2000/02/15 03:37:47 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.69 2000/02/20 21:32:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -516,6 +516,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
case T_Param:
case T_Aggref:
case T_ArrayRef:
+ case T_RelabelType:
{
result = (Node *) expr;
break;
@@ -627,6 +628,9 @@ exprType(Node *expr)
case T_Param:
type = ((Param *) expr)->paramtype;
break;
+ case T_RelabelType:
+ type = ((RelabelType *) expr)->resulttype;
+ break;
case T_SubLink:
{
SubLink *sublink = (SubLink *) expr;
@@ -697,6 +701,9 @@ exprTypmod(Node *expr)
}
}
break;
+ case T_RelabelType:
+ return ((RelabelType *) expr)->resulttypmod;
+ break;
default:
break;
}
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,