Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants - Mailing list pgsql-bugs

From Heikki Linnakangas
Subject Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants
Date
Msg-id 48A1D6DF.1020403@enterprisedb.com
Whole thread Raw
In response to Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants  ("Heikki Linnakangas" <heikki@enterprisedb.com>)
Responses Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants
List pgsql-bugs
Heikki Linnakangas wrote:
> Tom Lane wrote:
>> Seriously, I think what this shows is that piecemeal pullup is wrong in
>> principle, and that the right approach is always to concat the
>> subquery's rtable in toto to the upper level, and then go from there on
>> adjusting varnos.  Do you want to look into that approach?
>
> You mean like pull_up_simple_subquery() does? Yeah, I can try that. This
> isn't really something I'm familiar with, but it's great exercise :-).

Here we go. Now that I see it, I do like this approach better.

--
   Heikki Linnakangas
   EnterpriseDB   http://www.enterprisedb.com
Index: src/backend/optimizer/prep/prepjointree.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/optimizer/prep/prepjointree.c,v
retrieving revision 1.44
diff -c -r1.44 prepjointree.c
*** src/backend/optimizer/prep/prepjointree.c    4 Oct 2006 00:29:54 -0000    1.44
--- src/backend/optimizer/prep/prepjointree.c    12 Aug 2008 18:22:28 -0000
***************
*** 46,52 ****
  static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
                           RangeTblEntry *rte);
  static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
!                            int parentRTindex, Query *setOpQuery);
  static void make_setop_translation_lists(Query *query,
                               Index newvarno,
                               List **col_mappings, List **translated_vars);
--- 46,52 ----
  static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
                           RangeTblEntry *rte);
  static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
!                int parentRTindex, Query *setOpQuery, int childRToffset);
  static void make_setop_translation_lists(Query *query,
                               Index newvarno,
                               List **col_mappings, List **translated_vars);
***************
*** 477,490 ****
  {
      int            varno = ((RangeTblRef *) jtnode)->rtindex;
      Query       *subquery = rte->subquery;

      /*
!      * Recursively scan the subquery's setOperations tree and copy the leaf
!      * subqueries into the parent rangetable.  Add AppendRelInfo nodes for
!      * them to the parent's append_rel_list, too.
       */
      Assert(subquery->setOperations);
!     pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery);

      /*
       * Mark the parent as an append relation.
--- 477,521 ----
  {
      int            varno = ((RangeTblRef *) jtnode)->rtindex;
      Query       *subquery = rte->subquery;
+     ListCell   *l;
+     int            rtoffset;

      /*
!      * Append the subquery rtable entries to upper query.
!      */
!     rtoffset = list_length(root->parse->rtable);
!     foreach(l, subquery->rtable)
!     {
!         RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
!
!         /*
!          * Make a modifiable copy of the child RTE and contained query.
!          */
!         rte = copyObject(rte);
!         Assert(rte->subquery != NULL);
!
!         /*
!          * Upper-level vars in subquery are now one level closer to their
!          * parent than before.    We don't have to worry about offsetting
!          * varnos, though, because any such vars must refer to stuff above the
!          * level of the query we are pulling into.
!          */
!         IncrementVarSublevelsUp((Node *) rte->subquery, -1, 1);
!
!         /*
!          * Attach child RTE to parent rtable.
!          */
!         root->parse->rtable = lappend(root->parse->rtable, rte);
!     }
!
!     /*
!      * Recursively scan the subquery's setOperations tree and add
!      * AppendRelInfo nodes for leaf subqueries to the parent's
!      * append_rel_list.
       */
      Assert(subquery->setOperations);
!     pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
!                                rtoffset);

      /*
       * Mark the parent as an append relation.
***************
*** 501,540 ****
   * is where to look up the RTE if setOp is a RangeTblRef.  This is *not* the
   * same as root->parse, which is the top-level Query we are pulling up into.
   * parentRTindex is the appendrel parent's index in root->parse->rtable.
   */
  static void
  pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
!                            Query *setOpQuery)
  {
      if (IsA(setOp, RangeTblRef))
      {
          RangeTblRef *rtr = (RangeTblRef *) setOp;
-         RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
-         Query       *subquery;
          int            childRTindex;
          AppendRelInfo *appinfo;
-         Query       *parse = root->parse;

          /*
!          * Make a modifiable copy of the child RTE and contained query.
!          */
!         rte = copyObject(rte);
!         subquery = rte->subquery;
!         Assert(subquery != NULL);
!
!         /*
!          * Upper-level vars in subquery are now one level closer to their
!          * parent than before.    We don't have to worry about offsetting
!          * varnos, though, because any such vars must refer to stuff above the
!          * level of the query we are pulling into.
!          */
!         IncrementVarSublevelsUp((Node *) subquery, -1, 1);
!
!         /*
!          * Attach child RTE to parent rtable.
           */
!         parse->rtable = lappend(parse->rtable, rte);
!         childRTindex = list_length(parse->rtable);

          /*
           * Build a suitable AppendRelInfo, and attach to parent's list.
--- 532,555 ----
   * is where to look up the RTE if setOp is a RangeTblRef.  This is *not* the
   * same as root->parse, which is the top-level Query we are pulling up into.
   * parentRTindex is the appendrel parent's index in root->parse->rtable.
+  *
+  * The child RTEs have already been copied to the parent. childRToffset
+  * tells us where in the parent's range table they were copied.
   */
  static void
  pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
!                            Query *setOpQuery, int childRToffset)
  {
      if (IsA(setOp, RangeTblRef))
      {
          RangeTblRef *rtr = (RangeTblRef *) setOp;
          int            childRTindex;
          AppendRelInfo *appinfo;

          /*
!          * Calculate the index in the parent's range table
           */
!         childRTindex = childRToffset + rtr->rtindex;

          /*
           * Build a suitable AppendRelInfo, and attach to parent's list.
***************
*** 566,573 ****
          SetOperationStmt *op = (SetOperationStmt *) setOp;

          /* Recurse to reach leaf queries */
!         pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery);
!         pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery);
      }
      else
      {
--- 581,590 ----
          SetOperationStmt *op = (SetOperationStmt *) setOp;

          /* Recurse to reach leaf queries */
!         pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
!                                    childRToffset);
!         pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
!                                    childRToffset);
      }
      else
      {

pgsql-bugs by date:

Previous
From: "Heikki Linnakangas"
Date:
Subject: Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants
Next
From: Tom Lane
Date:
Subject: Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants