diff --git a/doc/src/sgml/ref/deallocate.sgml b/doc/src/sgml/ref/deallocate.sgml
index 9481708dd0660ed68281965f033f7d88bd831ed4..1baff4acfbe9e89d67273c3d24e3d15e99ba37da 100644
--- a/doc/src/sgml/ref/deallocate.sgml
+++ b/doc/src/sgml/ref/deallocate.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/deallocate.sgml,v 1.7 2004/09/30 04:23:27 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/deallocate.sgml,v 1.8 2006/01/15 22:18:46 neilc Exp $
 PostgreSQL documentation
 -->
 
@@ -25,7 +25,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-DEALLOCATE [ PREPARE ] <replaceable class="parameter">plan_name</replaceable>
+DEALLOCATE [ PREPARE ] <replaceable class="parameter">name</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -58,7 +58,7 @@ DEALLOCATE [ PREPARE ] <replaceable class="parameter">plan_name</replaceable>
    </varlistentry>
 
    <varlistentry>
-    <term><replaceable class="parameter">plan_name</replaceable></term>
+    <term><replaceable class="parameter">name</replaceable></term>
     <listitem>
      <para>
       The name of the prepared statement to deallocate.
diff --git a/doc/src/sgml/ref/execute.sgml b/doc/src/sgml/ref/execute.sgml
index 628617c5084a5a96db2dd083234cac79a516861f..68a240e3831979c26a64d45f6629a6b80ba114a3 100644
--- a/doc/src/sgml/ref/execute.sgml
+++ b/doc/src/sgml/ref/execute.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/execute.sgml,v 1.12 2004/09/30 04:23:27 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/execute.sgml,v 1.13 2006/01/15 22:18:46 neilc Exp $
 PostgreSQL documentation
 -->
 
@@ -25,7 +25,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-EXECUTE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable class="PARAMETER">parameter</replaceable> [, ...] ) ]
+EXECUTE <replaceable class="PARAMETER">name</replaceable> [ (<replaceable class="PARAMETER">parameter</replaceable> [, ...] ) ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -60,7 +60,7 @@ EXECUTE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable c
 
   <variablelist>
    <varlistentry>
-    <term><replaceable class="PARAMETER">plan_name</replaceable></term>
+    <term><replaceable class="PARAMETER">name</replaceable></term>
     <listitem>
      <para>
       The name of the prepared statement to execute.
@@ -73,10 +73,9 @@ EXECUTE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable c
     <listitem>
      <para>
       The actual value of a parameter to the prepared statement.  This
-      must be an expression yielding a value of a type compatible with
-      the data type specified for this parameter position in the
-      <command>PREPARE</command> command that created the prepared
-      statement.
+      must be an expression yielding a value that is compatible with
+      the data type of this parameter, as was determined when the
+      prepared statement was created.
      </para>
     </listitem>
    </varlistentry>
diff --git a/doc/src/sgml/ref/prepare.sgml b/doc/src/sgml/ref/prepare.sgml
index 51c39851173c93233e09461c383143e4ca3e477c..738b6320a4b27dea17b934d002f1a6e16c9d9948 100644
--- a/doc/src/sgml/ref/prepare.sgml
+++ b/doc/src/sgml/ref/prepare.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/prepare.sgml,v 1.17 2006/01/08 07:00:25 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/prepare.sgml,v 1.18 2006/01/15 22:18:46 neilc Exp $
 PostgreSQL documentation
 -->
 
@@ -25,7 +25,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-PREPARE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable class="PARAMETER">datatype</replaceable> [, ...] ) ] AS <replaceable class="PARAMETER">statement</replaceable>
+PREPARE <replaceable class="PARAMETER">name</replaceable> [ (<replaceable class="PARAMETER">datatype</replaceable> [, ...] ) ] AS <replaceable class="PARAMETER">statement</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -45,13 +45,15 @@ PREPARE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable c
 
   <para>
    Prepared statements can take parameters: values that are
-   substituted into the statement when it is executed. To include
-   parameters in a prepared statement, supply a list of data types in
-   the <command>PREPARE</command> statement, and, in the statement to
-   be prepared itself, refer to the parameters by position using
-   <literal>$1</literal>, <literal>$2</literal>, etc. When executing
-   the statement, specify the actual values for these parameters in
-   the <command>EXECUTE</command> statement.  Refer to <xref
+   substituted into the statement when it is executed. When creating
+   the prepared statement, refer to parameters by position, using
+   <literal>$1</>, <literal>$2</>, etc. A corresponding list of
+   parameter data types can optionally be specified. When a
+   parameter's data type is not specified or is declared as
+   <literal>unknown</literal>, the type is inferred from the context
+   in which the parameter is used (if possible). When executing the
+   statement, specify the actual values for these parameters in the
+   <command>EXECUTE</command> statement.  Refer to <xref
    linkend="sql-execute" endterm="sql-execute-title"> for more
    information about that.
   </para>
