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 48A41D89.8030306@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:
> Probably not.  But it strikes me that there's another sin of omission
> here: function and values RTEs need to be tweaked too, because they
> contain expressions thst could have uplevel Vars in them.  I'm not
> certain such RTEs could appear at top level in a UNION query, but I'm
> not sure they couldn't either.

Hmm. Maybe through a rewrite or something?

We should use range_table_walker, which knows how to descend into all
kinds of RTEs...

--
   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    14 Aug 2008 11:50:22 -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,53 ----
  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.
--- 478,511 ----
  {
      int            varno = ((RangeTblRef *) jtnode)->rtindex;
      Query       *subquery = rte->subquery;
+     int            rtoffset;
+     List       *rtable;

      /*
!      * Append the subquery rtable entries to upper query.
!      */
!     rtoffset = list_length(root->parse->rtable);
!
!     /*
!      * Append child RTEs to parent rtable.
!      *
!      * 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.
!      */
!     rtable = copyObject(subquery->rtable);
!     IncrementVarSublevelsUp_rtable(rtable, -1, 1);
!     root->parse->rtable = list_concat(root->parse->rtable, rtable);
!
!     /*
!      * 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.
--- 521,546 ----
   * 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
      {
--- 572,581 ----
          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
      {
Index: src/backend/rewrite/rewriteManip.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/rewrite/rewriteManip.c,v
retrieving revision 1.102
diff -c -r1.102 rewriteManip.c
*** src/backend/rewrite/rewriteManip.c    4 Oct 2006 00:29:56 -0000    1.102
--- src/backend/rewrite/rewriteManip.c    14 Aug 2008 11:50:36 -0000
***************
*** 509,514 ****
--- 509,529 ----
                                      0);
  }

+ void
+ IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up,
+                                int min_sublevels_up)
+ {
+     IncrementVarSublevelsUp_context context;
+
+     context.delta_sublevels_up = delta_sublevels_up;
+     context.min_sublevels_up = min_sublevels_up;
+
+     range_table_walker(rtable,
+                        IncrementVarSublevelsUp_walker,
+                        (void *) &context,
+                        0);
+ }
+

  /*
   * rangeTableEntry_used - detect whether an RTE is referenced somewhere
Index: src/include/rewrite/rewriteManip.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/rewrite/rewriteManip.h,v
retrieving revision 1.42
diff -c -r1.42 rewriteManip.h
*** src/include/rewrite/rewriteManip.h    5 Mar 2006 15:58:58 -0000    1.42
--- src/include/rewrite/rewriteManip.h    14 Aug 2008 11:38:08 -0000
***************
*** 22,27 ****
--- 22,29 ----
                 int sublevels_up);
  extern void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
                          int min_sublevels_up);
+ extern void IncrementVarSublevelsUp_rtable(List *rtable,
+                                int delta_sublevels_up,    int min_sublevels_up);

  extern bool rangeTableEntry_used(Node *node, int rt_index,
                       int sublevels_up);

В списке pgsql-bugs по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants
Следующее
От: "Abuzar"
Дата:
Сообщение: BUG #4354: Text Type converted to Memo