提交 0e952cdb 编写于 作者: T Tom Lane

Fix longstanding bug with VIEW using BETWEEN: OffsetVarNodes would get

applied to the duplicated subtree twice.  Probably someday we should
fix the parser not to generate multiple links to the same subtree,
but for now a quick copyObject() is the path of least resistance.
上级 4408f042
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: view.c,v 1.50 2000/10/26 17:04:12 tgl Exp $ * $Id: view.c,v 1.51 2000/12/21 17:36:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -156,12 +156,12 @@ FormViewRetrieveRule(char *viewName, Query *viewParse) ...@@ -156,12 +156,12 @@ FormViewRetrieveRule(char *viewName, Query *viewParse)
static void static void
DefineViewRules(char *viewName, Query *viewParse) DefineViewRules(char *viewName, Query *viewParse)
{ {
RuleStmt *retrieve_rule = NULL; RuleStmt *retrieve_rule;
#ifdef NOTYET #ifdef NOTYET
RuleStmt *replace_rule = NULL; RuleStmt *replace_rule;
RuleStmt *append_rule = NULL; RuleStmt *append_rule;
RuleStmt *delete_rule = NULL; RuleStmt *delete_rule;
#endif #endif
...@@ -198,16 +198,11 @@ DefineViewRules(char *viewName, Query *viewParse) ...@@ -198,16 +198,11 @@ DefineViewRules(char *viewName, Query *viewParse)
* Of course we must also increase the 'varnos' of all the Var nodes * Of course we must also increase the 'varnos' of all the Var nodes
* by 2... * by 2...
* *
* These extra RT entries are not actually used in the query, obviously. * These extra RT entries are not actually used in the query,
* We add them so that views look the same as ON SELECT rules --- * except for run-time permission checking.
* the rule rewriter assumes that ALL rules have OLD and NEW RTEs.
*
* NOTE: these are destructive changes. It would be difficult to
* make a complete copy of the parse tree and make the changes
* in the copy.
*--------------------------------------------------------------- *---------------------------------------------------------------
*/ */
static void static Query *
UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
{ {
List *new_rt; List *new_rt;
...@@ -215,7 +210,17 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) ...@@ -215,7 +210,17 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
*rt_entry2; *rt_entry2;
/* /*
* create the 2 new range table entries and form the new range * Make a copy of the given parsetree. It's not so much that we
* don't want to scribble on our input, it's that the parser has
* a bad habit of outputting multiple links to the same subtree
* for constructs like BETWEEN, and we mustn't have OffsetVarNodes
* increment the varno of a Var node twice. copyObject will expand
* any multiply-referenced subtree into multiple copies.
*/
viewParse = (Query *) copyObject(viewParse);
/*
* Create the 2 new range table entries and form the new range
* table... OLD first, then NEW.... * table... OLD first, then NEW....
*/ */
rt_entry1 = addRangeTableEntry(NULL, viewName, rt_entry1 = addRangeTableEntry(NULL, viewName,
...@@ -230,16 +235,14 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) ...@@ -230,16 +235,14 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
new_rt = lcons(rt_entry1, lcons(rt_entry2, viewParse->rtable)); new_rt = lcons(rt_entry1, lcons(rt_entry2, viewParse->rtable));
/*
* Now the tricky part.... Update the range table in place... Be
* careful here, or hell breaks loooooooooooooOOOOOOOOOOOOOOOOOOSE!
*/
viewParse->rtable = new_rt; viewParse->rtable = new_rt;
/* /*
* now offset all var nodes by 2, and jointree RT indexes too. * Now offset all var nodes by 2, and jointree RT indexes too.
*/ */
OffsetVarNodes((Node *) viewParse, 2, 0); OffsetVarNodes((Node *) viewParse, 2, 0);
return viewParse;
} }
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
...@@ -257,15 +260,11 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) ...@@ -257,15 +260,11 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
void void
DefineView(char *viewName, Query *viewParse) DefineView(char *viewName, Query *viewParse)
{ {
List *viewTlist;
viewTlist = viewParse->targetList;
/* /*
* Create the "view" relation NOTE: if it already exists, the xact * Create the "view" relation NOTE: if it already exists, the xact
* will be aborted. * will be aborted.
*/ */
DefineVirtualRelation(viewName, viewTlist); DefineVirtualRelation(viewName, viewParse->targetList);
/* /*
* The relation we have just created is not visible to any other * The relation we have just created is not visible to any other
...@@ -276,11 +275,13 @@ DefineView(char *viewName, Query *viewParse) ...@@ -276,11 +275,13 @@ DefineView(char *viewName, Query *viewParse)
/* /*
* The range table of 'viewParse' does not contain entries for the * The range table of 'viewParse' does not contain entries for the
* "OLD" and "NEW" relations. So... add them! NOTE: we make the * "OLD" and "NEW" relations. So... add them!
* update in place! After this call 'viewParse' will never be what it */
* used to be... viewParse = UpdateRangeTableOfViewParse(viewName, viewParse);
/*
* Now create the rules associated with the view.
*/ */
UpdateRangeTableOfViewParse(viewName, viewParse);
DefineViewRules(viewName, viewParse); DefineViewRules(viewName, viewParse);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册