diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 284a5bf..af0755d 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -33,6 +33,7 @@
 #include "tcop/pquery.h"
 #include "tcop/utility.h"
 #include "utils/builtins.h"
+#include "utils/lsyscache.h"
 #include "utils/snapmgr.h"
 #include "utils/timestamp.h"
 
@@ -176,6 +177,42 @@ PrepareQuery(ParseState *pstate, PrepareStmt *stmt,
 }
 
 /*
+ * Parser callback for resolving parameter references from an existing
+ * ParamListInfo structure.
+ */
+static Node *
+pli_paramref_hook(ParseState *pstate, ParamRef *pref)
+{
+	ParamListInfo paramInfo = (ParamListInfo) pstate->p_ref_hook_state;
+	int			paramno = pref->number;
+	ParamExternData *ped;
+	ParamExternData pedws;
+	Param	   *param;
+
+	/* Check parameter number is valid */
+	if (paramno <= 0 || paramno > paramInfo->numParams)
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_PARAMETER),
+				 errmsg("there is no parameter $%d", paramno),
+				 parser_errposition(pstate, pref->location)));
+
+	if (paramInfo->paramFetch != NULL)
+		ped = paramInfo->paramFetch(paramInfo, paramno, false, &pedws);
+	else
+		ped = &paramInfo->params[paramno - 1];
+
+	param = makeNode(Param);
+	param->paramkind = PARAM_EXTERN;
+	param->paramid = paramno;
+	param->paramtype = ped->ptype;
+	param->paramtypmod = -1;
+	param->paramcollid = get_typcollation(param->paramtype);
+	param->location = pref->location;
+
+	return (Node *) param;
+}
+
+/*
  * ExecuteQuery --- implement the 'EXECUTE' utility statement.
  *
  * This code also supports CREATE TABLE ... AS EXECUTE.  That case is
@@ -199,6 +236,10 @@ ExecuteQuery(ParseState *pstate,
 	int			eflags;
 	long		count;
 
+	Assert(pstate->p_paramref_hook == NULL);
+	pstate->p_ref_hook_state = (void *) params;
+	pstate->p_paramref_hook = pli_paramref_hook;
+
 	/* Look it up in the hash table */
 	entry = FetchPreparedStatement(stmt->name, true);
 
@@ -635,6 +676,9 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 
 		pstate = make_parsestate(NULL);
 		pstate->p_sourcetext = queryString;
+		/* XXX what about p_queryEnv? */
+		if (params && params->parserSetup)
+			params->parserSetup(pstate, params->parserSetupArg);
 
 		/*
 		 * Need an EState to evaluate parameters; must not delete it till end
diff --git a/src/test/regress/expected/prepare.out b/src/test/regress/expected/prepare.out
index 3306c69..a0fec13 100644
--- a/src/test/regress/expected/prepare.out
+++ b/src/test/regress/expected/prepare.out
@@ -187,3 +187,26 @@ SELECT name, statement, parameter_types FROM pg_prepared_statements
 ------+-----------+-----------------
 (0 rows)
 
+-- check parameter handling
+CREATE TABLE t1 (a int);
+PREPARE p1 AS INSERT INTO t1 (a) VALUES ($1);
+CREATE FUNCTION f1(x int) RETURNS int
+LANGUAGE SQL
+AS $$
+EXECUTE p1($1);
+SELECT null::int;
+$$;
+SELECT f1(2);
+ f1 
+----
+   
+(1 row)
+
+SELECT * FROM t1;
+ a 
+---
+ 2
+(1 row)
+
+DROP FUNCTION f1(int);
+DROP TABLE t1;
diff --git a/src/test/regress/sql/prepare.sql b/src/test/regress/sql/prepare.sql
index 985d0f0..6a16858 100644
--- a/src/test/regress/sql/prepare.sql
+++ b/src/test/regress/sql/prepare.sql
@@ -78,3 +78,24 @@ SELECT name, statement, parameter_types FROM pg_prepared_statements
 DEALLOCATE ALL;
 SELECT name, statement, parameter_types FROM pg_prepared_statements
     ORDER BY name;
+
+
+-- check parameter handling
+
+CREATE TABLE t1 (a int);
+
+PREPARE p1 AS INSERT INTO t1 (a) VALUES ($1);
+
+CREATE FUNCTION f1(x int) RETURNS int
+LANGUAGE SQL
+AS $$
+EXECUTE p1($1);
+SELECT null::int;
+$$;
+
+SELECT f1(2);
+
+SELECT * FROM t1;
+
+DROP FUNCTION f1(int);
+DROP TABLE t1;
