@@ -353,6 +353,107 @@ DefineViewRules(Oid viewOid, Query *viewParse, bool replace)
353353 */
354354}
355355
356+ /*---------------------------------------------------------------
357+ * UpdateRangeTableOfViewParse
358+ *
359+ * Update the range table of the given parsetree.
360+ * This update consists of adding two new entries IN THE BEGINNING
361+ * of the range table (otherwise the rule system will die a slow,
362+ * horrible and painful death, and we do not want that now, do we?)
363+ * one for the OLD relation and one for the NEW one (both of
364+ * them refer in fact to the "view" relation).
365+ *
366+ * Of course we must also increase the 'varnos' of all the Var nodes
367+ * by 2...
368+ *
369+ * These extra RT entries are not actually used in the query,
370+ * except for run-time locking.
371+ *---------------------------------------------------------------
372+ */
373+ static Query *
374+ UpdateRangeTableOfViewParse (Oid viewOid ,Query * viewParse )
375+ {
376+ Relation viewRel ;
377+ List * new_rt ;
378+ ParseNamespaceItem * nsitem ;
379+ RangeTblEntry * rt_entry1 ,
380+ * rt_entry2 ;
381+ RTEPermissionInfo * rte_perminfo1 ;
382+ ParseState * pstate ;
383+ ListCell * lc ;
384+
385+ /*
386+ * Make a copy of the given parsetree. It's not so much that we don't
387+ * want to scribble on our input, it's that the parser has a bad habit of
388+ * outputting multiple links to the same subtree for constructs like
389+ * BETWEEN, and we mustn't have OffsetVarNodes increment the varno of a
390+ * Var node twice. copyObject will expand any multiply-referenced subtree
391+ * into multiple copies.
392+ */
393+ viewParse = copyObject (viewParse );
394+
395+ /* Create a dummy ParseState for addRangeTableEntryForRelation */
396+ pstate = make_parsestate (NULL );
397+
398+ /* need to open the rel for addRangeTableEntryForRelation */
399+ viewRel = relation_open (viewOid ,AccessShareLock );
400+
401+ /*
402+ * Create the 2 new range table entries and form the new range table...
403+ * OLD first, then NEW....
404+ */
405+ nsitem = addRangeTableEntryForRelation (pstate ,viewRel ,
406+ AccessShareLock ,
407+ makeAlias ("old" ,NIL ),
408+ false, false);
409+ rt_entry1 = nsitem -> p_rte ;
410+ rte_perminfo1 = nsitem -> p_perminfo ;
411+ nsitem = addRangeTableEntryForRelation (pstate ,viewRel ,
412+ AccessShareLock ,
413+ makeAlias ("new" ,NIL ),
414+ false, false);
415+ rt_entry2 = nsitem -> p_rte ;
416+
417+ /*
418+ * Add only the "old" RTEPermissionInfo at the head of view query's list
419+ * and update the other RTEs' perminfoindex accordingly. When rewriting a
420+ * query on the view, ApplyRetrieveRule() will transfer the view
421+ * relation's permission details into this RTEPermissionInfo. That's
422+ * needed because the view's RTE itself will be transposed into a subquery
423+ * RTE that can't carry the permission details; see the code stanza toward
424+ * the end of ApplyRetrieveRule() for how that's done.
425+ */
426+ viewParse -> rteperminfos = lcons (rte_perminfo1 ,viewParse -> rteperminfos );
427+ foreach (lc ,viewParse -> rtable )
428+ {
429+ RangeTblEntry * rte = lfirst (lc );
430+
431+ if (rte -> perminfoindex > 0 )
432+ rte -> perminfoindex += 1 ;
433+ }
434+
435+ /*
436+ * Also make the "new" RTE's RTEPermissionInfo undiscoverable. This is a
437+ * bit of a hack given that all the non-child RTE_RELATION entries really
438+ * should have a RTEPermissionInfo, but this dummy "new" RTE is going to
439+ * go away anyway in the very near future.
440+ */
441+ rt_entry2 -> perminfoindex = 0 ;
442+
443+ new_rt = lcons (rt_entry1 ,lcons (rt_entry2 ,viewParse -> rtable ));
444+
445+ viewParse -> rtable = new_rt ;
446+
447+ /*
448+ * Now offset all var nodes by 2, and jointree RT indexes too.
449+ */
450+ OffsetVarNodes ((Node * )viewParse ,2 ,0 );
451+
452+ relation_close (viewRel ,AccessShareLock );
453+
454+ return viewParse ;
455+ }
456+
356457/*
357458 * DefineView
358459 *Execute a CREATE VIEW command.
@@ -515,6 +616,12 @@ DefineView(ViewStmt *stmt, const char *queryString,
515616void
516617StoreViewQuery (Oid viewOid ,Query * viewParse ,bool replace )
517618{
619+ /*
620+ * The range table of 'viewParse' does not contain entries for the "OLD"
621+ * and "NEW" relations. So... add them!
622+ */
623+ viewParse = UpdateRangeTableOfViewParse (viewOid ,viewParse );
624+
518625/*
519626 * Now create the rules associated with the view.
520627 */