From 85c0eac1afd92201638a4af6ab6e936f47727551 Mon Sep 17 00:00:00 2001 From: Neil Conway Date: Sun, 19 Feb 2006 00:04:28 +0000 Subject: [PATCH] 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. --- doc/src/sgml/ref/create_table.sgml | 9 ++- doc/src/sgml/ref/create_table_as.sgml | 95 ++++++++++++++++++++--- src/backend/commands/prepare.c | 6 +- src/backend/executor/execMain.c | 47 ++++++++++- src/backend/nodes/copyfuncs.c | 10 ++- src/backend/nodes/equalfuncs.c | 10 ++- src/backend/nodes/outfuncs.c | 7 +- src/backend/nodes/readfuncs.c | 5 +- src/backend/parser/analyze.c | 6 +- src/backend/parser/gram.y | 36 ++++----- src/include/nodes/parsenodes.h | 45 ++++++----- src/test/regress/expected/temp.out | 28 +++++++ src/test/regress/expected/without_oid.out | 15 ++++ src/test/regress/input/tablespace.source | 11 +++ src/test/regress/output/tablespace.source | 21 +++++ src/test/regress/sql/temp.sql | 19 +++++ 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 5dfeca1953..a4cdc25018 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -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 is done + at each commit. diff --git a/doc/src/sgml/ref/create_table_as.sgml b/doc/src/sgml/ref/create_table_as.sgml index 201188d99c..7e7fa7b673 100644 --- a/doc/src/sgml/ref/create_table_as.sgml +++ b/doc/src/sgml/ref/create_table_as.sgml @@ -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 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. + + diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index f0afdbba36..4fd43d7f49 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 a0f9cfedd3..99c3bca0a9 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 6578bf37af..91f06df039 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 a9fdc95f6b..9a2a5fd0d5 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 d6d63ee096..9884b0e4db 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 eb2886d843..19cb6e9544 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 abfb0fbf30..057ff41518 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 88d32d837d..6cb6f96fa4 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 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), diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 0efe47fc6e..a251e0759d 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 897ae751bd..c9a14fc435 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 fbe617f949..5e46aa8ebe 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 d094bd7081..9e2c358094 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 42c4bc628d..d75493fb0b 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 972d511ab7..6a4b856144 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 06c9c69245..1a10a8533d 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;