Index: src/backend/optimizer/path/pathkeys.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v
retrieving revision 1.79
diff -c -r1.79 pathkeys.c
*** src/backend/optimizer/path/pathkeys.c	4 Oct 2006 00:29:54 -0000	1.79
--- src/backend/optimizer/path/pathkeys.c	8 Jan 2008 21:04:22 -0000
***************
*** 423,437 ****
  									 false);
  
  			/*
! 			 * We can remove explicit tests of this outer-join qual, too,
! 			 * since we now have tests forcing each of its sides to the same
! 			 * value.
  			 */
! 			process_implied_equality(root,
! 									 leftop, rightop,
! 									 rinfo->left_sortop, rinfo->right_sortop,
! 									 rinfo->left_relids, rinfo->right_relids,
! 									 true);
  
  			/*
  			 * And recurse to see if we can deduce anything from INNERVAR =
--- 423,438 ----
  									 false);
  
  			/*
! 			 * We used to think we could remove explicit tests of this
! 			 * outer-join qual, too, since we now have tests forcing each of
! 			 * its sides to the same value.  However, that fails in some
! 			 * corner cases where lower outer joins could cause one of the
! 			 * variables to go to NULL.  (BUG in 8.2 through 8.2.6.)
! 			 * So now we just leave it in place, but mark it with selectivity
! 			 * 1.0 so that we don't underestimate the join size output ---
! 			 * it's mostly redundant with the constant constraints.
  			 */
! 			rinfo->this_selec = 1.0;
  
  			/*
  			 * And recurse to see if we can deduce anything from INNERVAR =
***************
*** 465,479 ****
  									 false);
  
  			/*
! 			 * We can remove explicit tests of this outer-join qual, too,
! 			 * since we now have tests forcing each of its sides to the same
! 			 * value.
  			 */
! 			process_implied_equality(root,
! 									 leftop, rightop,
! 									 rinfo->left_sortop, rinfo->right_sortop,
! 									 rinfo->left_relids, rinfo->right_relids,
! 									 true);
  
  			/*
  			 * And recurse to see if we can deduce anything from INNERVAR =
--- 466,481 ----
  									 false);
  
  			/*
! 			 * We used to think we could remove explicit tests of this
! 			 * outer-join qual, too, since we now have tests forcing each of
! 			 * its sides to the same value.  However, that fails in some
! 			 * corner cases where lower outer joins could cause one of the
! 			 * variables to go to NULL.  (BUG in 8.2 through 8.2.6.)
! 			 * So now we just leave it in place, but mark it with selectivity
! 			 * 1.0 so that we don't underestimate the join size output ---
! 			 * it's mostly redundant with the constant constraints.
  			 */
! 			rinfo->this_selec = 1.0;
  
  			/*
  			 * And recurse to see if we can deduce anything from INNERVAR =
***************
*** 542,566 ****
  										 rinfo->right_sortop,
  										 rinfo->right_relids,
  										 false);
- 				/* ... and remove COALESCE() = CONSTANT */
- 				process_implied_const_eq(root, equi_key_set, relids,
- 										 item1,
- 										 sortop1,
- 										 item1_relids,
- 										 true);
  
  				/*
! 				 * We can remove explicit tests of this outer-join qual, too,
! 				 * since we now have tests forcing each of its sides to the
! 				 * same value.
  				 */
! 				process_implied_equality(root,
! 										 leftop, rightop,
! 										 rinfo->left_sortop,
! 										 rinfo->right_sortop,
! 										 rinfo->left_relids,
! 										 rinfo->right_relids,
! 										 true);
  
  				/*
  				 * And recurse to see if we can deduce anything from LEFTVAR =
--- 544,565 ----
  										 rinfo->right_sortop,
  										 rinfo->right_relids,
  										 false);
  
  				/*
! 				 * We used to think we could remove explicit tests of this
! 				 * outer-join qual, too, since we now have tests forcing each
! 				 * of its sides to the same value.  However, that fails in
! 				 * some corner cases where lower outer joins could cause one
! 				 * of the variables to go to NULL.  (BUG in 8.2 through
! 				 * 8.2.6.)  So now we just leave it in place, but mark it with
! 				 * selectivity 1.0 so that we don't underestimate the join
! 				 * size output --- it's mostly redundant with the constant
! 				 * constraints.
! 				 *
! 				 * Ideally we'd do that for the COALESCE() = CONSTANT rinfo,
! 				 * too, but we don't have easy access to that here.
  				 */
