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

Поиск
Список
Период
Сортировка
От Heikki Linnakangas
Тема Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants
Дата
Msg-id 48A28684.60002@enterprisedb.com
обсуждение исходный текст
Ответ на Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-bugs
Tom Lane wrote:
> Hm, the "Assert(rte->subquery != NULL)" doesn't seem right ...
> couldn't there be non-RTE_SUBQUERY rtes in the child?  I think the
> original coding was guaranteed to visit only subquery-type RTEs
> but I'm much less convinced about this one.  It might
> be better to say
>     if (rte->rtekind == RTE_SUBQUERY)
>         IncrementVarSublevelsUp(...);
>
> Or maybe it's okay; I'm too lazy to recheck the representation of
> UNION ALL right now.

Oh, indeed it's not okay. The original UNION ALL view is a prime example
of that. I didn't notice because I was testing without assertions.

Hmm, do we need the copyObject() call for non-subquery RTEs? I'm
guessing no, because they're not modified.

--
   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    13 Aug 2008 06:41:49 -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,520 ----
  {
      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);
!
!         /*
!          * 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.
!          */
!         if (rte->subquery)
!         {
!             /* Make a modifiable copy of the child RTE and contained query. */
!             rte = copyObject(rte);
!             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.
***************
*** 500,540 ****
   * Note that setOpQuery is the Query containing the setOp node, whose rtable
   * 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.
--- 530,555 ----
   * Note that setOpQuery is the Query containing the setOp node, whose rtable
   * 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 по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants
Следующее
От: "Bhaskar Sirohi"
Дата:
Сообщение: BUG #4352: Service fails to start when moved from domain to workgroup