diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 5dfeca1953c3fa5ab793c1232a7191b114ceb342..a4cdc2501876f0255c6b458e5ba9d7273631fa1d 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.99 2006/01/16 20:48:49 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.100 2006/02/19 00:04:26 neilc Exp $
 PostgreSQL documentation
 -->
 
@@ -580,9 +580,10 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
         <term><literal>DELETE ROWS</literal></term>
         <listitem>
          <para>
-          All rows in the temporary table will be deleted at the
-          end of each transaction block.  Essentially, an automatic
-          <xref linkend="sql-truncate"> is done at each commit.
+          All rows in the temporary table will be deleted at the end
+          of each transaction block.  Essentially, an automatic <xref
+          linkend="sql-truncate" endterm="sql-truncate-title"> is done
+          at each commit.
          </para>
         </listitem>
        </varlistentry>
diff --git a/doc/src/sgml/ref/create_table_as.sgml b/doc/src/sgml/ref/create_table_as.sgml
index 201188d99cc67a6d4bf82716016455c015f1f317..7e7fa7b6731c5543e4fd78ee93645e276a6d023e 100644
--- a/doc/src/sgml/ref/create_table_as.sgml
+++ b/doc/src/sgml/ref/create_table_as.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.31 2005/11/01 21:09:50 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.32 2006/02/19 00:04:26 neilc Exp $
 PostgreSQL documentation
 -->
 
@@ -21,7 +21,10 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name</replaceable>
-    [ (<replaceable>column_name</replaceable> [, ...] ) ] [ [ WITH | WITHOUT ] OIDS ]
+    [ (<replaceable>column_name</replaceable> [, ...] ) ]
+    [ WITH OIDS | WITHOUT OIDS ]
+    [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
+    [ TABLESPACE <replaceable class="PARAMETER">tablespace</replaceable> ]
     AS <replaceable>query</replaceable>
 </synopsis>
  </refsynopsisdiv>
@@ -113,6 +116,65 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name
      </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>ON COMMIT</literal></term>
+    <listitem>
+     <para>
+      The behavior of temporary tables at the end of a transaction
+      block can be controlled using <literal>ON COMMIT</literal>.
+      The three options are:
+
+      <variablelist>
+       <varlistentry>
+        <term><literal>PRESERVE ROWS</literal></term>
+        <listitem>
+         <para>
+          No special action is taken at the ends of transactions.
+          This is the default behavior.
+         </para>
+        </listitem>
+       </varlistentry>
+
+       <varlistentry>
+        <term><literal>DELETE ROWS</literal></term>
+        <listitem>
+         <para>
+          All rows in the temporary table will be deleted at the end
+          of each transaction block.  Essentially, an automatic <xref
+          linkend="sql-truncate" endterm="sql-truncate-title"> is done
+          at each commit.
+         </para>
+        </listitem>
+       </varlistentry>
+
+       <varlistentry>
+        <term><literal>DROP</literal></term>
+        <listitem>
+         <para>
+          The temporary table will be dropped at the end of the current
+          transaction block.
+         </para>
+        </listitem>
+       </varlistentry>
+      </variablelist>
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>TABLESPACE <replaceable class="PARAMETER">tablespace</replaceable></literal></term>
+    <listitem>
+     <para>
+      The <replaceable class="PARAMETER">tablespace</replaceable> is the name
+      of the tablespace in which the new table is to be created.
+      If not specified,
+      <xref linkend="guc-default-tablespace"> is used, or the database's
+      default tablespace if <varname>default_tablespace</> is an empty
+      string.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><replaceable>query</replaceable></term>
     <listitem>
@@ -168,6 +230,20 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name
 <programlisting>
 CREATE TABLE films_recent AS
   SELECT * FROM films WHERE date_prod &gt;= '2002-01-01';
+</programlisting>
+  </para>
+
+  <para>
+   Create a new temporary table that will be dropped at commit
+   <literal>films_recent</literal> with oids consisting of only
+   recent entries from the table <literal>films</literal> using a
+   prepared statement:
+
+<programlisting>
+PREPARE recentfilms(date) AS
+  SELECT * FROM films WHERE date_prod &gt; $1;
+CREATE TEMP TABLE films_recent WITH OIDS ON COMMIT DROP AS
+  EXECUTE recentfilms('2002-01-01');
 </programlisting>
   </para>
  </refsect1>
@@ -188,13 +264,6 @@ CREATE TABLE films_recent AS
      </para>
     </listitem>
 
-    <listitem>
-     <para>
-      The standard defines an <literal>ON COMMIT</literal> clause;
-      this is not currently implemented by <productname>PostgreSQL</>.
-     </para>
-    </listitem>
-
     <listitem>
      <para>
       The standard defines a <literal>WITH [ NO ] DATA</literal> clause;
@@ -219,6 +288,14 @@ CREATE TABLE films_recent AS
       for details.
      </para>
     </listitem>
+
+    <listitem>
+     <para>
+      The <productname>PostgreSQL</productname> concept of tablespaces is not
+      part of the standard.  Hence, the clause <literal>TABLESPACE</literal>
+      is an extension.
+     </para>
+    </listitem>
    </itemizedlist>
   </para>
  </refsect1>
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index f0afdbba3675d0cfbd7d7bfe99610d06be3e4821..4fd43d7f4966ec6e154d293ea930e7dc8545552a 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.47 2006/01/18 06:49:26 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.48 2006/02/19 00:04:26 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -196,6 +196,10 @@ ExecuteQuery(ExecuteStmt *stmt, ParamListInfo params,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 					 errmsg("prepared statement is not a SELECT")));
 		query->into = copyObject(stmt->into);
