aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2008-08-14 20:31:29 +0000
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2008-08-14 20:31:29 +0000
commitf24f233f6a9fb3af211c2fc658c5068e63593a8c (patch)
tree410b5c1e6ccf7441eef2c3e4f9912f7b1658a36d /src
parente006a24ad152b3faec748afe8c1ff0829699b2e6 (diff)
downloadpostgresql-f24f233f6a9fb3af211c2fc658c5068e63593a8c.tar.gz
postgresql-f24f233f6a9fb3af211c2fc658c5068e63593a8c.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/prep/prepjointree.c68
-rw-r--r--src/backend/rewrite/rewriteManip.c21
-rw-r--r--src/include/rewrite/rewriteManip.h4
3 files changed, 61 insertions, 32 deletions
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index b4be3d8d0c1..241ad668072 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -16,7 +16,7 @@
*
*
* 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,
RangeTblEntry *rte);
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,
Index newvarno,
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;
Query *subquery = rte->subquery;
+ int rtoffset;
+ List *rtable;
/*
- * 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.
+ * 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);
+ pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
+ rtoffset);
/*
* 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
* 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)
+ Query *setOpQuery, int childRToffset)
{
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.
+ * Calculate the index in the parent's range table
*/
- parse->rtable = lappend(parse->rtable, rte);
- childRTindex = list_length(parse->rtable);
+ childRTindex = childRToffset + rtr->rtindex;
/*
* 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;
/* 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);
+ pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
+ childRToffset);
+ pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
+ childRToffset);
}
else
{
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 60492fe3d09..1202c31314d 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -7,7 +7,7 @@
*
*
* 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);
}
+/*
+ * 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
diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h
index 05da127ffae..110d8ac0d11 100644
--- a/src/include/rewrite/rewriteManip.h
+++ b/src/include/rewrite/rewriteManip.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* 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);
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);