diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index ea48d2f07a..17c13d6858 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;