diff options
-rw-r--r-- | doc/src/sgml/ref/create_table.sgml | 9 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_table_as.sgml | 95 | ||||
-rw-r--r-- | src/backend/commands/prepare.c | 6 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 47 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 10 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 10 | ||||
-rw-r--r-- | src/backend/nodes/outfuncs.c | 7 | ||||
-rw-r--r-- | src/backend/nodes/readfuncs.c | 5 | ||||
-rw-r--r-- | src/backend/parser/analyze.c | 6 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 36 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 45 | ||||
-rw-r--r-- | src/test/regress/expected/temp.out | 28 | ||||
-rw-r--r-- | src/test/regress/expected/without_oid.out | 15 | ||||
-rw-r--r-- | src/test/regress/input/tablespace.source | 11 | ||||
-rw-r--r-- | src/test/regress/output/tablespace.source | 21 | ||||
-rw-r--r-- | src/test/regress/sql/temp.sql | 19 | ||||
-rw-r--r-- | src/test/regress/sql/without_oid.sql | 12 |
17 files changed, 322 insertions, 60 deletions
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index 5dfeca1953c..a4cdc250187 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 201188d99cc..7e7fa7b6731 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> @@ -114,6 +117,65 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name </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> <para> @@ -170,6 +232,20 @@ CREATE TABLE films_recent AS SELECT * FROM films WHERE date_prod >= '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 > $1; +CREATE TEMP TABLE films_recent WITH OIDS ON COMMIT DROP AS + EXECUTE recentfilms('2002-01-01'); +</programlisting> + </para> </refsect1> <refsect1> @@ -190,13 +266,6 @@ CREATE TABLE films_recent AS <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; this is not currently implemented by <productname>PostgreSQL</>. The behavior provided by <productname>PostgreSQL</> is equivalent @@ -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 f0afdbba367..4fd43d7f496 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 a0f9cfedd3f..99c3bca0a9a 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,11 +731,20 @@ 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 */ intoName = parseTree->into->relname; @@ -747,13 +757,44 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly) 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 */ tupdesc = CreateTupleDescCopy(tupType); 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 6578bf37afd..91f06df039a 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 a9fdc95f6bb..9a2a5fd0d59 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 d6d63ee096f..9884b0e4db4 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 eb2886d8437..19cb6e9544f 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 abfb0fbf303..057ff415185 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 88d32d837d4..6cb6f96fa4f 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 0efe47fc6e5..a251e0759d3 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 897ae751bd9..c9a14fc435b 100644 --- a/src/test/regress/expected/temp.out +++ b/src/test/regress/expected/temp.out @@ -64,6 +64,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; CREATE TEMP TABLE temptest(col int) ON COMMIT DROP; @@ -79,9 +94,22 @@ SELECT * FROM temptest; 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 fbe617f9495..5e46aa8ebee 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 d094bd70811..9e2c3580947 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 42c4bc628d5..d75493fb0b6 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 972d511ab76..6a4b8561449 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 06c9c69245b..1a10a8533df 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; |