Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f24f233

Browse files
committed
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.
1 parent e006a24 commit f24f233

File tree

3 files changed

+61
-32
lines changed

3 files changed

+61
-32
lines changed

src/backend/optimizer/prep/prepjointree.c

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
*
1818
* IDENTIFICATION
19-
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.51 2008/08/14 18:47:59 tgl Exp $
19+
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.52 2008/08/14 20:31:29 heikki Exp $
2020
*
2121
*-------------------------------------------------------------------------
2222
*/
@@ -47,7 +47,8 @@ static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
4747
static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
4848
RangeTblEntry *rte);
4949
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
50-
int parentRTindex, Query *setOpQuery);
50+
int parentRTindex, Query *setOpQuery,
51+
int childRToffset);
5152
static void make_setop_translation_lists(Query *query,
5253
Index newvarno,
5354
List **col_mappings, List **translated_vars);
@@ -560,14 +561,34 @@ pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
560561
{
561562
int varno = ((RangeTblRef *) jtnode)->rtindex;
562563
Query *subquery = rte->subquery;
564+
int rtoffset;
565+
List *rtable;
563566

564567
/*
565-
* Recursively scan the subquery's setOperations tree and copy the leaf
566-
* subqueries into the parent rangetable. Add AppendRelInfo nodes for
567-
* them to the parent's append_rel_list, too.
568+
* Append the subquery rtable entries to upper query.
569+
*/
570+
rtoffset = list_length(root->parse->rtable);
571+
572+
/*
573+
* Append child RTEs to parent rtable.
574+
*
575+
* Upper-level vars in subquery are now one level closer to their
576+
* parent than before. We don't have to worry about offsetting
577+
* varnos, though, because any such vars must refer to stuff above the
578+
* level of the query we are pulling into.
579+
*/
580+
rtable = copyObject(subquery->rtable);
581+
IncrementVarSublevelsUp_rtable(rtable, -1, 1);
582+
root->parse->rtable = list_concat(root->parse->rtable, rtable);
583+
584+
/*
585+
* Recursively scan the subquery's setOperations tree and add
586+
* AppendRelInfo nodes for leaf subqueries to the parent's
587+
* append_rel_list.
568588
*/
569589
Assert(subquery->setOperations);
570-
pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery);
590+
pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
591+
rtoffset);
571592

572593
/*
573594
* Mark the parent as an append relation.
@@ -583,41 +604,26 @@ pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
583604
* Note that setOpQuery is the Query containing the setOp node, whose rtable
584605
* is where to look up the RTE if setOp is a RangeTblRef. This is *not* the
585606
* same as root->parse, which is the top-level Query we are pulling up into.
607+
*
586608
* parentRTindex is the appendrel parent's index in root->parse->rtable.
609+
*
610+
* The child RTEs have already been copied to the parent. childRToffset
611+
* tells us where in the parent's range table they were copied.
587612
*/
588613
static void
589614
pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
590-
Query *setOpQuery)
615+
Query *setOpQuery, int childRToffset)
591616
{
592617
if (IsA(setOp, RangeTblRef))
593618
{
594619
RangeTblRef *rtr = (RangeTblRef *) setOp;
595-
RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
596-
Query *subquery;
597620
int childRTindex;
598621
AppendRelInfo *appinfo;
599-
Query *parse = root->parse;
600-
601-
/*
602-
* Make a modifiable copy of the child RTE and contained query.
603-
*/
604-
rte = copyObject(rte);
605-
subquery = rte->subquery;
606-
Assert(subquery != NULL);
607-
608-
/*
609-
* Upper-level vars in subquery are now one level closer to their
610-
* parent than before. We don't have to worry about offsetting
611-
* varnos, though, because any such vars must refer to stuff above the
612-
* level of the query we are pulling into.
613-
*/
614-
IncrementVarSublevelsUp((Node *) subquery, -1, 1);
615622

616623
/*
617-
* Attach child RTE to parent rtable.
624+
* Calculate the index in the parent's range table
618625
*/
619-
parse->rtable = lappend(parse->rtable, rte);
620-
childRTindex = list_length(parse->rtable);
626+
childRTindex = childRToffset + rtr->rtindex;
621627

622628
/*
623629
* 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,
649655
SetOperationStmt *op = (SetOperationStmt *) setOp;
650656

651657
/* Recurse to reach leaf queries */
652-
pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery);
653-
pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery);
658+
pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
659+
childRToffset);
660+
pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
661+
childRToffset);
654662
}
655663
else
656664
{

src/backend/rewrite/rewriteManip.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.108 2008/08/14 18:47:59 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.109 2008/08/14 20:31:29 heikki Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -533,6 +533,25 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
533533
0);
534534
}
535535

536+
/*
537+
* IncrementVarSublevelsUp_rtable -
538+
* Same as IncrementVarSublevelsUp, but to be invoked on a range table.
539+
*/
540+
void
541+
IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up,
542+
int min_sublevels_up)
543+
{
544+
IncrementVarSublevelsUp_context context;
545+
546+
context.delta_sublevels_up = delta_sublevels_up;
547+
context.min_sublevels_up = min_sublevels_up;
548+
549+
range_table_walker(rtable,
550+
IncrementVarSublevelsUp_walker,
551+
(void *) &context,
552+
0);
553+
}
554+
536555

537556
/*
538557
* rangeTableEntry_used - detect whether an RTE is referenced somewhere

src/include/rewrite/rewriteManip.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.44 2008/01/01 19:45:58 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.45 2008/08/14 20:31:29 heikki Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -22,6 +22,8 @@ extern void ChangeVarNodes(Node *node, int old_varno, int new_varno,
2222
int sublevels_up);
2323
extern void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
2424
int min_sublevels_up);
25+
extern void IncrementVarSublevelsUp_rtable(List *rtable,
26+
int delta_sublevels_up, int min_sublevels_up);
2527

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

0 commit comments

Comments
 (0)