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 | 48A41D89.8030306@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 (Tom Lane <tgl@sss.pgh.pa.us>) |
Responses |
Re: BUG #4350: 'select' acess given to views containing "union all" even though user has no grants
|
List | 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 by date: