Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0e952cd

Browse files
committed
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.
1 parent 4408f04 commit 0e952cd

File tree

1 file changed

+29
-28
lines changed

1 file changed

+29
-28
lines changed

src/backend/commands/view.c

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: view.c,v 1.50 2000/10/26 17:04:12 tgl Exp $
9+
* $Id: view.c,v 1.51 2000/12/21 17:36:15 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -156,12 +156,12 @@ FormViewRetrieveRule(char *viewName, Query *viewParse)
156156
static void
157157
DefineViewRules(char *viewName, Query *viewParse)
158158
{
159-
RuleStmt *retrieve_rule = NULL;
159+
RuleStmt *retrieve_rule;
160160

161161
#ifdef NOTYET
162-
RuleStmt *replace_rule = NULL;
163-
RuleStmt *append_rule = NULL;
164-
RuleStmt *delete_rule = NULL;
162+
RuleStmt *replace_rule;
163+
RuleStmt *append_rule;
164+
RuleStmt *delete_rule;
165165

166166
#endif
167167

@@ -198,24 +198,29 @@ DefineViewRules(char *viewName, Query *viewParse)
198198
* Of course we must also increase the 'varnos' of all the Var nodes
199199
* by 2...
200200
*
201-
* These extra RT entries are not actually used in the query, obviously.
202-
* We add them so that views look the same as ON SELECT rules ---
203-
* the rule rewriter assumes that ALL rules have OLD and NEW RTEs.
204-
*
205-
* NOTE: these are destructive changes. It would be difficult to
206-
* make a complete copy of the parse tree and make the changes
207-
* in the copy.
201+
* These extra RT entries are not actually used in the query,
202+
* except for run-time permission checking.
208203
*---------------------------------------------------------------
209204
*/
210-
static void
205+
static Query *
211206
UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
212207
{
213208
List *new_rt;
214209
RangeTblEntry *rt_entry1,
215210
*rt_entry2;
216211

217212
/*
218-
* create the 2 new range table entries and form the new range
213+
* Make a copy of the given parsetree. It's not so much that we
214+
* don't want to scribble on our input, it's that the parser has
215+
* a bad habit of outputting multiple links to the same subtree
216+
* for constructs like BETWEEN, and we mustn't have OffsetVarNodes
217+
* increment the varno of a Var node twice. copyObject will expand
218+
* any multiply-referenced subtree into multiple copies.
219+
*/
220+
viewParse = (Query *) copyObject(viewParse);
221+
222+
/*
223+
* Create the 2 new range table entries and form the new range
219224
* table... OLD first, then NEW....
220225
*/
221226
rt_entry1 = addRangeTableEntry(NULL, viewName,
@@ -230,16 +235,14 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
230235

231236
new_rt = lcons(rt_entry1, lcons(rt_entry2, viewParse->rtable));
232237

233-
/*
234-
* Now the tricky part.... Update the range table in place... Be
235-
* careful here, or hell breaks loooooooooooooOOOOOOOOOOOOOOOOOOSE!
236-
*/
237238
viewParse->rtable = new_rt;
238239

239240
/*
240-
* now offset all var nodes by 2, and jointree RT indexes too.
241+
* Now offset all var nodes by 2, and jointree RT indexes too.
241242
*/
242243
OffsetVarNodes((Node *) viewParse, 2, 0);
244+
245+
return viewParse;
243246
}
244247

245248
/*-------------------------------------------------------------------
@@ -257,15 +260,11 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
257260
void
258261
DefineView(char *viewName, Query *viewParse)
259262
{
260-
List *viewTlist;
261-
262-
viewTlist = viewParse->targetList;
263-
264263
/*
265264
* Create the "view" relation NOTE: if it already exists, the xact
266265
* will be aborted.
267266
*/
268-
DefineVirtualRelation(viewName, viewTlist);
267+
DefineVirtualRelation(viewName, viewParse->targetList);
269268

270269
/*
271270
* The relation we have just created is not visible to any other
@@ -276,11 +275,13 @@ DefineView(char *viewName, Query *viewParse)
276275

277276
/*
278277
* The range table of 'viewParse' does not contain entries for the
279-
* "OLD" and "NEW" relations. So... add them! NOTE: we make the
280-
* update in place! After this call 'viewParse' will never be what it
281-
* used to be...
278+
* "OLD" and "NEW" relations. So... add them!
279+
*/
280+
viewParse = UpdateRangeTableOfViewParse(viewName, viewParse);
281+
282+
/*
283+
* Now create the rules associated with the view.
282284
*/
283-
UpdateRangeTableOfViewParse(viewName, viewParse);
284285
DefineViewRules(viewName, viewParse);
285286
}
286287

0 commit comments

Comments
 (0)