Add TABLESPACE and ON COMMIT clauses to CREATE TABLE AS. ON COMMIT is
required by the SQL standard, and TABLESPACE is useful functionality. Patch from Kris Jurka, minor editorialization by Neil Conway.
This commit is contained in:
parent
8c5dfbabff
commit
85c0eac1af
@ -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>
|
||||
|
@ -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 >= '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>
|
||||
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user