Add TABLESPACE and ON COMMIT clauses to CREATE TABLE AS. ON COMMIT is
authorNeil Conway
Sun, 19 Feb 2006 00:04:28 +0000 (00:04 +0000)
committerNeil Conway
Sun, 19 Feb 2006 00:04:28 +0000 (00:04 +0000)
required by the SQL standard, and TABLESPACE is useful functionality.
Patch from Kris Jurka, minor editorialization by Neil Conway.

17 files changed:
doc/src/sgml/ref/create_table.sgml
doc/src/sgml/ref/create_table_as.sgml
src/backend/commands/prepare.c
src/backend/executor/execMain.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/include/nodes/parsenodes.h
src/test/regress/expected/temp.out
src/test/regress/expected/without_oid.out
src/test/regress/input/tablespace.source
src/test/regress/output/tablespace.source
src/test/regress/sql/temp.sql
src/test/regress/sql/without_oid.sql

index 5dfeca1953c3fa5ab793c1232a7191b114ceb342..a4cdc2501876f0255c6b458e5ba9d7273631fa1d 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -580,9 +580,10 @@ and table_constraint is:
         DELETE ROWS
         
          
-          All rows in the temporary table will be deleted at the
-          end of each transaction block.  Essentially, an automatic
-           is done at each commit.
+          All rows in the temporary table will be deleted at the end
+          of each transaction block.  Essentially, an automatic 
+          linkend="sql-truncate" endterm="sql-truncate-title"> is done
+          at each commit.
          
         
        
index 201188d99cc67a6d4bf82716016455c015f1f317..7e7fa7b6731c5543e4fd78ee93645e276a6d023e 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -21,7 +21,10 @@ PostgreSQL documentation
  
 
 CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name
-    [ (column_name [, ...] ) ] [ [ WITH | WITHOUT ] OIDS ]
+    [ (column_name [, ...] ) ]
+    [ WITH OIDS | WITHOUT OIDS ]
+    [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
+    [ TABLESPACE tablespace ]
     AS query
 
  
@@ -113,6 +116,65 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name
      
    
 
+   
+    ON COMMIT
+    
+     
+      The behavior of temporary tables at the end of a transaction
+      block can be controlled using ON COMMIT.
+      The three options are:
+
+      
+       
+        PRESERVE ROWS
+        
+         
+          No special action is taken at the ends of transactions.
+          This is the default behavior.
+         
+        
+       
+
+       
+        DELETE ROWS
+        
+         
+          All rows in the temporary table will be deleted at the end
+          of each transaction block.  Essentially, an automatic 
+          linkend="sql-truncate" endterm="sql-truncate-title"> is done
+          at each commit.
+         
+        
+       
+
+       
+        DROP
+        
+         
+          The temporary table will be dropped at the end of the current
+          transaction block.
+         
+        
+       
+      
+     
+    
+   
+
+   
+    TABLESPACE tablespace
+    
+     
+      The tablespace is the name
+      of the tablespace in which the new table is to be created.
+      If not specified,
+       is used, or the database's
+      default tablespace if default_tablespace is an empty
+      string.
+     
+    
+   
+
    
     query
     
@@ -168,6 +230,20 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name
 
 CREATE TABLE films_recent AS
   SELECT * FROM films WHERE date_prod >= '2002-01-01';
+
+  
+
+  
+   Create a new temporary table that will be dropped at commit
+   films_recent with oids consisting of only
+   recent entries from the table films using a
+   prepared statement:
+
+
+PREPARE recentfilms(date) AS
+  SELECT * FROM films WHERE date_prod > $1;
+CREATE TEMP TABLE films_recent WITH OIDS ON COMMIT DROP AS
+  EXECUTE recentfilms('2002-01-01');
 
   
  
@@ -188,13 +264,6 @@ CREATE TABLE films_recent AS
      
     
 
-    
-     
-      The standard defines an ON COMMIT clause;
-      this is not currently implemented by PostgreSQL.
-     
-    
-
     
      
       The standard defines a WITH [ NO ] DATA clause;
@@ -219,6 +288,14 @@ CREATE TABLE films_recent AS
       for details.
      
     
+
+    
+     
+      The PostgreSQL concept of tablespaces is not
+      part of the standard.  Hence, the clause TABLESPACE
+      is an extension.
+     
+    
    
   
  
index f0afdbba3675d0cfbd7d7bfe99610d06be3e4821..4fd43d7f4966ec6e154d293ea930e7dc8545552a 100644 (file)
@@ -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);
    }
index a0f9cfedd3f17d7f042e73382d3c01f886ba8d34..99c3bca0a9a8202342472d9585963acbc37cff45 100644 (file)
@@ -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);
index 6578bf37afddcc48406cb32cf3e81639917878b7..91f06df039af84b22b444a4738caa8bfe30fc15b 100644 (file)
@@ -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;
index a9fdc95f6bbbebd01d415114d7d3b12a85fc7246..9a2a5fd0d59b65633a234519887db3a74b64c8d4 100644 (file)
@@ -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;
index d6d63ee096f487a63630580543e75b864064bb97..9884b0e4db4fa76288525db804714a5893e47e5b 100644 (file)
@@ -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);
index eb2886d843700f735edcba07ccb88d8b0dc675e1..19cb6e9544f9c4d2006fd732bb6162a0009a6107 100644 (file)
@@ -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);
index abfb0fbf30347a71ed235eaac33d9c2c9240d79c..057ff41518553448e87d4947b4beaffd85568c60 100644 (file)
@@ -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);
index 88d32d837d45b70ef3ab564730168b4434d87140..6cb6f96fa4f5ea7480d2f42d0b6b2c29384e1b09 100644 (file)
@@ -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   TriggerForType OptTemp
 %type  OnCommitOption
-%type  OptWithOids WithOidsAs
+%type  OptWithOids
 
 %type    for_locking_clause opt_for_locking_clause
 %type    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),
index 0efe47fc6e5d5a62f5d12a55f3b1e2af8f961e3c..a251e0759d394c1b5cd49698de369a8a4a987b74 100644 (file)
@@ -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 */
index 897ae751bd9f6560db1c29e026bbf269c798999a..c9a14fc435b555d53070dc2e362a75fa35fa8274 100644 (file)
@@ -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);
index fbe617f94959f5a4eb39eb3fe7ebaaa5552f1fab..5e46aa8ebee80557b7ee2145beee1610006cbc08 100644 (file)
@@ -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;
index d094bd70811cabcac08cef4070a17c004b46ec93..9e2c35809478013da49b60ebfba1ae14995c8ea6 100644 (file)
@@ -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
index 42c4bc628d50f992e190e64bfab31a09661e935f..d75493fb0b60b8f0397414cb525264ff3c81efff 100644 (file)
@@ -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;
index 972d511ab7635bf659bdabee4b8884831db1f9dd..6a4b8561449a676bb6790baaf06cde35cc55b35b 100644 (file)
@@ -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;
index 06c9c69245b927d73b70fad8156346cf6a5c9884..1a10a8533dff3d0f502b43f5f857e46052192de8 100644 (file)
@@ -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;