+		query->intoHasOids = stmt->into_has_oids;
+		query->intoOnCommit = stmt->into_on_commit;
+		if (stmt->into_tbl_space)
+			query->intoTableSpaceName = pstrdup(stmt->into_tbl_space);
 
 		MemoryContextSwitchTo(oldContext);
 	}
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index a0f9cfedd3f17d7f042e73382d3c01f886ba8d34..99c3bca0a9a8202342472d9585963acbc37cff45 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.265 2006/01/12 21:48:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.266 2006/02/19 00:04:26 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,6 +37,7 @@
 #include "catalog/heap.h"
 #include "catalog/namespace.h"
 #include "commands/tablecmds.h"
+#include "commands/tablespace.h"
 #include "commands/trigger.h"
 #include "executor/execdebug.h"
 #include "executor/execdefs.h"
@@ -730,10 +731,19 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
 	{
 		char	   *intoName;
 		Oid			namespaceId;
+		Oid			tablespaceId;
 		AclResult	aclresult;
 		Oid			intoRelationId;
 		TupleDesc	tupdesc;
 
+		/*
+		 * Check consistency of arguments
+		 */
+		if (parseTree->intoOnCommit != ONCOMMIT_NOOP && !parseTree->into->istemp)
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+					 errmsg("ON COMMIT can only be used on temporary tables")));
+
 		/*
 		 * find namespace to create in, check permissions
 		 */
@@ -746,6 +756,37 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
 			aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
 						   get_namespace_name(namespaceId));
 
+		/*
+		 * Select tablespace to use.  If not specified, use default_tablespace
+		 * (which may in turn default to database's default).
+		 */
+		if (parseTree->intoTableSpaceName)
+		{
+			tablespaceId = get_tablespace_oid(parseTree->intoTableSpaceName);
+			if (!OidIsValid(tablespaceId))
+				ereport(ERROR,
+						(errcode(ERRCODE_UNDEFINED_OBJECT),
+						 errmsg("tablespace \"%s\" does not exist",
+								parseTree->intoTableSpaceName)));
+		} else
+		{
+			tablespaceId = GetDefaultTablespace();
+			/* note InvalidOid is OK in this case */
+		}
+
+		/* Check permissions except when using the database's default */
+		if (OidIsValid(tablespaceId))
+		{
+			AclResult	aclresult;
+
+			aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
+											   ACL_CREATE);
+
+			if (aclresult != ACLCHECK_OK)
+				aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
+							   get_tablespace_name(tablespaceId));
+		}
+
 		/*
 		 * have to copy tupType to get rid of constraints
 		 */