@@ -84,7 +86,7 @@ PREPARE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable c
 
   <variablelist>
    <varlistentry>
-    <term><replaceable class="PARAMETER">plan_name</replaceable></term>
+    <term><replaceable class="PARAMETER">name</replaceable></term>
     <listitem>
      <para>
       An arbitrary name given to this particular prepared
@@ -99,8 +101,11 @@ PREPARE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable c
     <term><replaceable class="PARAMETER">datatype</replaceable></term>
     <listitem>
      <para>
-      The data type of a parameter to the prepared statement.  To
-      refer to the parameters in the prepared statement itself, use
+      The data type of a parameter to the prepared statement.  If the
+      data type of a particular parameter is unspecified or is
+      specified as <literal>unknown</literal>, it will be inferred
+      from the context in which the parameter is used. To refer to the
+      parameters in the prepared statement itself, use
       <literal>$1</literal>, <literal>$2</literal>, etc.
      </para>
     </listitem>
@@ -155,8 +160,8 @@ PREPARE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable c
  <refsect1 id="sql-prepare-examples">
   <title id="sql-prepare-examples-title">Examples</title>
   <para>
-   Create a prepared query for an <command>INSERT</command> statement,
-   and then execute it:
+   Create a prepared statement for an <command>INSERT</command>
+   statement, and then execute it:
 <programlisting>
 PREPARE fooplan (int, text, bool, numeric) AS
     INSERT INTO foo VALUES($1, $2, $3, $4);
@@ -165,14 +170,17 @@ EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00);
   </para>
 
   <para>
-   Create a prepared query for a <command>SELECT</command> statement,
-   and then execute it:
+   Create a prepared statement for a <command>SELECT</command>
+   statement, and then execute it:
 <programlisting>
-PREPARE usrrptplan (int, date) AS
+PREPARE usrrptplan (int) AS
     SELECT * FROM users u, logs l WHERE u.usrid=$1 AND u.usrid=l.usrid
     AND l.date = $2;
 EXECUTE usrrptplan(1, current_date);
 </programlisting>
+
+   Note that the data type of the second parameter is not specified,
+   so it is inferred from the context in which <literal>$2</> is used.
   </para>
  </refsect1>
  <refsect1>
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index a8e151088235262da440a63721b3acad29f188f6..abfb0fbf30347a71ed235eaac33d9c2c9240d79c 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.327 2005/11/22 18:17:15 momjian Exp $
+ *	$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.328 2006/01/15 22:18:46 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2584,10 +2584,11 @@ static Query *
 transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
 {
 	Query	   *result = makeNode(Query);
-	List	   *argtype_oids = NIL;		/* argtype OIDs in a list */
+	List	   *argtype_oids;		/* argtype OIDs in a list */
 	Oid		   *argtoids = NULL;	/* and as an array */
 	int			nargs;
 	List	   *queries;
+	int			i;
 
 	result->commandType = CMD_UTILITY;
 	result->utilityStmt = (Node *) stmt;
@@ -2598,27 +2599,27 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
 	if (nargs)
 	{
 		ListCell   *l;
-		int			i = 0;
 
 		argtoids = (Oid *) palloc(nargs * sizeof(Oid));
+		i = 0;
 
 		foreach(l, stmt->argtypes)
 		{
 			TypeName   *tn = lfirst(l);
 			Oid			toid = typenameTypeId(tn);
 
-			argtype_oids = lappend_oid(argtype_oids, toid);
 			argtoids[i++] = toid;
 		}
 	}
 
-	stmt->argtype_oids = argtype_oids;
-
 	/*
-	 * Analyze the statement using these parameter types (any parameters
-	 * passed in from above us will not be visible to it).
+	 * Analyze the statement using these parameter types (any
+	 * parameters passed in from above us will not be visible to it),
+	 * allowing information about unknown parameters to be deduced
+	 * from context.
 	 */
-	queries = parse_analyze((Node *) stmt->query, argtoids, nargs);
+	queries = parse_analyze_varparams((Node *) stmt->query,
+									  &argtoids, &nargs);
 
 	/*
 	 * Shouldn't get any extra statements, since grammar only allows
@@ -2627,8 +2628,26 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
 	if (list_length(queries) != 1)
 		elog(ERROR, "unexpected extra stuff in prepared statement");
 
-	stmt->query = linitial(queries);
+	/*
+	 * Check that all parameter types were determined, and convert the
+	 * array of OIDs into a list for storage.
+	 */
+	argtype_oids = NIL;
+	for (i = 0; i < nargs; i++)
+	{
+		Oid			argtype = argtoids[i];
 
+		if (argtype == InvalidOid || argtype == UNKNOWNOID)
+			ereport(ERROR,
+					(errcode(ERRCODE_INDETERMINATE_DATATYPE),
+					 errmsg("could not determine data type of parameter $%d",
+							i + 1)));
+
+		argtype_oids = lappend_oid(argtype_oids, argtype);
+	}
+
+	stmt->argtype_oids = argtype_oids;
+	stmt->query = linitial(queries);
 	return result;
 }
 
