diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
index 509d9e0dfa12fb039b6417828e3a11b814fd4dd5..64d0c77489bbc1ac2b7c9dcbf6ce5b4a4ab6005b 100644
--- a/src/backend/commands/portalcmds.c
+++ b/src/backend/commands/portalcmds.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.30 2004/07/31 00:45:31 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.31 2004/08/02 01:30:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,7 +36,7 @@
  *		Execute SQL DECLARE CURSOR command.
  */
 void
-PerformCursorOpen(DeclareCursorStmt *stmt)
+PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params)
 {
 	List	   *rewritten;
 	Query	   *query;
@@ -104,6 +104,17 @@ PerformCursorOpen(DeclareCursorStmt *stmt)
 					  list_make1(plan),
 					  PortalGetHeapMemory(portal));
 
+	/*
+	 * Also copy the outer portal's parameter list into the inner portal's
+	 * memory context.  We want to pass down the parameter values in case
+	 * we had a command like
+	 *			DECLARE c CURSOR FOR SELECT ... WHERE foo = $1
+	 * This will have been parsed using the outer parameter set and the
+	 * parameter value needs to be preserved for use when the cursor is
+	 * executed.
+	 */
+	params = copyParamList(params);
+
 	MemoryContextSwitchTo(oldContext);
 
 	/*
@@ -123,9 +134,9 @@ PerformCursorOpen(DeclareCursorStmt *stmt)
 	}
 
 	/*
-	 * Start execution --- never any params for a cursor.
+	 * Start execution, inserting parameters if any.
 	 */
-	PortalStart(portal, NULL);
+	PortalStart(portal, params);
 
 	Assert(portal->strategy == PORTAL_ONE_SELECT);
 
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 9c183cb7827b193881a6cbfa1e44f4d296278e5d..d4c8357ff0b4d0b54efbe4853b3e0cfd4a4c8810 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2003, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.28 2004/06/11 01:08:38 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.29 2004/08/02 01:30:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -200,7 +200,7 @@ ExecuteQuery(ExecuteStmt *stmt, DestReceiver *dest, char *completionTag)
 
 /*
  * Evaluates a list of parameters, using the given executor state. It
- * requires a list of the parameter values themselves, and a list of
+ * requires a list of the parameter expressions themselves, and a list of
  * their types. It returns a filled-in ParamListInfo -- this can later
  * be passed to CreateQueryDesc(), which allows the executor to make use
  * of the parameters during query execution.
@@ -211,7 +211,7 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
 	int			nargs = list_length(argtypes);
 	ParamListInfo paramLI;
 	List	   *exprstates;
-	ListCell   *l;
+	ListCell   *le, *la;
 	int			i = 0;
 
 	/* Parser should have caught this error, but check for safety */
@@ -223,9 +223,9 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
 	paramLI = (ParamListInfo)
 		palloc0((nargs + 1) * sizeof(ParamListInfoData));
 
-	foreach(l, exprstates)
+	forboth(le, exprstates, la, argtypes)
 	{
-		ExprState  *n = lfirst(l);
+		ExprState  *n = lfirst(le);
 		bool		isNull;
 
 		paramLI[i].value = ExecEvalExprSwitchContext(n,
@@ -234,6 +234,7 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
 													 NULL);
 		paramLI[i].kind = PARAM_NUM;
 		paramLI[i].id = i + 1;
+		paramLI[i].ptype = lfirst_oid(la);
 		paramLI[i].isnull = isNull;
 
 		i++;
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 2dead1e15a123b4a7390266789049b49cfa54ed3..d73c65aa6b29aead75f63d503c046201d32c43de 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.21 2004/08/01 20:30:48 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.22 2004/08/02 01:30:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -168,7 +168,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
 			/* schemas should contain only utility stmts */
 			Assert(querytree->commandType == CMD_UTILITY);
 			/* do this step */
-			ProcessUtility(querytree->utilityStmt, None_Receiver, NULL);
+			ProcessUtility(querytree->utilityStmt, NULL, None_Receiver, NULL);
 			/* make sure later steps can see the object created here */
 			CommandCounterIncrement();
 		}
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index e4362c38f58437e90aa13057d528b119fccfc967..6ac61d3c5beb12389149bdea69e9a33ef7607fdf 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.164 2004/06/09 19:08:14 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.165 2004/08/02 01:30:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -589,56 +589,18 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
 	else
 	{
 		/*
-		 * All other parameter types must be sought in
-		 * ecxt_param_list_info. NOTE: The last entry in the param array
-		 * is always an entry with kind == PARAM_INVALID.
+		 * All other parameter types must be sought in ecxt_param_list_info.
 		 */
-		ParamListInfo paramList = econtext->ecxt_param_list_info;
-		char	   *thisParamName = expression->paramname;
-		bool		matchFound = false;
-
-		if (paramList != NULL)
-		{
-			while (paramList->kind != PARAM_INVALID && !matchFound)
-			{
-				if (thisParamKind == paramList->kind)
-				{
-					switch (thisParamKind)
-					{
-						case PARAM_NAMED:
-							if (strcmp(paramList->name, thisParamName) == 0)
-								matchFound = true;
-							break;
-						case PARAM_NUM:
-							if (paramList->id == thisParamId)
-								matchFound = true;
-							break;
-						default:
-							elog(ERROR, "unrecognized paramkind: %d",
-								 thisParamKind);
-					}
-				}
-				if (!matchFound)
-					paramList++;
-			}					/* while */
-		}						/* if */
-
-		if (!matchFound)
-		{
-			if (thisParamKind == PARAM_NAMED)
-				ereport(ERROR,
-						(errcode(ERRCODE_UNDEFINED_OBJECT),
-						 errmsg("no value found for parameter \"%s\"",
-								thisParamName)));
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_UNDEFINED_OBJECT),
-						 errmsg("no value found for parameter %d",
-								thisParamId)));
-		}
-
-		*isNull = paramList->isnull;
-		return paramList->value;
+		ParamListInfo paramInfo;
+
+		paramInfo = lookupParam(econtext->ecxt_param_list_info,
+								thisParamKind,
+								expression->paramname,
+								thisParamId,
+								false);
+		Assert(paramInfo->ptype == expression->paramtype);
+		*isNull = paramInfo->isnull;
+		return paramInfo->value;
 	}
 }
 
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 0073f8f55c16082a2cec328ef114de8e0f86a67e..cfcccb6169e309682240d986413a8128845f1a41 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.83 2004/07/15 13:51:38 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.84 2004/08/02 01:30:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,6 +58,7 @@ typedef struct local_es
  */
 typedef struct
 {
+	Oid        *argtypes;       /* resolved types of arguments */
 	Oid			rettype;		/* actual return type */
 	int			typlen;			/* length of the return type */
 	bool		typbyval;		/* true if return type is pass by value */
@@ -223,6 +224,7 @@ init_sql_fcache(FmgrInfo *finfo)
 	}
 	else
 		argOidVect = NULL;
+	fcache->argtypes = argOidVect;
 
 	tmp = SysCacheGetAttr(PROCOID,
 						  procedureTuple,
@@ -283,7 +285,8 @@ postquel_getnext(execution_state *es)
 
 	if (es->qd->operation == CMD_UTILITY)
 	{
-		ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->dest, NULL);
+		ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->params,
+					   es->qd->dest, NULL);
 		return NULL;
 	}
 
