]> granicus.if.org Git - postgresql/commitdiff
Fix subquery pullup logic to not be fooled when a view that appears
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 10 Jan 2004 00:30:21 +0000 (00:30 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 10 Jan 2004 00:30:21 +0000 (00:30 +0000)
'simple' references another view that is not simple.  Must recheck
conditions after performing recursive pullup.  Per example from
Laurent Perez, 9-Jan-04.

src/backend/optimizer/prep/prepjointree.c

index 7aa191644add239637cd6bb241396f5497468303..90485171d9786c62796452aa803fefcb47c1875d 100644 (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.