Fix pull_up_simple_union_all to copy all rtable entries from child subquery to

parent, not only those with RangeTblRefs. We need them in ExecCheckRTPerms.

Report by Brendan O'Shea. Back-patch to 8.2, where pull_up_simple_union_all
was introduced.
This commit is contained in:
Heikki Linnakangas 2008-08-14 20:31:29 +00:00
parent e006a24ad1
commit f24f233f6a
3 changed files with 61 additions and 32 deletions

View File

@ -16,7 +16,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.51 2008/08/14 18:47:59 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.52 2008/08/14 20:31:29 heikki Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -47,7 +47,8 @@ static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
RangeTblEntry *rte); RangeTblEntry *rte);
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
int parentRTindex, Query *setOpQuery); int parentRTindex, Query *setOpQuery,
int childRToffset);
static void make_setop_translation_lists(Query *query, static void make_setop_translation_lists(Query *query,
Index newvarno, Index newvarno,
List **col_mappings, List **translated_vars); List **col_mappings, List **translated_vars);
@ -560,14 +561,34 @@ pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
{ {
int varno = ((RangeTblRef *) jtnode)->rtindex; int varno = ((RangeTblRef *) jtnode)->rtindex;
Query *subquery = rte->subquery; Query *subquery = rte->subquery;
int rtoffset;
List *rtable;
/* /*
* Recursively scan the subquery's setOperations tree and copy the leaf * Append the subquery rtable entries to upper query.
* subqueries into the parent rangetable. Add AppendRelInfo nodes for */
* them to the parent's append_rel_list, too. 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); Assert(subquery->setOperations);
pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery); pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
rtoffset);
/* /*
* Mark the parent as an append relation. * Mark the parent as an append relation.
@ -583,41 +604,26 @@ pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
* Note that setOpQuery is the Query containing the setOp node, whose rtable * 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 * 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. * 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. * 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 static void
pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex, pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
Query *setOpQuery) Query *setOpQuery, int childRToffset)
{ {
if (IsA(setOp, RangeTblRef)) if (IsA(setOp, RangeTblRef))
{ {
RangeTblRef *rtr = (RangeTblRef *) setOp; RangeTblRef *rtr = (RangeTblRef *) setOp;
RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
Query *subquery;
int childRTindex; int childRTindex;
AppendRelInfo *appinfo; AppendRelInfo *appinfo;
Query *parse = root->parse;
/* /*
* Make a modifiable copy of the child RTE and contained query. * Calculate the index in the parent's range table
*/ */
rte = copyObject(rte); childRTindex = childRToffset + rtr->rtindex;
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. * Build a suitable AppendRelInfo, and attach to parent's list.
@ -649,8 +655,10 @@ pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
SetOperationStmt *op = (SetOperationStmt *) setOp; SetOperationStmt *op = (SetOperationStmt *) setOp;
/* Recurse to reach leaf queries */ /* Recurse to reach leaf queries */
pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery); pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery); childRToffset);
pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
childRToffset);
} }
else else
{ {

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.108 2008/08/14 18:47:59 tgl Exp $ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.109 2008/08/14 20:31:29 heikki Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -533,6 +533,25 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
0); 0);
} }
/*
* IncrementVarSublevelsUp_rtable -
* Same as IncrementVarSublevelsUp, but to be invoked on a range table.
*/
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 * rangeTableEntry_used - detect whether an RTE is referenced somewhere

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.44 2008/01/01 19:45:58 momjian Exp $ * $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.45 2008/08/14 20:31:29 heikki Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -22,6 +22,8 @@ extern void ChangeVarNodes(Node *node, int old_varno, int new_varno,
int sublevels_up); int sublevels_up);
extern void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, extern void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
int min_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, extern bool rangeTableEntry_used(Node *node, int rt_index,
int sublevels_up); int sublevels_up);