aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/rewrite/rewriteManip.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index ea48d2f07a3..17c13d68585 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.79 2003/09/25 06:58:01 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.80 2003/10/20 20:01:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -99,7 +99,7 @@ bool
checkExprHasSubLink(Node *node)
{
/*
- * If a Query is passed, examine it --- but we will not recurse into
+ * If a Query is passed, examine it --- but we need not recurse into
* sub-Queries.
*/
return query_or_expression_tree_walker(node,
@@ -755,10 +755,12 @@ AddQual(Query *parsetree, Node *qual)
/*
* Make sure query is marked correctly if added qual has sublinks or
* aggregates (not sure it can ever have aggs, but sublinks
- * definitely).
+ * definitely). Need not search qual when query is already marked.
*/
- parsetree->hasAggs |= checkExprHasAggs(copy);
- parsetree->hasSubLinks |= checkExprHasSubLink(copy);
+ if (!parsetree->hasAggs)
+ parsetree->hasAggs = checkExprHasAggs(copy);
+ if (!parsetree->hasSubLinks)
+ parsetree->hasSubLinks = checkExprHasSubLink(copy);
}
/*
@@ -809,10 +811,12 @@ AddHavingQual(Query *parsetree, Node *havingQual)
/*
* Make sure query is marked correctly if added qual has sublinks or
* aggregates (not sure it can ever have aggs, but sublinks
- * definitely).
+ * definitely). Need not search qual when query is already marked.
*/
- parsetree->hasAggs |= checkExprHasAggs(copy);
- parsetree->hasSubLinks |= checkExprHasSubLink(copy);
+ if (!parsetree->hasAggs)
+ parsetree->hasAggs = checkExprHasAggs(copy);
+ if (!parsetree->hasSubLinks)
+ parsetree->hasSubLinks = checkExprHasSubLink(copy);
}
@@ -845,6 +849,12 @@ AddInvertedQual(Query *parsetree, Node *qual)
* entry with matching resno from targetlist, if there is one.
* If not, we either change the unmatched Var's varno to update_varno
* (when event == CMD_UPDATE) or replace it with a constant NULL.
+ *
+ * Note: the business with inserted_sublink is needed to update hasSubLinks
+ * in subqueries when the replacement adds a subquery inside a subquery.
+ * Messy, isn't it? We do not need to do similar pushups for hasAggs,
+ * because it isn't possible for this transformation to insert a level-zero
+ * aggregate reference into a subquery --- it could only insert outer aggs.
*/
typedef struct
@@ -854,6 +864,7 @@ typedef struct
List *targetlist;
int event;
int update_varno;
+ bool inserted_sublink;
} ResolveNew_context;
static Node *
@@ -904,6 +915,9 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
/* Adjust varlevelsup if tlist item is from higher query */
if (this_varlevelsup > 0)
IncrementVarSublevelsUp(n, this_varlevelsup, 0);
+ /* Report it if we are adding a sublink to query */
+ if (!context->inserted_sublink)
+ context->inserted_sublink = checkExprHasSubLink(n);
return n;
}
}
@@ -914,12 +928,17 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
Query *newnode;
+ bool save_inserted_sublink;
context->sublevels_up++;
+ save_inserted_sublink = context->inserted_sublink;
+ context->inserted_sublink = false;
newnode = query_tree_mutator((Query *) node,
ResolveNew_mutator,
(void *) context,
0);
+ newnode->hasSubLinks |= context->inserted_sublink;
+ context->inserted_sublink = save_inserted_sublink;
context->sublevels_up--;
return (Node *) newnode;
}
@@ -938,6 +957,7 @@ ResolveNew(Node *node, int target_varno, int sublevels_up,
context.targetlist = targetlist;
context.event = event;
context.update_varno = update_varno;
+ context.inserted_sublink = false;
/*
* Must be prepared to start with a Query or a bare expression tree;