@@ -753,7 +794,7 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
 
 		intoRelationId = heap_create_with_catalog(intoName,
 												  namespaceId,
-												  InvalidOid,
+												  tablespaceId,
 												  InvalidOid,
 												  GetUserId(),
 												  tupdesc,
@@ -761,7 +802,7 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
 												  false,
 												  true,
 												  0,
-												  ONCOMMIT_NOOP,
+												  parseTree->intoOnCommit,
 												  allowSystemTableMods);
 
 		FreeTupleDesc(tupdesc);
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 6578bf37afddcc48406cb32cf3e81639917878b7..91f06df039af84b22b444a4738caa8bfe30fc15b 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.326 2006/02/04 19:06:46 adunstan Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.327 2006/02/19 00:04:26 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1662,6 +1662,8 @@ _copyQuery(Query *from)
 	COPY_SCALAR_FIELD(resultRelation);
 	COPY_NODE_FIELD(into);
 	COPY_SCALAR_FIELD(intoHasOids);
+	COPY_SCALAR_FIELD(intoOnCommit);
+	COPY_STRING_FIELD(intoTableSpaceName);
 	COPY_SCALAR_FIELD(hasAggs);
 	COPY_SCALAR_FIELD(hasSubLinks);
 	COPY_NODE_FIELD(rtable);
@@ -1729,6 +1731,8 @@ _copySelectStmt(SelectStmt *from)
 	COPY_NODE_FIELD(into);
 	COPY_NODE_FIELD(intoColNames);
 	COPY_SCALAR_FIELD(intoHasOids);
+	COPY_SCALAR_FIELD(intoOnCommit);
+	COPY_STRING_FIELD(intoTableSpaceName);
 	COPY_NODE_FIELD(targetList);
 	COPY_NODE_FIELD(fromClause);
 	COPY_NODE_FIELD(whereClause);
@@ -2631,6 +2635,10 @@ _copyExecuteStmt(ExecuteStmt *from)
 
 	COPY_STRING_FIELD(name);
 	COPY_NODE_FIELD(into);
+	COPY_SCALAR_FIELD(into_contains_oids);
+	COPY_SCALAR_FIELD(into_has_oids);
+	COPY_SCALAR_FIELD(into_on_commit);
+	COPY_STRING_FIELD(into_tbl_space);
 	COPY_NODE_FIELD(params);
 
 	return newnode;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index a9fdc95f6bbbebd01d415114d7d3b12a85fc7246..9a2a5fd0d59b65633a234519887db3a74b64c8d4 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.262 2006/02/04 19:06:46 adunstan Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.263 2006/02/19 00:04:26 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -673,6 +673,8 @@ _equalQuery(Query *a, Query *b)
 	COMPARE_SCALAR_FIELD(resultRelation);
 	COMPARE_NODE_FIELD(into);
 	COMPARE_SCALAR_FIELD(intoHasOids);
+	COMPARE_SCALAR_FIELD(intoOnCommit);
+	COMPARE_STRING_FIELD(intoTableSpaceName);
 	COMPARE_SCALAR_FIELD(hasAggs);
 	COMPARE_SCALAR_FIELD(hasSubLinks);
 	COMPARE_NODE_FIELD(rtable);
@@ -732,6 +734,8 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b)
 	COMPARE_NODE_FIELD(into);
 	COMPARE_NODE_FIELD(intoColNames);
 	COMPARE_SCALAR_FIELD(intoHasOids);
+	COMPARE_SCALAR_FIELD(intoOnCommit);
+	COMPARE_STRING_FIELD(intoTableSpaceName);
 	COMPARE_NODE_FIELD(targetList);
 	COMPARE_NODE_FIELD(fromClause);
 	COMPARE_NODE_FIELD(whereClause);
