diff --git a/src/backend/parser/parse_param.c b/src/backend/parser/parse_param.c
index ba91028c891754c15ce5077cdccc94a74937b5b4..11244f7a3e3707fa0ad539a7b5aa6cc38148f8ce 100644
--- a/src/backend/parser/parse_param.c
+++ b/src/backend/parser/parse_param.c
@@ -17,7 +17,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/parse_param.c,v 2.4 2010/02/26 02:00:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/parse_param.c,v 2.5 2010/08/18 12:20:15 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@ typedef struct FixedParamState
 {
 	Oid		   *paramTypes;		/* array of parameter type OIDs */
 	int			numParams;		/* number of array entries */
+	Oid		   *unknownParamTypes; /* resolved types of 'unknown' params  */
 } FixedParamState;
 
 /*
@@ -55,6 +56,9 @@ static Node *variable_paramref_hook(ParseState *pstate, ParamRef *pref);
 static Node *variable_coerce_param_hook(ParseState *pstate, Param *param,
 						   Oid targetTypeId, int32 targetTypeMod,
 						   int location);
+static Node *fixed_coerce_param_hook(ParseState *pstate, Param *param,
+						   Oid targetTypeId, int32 targetTypeMod,
+						   int location);
 static bool check_parameter_resolution_walker(Node *node, ParseState *pstate);
 
 
@@ -69,9 +73,10 @@ parse_fixed_parameters(ParseState *pstate,
 
 	parstate->paramTypes = paramTypes;
 	parstate->numParams = numParams;
+	parstate->unknownParamTypes = NULL;
 	pstate->p_ref_hook_state = (void *) parstate;
 	pstate->p_paramref_hook = fixed_paramref_hook;
-	/* no need to use p_coerce_param_hook */
+	pstate->p_coerce_param_hook = fixed_coerce_param_hook;
 }
 
 /*
@@ -170,6 +175,83 @@ variable_paramref_hook(ParseState *pstate, ParamRef *pref)
 	return (Node *) param;
 }
 
+/*
+ * Coerce a Param to a query-requested datatype, in the fixed params case.
+ *
+ * 'unknown' type params are coerced to the type requested, analogous to the
+ * coercion of unknown constants performed in coerce_type(). We can't change
+ * the param types like we do in the varparams case, so the coercion is done
+ * at runtime using CoerceViaIO nodes.
+ */
+static Node *
+fixed_coerce_param_hook(ParseState *pstate, Param *param,
+						Oid targetTypeId, int32 targetTypeMode,
+						int location)
+{
+	if (param->paramkind == PARAM_EXTERN && param->paramtype == UNKNOWNOID)
+	{
+		FixedParamState *parstate = (FixedParamState *) pstate->p_ref_hook_state;
+		Oid *unknownParamTypes = parstate->unknownParamTypes;
+		int			paramno = param->paramid;
+		CoerceViaIO *iocoerce;
+
+		if (paramno <= 0 ||		/* shouldn't happen, but... */
+			paramno > parstate->numParams)
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_PARAMETER),
+					 errmsg("there is no parameter $%d", paramno),
+					 parser_errposition(pstate, param->location)));
+
+		/* Allocate the array on first use */
+		if (unknownParamTypes == NULL)
+		{
+			unknownParamTypes = palloc0(parstate->numParams * sizeof(Oid));
+			parstate->unknownParamTypes = unknownParamTypes;
+		}
+
+		/*
+		 * If the same parameter is used multiple times in the query, make
+		 * sure it's always resolved to the same type. The code would cope
+		 * with differing interpretations, but it might lead to surprising
+		 * results. The varparams code forbids that anyway, so better be
+		 * consistent.
+		 */
+		if (unknownParamTypes[paramno - 1] == InvalidOid)
+		{
+			/* We've successfully resolved the type */
+			unknownParamTypes[paramno - 1] = targetTypeId;
+		}
+		else if (unknownParamTypes[paramno - 1] == targetTypeId)
+		{
+			/* We previously resolved the type, and it matches */
+		}
+		else
+		{
+			/* Ooops */
+			ereport(ERROR,
+					(errcode(ERRCODE_AMBIGUOUS_PARAMETER),
+					 errmsg("inconsistent types deduced for parameter $%d",
+							paramno),
+					 errdetail("%s versus %s",
+							   format_type_be(unknownParamTypes[paramno - 1]),
+							   format_type_be(targetTypeId)),
+					 parser_errposition(pstate, param->location)));
+		}
+
+		/* Build a CoerceViaIO node */
+		iocoerce = makeNode(CoerceViaIO);
+		iocoerce->arg = (Expr *) param;
+		iocoerce->resulttype = targetTypeId;
+		iocoerce->coerceformat = COERCE_IMPLICIT_CAST;
+		iocoerce->location = location;
+
+		return (Node *) iocoerce;
+	}
+
+	/* Else signal to proceed with normal coercion */
+	return NULL;
+}
+
 /*
  * Coerce a Param to a query-requested datatype, in the varparams case.
  */