diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/commands/view.c | 74 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 25 |
2 files changed, 89 insertions, 10 deletions
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 270b9f8b133..10caef1375b 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.86 2004/12/31 21:59:42 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.87 2005/02/02 06:36:00 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ #include "commands/view.h" #include "miscadmin.h" #include "nodes/makefuncs.h" +#include "optimizer/clauses.h" #include "parser/parse_relation.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteManip.h" @@ -30,7 +31,55 @@ static void checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc); +static bool isViewOnTempTable_walker(Node *node, void *context); +/*--------------------------------------------------------------------- + * isViewOnTempTable + * + * Returns true iff any of the relations underlying this view are + * temporary tables. + *--------------------------------------------------------------------- + */ +static bool +isViewOnTempTable(Query *viewParse) +{ + return isViewOnTempTable_walker((Node *) viewParse, NULL); +} + +static bool +isViewOnTempTable_walker(Node *node, void *context) +{ + if (node == NULL) + return false; + + if (IsA(node, Query)) + { + Query *query = (Query *) node; + ListCell *rtable; + + foreach (rtable, query->rtable) + { + RangeTblEntry *rte = lfirst(rtable); + if (rte->rtekind == RTE_RELATION) + { + Relation rel = heap_open(rte->relid, AccessShareLock); + bool istemp = rel->rd_istemp; + heap_close(rel, AccessShareLock); + if (istemp) + return true; + } + } + + return query_tree_walker(query, + isViewOnTempTable_walker, + context, + QTW_IGNORE_JOINALIASES); + } + + return expression_tree_walker(node, + isViewOnTempTable_walker, + context); +} /*--------------------------------------------------------------------- * DefineVirtualRelation @@ -118,6 +167,13 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace) RelationGetRelationName(rel)); /* + * Due to the namespace visibility rules for temporary + * objects, we should only end up replacing a temporary view + * with another temporary view, and vice versa. + */ + Assert(relation->istemp == rel->rd_istemp); + + /* * Create a tuple descriptor to compare against the existing view, * and verify it matches. */ @@ -326,17 +382,29 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse) *------------------------------------------------------------------- */ void -DefineView(const RangeVar *view, Query *viewParse, bool replace) +DefineView(RangeVar *view, Query *viewParse, bool replace) { Oid viewOid; /* + * If the user didn't explicitly ask for a temporary view, check + * whether we need one implicitly. + */ + if (!view->istemp) + { + view->istemp = isViewOnTempTable(viewParse); + if (view->istemp) + ereport(NOTICE, + (errmsg("view \"%s\" will be a temporary view", + view->relname))); + } + + /* * Create the view relation * * NOTE: if it already exists and replace is false, the xact will be * aborted. */ - viewOid = DefineVirtualRelation(view, viewParse->targetList, replace); /* diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 757a17e891b..69e70821970 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.482 2005/01/27 03:17:59 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.483 2005/02/02 06:36:01 neilc Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -4075,24 +4075,35 @@ transaction_mode_list_or_empty: /***************************************************************************** * - * QUERY: - * create view <viewname> '('target-list ')' AS <query> + * QUERY: + * CREATE [ OR REPLACE ] [ TEMP ] VIEW <viewname> '('target-list ')' AS <query> * *****************************************************************************/ -ViewStmt: CREATE opt_or_replace VIEW qualified_name opt_column_list +ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list AS SelectStmt { ViewStmt *n = makeNode(ViewStmt); - n->replace = $2; + n->replace = false; n->view = $4; + n->view->istemp = $2; n->aliases = $5; n->query = (Query *) $7; - $$ = (Node *)n; + $$ = (Node *) n; + } + | CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list + AS SelectStmt + { + ViewStmt *n = makeNode(ViewStmt); + n->replace = true; + n->view = $6; + n->view->istemp = $4; + n->aliases = $7; + n->query = (Query *) $9; + $$ = (Node *) n; } ; - /***************************************************************************** * * QUERY: |