diff --git a/src/test/regress/expected/prepare.out b/src/test/regress/expected/prepare.out
index 54616199b60e889f23c2b711f877125dceb336ec..f7d1a7581497ffb3dc86cd402c8f97ffada81199 100644
--- a/src/test/regress/expected/prepare.out
+++ b/src/test/regress/expected/prepare.out
@@ -58,14 +58,6 @@ SELECT name, statement, parameter_types FROM pg_prepared_statements;
 PREPARE q2(text) AS
 	SELECT datname, datistemplate, datallowconn
 	FROM pg_database WHERE datname = $1;
-SELECT name, statement, parameter_types FROM pg_prepared_statements;
- name |                                               statement                                                | parameter_types 
-------+--------------------------------------------------------------------------------------------------------+-----------------
- q2   | PREPARE q2(text) AS
-	SELECT datname, datistemplate, datallowconn
-	FROM pg_database WHERE datname = $1; | {25}
-(1 row)
-
 EXECUTE q2('regression');
   datname   | datistemplate | datallowconn 
 ------------+---------------+--------------
@@ -75,17 +67,6 @@ EXECUTE q2('regression');
 PREPARE q3(text, int, float, boolean, oid, smallint) AS
 	SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR
 	ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int);
-SELECT name, statement, parameter_types FROM pg_prepared_statements;
- name |                                                                                    statement                                                                                    |   parameter_types    
-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------
- q2   | PREPARE q2(text) AS
-	SELECT datname, datistemplate, datallowconn
-	FROM pg_database WHERE datname = $1;                                                                          | {25}
- q3   | PREPARE q3(text, int, float, boolean, oid, smallint) AS
-	SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR
-	ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int); | {25,23,701,16,26,21}
-(2 rows)
-
 EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 500::oid, 4::bigint);
  unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 
 ---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------
@@ -160,3 +141,26 @@ SELECT * FROM q5_prep_results;
     5905 |    9537 |   1 |    1 |   5 |      5 |       5 |      905 |        1905 |       905 |     5905 |  10 |   11 | DTAAAA   | VCOAAA   | HHHHxx
 (16 rows)
 
+-- unknown or unspecified parameter types: should succeed
+PREPARE q6 AS
+    SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;
+PREPARE q7(unknown) AS
+    SELECT * FROM road WHERE thepath = $1;
+SELECT name, statement, parameter_types FROM pg_prepared_statements
+    ORDER BY name;
+ name |                                                                                    statement                                                                                    |   parameter_types    
+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------
+ q2   | PREPARE q2(text) AS
+	SELECT datname, datistemplate, datallowconn
+	FROM pg_database WHERE datname = $1;                                                                          | {25}
+ q3   | PREPARE q3(text, int, float, boolean, oid, smallint) AS
+	SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR
+	ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int); | {25,23,701,16,26,21}
+ q5   | PREPARE q5(int, text) AS
+	SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2;                                                                                              | {23,25}
+ q6   | PREPARE q6 AS
+    SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;                                                                                                     | {23,19}
+ q7   | PREPARE q7(unknown) AS
+    SELECT * FROM road WHERE thepath = $1;                                                                                                               | {602}
+(5 rows)
+
diff --git a/src/test/regress/sql/prepare.sql b/src/test/regress/sql/prepare.sql
index 95db2a0910f8e60b4d171f46710a4df36164ed18..d42b7a0879f1a7e9ac5710dfeece83bfe8426d6f 100644
--- a/src/test/regress/sql/prepare.sql
+++ b/src/test/regress/sql/prepare.sql
@@ -34,16 +34,12 @@ PREPARE q2(text) AS
 	SELECT datname, datistemplate, datallowconn
 	FROM pg_database WHERE datname = $1;
 
-SELECT name, statement, parameter_types FROM pg_prepared_statements;
-
 EXECUTE q2('regression');
 
 PREPARE q3(text, int, float, boolean, oid, smallint) AS
 	SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR
 	ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int);
 
-SELECT name, statement, parameter_types FROM pg_prepared_statements;
-
 EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 500::oid, 4::bigint);
 
 -- too few params
@@ -63,3 +59,12 @@ PREPARE q5(int, text) AS
 	SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2;
 CREATE TEMPORARY TABLE q5_prep_results AS EXECUTE q5(200, 'DTAAAA');
 SELECT * FROM q5_prep_results;
+
+-- unknown or unspecified parameter types: should succeed
+PREPARE q6 AS
+    SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;
+PREPARE q7(unknown) AS
+    SELECT * FROM road WHERE thepath = $1;
+
+SELECT name, statement, parameter_types FROM pg_prepared_statements
+    ORDER BY name;