@@ -332,6 +335,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
 		{
 			paramLI[i].kind = PARAM_NUM;
 			paramLI[i].id = i + 1;
+			paramLI[i].ptype = fcache->argtypes[i];
 			paramLI[i].value = fcinfo->arg[i];
 			paramLI[i].isnull = fcinfo->argnull[i];
 		}
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 7840f5f787afc86854c829bf87f414da83455f73..33379d5222246c7f2ad64ccf5a8f77692dcfa7e7 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.122 2004/07/31 20:55:41 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.123 2004/08/02 01:30:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -820,6 +820,7 @@ SPI_cursor_open(const char *name, void *plan, Datum *Values, const char *Nulls)
 		{
 			paramLI[k].kind = PARAM_NUM;
 			paramLI[k].id = k + 1;
+			paramLI[k].ptype = spiplan->argtypes[k];
 			paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
 			if (paramLI[k].isnull)
 			{
@@ -1251,7 +1252,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
 				res = SPI_OK_UTILITY;
 				if (plan == NULL)
 				{
-					ProcessUtility(queryTree->utilityStmt, dest, NULL);
+					ProcessUtility(queryTree->utilityStmt, NULL, dest, NULL);
 					CommandCounterIncrement();
 				}
 			}
@@ -1319,6 +1320,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
 		{
 			paramLI[k].kind = PARAM_NUM;
 			paramLI[k].id = k + 1;
+			paramLI[k].ptype = plan->argtypes[k];
 			paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
 			paramLI[k].value = Values[k];
 		}
@@ -1366,7 +1368,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
 			dest = CreateDestReceiver(queryTree->canSetTag ? SPI : None, NULL);
 			if (queryTree->commandType == CMD_UTILITY)
 			{
-				ProcessUtility(queryTree->utilityStmt, dest, NULL);
+				ProcessUtility(queryTree->utilityStmt, paramLI, dest, NULL);
 				res = SPI_OK_UTILITY;
 				CommandCounterIncrement();
 			}
diff --git a/src/backend/nodes/Makefile b/src/backend/nodes/Makefile
index a4c19201bb2f9b92ec99299875136c6f75b70012..86f533e7a0e4c3c1a7d0b819f9f3b04867154023 100644
--- a/src/backend/nodes/Makefile
+++ b/src/backend/nodes/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for backend/nodes
 #
 # IDENTIFICATION
-#    $PostgreSQL: pgsql/src/backend/nodes/Makefile,v 1.16 2004/01/07 18:43:36 neilc Exp $
+#    $PostgreSQL: pgsql/src/backend/nodes/Makefile,v 1.17 2004/08/02 01:30:42 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -14,7 +14,7 @@ include $(top_builddir)/src/Makefile.global
 
 OBJS = nodeFuncs.o nodes.o list.o bitmapset.o \
        copyfuncs.o equalfuncs.o makefuncs.o \
-       outfuncs.o readfuncs.o print.o read.o value.o
+       outfuncs.o readfuncs.o print.o read.o params.o value.o
 
 all: SUBSYS.o
 
diff --git a/src/backend/nodes/params.c b/src/backend/nodes/params.c
new file mode 100644
index 0000000000000000000000000000000000000000..43bc40b9e1c6bbeb6c00ad0925c5be94422c98b9
--- /dev/null
+++ b/src/backend/nodes/params.c
@@ -0,0 +1,122 @@
+/*-------------------------------------------------------------------------
+ *
+ * params.c
+ *	  Support functions for plan parameter lists.
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  $PostgreSQL: pgsql/src/backend/nodes/params.c,v 1.1 2004/08/02 01:30:42 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "nodes/params.h"
+#include "utils/datum.h"
+#include "utils/lsyscache.h"
+
+
+/*
+ * Copy a ParamList.
+ *
+ * The result is allocated in CurrentMemoryContext.
+ */
+ParamListInfo
+copyParamList(ParamListInfo from)
+{
+	ParamListInfo retval;
+	int i, size;
+
+	if (from == NULL)
+		return NULL;
+
+	size = 0;
+	while (from[size].kind != PARAM_INVALID)
+		size++;
+
+	retval = (ParamListInfo) palloc0((size + 1) * sizeof(ParamListInfoData));
+
+	for (i = 0; i < size; i++) {
+		/* copy metadata */
+		retval[i].kind = from[i].kind;
+		if (from[i].kind == PARAM_NAMED)
+			retval[i].name = pstrdup(from[i].name);
+		retval[i].id = from[i].id;
+		retval[i].ptype = from[i].ptype;
+
+		/* copy value */
+		retval[i].isnull = from[i].isnull;
+		if (from[i].isnull)
+		{
+			retval[i].value = from[i].value; /* nulls just copy */
+		}
+		else
+		{
+			int16 typLen;
+			bool  typByVal;
+
+			get_typlenbyval(from[i].ptype, &typLen, &typByVal);
+			retval[i].value = datumCopy(from[i].value, typByVal, typLen);
+		}
+	}
+
+	retval[size].kind = PARAM_INVALID;
+
+	return retval;
+}
+
+/*
+ * Search a ParamList for a given parameter.
+ *
+ * On success, returns a pointer to the parameter's entry.
+ * On failure, returns NULL if noError is true, else ereports the error.
+ */
+ParamListInfo
+lookupParam(ParamListInfo paramList, int thisParamKind,
+			const char *thisParamName, AttrNumber thisParamId,
+			bool noError)
+{
+	if (paramList != NULL)
+	{
+		while (paramList->kind != PARAM_INVALID)
+		{
+			if (thisParamKind == paramList->kind)
+			{
+				switch (thisParamKind)
+				{
+					case PARAM_NAMED:
+						if (strcmp(paramList->name, thisParamName) == 0)
+							return paramList;
+						break;
+					case PARAM_NUM:
+						if (paramList->id == thisParamId)
+							return paramList;
+						break;
+					default:
+						elog(ERROR, "unrecognized paramkind: %d",
+							 thisParamKind);
+				}
+			}
+			paramList++;
+		}
+	}
+
+	if (!noError)
+	{
+		if (thisParamKind == PARAM_NAMED)
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_OBJECT),
+					 errmsg("no value found for parameter \"%s\"",
+							thisParamName)));
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_OBJECT),
+					 errmsg("no value found for parameter %d",
+							thisParamId)));
+	}
+
+	return NULL;
+}
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index e7088d2b7610bea2b450f3e5079497b1b339fba1..68d2529889e86d7c884acb63c4ed8fdcb1a3a0e7 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.176 2004/06/11 01:08:54 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.177 2004/08/02 01:30:43 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -1120,39 +1120,20 @@ eval_const_expressions_mutator(Node *node,
 	if (IsA(node, Param))
 	{
 		Param	   *param = (Param *) node;
-		int			thisParamKind = param->paramkind;
 
 		/* OK to try to substitute value? */
-		if (context->estimate && thisParamKind != PARAM_EXEC &&
+		if (context->estimate && param->paramkind != PARAM_EXEC &&
 			PlannerBoundParamList != NULL)
 		{
-			ParamListInfo paramList = PlannerBoundParamList;
-			bool		matchFound = false;
+			ParamListInfo paramInfo;
 
 			/* Search to see if we've been given a value for this Param */
-			while (paramList->kind != PARAM_INVALID && !matchFound)
-			{
-				if (thisParamKind == paramList->kind)
-				{
-					switch (thisParamKind)
-					{
-						case PARAM_NAMED:
-							if (strcmp(paramList->name, param->paramname) == 0)
-								matchFound = true;
-							break;
-						case PARAM_NUM:
-							if (paramList->id == param->paramid)
-								matchFound = true;
-							break;
-						default:
-							elog(ERROR, "unrecognized paramkind: %d",
-								 thisParamKind);
-					}
-				}
-				if (!matchFound)
-					paramList++;
-			}
-			if (matchFound)
+			paramInfo = lookupParam(PlannerBoundParamList,
+									param->paramkind,
+									param->paramname,
+									param->paramid,
+									true);
+			if (paramInfo)
 			{
 				/*
 				 * Found it, so return a Const representing the param value.
@@ -1164,11 +1145,12 @@ eval_const_expressions_mutator(Node *node,
 				int16		typLen;
 				bool		typByVal;
 
+				Assert(paramInfo->ptype == param->paramtype);
 				get_typlenbyval(param->paramtype, &typLen, &typByVal);
 				return (Node *) makeConst(param->paramtype,
 										  (int) typLen,
-										  paramList->value,
-										  paramList->isnull,
+										  paramInfo->value,
+										  paramInfo->isnull,
 										  typByVal);
 			}
 		}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 89ee40a53215141c806934442709303a9242570a..bfbe0a53c5c5caee1cfae7e6e99dd365842f2405 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.427 2004/07/31 00:45:36 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.428 2004/08/02 01:30:44 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -1488,6 +1488,7 @@ exec_bind_message(StringInfo input_message)
 
 			params[i].kind = PARAM_NUM;
 			params[i].id = i + 1;
+			params[i].ptype = ptype;
 			params[i].isnull = isNull;
 
 			i++;
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 8973cca6d2673ab9d9db61680d36ddd7a61d5917..588523f84936843e61b23884a19b14df384e1c1c 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.82 2004/07/31 00:45:36 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.83 2004/08/02 01:30:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -833,14 +833,14 @@ PortalRunUtility(Portal portal, Query *query,
 	if (query->canSetTag)
 	{
 		/* utility statement can override default tag string */
-		ProcessUtility(utilityStmt, dest, completionTag);
+		ProcessUtility(utilityStmt, portal->portalParams, dest, completionTag);
 		if (completionTag && completionTag[0] == '\0' && portal->commandTag)
 			strcpy(completionTag, portal->commandTag);	/* use the default */
 	}
 	else
 	{
 		/* utility added by rewrite cannot set tag */
-		ProcessUtility(utilityStmt, dest, NULL);
+		ProcessUtility(utilityStmt, portal->portalParams, dest, NULL);
 	}
 
 	/* Some utility statements may change context on us */
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index d8d718a18239ff17f7d268d1720e43f993d04744..b9c50d7d81c72d03544ac79e7d6a29fc4f465ee7 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.222 2004/08/01 17:32:18 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.223 2004/08/02 01:30:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -294,6 +294,7 @@ check_xact_readonly(Node *parsetree)
  *		general utility function invoker
  *
  *	parsetree: the parse tree for the utility statement
+ *	params: parameters to use during execution (currently only used by DECLARE)
  *	dest: where to send results
  *	completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
  *		in which to store a command completion status string.
@@ -305,6 +306,7 @@ check_xact_readonly(Node *parsetree)
  */
 void
 ProcessUtility(Node *parsetree,
+			   ParamListInfo params,
 			   DestReceiver *dest,
 			   char *completionTag)
 {
@@ -406,7 +408,7 @@ ProcessUtility(Node *parsetree,
 			 * Portal (cursor) manipulation
 			 */
 		case T_DeclareCursorStmt:
-			PerformCursorOpen((DeclareCursorStmt *) parsetree);
+			PerformCursorOpen((DeclareCursorStmt *) parsetree, params);
 			break;
 
 		case T_ClosePortalStmt:
diff --git a/src/include/commands/portalcmds.h b/src/include/commands/portalcmds.h
index 60e7d524d29c5c88e890c8b60b2c1d7688f7b9de..b16ef2338463b0d4aad8ccc983c0d1966d629327 100644
--- a/src/include/commands/portalcmds.h
+++ b/src/include/commands/portalcmds.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/portalcmds.h,v 1.15 2004/07/17 03:30:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/portalcmds.h,v 1.16 2004/08/02 01:30:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,7 +17,7 @@
 #include "utils/portal.h"
 
 
-extern void PerformCursorOpen(DeclareCursorStmt *stmt);
+extern void PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params);
 
 extern void PerformPortalFetch(FetchStmt *stmt, DestReceiver *dest,
 				   char *completionTag);
diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h
index e22ff27a3b7967ac798abd6bd4a0b4fcbbf85a08..d4acbe2699e527fb2eca78cfceac90b58810a764 100644
--- a/src/include/nodes/params.h
+++ b/src/include/nodes/params.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/params.h,v 1.24 2003/11/29 22:41:06 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/params.h,v 1.25 2004/08/02 01:30:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,7 +56,8 @@
  *
  *		kind   : the kind of parameter (PARAM_NAMED or PARAM_NUM)
  *		name   : the parameter name (valid if kind == PARAM_NAMED)
- *		id	   : the parameter id (valid if kind == PARAM_NUM)
+ *		id     : the parameter id (valid if kind == PARAM_NUM)
+ *		ptype  : the type of the parameter value
  *		isnull : true if the value is null (if so 'value' is undefined)
  *		value  : the value that has to be substituted in the place
  *				 of the parameter.
@@ -72,6 +73,7 @@ typedef struct ParamListInfoData
 	int			kind;
 	char	   *name;
 	AttrNumber	id;
+	Oid			ptype;
 	bool		isnull;
 	Datum		value;
 } ParamListInfoData;
@@ -103,4 +105,11 @@ typedef struct ParamExecData
 	bool		isnull;
 } ParamExecData;
 
+
+/* Functions found in src/backend/nodes/params.c */
+extern ParamListInfo copyParamList(ParamListInfo from);
+extern ParamListInfo lookupParam(ParamListInfo paramList, int thisParamKind,
+								 const char *thisParamName, AttrNumber thisParamId,
+								 bool noError);
+
 #endif   /* PARAMS_H */
diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h
index 59a9a8133d1545d423e7ab134bca96adcdb4cd8e..a5398e0dedae80c63699cfcf75228b69d5389d07 100644
--- a/src/include/tcop/utility.h
+++ b/src/include/tcop/utility.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/tcop/utility.h,v 1.21 2003/11/29 22:41:14 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/tcop/utility.h,v 1.22 2004/08/02 01:30:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,8 +16,9 @@
 
 #include "executor/execdesc.h"
 
-extern void ProcessUtility(Node *parsetree, DestReceiver *dest,
-			   char *completionTag);
+
+extern void ProcessUtility(Node *parsetree, ParamListInfo params,
+						   DestReceiver *dest, char *completionTag);
 
 extern bool UtilityReturnsTuples(Node *parsetree);
 
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index f075b96c0fc6af539c92578da358a2f4121c49eb..124d3c4bad29207ebf71e8c1c8f607122e1a4c47 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.112 2004/08/01 17:32:21 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.113 2004/08/02 01:30:49 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -3582,7 +3582,7 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
 	 * need to have more than one active param list.
 	 */
 	paramLI = (ParamListInfo)
-		MemoryContextAlloc(econtext->ecxt_per_tuple_memory,
+		MemoryContextAllocZero(econtext->ecxt_per_tuple_memory,
 						(expr->nparams + 1) * sizeof(ParamListInfoData));
 
 	/*
@@ -3591,12 +3591,11 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
 	for (i = 0; i < expr->nparams; i++)
 	{
 		PLpgSQL_datum *datum = estate->datums[expr->params[i]];
-		Oid			paramtypeid;
 
 		paramLI[i].kind = PARAM_NUM;
 		paramLI[i].id = i + 1;
 		exec_eval_datum(estate, datum, expr->plan_argtypes[i],
-						&paramtypeid,
+						&paramLI[i].ptype,
 						&paramLI[i].value, &paramLI[i].isnull);
 	}
 	paramLI[i].kind = PARAM_INVALID;
diff --git a/src/test/regress/expected/portals.out b/src/test/regress/expected/portals.out
index b8f834189823e1462dee43f512058b0744c8854b..a46a14ce80ce8ce7fc2ea28a9c045f97ebaaf273 100644
--- a/src/test/regress/expected/portals.out
+++ b/src/test/regress/expected/portals.out
@@ -738,3 +738,38 @@ ROLLBACK;
 -- should fail
 FETCH FROM foo26;
 ERROR:  cursor "foo26" does not exist
+--
+-- Parameterized DECLARE needs to insert param values into the cursor portal
+--
+BEGIN;
+CREATE FUNCTION declares_cursor(text)
+   RETURNS void
+   AS 'DECLARE c CURSOR FOR SELECT stringu1 FROM tenk1 WHERE stringu1 LIKE $1;'
+   LANGUAGE 'sql';
+SELECT declares_cursor('AB%');
+ declares_cursor 
+-----------------
+ 
+(1 row)
+
+FETCH ALL FROM c;
+ stringu1 
+----------
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+ ABAAAA
+(15 rows)
+
+ROLLBACK;
diff --git a/src/test/regress/sql/portals.sql b/src/test/regress/sql/portals.sql
index 807c847bc3c1da72e71f7836d079a44092ef4634..c7e29c378680f6dbf53e99841949b49537e04f6e 100644
--- a/src/test/regress/sql/portals.sql
+++ b/src/test/regress/sql/portals.sql
@@ -218,3 +218,20 @@ ROLLBACK;
 
 -- should fail
 FETCH FROM foo26;
+
+--
+-- Parameterized DECLARE needs to insert param values into the cursor portal
+--
+
+BEGIN;
+
+CREATE FUNCTION declares_cursor(text)
+   RETURNS void
+   AS 'DECLARE c CURSOR FOR SELECT stringu1 FROM tenk1 WHERE stringu1 LIKE $1;'
+   LANGUAGE 'sql';
+
+SELECT declares_cursor('AB%');
+
+FETCH ALL FROM c;
+
+ROLLBACK;