@@ -1493,6 +1497,10 @@ _equalExecuteStmt(ExecuteStmt *a, ExecuteStmt *b)
 {
 	COMPARE_STRING_FIELD(name);
 	COMPARE_NODE_FIELD(into);
+	COMPARE_SCALAR_FIELD(into_contains_oids);
+	COMPARE_SCALAR_FIELD(into_has_oids);
+	COMPARE_SCALAR_FIELD(into_on_commit);
+	COMPARE_STRING_FIELD(into_tbl_space);
 	COMPARE_NODE_FIELD(params);
 
 	return true;
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index d6d63ee096f487a63630580543e75b864064bb97..9884b0e4db4fa76288525db804714a5893e47e5b 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.267 2006/01/31 21:39:23 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.268 2006/02/19 00:04:26 neilc Exp $
  *
  * NOTES
  *	  Every node type that can appear in stored rules' parsetrees *must*
@@ -1374,6 +1374,8 @@ _outSelectStmt(StringInfo str, SelectStmt *node)
 	WRITE_NODE_FIELD(into);
 	WRITE_NODE_FIELD(intoColNames);
 	WRITE_ENUM_FIELD(intoHasOids, ContainsOids);
+	WRITE_ENUM_FIELD(intoOnCommit, OnCommitAction);
+	WRITE_STRING_FIELD(intoTableSpaceName);
 	WRITE_NODE_FIELD(targetList);
 	WRITE_NODE_FIELD(fromClause);
 	WRITE_NODE_FIELD(whereClause);
@@ -1504,6 +1506,9 @@ _outQuery(StringInfo str, Query *node)
 
 	WRITE_INT_FIELD(resultRelation);
 	WRITE_NODE_FIELD(into);
+	WRITE_BOOL_FIELD(intoHasOids);
+	WRITE_ENUM_FIELD(intoOnCommit, OnCommitAction);
+	WRITE_STRING_FIELD(intoTableSpaceName);
 	WRITE_BOOL_FIELD(hasAggs);
 	WRITE_BOOL_FIELD(hasSubLinks);
 	WRITE_NODE_FIELD(rtable);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index eb2886d843700f735edcba07ccb88d8b0dc675e1..19cb6e9544f9c4d2006fd732bb6162a0009a6107 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.183 2005/12/28 01:29:59 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.184 2006/02/19 00:04:26 neilc Exp $
  *
  * NOTES
  *	  Path and Plan nodes do not have any readfuncs support, because we
@@ -140,6 +140,9 @@ _readQuery(void)
 	READ_NODE_FIELD(utilityStmt);
 	READ_INT_FIELD(resultRelation);
 	READ_NODE_FIELD(into);
+	READ_BOOL_FIELD(intoHasOids);
+	READ_ENUM_FIELD(intoOnCommit, OnCommitAction);
+	READ_STRING_FIELD(intoTableSpaceName);
 	READ_BOOL_FIELD(hasAggs);
 	READ_BOOL_FIELD(hasSubLinks);
 	READ_NODE_FIELD(rtable);
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index abfb0fbf30347a71ed235eaac33d9c2c9240d79c..057ff41518553448e87d4947b4beaffd85568c60 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.328 2006/01/15 22:18:46 neilc Exp $
+ *	$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.329 2006/02/19 00:04:26 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1818,6 +1818,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
 		applyColumnNames(qry->targetList, stmt->intoColNames);
 
 	qry->intoHasOids = interpretOidsOption(stmt->intoHasOids);
+	qry->intoOnCommit = stmt->intoOnCommit;
+	qry->intoTableSpaceName = stmt->intoTableSpaceName;
 
 	/* mark column origins */
 	markTargetListOrigins(pstate, qry->targetList);
@@ -2662,6 +2664,8 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
 
 	paramtypes = FetchPreparedStatementParams(stmt->name);
 
+	stmt->into_has_oids = interpretOidsOption(stmt->into_contains_oids);
+
 	if (stmt->params || paramtypes)
 	{
 		int			nparams = list_length(stmt->params);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 88d32d837d45b70ef3ab564730168b4434d87140..6cb6f96fa4f5ea7480d2f42d0b6b2c29384e1b09 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.529 2006/02/12 19:11:01 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.530 2006/02/19 00:04:27 neilc Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -239,7 +239,7 @@ static void doNegateFloat(Value *v);
 
 %type <boolean>  TriggerForType OptTemp
 %type <oncommit> OnCommitOption
-%type <withoids> OptWithOids WithOidsAs
+%type <withoids> OptWithOids
 
 %type <node>	for_locking_clause opt_for_locking_clause
 %type <list>	locked_rels_list
@@ -2171,7 +2171,8 @@ OptConsTableSpace:   USING INDEX TABLESPACE name	{ $$ = $4; }
  */
 
 CreateAsStmt:
-			CREATE OptTemp TABLE qualified_name OptCreateAs WithOidsAs SelectStmt
+		CREATE OptTemp TABLE qualified_name OptCreateAs
+			OptWithOids OnCommitOption OptTableSpace AS SelectStmt
 				{
 					/*
 					 * When the SelectStmt is a set-operation tree, we must
@@ -2180,7 +2181,7 @@ CreateAsStmt:
 					 * to find it.	Similarly, the output column names must
 					 * be attached to that Select's target list.
 					 */
-					SelectStmt *n = findLeftmostSelect((SelectStmt *) $7);
+					SelectStmt *n = findLeftmostSelect((SelectStmt *) $10);
 					if (n->into != NULL)
 						ereport(ERROR,
 								(errcode(ERRCODE_SYNTAX_ERROR),
@@ -2189,22 +2190,12 @@ CreateAsStmt:
 					n->into = $4;
 					n->intoColNames = $5;
 					n->intoHasOids = $6;
-					$$ = $7;
+					n->intoOnCommit = $7;
+					n->intoTableSpaceName = $8;
+					$$ = $10;
 				}
 		;
 
-/*
- * To avoid a shift/reduce conflict in CreateAsStmt, we need to
- * include the 'AS' terminal in the parsing of WITH/WITHOUT
- * OIDS. Unfortunately that means this production is effectively a
- * duplicate of OptWithOids.
- */
-WithOidsAs:
-			WITH OIDS AS 							{ $$ = MUST_HAVE_OIDS; }
-			| WITHOUT OIDS AS 						{ $$ = MUST_NOT_HAVE_OIDS; }
-			| AS 									{ $$ = DEFAULT_OIDS; }
-			;
-
 OptCreateAs:
 			'(' CreateAsList ')'					{ $$ = $2; }
 			| /*EMPTY*/								{ $$ = NIL; }
@@ -5066,13 +5057,18 @@ ExecuteStmt: EXECUTE name execute_param_clause
 					n->into = NULL;
 					$$ = (Node *) n;
 				}
-			| CREATE OptTemp TABLE qualified_name OptCreateAs AS EXECUTE name execute_param_clause
+			| CREATE OptTemp TABLE qualified_name OptCreateAs
+				OptWithOids OnCommitOption OptTableSpace AS
+				EXECUTE name execute_param_clause
 				{
 					ExecuteStmt *n = makeNode(ExecuteStmt);
-					n->name = $8;
-					n->params = $9;
+					n->name = $11;
+					n->params = $12;
 					$4->istemp = $2;
 					n->into = $4;
+					n->into_contains_oids = $6;
+					n->into_on_commit = $7;
+					n->into_tbl_space = $8;
 					if ($5)
 						ereport(ERROR,
 								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 0efe47fc6e5d5a62f5d12a55f3b1e2af8f961e3c..a251e0759d394c1b5cd49698de369a8a4a987b74 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.300 2006/02/04 19:06:46 adunstan Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.301 2006/02/19 00:04:27 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,16 @@ typedef enum QuerySource
 	QSRC_NON_INSTEAD_RULE		/* added by non-INSTEAD rule */
 } QuerySource;
 
+/* What to do at commit time for temporary relations */
+typedef enum OnCommitAction
+{
+	ONCOMMIT_NOOP,				/* No ON COMMIT clause (do nothing) */
+	ONCOMMIT_PRESERVE_ROWS,		/* ON COMMIT PRESERVE ROWS (do nothing) */
+	ONCOMMIT_DELETE_ROWS,		/* ON COMMIT DELETE ROWS */
+	ONCOMMIT_DROP				/* ON COMMIT DROP */
+} OnCommitAction;
+
+
 /*
  * Grantable rights are encoded so that we can OR them together in a bitmask.
  * The present representation of AclItem limits us to 16 distinct rights,
@@ -82,6 +92,8 @@ typedef struct Query
 
 	RangeVar   *into;			/* target relation for SELECT INTO */
 	bool		intoHasOids;	/* should target relation contain OIDs? */
+	OnCommitAction	intoOnCommit;		/* what do we do at COMMIT? */
+	char	   *intoTableSpaceName;	/* table space to use, or NULL */
 
 	bool		hasAggs;		/* has aggregates in tlist or havingQual */
 	bool		hasSubLinks;	/* has subquery SubLink */
@@ -674,14 +686,16 @@ typedef struct SelectStmt
 	/*
 	 * These fields are used only in "leaf" SelectStmts.
 	 *
-	 * into, intoColNames and intoHasOids are a kluge; they belong somewhere
-	 * else...
+	 * into, intoColNames, intoHasOids, intoOnCommit, and
+	 * intoTableSpaceName are a kluge; they belong somewhere else...
 	 */
 	List	   *distinctClause; /* NULL, list of DISTINCT ON exprs, or
 								 * lcons(NIL,NIL) for all (SELECT DISTINCT) */
 	RangeVar   *into;			/* target table (for select into table) */
 	List	   *intoColNames;	/* column names for into table */
 	ContainsOids intoHasOids;	/* should target table have OIDs? */
+	OnCommitAction	intoOnCommit;		/* what do we do at COMMIT? */
+	char	   *intoTableSpaceName;		/* table space to use, or NULL */
 	List	   *targetList;		/* the target list (of ResTarget) */
 	List	   *fromClause;		/* the FROM clause */
 	Node	   *whereClause;	/* WHERE qualification */
@@ -976,15 +990,6 @@ typedef struct CopyStmt
  * ----------------------
  */
 
-/* What to do at commit time for temporary relations */
-typedef enum OnCommitAction
-{
-	ONCOMMIT_NOOP,				/* No ON COMMIT clause (do nothing) */
-	ONCOMMIT_PRESERVE_ROWS,		/* ON COMMIT PRESERVE ROWS (do nothing) */
-	ONCOMMIT_DELETE_ROWS,		/* ON COMMIT DELETE ROWS */
-	ONCOMMIT_DROP				/* ON COMMIT DROP */
-} OnCommitAction;
-
 typedef struct CreateStmt
 {
 	NodeTag		type;
@@ -1862,10 +1867,14 @@ typedef struct PrepareStmt
 
 typedef struct ExecuteStmt
 {
-	NodeTag		type;
-	char	   *name;			/* The name of the plan to execute */
-	RangeVar   *into;			/* Optional table to store results in */
-	List	   *params;			/* Values to assign to parameters */
+	NodeTag			type;
+	char		   *name;				/* The name of the plan to execute */
+	RangeVar	   *into;				/* Optional table to store results in */
+	ContainsOids	into_contains_oids;	/* Should it have OIDs? */
+	bool			into_has_oids;		/* Merge GUC info with user input */
+	OnCommitAction	into_on_commit;		/* What do we do at COMMIT? */
+	char		   *into_tbl_space;		/* Tablespace to use, or NULL */
+	List		   *params;				/* Values to assign to parameters */
 } ExecuteStmt;
 
 
@@ -1887,7 +1896,7 @@ typedef struct DropOwnedStmt
 	NodeTag		type;
 	List	   *roles;
 	DropBehavior behavior;
-}	DropOwnedStmt;
+} DropOwnedStmt;
 
 /*
  *		REASSIGN OWNED statement
@@ -1897,6 +1906,6 @@ typedef struct ReassignOwnedStmt
 	NodeTag		type;
 	List	   *roles;
 	char	   *newrole;
-}	ReassignOwnedStmt;
+} ReassignOwnedStmt;
 
 #endif   /* PARSENODES_H */
diff --git a/src/test/regress/expected/temp.out b/src/test/regress/expected/temp.out
index 897ae751bd9f6560db1c29e026bbf269c798999a..c9a14fc435b555d53070dc2e362a75fa35fa8274 100644
--- a/src/test/regress/expected/temp.out
+++ b/src/test/regress/expected/temp.out
@@ -63,6 +63,21 @@ SELECT * FROM temptest;
 -----
 (0 rows)
 
+DROP TABLE temptest;
+BEGIN;
+CREATE TEMP TABLE temptest(col) ON COMMIT DELETE ROWS AS SELECT 1;
+SELECT * FROM temptest;
+ col 
+-----
+   1
+(1 row)
+
+COMMIT;
+SELECT * FROM temptest;
+ col 
+-----
+(0 rows)
+
 DROP TABLE temptest;
 -- Test ON COMMIT DROP
 BEGIN;
@@ -76,12 +91,25 @@ SELECT * FROM temptest;
    2
 (2 rows)
 
+COMMIT;
+SELECT * FROM temptest;
+ERROR:  relation "temptest" does not exist
+BEGIN;
+CREATE TEMP TABLE temptest(col) ON COMMIT DROP AS SELECT 1;
+SELECT * FROM temptest;
+ col 
+-----
+   1
+(1 row)
+
 COMMIT;
 SELECT * FROM temptest;
 ERROR:  relation "temptest" does not exist
 -- ON COMMIT is only allowed for TEMP
 CREATE TABLE temptest(col int) ON COMMIT DELETE ROWS;
 ERROR:  ON COMMIT can only be used on temporary tables
+CREATE TABLE temptest(col) ON COMMIT DELETE ROWS AS SELECT 1;
+ERROR:  ON COMMIT can only be used on temporary tables
 -- Test foreign keys
 BEGIN;
 CREATE TEMP TABLE temptest1(col int PRIMARY KEY);
diff --git a/src/test/regress/expected/without_oid.out b/src/test/regress/expected/without_oid.out
index fbe617f94959f5a4eb39eb3fe7ebaaa5552f1fab..5e46aa8ebee80557b7ee2145beee1610006cbc08 100644
--- a/src/test/regress/expected/without_oid.out
+++ b/src/test/regress/expected/without_oid.out
@@ -76,6 +76,21 @@ SELECT count(oid) FROM create_table_test2;
 -- should fail
 SELECT count(oid) FROM create_table_test3;
 ERROR:  column "oid" does not exist
+PREPARE table_source(int) AS
+    SELECT a + b AS c1, a - b AS c2, $1 AS c3 FROM create_table_test;
+CREATE TABLE execute_with WITH OIDS AS EXECUTE table_source(1);
+CREATE TABLE execute_without WITHOUT OIDS AS EXECUTE table_source(2);
+SELECT count(oid) FROM execute_with;
+ count 
+-------
+     2
+(1 row)
+
+-- should fail
+SELECT count(oid) FROM execute_without;
+ERROR:  column "oid" does not exist
 DROP TABLE create_table_test;
 DROP TABLE create_table_test2;
 DROP TABLE create_table_test3;
+DROP TABLE execute_with;
+DROP TABLE execute_without;
diff --git a/src/test/regress/input/tablespace.source b/src/test/regress/input/tablespace.source
index d094bd70811cabcac08cef4070a17c004b46ec93..9e2c35809478013da49b60ebfba1ae14995c8ea6 100644
--- a/src/test/regress/input/tablespace.source
+++ b/src/test/regress/input/tablespace.source
@@ -12,6 +12,17 @@ SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
 INSERT INTO testschema.foo VALUES(1);
 INSERT INTO testschema.foo VALUES(2);
 
+-- tables from dynamic sources
+CREATE TABLE testschema.asselect TABLESPACE testspace AS SELECT 1;
+SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
+    where c.reltablespace = t.oid AND c.relname = 'asselect';
+
+PREPARE selectsource(int) AS SELECT $1;
+CREATE TABLE testschema.asexecute TABLESPACE testspace
+    AS EXECUTE selectsource(2);
+SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
+    where c.reltablespace = t.oid AND c.relname = 'asexecute';
+
 -- index
 CREATE INDEX foo_idx on testschema.foo(i) TABLESPACE testspace;
 SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
diff --git a/src/test/regress/output/tablespace.source b/src/test/regress/output/tablespace.source
index 42c4bc628d50f992e190e64bfab31a09661e935f..d75493fb0b60b8f0397414cb525264ff3c81efff 100644
--- a/src/test/regress/output/tablespace.source
+++ b/src/test/regress/output/tablespace.source
@@ -13,6 +13,25 @@ SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
 
 INSERT INTO testschema.foo VALUES(1);
 INSERT INTO testschema.foo VALUES(2);
+-- tables from dynamic sources
+CREATE TABLE testschema.asselect TABLESPACE testspace AS SELECT 1;
+SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
+    where c.reltablespace = t.oid AND c.relname = 'asselect';
+ relname  |  spcname  
+----------+-----------
+ asselect | testspace
+(1 row)
+
+PREPARE selectsource(int) AS SELECT $1;
+CREATE TABLE testschema.asexecute TABLESPACE testspace
+    AS EXECUTE selectsource(2);
+SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
+    where c.reltablespace = t.oid AND c.relname = 'asexecute';
+  relname  |  spcname  
+-----------+-----------
+ asexecute | testspace
+(1 row)
+
 -- index
 CREATE INDEX foo_idx on testschema.foo(i) TABLESPACE testspace;
 SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
@@ -32,6 +51,8 @@ ERROR:  tablespace "nosuchspace" does not exist
 DROP TABLESPACE testspace;
 ERROR:  tablespace "testspace" is not empty
 DROP SCHEMA testschema CASCADE;
+NOTICE:  drop cascades to table testschema.asexecute
+NOTICE:  drop cascades to table testschema.asselect
 NOTICE:  drop cascades to table testschema.foo
 -- Should succeed
 DROP TABLESPACE testspace;
diff --git a/src/test/regress/sql/temp.sql b/src/test/regress/sql/temp.sql
index 972d511ab7635bf659bdabee4b8884831db1f9dd..6a4b8561449a676bb6790baaf06cde35cc55b35b 100644
--- a/src/test/regress/sql/temp.sql
+++ b/src/test/regress/sql/temp.sql
@@ -66,6 +66,16 @@ SELECT * FROM temptest;
 
 DROP TABLE temptest;
 
+BEGIN;
+CREATE TEMP TABLE temptest(col) ON COMMIT DELETE ROWS AS SELECT 1;
+
+SELECT * FROM temptest;
+COMMIT;
+
+SELECT * FROM temptest;
+
+DROP TABLE temptest;
+
 -- Test ON COMMIT DROP
 
 BEGIN;
@@ -80,9 +90,18 @@ COMMIT;
 
 SELECT * FROM temptest;
 
+BEGIN;
+CREATE TEMP TABLE temptest(col) ON COMMIT DROP AS SELECT 1;
+
+SELECT * FROM temptest;
+COMMIT;
+
+SELECT * FROM temptest;
+
 -- ON COMMIT is only allowed for TEMP
 
 CREATE TABLE temptest(col int) ON COMMIT DELETE ROWS;
+CREATE TABLE temptest(col) ON COMMIT DELETE ROWS AS SELECT 1;
 
 -- Test foreign keys
 BEGIN;
diff --git a/src/test/regress/sql/without_oid.sql b/src/test/regress/sql/without_oid.sql
index 06c9c69245b927d73b70fad8156346cf6a5c9884..1a10a8533dff3d0f502b43f5f857e46052192de8 100644
--- a/src/test/regress/sql/without_oid.sql
+++ b/src/test/regress/sql/without_oid.sql
@@ -74,6 +74,18 @@ SELECT count(oid) FROM create_table_test2;
 -- should fail
 SELECT count(oid) FROM create_table_test3;
 
+PREPARE table_source(int) AS
+    SELECT a + b AS c1, a - b AS c2, $1 AS c3 FROM create_table_test;
+
+CREATE TABLE execute_with WITH OIDS AS EXECUTE table_source(1);
+CREATE TABLE execute_without WITHOUT OIDS AS EXECUTE table_source(2);
+
+SELECT count(oid) FROM execute_with;
+-- should fail
+SELECT count(oid) FROM execute_without;
+
 DROP TABLE create_table_test;
 DROP TABLE create_table_test2;
 DROP TABLE create_table_test3;
+DROP TABLE execute_with;
+DROP TABLE execute_without;