diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index da6482b4c3c172ad79738789821d1a956748de7b..a06e647f4b8b2983a477495deb7d3f4d564c531a 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/analyzejoins.c,v 1.1 2010/03/28 22:59:32 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/analyzejoins.c,v 1.2 2010/05/23 16:34:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -343,6 +343,24 @@ remove_rel_from_query(PlannerInfo *root, int relid)
 		}
 	}
 
+	/*
+	 * Likewise remove references from SpecialJoinInfo data structures.
+	 *
+	 * This is relevant in case the outer join we're deleting is nested
+	 * inside other outer joins: the upper joins' relid sets have to be
+	 * adjusted.  The RHS of the target outer join will be made empty here,
+	 * but that's OK since caller will delete that SpecialJoinInfo entirely.
+	 */
+	foreach(l, root->join_info_list)
+	{
+		SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
+
+		sjinfo->min_lefthand = bms_del_member(sjinfo->min_lefthand, relid);
+		sjinfo->min_righthand = bms_del_member(sjinfo->min_righthand, relid);
+		sjinfo->syn_lefthand = bms_del_member(sjinfo->syn_lefthand, relid);
+		sjinfo->syn_righthand = bms_del_member(sjinfo->syn_righthand, relid);
+	}
+
 	/*
 	 * Likewise remove references from PlaceHolderVar data structures.
 	 *
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 5fd7d79b45d6496e7455b9cc15029e49ccebee76..6dfc710be01d7e40a5f834f79290c9beb782c60c 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2525,6 +2525,20 @@ explain (costs off)
  Seq Scan on a
 (1 row)
 
+-- check optimization of outer join within another special join
+explain (costs off)
+select id from a where id in (
+	select b.id from b left join c on b.id = c.id
+);
+         QUERY PLAN         
+----------------------------
+ Hash Semi Join
+   Hash Cond: (a.id = b.id)
+   ->  Seq Scan on a
+   ->  Hash
+         ->  Seq Scan on b
+(5 rows)
+
 rollback;
 create temp table parent (k int primary key, pd int);
 NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "parent_pkey" for table "parent"
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index d627973a091fbe7625eaf0555a6f4e144864b341..8657636757a3e3c7a5b71bdb0a5d78547a4f5e4a 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -588,6 +588,12 @@ explain (costs off)
   SELECT a.* FROM a LEFT JOIN (b left join c on b.c_id = c.id)
   ON (a.b_id = b.id);
 
+-- check optimization of outer join within another special join
+explain (costs off)
+select id from a where id in (
+	select b.id from b left join c on b.id = c.id
+);
+
 rollback;
 
 create temp table parent (k int primary key, pd int);