! 				rinfo->this_selec = 1.0;
  
  				/*
  				 * And recurse to see if we can deduce anything from LEFTVAR =
Index: src/test/regress/expected/join.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/join.out,v
retrieving revision 1.28.2.4
diff -c -r1.28.2.4 join.out
*** src/test/regress/expected/join.out	31 Aug 2007 01:44:14 -0000	1.28.2.4
--- src/test/regress/expected/join.out	8 Jan 2008 21:04:22 -0000
***************
*** 2290,2292 ****
--- 2290,2323 ----
       301 |         |          |          |        1
  (3 rows)
  
+ --
+ -- regression test for improper pushing of constants across outer-join clauses
+ -- (as seen in early 8.2.x releases)
+ --
+ create temp table zt1 (f1 int primary key);
+ NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "zt1_pkey" for table "zt1"
+ create temp table zt2 (f2 int primary key);
+ NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "zt2_pkey" for table "zt2"
+ create temp table zt3 (f3 int primary key);
+ NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "zt3_pkey" for table "zt3"
+ insert into zt1 values(53);
+ insert into zt2 values(53);
+ select * from
+   zt2 left join zt3 on (f2 = f3)
+       left join zt1 on (f3 = f1)
+ where f2 = 53;
+  f2 | f3 | f1 
+ ----+----+----
+  53 |    |   
+ (1 row)
+ 
+ create temp view zv1 as select *,'dummy'::text AS junk from zt1;
+ select * from
+   zt2 left join zt3 on (f2 = f3)
+       left join zv1 on (f3 = f1)
+ where f2 = 53;
+  f2 | f3 | f1 | junk 
+ ----+----+----+------
+  53 |    |    | 
+ (1 row)
+ 
Index: src/test/regress/expected/join_1.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/join_1.out,v
retrieving revision 1.10.2.4
diff -c -r1.10.2.4 join_1.out
*** src/test/regress/expected/join_1.out	31 Aug 2007 01:44:14 -0000	1.10.2.4
--- src/test/regress/expected/join_1.out	8 Jan 2008 21:04:22 -0000
***************
*** 2290,2292 ****
--- 2290,2323 ----
       301 |         |          |          |        1
  (3 rows)
  
+ --
+ -- regression test for improper pushing of constants across outer-join clauses
+ -- (as seen in early 8.2.x releases)
+ --
+ create temp table zt1 (f1 int primary key);
+ NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "zt1_pkey" for table "zt1"
+ create temp table zt2 (f2 int primary key);
+ NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "zt2_pkey" for table "zt2"
+ create temp table zt3 (f3 int primary key);
+ NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "zt3_pkey" for table "zt3"
+ insert into zt1 values(53);
+ insert into zt2 values(53);
+ select * from
+   zt2 left join zt3 on (f2 = f3)
+       left join zt1 on (f3 = f1)
+ where f2 = 53;
+  f2 | f3 | f1 
+ ----+----+----
+  53 |    |   
+ (1 row)
+ 
+ create temp view zv1 as select *,'dummy'::text AS junk from zt1;
+ select * from
+   zt2 left join zt3 on (f2 = f3)
+       left join zv1 on (f3 = f1)
+ where f2 = 53;
+  f2 | f3 | f1 | junk 
+ ----+----+----+------
+  53 |    |    | 
+ (1 row)
+ 
Index: src/test/regress/sql/join.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/join.sql,v
retrieving revision 1.19.2.4
diff -c -r1.19.2.4 join.sql
*** src/test/regress/sql/join.sql	31 Aug 2007 01:44:14 -0000	1.19.2.4
--- src/test/regress/sql/join.sql	8 Jan 2008 21:04:22 -0000
***************
*** 462,464 ****
--- 462,487 ----
       left join (SELECT * FROM yy where pkyy = 101) as yya ON yy.pkyy = yya.pkyy
       left join xx xxa on yya.pkxx = xxa.pkxx
       left join xx xxb on coalesce (xxa.pkxx, 1) = xxb.pkxx;
+ 
+ --
+ -- regression test for improper pushing of constants across outer-join clauses
+ -- (as seen in early 8.2.x releases)
+ --
+ 
+ create temp table zt1 (f1 int primary key);
+ create temp table zt2 (f2 int primary key);
+ create temp table zt3 (f3 int primary key);
+ insert into zt1 values(53);
+ insert into zt2 values(53);
+ 
+ select * from
+   zt2 left join zt3 on (f2 = f3)
+       left join zt1 on (f3 = f1)
+ where f2 = 53;
+ 
+ create temp view zv1 as select *,'dummy'::text AS junk from zt1;
+ 
+ select * from
+   zt2 left join zt3 on (f2 = f3)
+       left join zv1 on (f3 = f1)
+ where f2 = 53;
