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)
156156static void
157157DefineViewRules (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 *
211206UpdateRangeTableOfViewParse (char * viewName ,Query * viewParse )
212207{
213208List * new_rt ;
214209RangeTblEntry * 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 */
221226rt_entry1 = addRangeTableEntry (NULL ,viewName ,
@@ -230,16 +235,14 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
230235
231236new_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- */
237238viewParse -> 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 */
242243OffsetVarNodes ((Node * )viewParse ,2 ,0 );
244+
245+ return viewParse ;
243246}
244247
245248/*-------------------------------------------------------------------
@@ -257,15 +260,11 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
257260void
258261DefineView (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 );
284285DefineViewRules (viewName ,viewParse );
285286}
286287