mirror of https://github.com/postgres/postgres
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:
parent
e006a24ad1
commit
f24f233f6a
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue