aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/parse_clause.c12
-rw-r--r--src/backend/parser/parse_coerce.c315
-rw-r--r--src/backend/parser/parse_expr.c5
-rw-r--r--src/backend/parser/parse_func.c11
4 files changed, 203 insertions, 140 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index a2cd7dccc15..b3a6b67f5c3 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.132 2004/06/09 19:08:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.133 2004/06/16 01:26:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -915,11 +915,11 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
* Insert coercion functions if needed. Note that a difference in
* typmod can only happen if input has typmod but outcoltypmod is -1.
* In that case we insert a RelabelType to clearly mark that result's
- * typmod is not same as input.
+ * typmod is not same as input. We never need coerce_type_typmod.
*/
if (l_colvar->vartype != outcoltype)
l_node = coerce_type(pstate, (Node *) l_colvar, l_colvar->vartype,
- outcoltype,
+ outcoltype, outcoltypmod,
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else if (l_colvar->vartypmod != outcoltypmod)
l_node = (Node *) makeRelabelType((Expr *) l_colvar,
@@ -930,7 +930,7 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
if (r_colvar->vartype != outcoltype)
r_node = coerce_type(pstate, (Node *) r_colvar, r_colvar->vartype,
- outcoltype,
+ outcoltype, outcoltypmod,
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else if (r_colvar->vartypmod != outcoltypmod)
r_node = (Node *) makeRelabelType((Expr *) r_colvar,
@@ -1276,7 +1276,7 @@ transformGroupClause(ParseState *pstate, List *grouplist,
if (restype == UNKNOWNOID)
{
tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
- restype, TEXTOID,
+ restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST);
restype = tle->resdom->restype = TEXTOID;
@@ -1528,7 +1528,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
if (restype == UNKNOWNOID && resolveUnknown)
{
tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
- restype, TEXTOID,
+ restype, TEXTOID, -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST);
restype = tle->resdom->restype = TEXTOID;
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index b12d1854aa8..3878d07d5a1 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.118 2004/06/06 00:41:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.119 2004/06/16 01:26:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -33,8 +33,13 @@
static Node *coerce_type_typmod(Node *node,
- Oid targetTypeId, int32 targetTypMod,
- CoercionForm cformat, bool isExplicit);
+ Oid targetTypeId, int32 targetTypMod,
+ CoercionForm cformat, bool isExplicit,
+ bool hideInputCoercion);
+static void hide_coercion_node(Node *node);
+static Node *build_coercion_expression(Node *node, Oid funcId,
+ Oid targetTypeId, int32 targetTypMod,
+ CoercionForm cformat, bool isExplicit);
static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
Oid targetTypeId,
CoercionContext ccontext,
@@ -67,22 +72,27 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
CoercionContext ccontext,
CoercionForm cformat)
{
- if (can_coerce_type(1, &exprtype, &targettype, ccontext))
- expr = coerce_type(pstate, expr, exprtype, targettype,
- ccontext, cformat);
- else
- expr = NULL;
+ Node *result;
+
+ if (!can_coerce_type(1, &exprtype, &targettype, ccontext))
+ return NULL;
+
+ result = coerce_type(pstate, expr, exprtype,
+ targettype, targettypmod,
+ ccontext, cformat);
/*
* If the target is a fixed-length type, it may need a length coercion
- * as well as a type coercion.
+ * as well as a type coercion. If we find ourselves adding both,
+ * force the inner coercion node to implicit display form.
*/
- if (expr != NULL)
- expr = coerce_type_typmod(expr, targettype, targettypmod,
- cformat,
- (cformat != COERCE_IMPLICIT_CAST));
+ result = coerce_type_typmod(result,
+ targettype, targettypmod,
+ cformat,
+ (cformat != COERCE_IMPLICIT_CAST),
+ (result != expr && !IsA(result, Const)));
- return expr;
+ return result;
}
@@ -93,10 +103,13 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
* The caller should already have determined that the coercion is possible;
* see can_coerce_type.
*
- * No coercion to a typmod (length) is performed here. The caller must
- * call coerce_type_typmod as well, if a typmod constraint is wanted.
+ * Normally, no coercion to a typmod (length) is performed here. The caller
+ * must call coerce_type_typmod as well, if a typmod constraint is wanted.
* (But if the target type is a domain, it may internally contain a
* typmod constraint, which will be applied inside coerce_to_domain.)
+ * In some cases pg_cast specifies a type coercion function that also
+ * applies length conversion, and in those cases only, the result will
+ * already be properly coerced to the specified typmod.
*
* pstate is only used in the case that we are able to resolve the type of
* a previously UNKNOWN Param. It is okay to pass pstate = NULL if the
@@ -104,7 +117,7 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
*/
Node *
coerce_type(ParseState *pstate, Node *node,
- Oid inputTypeId, Oid targetTypeId,
+ Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
CoercionContext ccontext, CoercionForm cformat)
{
Node *result;
@@ -178,7 +191,7 @@ coerce_type(ParseState *pstate, Node *node,
/* If target is a domain, apply constraints. */
if (targetTyptype == 'd')
result = coerce_to_domain(result, InvalidOid, targetTypeId,
- cformat);
+ cformat, false);
ReleaseSysCache(targetType);
@@ -240,13 +253,14 @@ coerce_type(ParseState *pstate, Node *node,
* Generate an expression tree representing run-time
* application of the conversion function. If we are dealing
* with a domain target type, the conversion function will
- * yield the base type.
+ * yield the base type (and we assume targetTypeMod must be -1).
*/
Oid baseTypeId = getBaseType(targetTypeId);
- result = (Node *) makeFuncExpr(funcId, baseTypeId,
- list_make1(node),
- cformat);
+ result = build_coercion_expression(node, funcId,
+ baseTypeId, targetTypeMod,
+ cformat,
+ (cformat != COERCE_IMPLICIT_CAST));
/*
* If domain, coerce to the domain type and relabel with
@@ -254,7 +268,7 @@ coerce_type(ParseState *pstate, Node *node,
*/
if (targetTypeId != baseTypeId)
result = coerce_to_domain(result, baseTypeId, targetTypeId,
- cformat);
+ cformat, true);
}
else
{
@@ -269,7 +283,7 @@ coerce_type(ParseState *pstate, Node *node,
* then we won't need a RelabelType node.
*/
result = coerce_to_domain(node, InvalidOid, targetTypeId,
- cformat);
+ cformat, false);
if (result == node)
{
/*
@@ -409,11 +423,13 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
* has not bothered to look this up)
* 'typeId': target type to coerce to
* 'cformat': coercion format
+ * 'hideInputCoercion': if true, hide the input coercion under this one.
*
* If the target type isn't a domain, the given 'arg' is returned as-is.
*/
Node *
-coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, CoercionForm cformat)
+coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
+ CoercionForm cformat, bool hideInputCoercion)
{
CoerceToDomain *result;
int32 typmod;
@@ -426,6 +442,10 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, CoercionForm cformat)
if (baseTypeId == typeId)
return arg;
+ /* Suppress display of nested coercion steps */
+ if (hideInputCoercion)
+ hide_coercion_node(arg);
+
/*
* If the domain applies a typmod to its base type, build the
* appropriate coercion step. Mark it implicit for display purposes,
@@ -444,7 +464,8 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, CoercionForm cformat)
if (typmod >= 0)
arg = coerce_type_typmod(arg, baseTypeId, typmod,
COERCE_IMPLICIT_CAST,
- (cformat != COERCE_IMPLICIT_CAST));
+ (cformat != COERCE_IMPLICIT_CAST),
+ false);
/*
* Now build the domain coercion node. This represents run-time
@@ -473,57 +494,142 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, CoercionForm cformat)
* The caller must have already ensured that the value is of the correct
* type, typically by applying coerce_type.
*
+ * cformat determines the display properties of the generated node (if any),
+ * while isExplicit may affect semantics. If hideInputCoercion is true
+ * *and* we generate a node, the input node is forced to IMPLICIT display
+ * form, so that only the typmod coercion node will be visible when
+ * displaying the expression.
+ *
* NOTE: this does not need to work on domain types, because any typmod
* coercion for a domain is considered to be part of the type coercion
* needed to produce the domain value in the first place. So, no getBaseType.
*/
static Node *
coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
- CoercionForm cformat, bool isExplicit)
+ CoercionForm cformat, bool isExplicit,
+ bool hideInputCoercion)
{
Oid funcId;
- int nargs;
/*
* A negative typmod is assumed to mean that no coercion is wanted.
+ * Also, skip coercion if already done.
*/
if (targetTypMod < 0 || targetTypMod == exprTypmod(node))
return node;
- funcId = find_typmod_coercion_function(targetTypeId, &nargs);
+ funcId = find_typmod_coercion_function(targetTypeId);
if (OidIsValid(funcId))
{
- List *args;
- Const *cons;
+ /* Suppress display of nested coercion steps */
+ if (hideInputCoercion)
+ hide_coercion_node(node);
+
+ node = build_coercion_expression(node, funcId,
+ targetTypeId, targetTypMod,
+ cformat, isExplicit);
+ }
- /* Pass given value, plus target typmod as an int4 constant */
+ return node;
+}
+
+/*
+ * Mark a coercion node as IMPLICIT so it will never be displayed by
+ * ruleutils.c. We use this when we generate a nest of coercion nodes
+ * to implement what is logically one conversion; the inner nodes are
+ * forced to IMPLICIT_CAST format. This does not change their semantics,
+ * only display behavior.
+ *
+ * It is caller error to call this on something that doesn't have a
+ * CoercionForm field.
+ */
+static void
+hide_coercion_node(Node *node)
+{
+ if (IsA(node, FuncExpr))
+ ((FuncExpr *) node)->funcformat = COERCE_IMPLICIT_CAST;
+ else if (IsA(node, RelabelType))
+ ((RelabelType *) node)->relabelformat = COERCE_IMPLICIT_CAST;
+ else if (IsA(node, RowExpr))
+ ((RowExpr *) node)->row_format = COERCE_IMPLICIT_CAST;
+ else if (IsA(node, CoerceToDomain))
+ ((CoerceToDomain *) node)->coercionformat = COERCE_IMPLICIT_CAST;
+ else
+ elog(ERROR, "unsupported node type: %d", (int) nodeTag(node));
+}
+
+/*
+ * build_coercion_expression()
+ * Construct a function-call expression for applying a pg_cast entry.
+ *
+ * This is used for both type-coercion and length-coercion functions,
+ * since there is no difference in terms of the calling convention.
+ */
+static Node *
+build_coercion_expression(Node *node, Oid funcId,
+ Oid targetTypeId, int32 targetTypMod,
+ CoercionForm cformat, bool isExplicit)
+{
+ HeapTuple tp;
+ Form_pg_proc procstruct;
+ int nargs;
+ List *args;
+ Const *cons;
+
+ tp = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(funcId),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "cache lookup failed for function %u", funcId);
+ procstruct = (Form_pg_proc) GETSTRUCT(tp);
+
+ /*
+ * Asserts essentially check that function is a legal coercion function.
+ * We can't make the seemingly obvious tests on prorettype and
+ * proargtypes[0], because of various binary-compatibility cases.
+ */
+ /* Assert(targetTypeId == procstruct->prorettype); */
+ Assert(!procstruct->proretset);
+ Assert(!procstruct->proisagg);
+ nargs = procstruct->pronargs;
+ Assert(nargs >= 1 && nargs <= 3);
+ /* Assert(procstruct->proargtypes[0] == exprType(node)); */
+ Assert(nargs < 2 || procstruct->proargtypes[1] == INT4OID);
+ Assert(nargs < 3 || procstruct->proargtypes[2] == BOOLOID);
+
+ ReleaseSysCache(tp);
+
+ args = list_make1(node);
+
+ if (nargs >= 2)
+ {
+ /* Pass target typmod as an int4 constant */
cons = makeConst(INT4OID,
sizeof(int32),
Int32GetDatum(targetTypMod),
false,
true);
- args = list_make2(node, cons);
+ args = lappend(args, cons);
+ }
- if (nargs == 3)
- {
- /* Pass it a boolean isExplicit parameter, too */
- cons = makeConst(BOOLOID,
- sizeof(bool),
- BoolGetDatum(isExplicit),
- false,
- true);
-
- args = lappend(args, cons);
- }
+ if (nargs == 3)
+ {
+ /* Pass it a boolean isExplicit parameter, too */
+ cons = makeConst(BOOLOID,
+ sizeof(bool),
+ BoolGetDatum(isExplicit),
+ false,
+ true);
- node = (Node *) makeFuncExpr(funcId, targetTypeId, args, cformat);
+ args = lappend(args, cons);
}
- return node;
+ return (Node *) makeFuncExpr(funcId, targetTypeId, args, cformat);
}
+
/*
* coerce_record_to_complex
* Coerce a RECORD to a specific composite type.
@@ -803,7 +909,7 @@ coerce_to_common_type(ParseState *pstate, Node *node,
if (inputTypeId == targetTypeId)
return node; /* no work */
if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
- node = coerce_type(pstate, node, inputTypeId, targetTypeId,
+ node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else
ereport(ERROR,
@@ -1528,8 +1634,8 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
{
/*
* If there's no pg_cast entry, perhaps we are dealing with a pair
- * of array types. If so, and if the element types have a
- * suitable cast, use array_type_coerce().
+ * of array types. If so, and if the element types have a suitable
+ * cast, use array_type_coerce() or array_type_length_coerce().
*/
Oid targetElemType;
Oid sourceElemType;
@@ -1541,7 +1647,23 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
if (find_coercion_pathway(targetElemType, sourceElemType,
ccontext, &elemfuncid))
{
- *funcid = F_ARRAY_TYPE_COERCE;
+ if (!OidIsValid(elemfuncid))
+ {
+ /* binary-compatible element type conversion */
+ *funcid = F_ARRAY_TYPE_COERCE;
+ }
+ else
+ {
+ /* does the function take a typmod arg? */
+ Oid argtypes[FUNC_MAX_ARGS];
+ int nargs;
+
+ (void) get_func_signature(elemfuncid, argtypes, &nargs);
+ if (nargs > 1)
+ *funcid = F_ARRAY_TYPE_LENGTH_COERCE;
+ else
+ *funcid = F_ARRAY_TYPE_COERCE;
+ }
result = true;
}
}
@@ -1554,14 +1676,8 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
/*
* find_typmod_coercion_function -- does the given type need length coercion?
*
- * If the target type possesses a function named for the type
- * and having parameter signature (targettype, int4), we assume that
- * the type requires coercion to its own length and that the said
- * function should be invoked to do that.
- *
- * Alternatively, the length-coercing function may have the signature
- * (targettype, int4, bool). On success, *nargs is set to report which
- * signature we found.
+ * If the target type possesses a pg_cast function from itself to itself,
+ * it must need length coercion.
*
* "bpchar" (ie, char(N)) and "numeric" are examples of such types.
*
@@ -1569,23 +1685,15 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
* function associated directly with the array type, but instead look for
* one associated with the element type. If one exists, we report
* array_length_coerce() as the coercion function to use.
- *
- * This mechanism may seem pretty grotty and in need of replacement by
- * something in pg_cast, but since typmod is only interesting for datatypes
- * that have special handling in the grammar, there's not really much
- * percentage in making it any easier to apply such coercions ...
*/
Oid
-find_typmod_coercion_function(Oid typeId, int *nargs)
+find_typmod_coercion_function(Oid typeId)
{
Oid funcid = InvalidOid;
bool isArray = false;
Type targetType;
Form_pg_type typeForm;
- char *typname;
- Oid typnamespace;
- Oid oid_array[FUNC_MAX_ARGS];
- HeapTuple ftup;
+ HeapTuple tuple;
targetType = typeidType(typeId);
typeForm = (Form_pg_type) GETSTRUCT(targetType);
@@ -1597,79 +1705,30 @@ find_typmod_coercion_function(Oid typeId, int *nargs)
{
/* Yes, switch our attention to the element type */
typeId = typeForm->typelem;
- ReleaseSysCache(targetType);
- targetType = typeidType(typeId);
- typeForm = (Form_pg_type) GETSTRUCT(targetType);
isArray = true;
}
+ ReleaseSysCache(targetType);
- /* Function name is same as type internal name, and in same namespace */
- typname = NameStr(typeForm->typname);
- typnamespace = typeForm->typnamespace;
-
- /* First look for parameters (type, int4) */
- MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
- oid_array[0] = typeId;
- oid_array[1] = INT4OID;
- *nargs = 2;
-
- ftup = SearchSysCache(PROCNAMENSP,
- CStringGetDatum(typname),
- Int16GetDatum(2),
- PointerGetDatum(oid_array),
- ObjectIdGetDatum(typnamespace));
- if (HeapTupleIsValid(ftup))
- {
- Form_pg_proc pform = (Form_pg_proc) GETSTRUCT(ftup);
-
- /* Make sure the function's result type is as expected */
- if (pform->prorettype == typeId && !pform->proretset &&
- !pform->proisagg)
- {
- /* Okay to use it */
- funcid = HeapTupleGetOid(ftup);
- }
- ReleaseSysCache(ftup);
- }
+ /* Look in pg_cast */
+ tuple = SearchSysCache(CASTSOURCETARGET,
+ ObjectIdGetDatum(typeId),
+ ObjectIdGetDatum(typeId),
+ 0, 0);
- if (!OidIsValid(funcid))
+ if (HeapTupleIsValid(tuple))
{
- /* Didn't find a function, so now try (type, int4, bool) */
- oid_array[2] = BOOLOID;
- *nargs = 3;
-
- ftup = SearchSysCache(PROCNAMENSP,
- CStringGetDatum(typname),
- Int16GetDatum(3),
- PointerGetDatum(oid_array),
- ObjectIdGetDatum(typnamespace));
- if (HeapTupleIsValid(ftup))
- {
- Form_pg_proc pform = (Form_pg_proc) GETSTRUCT(ftup);
+ Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
- /* Make sure the function's result type is as expected */
- if (pform->prorettype == typeId && !pform->proretset &&
- !pform->proisagg)
- {
- /* Okay to use it */
- funcid = HeapTupleGetOid(ftup);
- }
- ReleaseSysCache(ftup);
- }
+ funcid = castForm->castfunc;
+ ReleaseSysCache(tuple);
}
- ReleaseSysCache(targetType);
-
/*
* Now, if we did find a coercion function for an array element type,
- * report array_length_coerce() as the function to use. We know it
- * takes three arguments always.
+ * report array_length_coerce() as the function to use.
*/
if (isArray && OidIsValid(funcid))
- {
funcid = F_ARRAY_LENGTH_COERCE;
- *nargs = 3;
- }
return funcid;
}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 3b4ad7cf8a0..6df4547ba2d 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.173 2004/06/09 19:08:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.174 2004/06/16 01:26:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1578,6 +1578,9 @@ exprTypmod(Node *expr)
*
* If coercedTypmod is not NULL, the typmod is stored there if the expression
* is a length-coercion function, else -1 is stored there.
+ *
+ * Note that a combined type-and-length coercion will be treated as a
+ * length coercion by this routine.
*/
bool
exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 781c94f8c2f..d5d71b67afd 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.170 2004/05/30 23:40:35 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.171 2004/06/16 01:26:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -150,7 +150,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
* these cases, so why duplicate code...
*/
return coerce_type(pstate, linitial(fargs),
- actual_arg_types[0], rettype,
+ actual_arg_types[0], rettype, -1,
COERCION_EXPLICIT, COERCE_EXPLICIT_CALL);
}
else if (fdresult == FUNCDETAIL_NORMAL)
@@ -726,11 +726,12 @@ func_get_detail(List *funcname,
{
Oid sourceType = argtypes[0];
Node *arg1 = linitial(fargs);
+ Oid cfuncid;
if ((sourceType == UNKNOWNOID && IsA(arg1, Const)) ||
(find_coercion_pathway(targetType, sourceType,
- COERCION_EXPLICIT, funcid) &&
- *funcid == InvalidOid))
+ COERCION_EXPLICIT, &cfuncid) &&
+ cfuncid == InvalidOid))
{
/* Yup, it's a type coercion */
*funcid = InvalidOid;
@@ -1122,7 +1123,7 @@ make_fn_arguments(ParseState *pstate,
lfirst(current_fargs) = coerce_type(pstate,
lfirst(current_fargs),
actual_arg_types[i],
- declared_arg_types[i],
+ declared_arg_types[i], -1,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST);
}