Repair interaction between IN-join processing and subselect pullup that
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 18 Oct 2003 16:52:15 +0000 (16:52 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 18 Oct 2003 16:52:15 +0000 (16:52 +0000)
I inadvertently broke a few days ago (per report from Sean Thomas).
Add regression test case to try to catch any similar breakage in future.

src/backend/optimizer/plan/subselect.c
src/test/regress/expected/subselect.out
src/test/regress/sql/subselect.sql

index d7d25c09f80aea4a85f68209500c6846a29bcf65..11612f408c9817446b0afc3593ef588abd989a16 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.82 2003/08/08 21:41:51 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.83 2003/10/18 16:52:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -493,8 +493,8 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
  * If rtindex is 0, we build Params to represent the sub-select outputs.
  * The paramids of the Params created are returned in the *righthandIds list.
  *
- * If rtindex is not 0, we build Vars using that rtindex as varno. The
- * Vars themselves are returned in *righthandIds (this is a bit of a type
+ * If rtindex is not 0, we build Vars using that rtindex as varno. Copies
+ * of the Var nodes are returned in *righthandIds (this is a bit of a type
  * cheat, but we can get away with it).
  */
 static List *
@@ -525,8 +525,11 @@ convert_sublink_opers(List *lefthand, List *operOids,
                                       te->resdom->restype,
                                       te->resdom->restypmod,
                                       0);
-           /* Record it for caller */
-           *righthandIds = lappend(*righthandIds, rightop);
+           /*
+            * Copy it for caller.  NB: we need a copy to avoid having
+            * doubly-linked substructure in the modified parse tree.
+            */
+           *righthandIds = lappend(*righthandIds, copyObject(rightop));
        }
        else
        {
@@ -735,7 +738,7 @@ convert_IN_to_join(Query *parse, SubLink *sublink)
 
    /*
     * Build the result qual expressions.  As a side effect,
-    * ininfo->sub_targetlist is filled with a list of the Vars
+    * ininfo->sub_targetlist is filled with a list of Vars
     * representing the subselect outputs.
     */
    exprs = convert_sublink_opers(sublink->lefthand,
index 5a2ef11c21b9cb294b74e89b8a9fdf1638f059d1..f7b8297809f98101aa2856da0e49fd43456580a7 100644 (file)
@@ -165,3 +165,39 @@ from int8_tbl group by q1 order by q1;
  4567890123456789 |      0.6
 (2 rows)
 
+--
+-- Test cases to catch unpleasant interactions between IN-join processing
+-- and subquery pullup.
+--
+select count(*) from
+  (select 1 from tenk1 a
+   where unique1 IN (select hundred from tenk1 b)) ss;
+ count 
+-------
+   100
+(1 row)
+
+select count(distinct ss.ten) from
+  (select ten from tenk1 a
+   where unique1 IN (select hundred from tenk1 b)) ss;
+ count 
+-------
+    10
+(1 row)
+
+select count(*) from
+  (select 1 from tenk1 a
+   where unique1 IN (select distinct hundred from tenk1 b)) ss;
+ count 
+-------
+   100
+(1 row)
+
+select count(distinct ss.ten) from
+  (select ten from tenk1 a
+   where unique1 IN (select distinct hundred from tenk1 b)) ss;
+ count 
+-------
+    10
+(1 row)
+
index c2cde6ac2071d7441669e79b215aa7388d57248f..5ff9d1cf875c44dc563a856e80e61a2b13980801 100644 (file)
@@ -75,3 +75,21 @@ SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field"
 
 select q1, float8(count(*)) / (select count(*) from int8_tbl)
 from int8_tbl group by q1 order by q1;
+
+--
+-- Test cases to catch unpleasant interactions between IN-join processing
+-- and subquery pullup.
+--
+
+select count(*) from
+  (select 1 from tenk1 a
+   where unique1 IN (select hundred from tenk1 b)) ss;
+select count(distinct ss.ten) from
+  (select ten from tenk1 a
+   where unique1 IN (select hundred from tenk1 b)) ss;
+select count(*) from
+  (select 1 from tenk1 a
+   where unique1 IN (select distinct hundred from tenk1 b)) ss;
+select count(distinct ss.ten) from
+  (select ten from tenk1 a
+   where unique1 IN (select distinct hundred from tenk1 b)) ss;