Fix subquery pullup logic to not be fooled when a view that appears

'simple' references another view that is not simple.  Must recheck
conditions after performing recursive pullup.  Per example from
Laurent Perez, 9-Jan-04.
This commit is contained in:
Tom Lane 2004-01-10 00:30:21 +00:00
parent 6bd343329e
commit e439fef6fc
1 changed files with 33 additions and 5 deletions

View File

@ -16,7 +16,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.14 2003/11/29 19:51:51 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.15 2004/01/10 00:30:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -168,10 +168,11 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
List *rt;
/*
* First make a modifiable copy of the subquery. This avoids
* problems if the same subquery is referenced from multiple
* jointree items (which can't happen normally, but might after
* rule rewriting).
* Need a modifiable copy of the subquery to hack on. Even if
* we didn't sometimes choose not to pull up below, we must do
* this to avoid problems if the same subquery is referenced from
* multiple jointree items (which can't happen normally, but might
* after rule rewriting).
*/
subquery = copyObject(subquery);
@ -196,6 +197,33 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
pull_up_subqueries(subquery, (Node *) subquery->jointree,
false);
/*
* Now we must recheck whether the subquery is still simple
* enough to pull up. If not, abandon processing it.
*
* We don't really need to recheck all the conditions involved,
* but it's easier just to keep this "if" looking the same as
* the one above.
*/
if (is_simple_subquery(subquery) &&
(!below_outer_join || has_nullable_targetlist(subquery)) &&
!contain_whole_tuple_var((Node *) parse, varno, 0))
{
/* good to go */
}
else
{
/*
* Give up, return unmodified RangeTblRef.
*
* Note: The work we just did will be redone when the
* subquery gets planned on its own. Perhaps we could avoid
* that by storing the modified subquery back into the
* rangetable, but I'm not gonna risk it now.
*/
return jtnode;
}
/*
* Adjust level-0 varnos in subquery so that we can append its
* rangetable to upper query's.