diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out
index 0eecade..16ed8e6 100644
--- a/src/test/regress/expected/partition_join.out
+++ b/src/test/regress/expected/partition_join.out
@@ -3993,6 +3993,416 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l t1 WHERE t1.a % 25 = 0
      |      | 525 | 0525
 (16 rows)
 
+-- Cases with non-nullable expressions in subquery results;
+-- make sure these go to null as expected
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM (SELECT 50 phv, * FROM prt1_l WHERE prt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2_l WHERE prt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and t2.a + t2.b = t1.b + t1.a) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+                                                                                                                 QUERY PLAN                                                                                                                 
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: (50), prt1_l_p1_p1.a, prt1_l_p1_p1.b, prt1_l_p1_p1.c, (75), prt2_l_p1_p1.a, prt2_l_p1_p1.b, prt2_l_p1_p1.c
+   Sort Key: (50), prt1_l_p1_p1.a, prt1_l_p1_p1.b, prt1_l_p1_p1.c, (75), prt2_l_p1_p1.a, prt2_l_p1_p1.b, prt2_l_p1_p1.c
+   ->  Result
+         Output: (50), prt1_l_p1_p1.a, prt1_l_p1_p1.b, prt1_l_p1_p1.c, (75), prt2_l_p1_p1.a, prt2_l_p1_p1.b, prt2_l_p1_p1.c
+         ->  Append
+               ->  Hash Full Join
+                     Output: prt1_l_p1_p1.a, prt1_l_p1_p1.b, prt1_l_p1_p1.c, prt2_l_p1_p1.a, prt2_l_p1_p1.b, prt2_l_p1_p1.c, (50), (75)
+                     Hash Cond: ((prt1_l_p1_p1.a = prt2_l_p1_p1.b) AND (prt1_l_p1_p1.b = prt2_l_p1_p1.a) AND ((prt1_l_p1_p1.c)::text = (prt2_l_p1_p1.c)::text) AND ((prt1_l_p1_p1.b + prt1_l_p1_p1.a) = (prt2_l_p1_p1.a + prt2_l_p1_p1.b)))
+                     Filter: (((50) = prt1_l_p1_p1.b) OR ((75) = prt2_l_p1_p1.b))
+                     ->  Seq Scan on public.prt1_l_p1_p1
+                           Output: prt1_l_p1_p1.a, prt1_l_p1_p1.b, prt1_l_p1_p1.c, 50
+                           Filter: ((prt1_l_p1_p1.a % 25) = 0)
+                     ->  Hash
+                           Output: prt2_l_p1_p1.a, prt2_l_p1_p1.b, prt2_l_p1_p1.c, (75)
+                           ->  Seq Scan on public.prt2_l_p1_p1
+                                 Output: prt2_l_p1_p1.a, prt2_l_p1_p1.b, prt2_l_p1_p1.c, 75
+                                 Filter: ((prt2_l_p1_p1.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: prt1_l_p1_p2.a, prt1_l_p1_p2.b, prt1_l_p1_p2.c, prt2_l_p1_p2.a, prt2_l_p1_p2.b, prt2_l_p1_p2.c, (50), (75)
+                     Hash Cond: ((prt1_l_p1_p2.a = prt2_l_p1_p2.b) AND (prt1_l_p1_p2.b = prt2_l_p1_p2.a) AND ((prt1_l_p1_p2.c)::text = (prt2_l_p1_p2.c)::text) AND ((prt1_l_p1_p2.b + prt1_l_p1_p2.a) = (prt2_l_p1_p2.a + prt2_l_p1_p2.b)))
+                     Filter: (((50) = prt1_l_p1_p2.b) OR ((75) = prt2_l_p1_p2.b))
+                     ->  Seq Scan on public.prt1_l_p1_p2
+                           Output: prt1_l_p1_p2.a, prt1_l_p1_p2.b, prt1_l_p1_p2.c, 50
+                           Filter: ((prt1_l_p1_p2.a % 25) = 0)
+                     ->  Hash
+                           Output: prt2_l_p1_p2.a, prt2_l_p1_p2.b, prt2_l_p1_p2.c, (75)
+                           ->  Seq Scan on public.prt2_l_p1_p2
+                                 Output: prt2_l_p1_p2.a, prt2_l_p1_p2.b, prt2_l_p1_p2.c, 75
+                                 Filter: ((prt2_l_p1_p2.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: prt1_l_p2_p1.a, prt1_l_p2_p1.b, prt1_l_p2_p1.c, prt2_l_p2_p1.a, prt2_l_p2_p1.b, prt2_l_p2_p1.c, (50), (75)
+                     Hash Cond: ((prt1_l_p2_p1.a = prt2_l_p2_p1.b) AND (prt1_l_p2_p1.b = prt2_l_p2_p1.a) AND ((prt1_l_p2_p1.c)::text = (prt2_l_p2_p1.c)::text) AND ((prt1_l_p2_p1.b + prt1_l_p2_p1.a) = (prt2_l_p2_p1.a + prt2_l_p2_p1.b)))
+                     Filter: (((50) = prt1_l_p2_p1.b) OR ((75) = prt2_l_p2_p1.b))
+                     ->  Seq Scan on public.prt1_l_p2_p1
+                           Output: prt1_l_p2_p1.a, prt1_l_p2_p1.b, prt1_l_p2_p1.c, 50
+                           Filter: ((prt1_l_p2_p1.a % 25) = 0)
+                     ->  Hash
+                           Output: prt2_l_p2_p1.a, prt2_l_p2_p1.b, prt2_l_p2_p1.c, (75)
+                           ->  Seq Scan on public.prt2_l_p2_p1
+                                 Output: prt2_l_p2_p1.a, prt2_l_p2_p1.b, prt2_l_p2_p1.c, 75
+                                 Filter: ((prt2_l_p2_p1.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: prt1_l_p2_p2.a, prt1_l_p2_p2.b, prt1_l_p2_p2.c, prt2_l_p2_p2.a, prt2_l_p2_p2.b, prt2_l_p2_p2.c, (50), (75)
+                     Hash Cond: ((prt1_l_p2_p2.a = prt2_l_p2_p2.b) AND (prt1_l_p2_p2.b = prt2_l_p2_p2.a) AND ((prt1_l_p2_p2.c)::text = (prt2_l_p2_p2.c)::text) AND ((prt1_l_p2_p2.b + prt1_l_p2_p2.a) = (prt2_l_p2_p2.a + prt2_l_p2_p2.b)))
+                     Filter: (((50) = prt1_l_p2_p2.b) OR ((75) = prt2_l_p2_p2.b))
+                     ->  Seq Scan on public.prt1_l_p2_p2
+                           Output: prt1_l_p2_p2.a, prt1_l_p2_p2.b, prt1_l_p2_p2.c, 50
+                           Filter: ((prt1_l_p2_p2.a % 25) = 0)
+                     ->  Hash
+                           Output: prt2_l_p2_p2.a, prt2_l_p2_p2.b, prt2_l_p2_p2.c, (75)
+                           ->  Seq Scan on public.prt2_l_p2_p2
+                                 Output: prt2_l_p2_p2.a, prt2_l_p2_p2.b, prt2_l_p2_p2.c, 75
+                                 Filter: ((prt2_l_p2_p2.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: prt1_l_p3_p1.a, prt1_l_p3_p1.b, prt1_l_p3_p1.c, prt2_l_p3_p1.a, prt2_l_p3_p1.b, prt2_l_p3_p1.c, (50), (75)
+                     Hash Cond: ((prt1_l_p3_p1.a = prt2_l_p3_p1.b) AND (prt1_l_p3_p1.b = prt2_l_p3_p1.a) AND ((prt1_l_p3_p1.c)::text = (prt2_l_p3_p1.c)::text) AND ((prt1_l_p3_p1.b + prt1_l_p3_p1.a) = (prt2_l_p3_p1.a + prt2_l_p3_p1.b)))
+                     Filter: (((50) = prt1_l_p3_p1.b) OR ((75) = prt2_l_p3_p1.b))
+                     ->  Seq Scan on public.prt1_l_p3_p1
+                           Output: prt1_l_p3_p1.a, prt1_l_p3_p1.b, prt1_l_p3_p1.c, 50
+                           Filter: ((prt1_l_p3_p1.a % 25) = 0)
+                     ->  Hash
+                           Output: prt2_l_p3_p1.a, prt2_l_p3_p1.b, prt2_l_p3_p1.c, (75)
+                           ->  Seq Scan on public.prt2_l_p3_p1
+                                 Output: prt2_l_p3_p1.a, prt2_l_p3_p1.b, prt2_l_p3_p1.c, 75
+                                 Filter: ((prt2_l_p3_p1.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: prt1_l_p3_p2.a, prt1_l_p3_p2.b, prt1_l_p3_p2.c, prt2_l_p3_p2.a, prt2_l_p3_p2.b, prt2_l_p3_p2.c, (50), (75)
+                     Hash Cond: ((prt1_l_p3_p2.a = prt2_l_p3_p2.b) AND (prt1_l_p3_p2.b = prt2_l_p3_p2.a) AND ((prt1_l_p3_p2.c)::text = (prt2_l_p3_p2.c)::text) AND ((prt1_l_p3_p2.b + prt1_l_p3_p2.a) = (prt2_l_p3_p2.a + prt2_l_p3_p2.b)))
+                     Filter: (((50) = prt1_l_p3_p2.b) OR ((75) = prt2_l_p3_p2.b))
+                     ->  Seq Scan on public.prt1_l_p3_p2
+                           Output: prt1_l_p3_p2.a, prt1_l_p3_p2.b, prt1_l_p3_p2.c, 50
+                           Filter: ((prt1_l_p3_p2.a % 25) = 0)
+                     ->  Hash
+                           Output: prt2_l_p3_p2.a, prt2_l_p3_p2.b, prt2_l_p3_p2.c, (75)
+                           ->  Seq Scan on public.prt2_l_p3_p2
+                                 Output: prt2_l_p3_p2.a, prt2_l_p3_p2.b, prt2_l_p3_p2.c, 75
+                                 Filter: ((prt2_l_p3_p2.b % 25) = 0)
+(78 rows)
+
+SELECT * FROM (SELECT 50 phv, * FROM prt1_l WHERE prt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2_l WHERE prt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and t2.a + t2.b = t1.b + t1.a) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+ phv | a  | b  |  c   | phv | a  | b  |  c   
+-----+----+----+------+-----+----+----+------
+  50 | 50 | 50 | 0050 |     |    |    | 
+     |    |    |      |  75 | 75 | 75 | 0075
+(2 rows)
+
+SELECT * FROM (SELECT 50 phv, * FROM uprt1_l WHERE uprt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2_l WHERE uprt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and t2.a + t2.b = t1.b + t1.a) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+ phv | a  | b  |  c   | phv | a  | b  |  c   
+-----+----+----+------+-----+----+----+------
+  50 | 50 | 50 | 0050 |     |    |    | 
+     |    |    |      |  75 | 75 | 75 | 0075
+(2 rows)
+
+-- Join with pruned partitions from joining relations
+--Getting server crash, need to be fix to get query output
+EXPLAIN (VERBOSE, COSTS OFF) 
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+ 300 | 0300 | 300 | 0300
+(1 row)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_l t1, uprt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+ 300 | 0300 | 300 | 0300
+(1 row)
+
+--Getting server crash, need to be fix to get query output
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |     | 
+  50 | 0050 |     | 
+ 100 | 0100 |     | 
+ 150 | 0150 |     | 
+ 200 | 0200 |     | 
+ 250 | 0250 |     | 
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 |     | 
+ 400 | 0400 |     | 
+(9 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM uprt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |     | 
+  50 | 0050 |     | 
+ 100 | 0100 |     | 
+ 150 | 0150 |     | 
+ 200 | 0200 |     | 
+ 250 | 0250 |     | 
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 |     | 
+ 400 | 0400 |     | 
+(9 rows)
+
+--Getting server crash, need to be fix to get query output
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+ 300 | 0300 | 300 | 0300
+     |      | 375 | 0375
+     |      | 450 | 0450
+     |      | 525 | 0525
+(4 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM uprt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+ 300 | 0300 | 300 | 0300
+     |      | 375 | 0375
+     |      | 450 | 0450
+     |      | 525 | 0525
+(4 rows)
+
+--Getting server crash, need to be fix to get query output
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |     | 
+  50 | 0050 |     | 
+ 100 | 0100 |     | 
+ 150 | 0150 |     | 
+ 200 | 0200 |     | 
+ 250 | 0250 |     | 
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 |     | 
+ 400 | 0400 |     | 
+     |      | 375 | 0375
+     |      | 450 | 0450
+     |      | 525 | 0525
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |     | 
+  50 | 0050 |     | 
+ 100 | 0100 |     | 
+ 150 | 0150 |     | 
+ 200 | 0200 |     | 
+ 250 | 0250 |     | 
+ 300 | 0300 | 300 | 0300
+ 350 | 0350 |     | 
+ 400 | 0400 |     | 
+     |      | 375 | 0375
+     |      | 450 | 0450
+     |      | 525 | 0525
+(12 rows)
+
+-- joins where one of the relations is proven empty
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a = 1 AND t1.a = 2;
+            QUERY PLAN            
+----------------------------------
+ Result
+   Output: t1.a, t1.c, t2.b, t2.c
+   One-Time Filter: false
+(3 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a = 1 AND t1.a = 2;
+ a | c | b | c 
+---+---+---+---
+(0 rows)
+
+--Getting server crash, need to be fix to get query output
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b;
+ a | c | b | c 
+---+---+---+---
+(0 rows)
+
+--Getting server crash, need to be fix to get query output
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0075
+   |   | 150 | 0150
+   |   | 225 | 0225
+   |   | 300 | 0300
+   |   | 375 | 0375
+   |   | 450 | 0450
+   |   | 525 | 0525
+(8 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN uprt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0075
+   |   | 150 | 0150
+   |   | 225 | 0225
+   |   | 300 | 0300
+   |   | 375 | 0375
+   |   | 450 | 0450
+   |   | 525 | 0525
+(8 rows)
+
+--Getting server crash, need to be fix to get query output
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0075
+   |   | 150 | 0150
+   |   | 225 | 0225
+   |   | 300 | 0300
+   |   | 375 | 0375
+   |   | 450 | 0450
+   |   | 525 | 0525
+(8 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN uprt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0075
+   |   | 150 | 0150
+   |   | 225 | 0225
+   |   | 300 | 0300
+   |   | 375 | 0375
+   |   | 450 | 0450
+   |   | 525 | 0525
+(8 rows)
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1_l t1 WHERE t1.a IN (SELECT t1.b FROM prt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+NOTICE:  join between relations (b 1) and (b 3) is considered for partition-wise join.
+                          QUERY PLAN                           
+---------------------------------------------------------------
+ Merge Append
+   Sort Key: t1.a
+   ->  Merge Semi Join
+         Output: t1.a, t1.b, t1.c
+         Merge Cond: (t1.a = t1_9.b)
+         ->  Sort
+               Output: t1.a, t1.b, t1.c
+               Sort Key: t1.a
+               ->  Append
+                     ->  Seq Scan on public.prt1_l_p1 t1
+                           Output: t1.a, t1.b, t1.c
+                           Filter: ((t1.a % 25) = 0)
+                     ->  Seq Scan on public.prt1_l_p1_p1 t1_1
+                           Output: t1_1.a, t1_1.b, t1_1.c
+                           Filter: ((t1_1.a % 25) = 0)
+                     ->  Seq Scan on public.prt1_l_p1_p2 t1_2
+                           Output: t1_2.a, t1_2.b, t1_2.c
+                           Filter: ((t1_2.a % 25) = 0)
+         ->  Sort
+               Output: t1_9.b
+               Sort Key: t1_9.b
+               ->  Append
+                     ->  Seq Scan on public.prt2_l_p1 t1_9
+                           Output: t1_9.b
+                           Filter: ((t1_9.b % 25) = 0)
+                     ->  Seq Scan on public.prt2_l_p1_p1 t1_10
+                           Output: t1_10.b
+                           Filter: ((t1_10.b % 25) = 0)
+                     ->  Seq Scan on public.prt2_l_p1_p2 t1_11
+                           Output: t1_11.b
+                           Filter: ((t1_11.b % 25) = 0)
+   ->  Merge Semi Join
+         Output: t1_3.a, t1_3.b, t1_3.c
+         Merge Cond: (t1_3.a = t1_12.b)
+         ->  Sort
+               Output: t1_3.a, t1_3.b, t1_3.c
+               Sort Key: t1_3.a
+               ->  Append
+                     ->  Seq Scan on public.prt1_l_p2 t1_3
+                           Output: t1_3.a, t1_3.b, t1_3.c
+                           Filter: ((t1_3.a % 25) = 0)
+                     ->  Seq Scan on public.prt1_l_p2_p1 t1_4
+                           Output: t1_4.a, t1_4.b, t1_4.c
+                           Filter: ((t1_4.a % 25) = 0)
+                     ->  Seq Scan on public.prt1_l_p2_p2 t1_5
+                           Output: t1_5.a, t1_5.b, t1_5.c
+                           Filter: ((t1_5.a % 25) = 0)
+         ->  Sort
+               Output: t1_12.b
+               Sort Key: t1_12.b
+               ->  Append
+                     ->  Seq Scan on public.prt2_l_p2 t1_12
+                           Output: t1_12.b
+                           Filter: ((t1_12.b % 25) = 0)
+                     ->  Seq Scan on public.prt2_l_p2_p1 t1_13
+                           Output: t1_13.b
+                           Filter: ((t1_13.b % 25) = 0)
+                     ->  Seq Scan on public.prt2_l_p2_p2 t1_14
+                           Output: t1_14.b
+                           Filter: ((t1_14.b % 25) = 0)
+   ->  Merge Semi Join
+         Output: t1_6.a, t1_6.b, t1_6.c
+         Merge Cond: (t1_6.a = t1_15.b)
+         ->  Sort
+               Output: t1_6.a, t1_6.b, t1_6.c
+               Sort Key: t1_6.a
+               ->  Append
+                     ->  Seq Scan on public.prt1_l_p3 t1_6
+                           Output: t1_6.a, t1_6.b, t1_6.c
+                           Filter: ((t1_6.a % 25) = 0)
+                     ->  Seq Scan on public.prt1_l_p3_p1 t1_7
+                           Output: t1_7.a, t1_7.b, t1_7.c
+                           Filter: ((t1_7.a % 25) = 0)
+                     ->  Seq Scan on public.prt1_l_p3_p2 t1_8
+                           Output: t1_8.a, t1_8.b, t1_8.c
+                           Filter: ((t1_8.a % 25) = 0)
+         ->  Sort
+               Output: t1_15.b
+               Sort Key: t1_15.b
+               ->  Append
+                     ->  Seq Scan on public.prt2_l_p3 t1_15
+                           Output: t1_15.b
+                           Filter: ((t1_15.b % 25) = 0)
+                     ->  Seq Scan on public.prt2_l_p3_p1 t1_16
+                           Output: t1_16.b
+                           Filter: ((t1_16.b % 25) = 0)
+                     ->  Seq Scan on public.prt2_l_p3_p2 t1_17
+                           Output: t1_17.b
+                           Filter: ((t1_17.b % 25) = 0)
+(89 rows)
+
+SELECT t1.* FROM prt1_l t1 WHERE t1.a IN (SELECT t1.b FROM prt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+NOTICE:  join between relations (b 1) and (b 3) is considered for partition-wise join.
+  a  |  b  |  c   
+-----+-----+------
+   0 |   0 | 0000
+ 150 | 150 | 0150
+ 300 | 300 | 0300
+ 450 | 450 | 0450
+(4 rows)
+
+SELECT t1.* FROM uprt1_l t1 WHERE t1.a IN (SELECT t1.b FROM uprt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+  a  |  b  |  c   
+-----+-----+------
+   0 |   0 | 0000
+ 150 | 150 | 0150
+ 300 | 300 | 0300
+ 450 | 450 | 0450
+(4 rows)
+
 --
 -- tests for list partitioned tables.
 --
@@ -4832,6 +5242,350 @@ SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1 WHERE t1.b %
  500 | 500 | 0010
 (8 rows)
 
+-- joins where one of the relations is proven empty
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1 t1, plt2 t2 WHERE t1.a = t2.b AND t1.a = 1 AND t1.a = 2;
+            QUERY PLAN            
+----------------------------------
+ Result
+   Output: t1.a, t1.c, t2.b, t2.c
+   One-Time Filter: false
+(3 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1 t1, plt2 t2 WHERE t1.a = t2.b AND t1.a = 1 AND t1.a = 2;
+ a | c | b | c 
+---+---+---+---
+(0 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 LEFT JOIN plt2 t2 ON t1.a = t2.b;
+              QUERY PLAN              
+--------------------------------------
+ Result
+   Output: plt1.a, plt1.c, t2.b, t2.c
+   One-Time Filter: false
+(3 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 LEFT JOIN plt2 t2 ON t1.a = t2.b;
+ a | c | b | c 
+---+---+---+---
+(0 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+                    QUERY PLAN                     
+---------------------------------------------------
+ Sort
+   Output: a, c, t2.b, t2.c
+   Sort Key: a, t2.b
+   ->  Hash Left Join
+         Output: a, c, t2.b, t2.c
+         Hash Cond: (t2.b = a)
+         ->  Append
+               ->  Seq Scan on public.plt2 t2
+                     Output: t2.b, t2.c
+                     Filter: ((t2.a % 25) = 0)
+               ->  Seq Scan on public.plt2_p1 t2_1
+                     Output: t2_1.b, t2_1.c
+                     Filter: ((t2_1.a % 25) = 0)
+               ->  Seq Scan on public.plt2_p2 t2_2
+                     Output: t2_2.b, t2_2.c
+                     Filter: ((t2_2.a % 25) = 0)
+               ->  Seq Scan on public.plt2_p3 t2_3
+                     Output: t2_3.b, t2_3.c
+                     Filter: ((t2_3.a % 25) = 0)
+         ->  Hash
+               Output: a, c
+               ->  Result
+                     Output: a, c
+                     One-Time Filter: false
+(24 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0001
+   |   | 150 | 0003
+   |   | 225 | 0004
+   |   | 300 | 0006
+   |   | 375 | 0007
+   |   | 450 | 0009
+   |   | 525 | 0010
+(8 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN uplt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0001
+   |   | 150 | 0003
+   |   | 225 | 0004
+   |   | 300 | 0006
+   |   | 375 | 0007
+   |   | 450 | 0009
+   |   | 525 | 0010
+(8 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 FULL JOIN plt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+                    QUERY PLAN                     
+---------------------------------------------------
+ Sort
+   Output: a, c, t2.b, t2.c
+   Sort Key: a, t2.b
+   ->  Hash Left Join
+         Output: a, c, t2.b, t2.c
+         Hash Cond: (t2.b = a)
+         ->  Append
+               ->  Seq Scan on public.plt2 t2
+                     Output: t2.b, t2.c
+                     Filter: ((t2.a % 25) = 0)
+               ->  Seq Scan on public.plt2_p1 t2_1
+                     Output: t2_1.b, t2_1.c
+                     Filter: ((t2_1.a % 25) = 0)
+               ->  Seq Scan on public.plt2_p2 t2_2
+                     Output: t2_2.b, t2_2.c
+                     Filter: ((t2_2.a % 25) = 0)
+               ->  Seq Scan on public.plt2_p3 t2_3
+                     Output: t2_3.b, t2_3.c
+                     Filter: ((t2_3.a % 25) = 0)
+         ->  Hash
+               Output: a, c
+               ->  Result
+                     Output: a, c
+                     One-Time Filter: false
+(24 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 FULL JOIN plt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0001
+   |   | 150 | 0003
+   |   | 225 | 0004
+   |   | 300 | 0006
+   |   | 375 | 0007
+   |   | 450 | 0009
+   |   | 525 | 0010
+(8 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1 WHERE a = 1 AND a = 2) t1 FULL JOIN uplt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0001
+   |   | 150 | 0003
+   |   | 225 | 0004
+   |   | 300 | 0006
+   |   | 375 | 0007
+   |   | 450 | 0009
+   |   | 525 | 0010
+(8 rows)
+
+-- lateral reference
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 1) and (b 4 5) is considered for partition-wise join.
+                                             QUERY PLAN                                              
+-----------------------------------------------------------------------------------------------------
+ Sort
+   Output: t1.a, t1.b, t1.c, t2.c, t3.c, (LEAST(t1.c, t2.c, t3.c))
+   Sort Key: t1.a, t1.b, t1.c, t2.c, (LEAST(t1.c, t2.c, t3.c))
+   ->  HashAggregate
+         Output: t1.a, t1.b, t1.c, t2.c, t3.c, (LEAST(t1.c, t2.c, t3.c))
+         Group Key: t1.a, t1.b, t1.c, t2.c, t3.c, (LEAST(t1.c, t2.c, t3.c))
+         ->  Append
+               ->  Nested Loop Left Join
+                     Output: t1.a, t1.b, t1.c, t2.c, t3.c, (LEAST(t1.c, t2.c, t3.c))
+                     ->  Seq Scan on public.plt1_p1 t1
+                           Output: t1.a, t1.b, t1.c
+                           Filter: ((t1.a % 25) = 0)
+                     ->  Hash Join
+                           Output: t2.c, t3.c, LEAST(t1.c, t2.c, t3.c)
+                           Hash Cond: (t3.c = t2.c)
+                           ->  Seq Scan on public.plt2_p1 t3
+                                 Output: t3.c
+                           ->  Hash
+                                 Output: t2.c
+                                 ->  Seq Scan on public.plt1_p1 t2
+                                       Output: t2.c
+                                       Filter: (t1.c = t2.c)
+               ->  Nested Loop Left Join
+                     Output: t1_1.a, t1_1.b, t1_1.c, t2_1.c, t3_1.c, (LEAST(t1_1.c, t2_1.c, t3_1.c))
+                     ->  Seq Scan on public.plt1_p2 t1_1
+                           Output: t1_1.a, t1_1.b, t1_1.c
+                           Filter: ((t1_1.a % 25) = 0)
+                     ->  Hash Join
+                           Output: t2_1.c, t3_1.c, LEAST(t1_1.c, t2_1.c, t3_1.c)
+                           Hash Cond: (t3_1.c = t2_1.c)
+                           ->  Seq Scan on public.plt2_p2 t3_1
+                                 Output: t3_1.c
+                           ->  Hash
+                                 Output: t2_1.c
+                                 ->  Seq Scan on public.plt1_p2 t2_1
+                                       Output: t2_1.c
+                                       Filter: (t1_1.c = t2_1.c)
+               ->  Nested Loop Left Join
+                     Output: t1_2.a, t1_2.b, t1_2.c, t2_2.c, t3_2.c, (LEAST(t1_2.c, t2_2.c, t3_2.c))
+                     ->  Seq Scan on public.plt1_p3 t1_2
+                           Output: t1_2.a, t1_2.b, t1_2.c
+                           Filter: ((t1_2.a % 25) = 0)
+                     ->  Hash Join
+                           Output: t2_2.c, t3_2.c, LEAST(t1_2.c, t2_2.c, t3_2.c)
+                           Hash Cond: (t3_2.c = t2_2.c)
+                           ->  Seq Scan on public.plt2_p3 t3_2
+                                 Output: t3_2.c
+                           ->  Hash
+                                 Output: t2_2.c
+                                 ->  Seq Scan on public.plt1_p3 t2_2
+                                       Output: t2_2.c
+                                       Filter: (t1_2.c = t2_2.c)
+(52 rows)
+
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 1) and (b 4 5) is considered for partition-wise join.
+  a  |  b  |  c   | t2c  | t3c  | least 
+-----+-----+------+------+------+-------
+   0 |   0 | 0000 | 0000 | 0000 | 0000
+  50 |  50 | 0001 | 0001 | 0001 | 0001
+ 100 | 100 | 0002 | 0002 | 0002 | 0002
+ 150 | 150 | 0003 | 0003 | 0003 | 0003
+ 200 | 200 | 0004 | 0004 | 0004 | 0004
+ 250 | 250 | 0005 | 0005 | 0005 | 0005
+ 300 | 300 | 0006 | 0006 | 0006 | 0006
+ 350 | 350 | 0007 | 0007 | 0007 | 0007
+ 400 | 400 | 0008 | 0008 | 0008 | 0008
+ 450 | 450 | 0009 | 0009 | 0009 | 0009
+ 500 | 500 | 0010 | 0010 | 0010 | 0010
+ 550 | 550 | 0011 | 0011 | 0011 | 0011
+(12 rows)
+
+SELECT distinct * FROM uplt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM uplt1 t2 JOIN uplt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+  a  |  b  |  c   | t2c  | t3c  | least 
+-----+-----+------+------+------+-------
+   0 |   0 | 0000 | 0000 | 0000 | 0000
+  50 |  50 | 0001 | 0001 | 0001 | 0001
+ 100 | 100 | 0002 | 0002 | 0002 | 0002
+ 150 | 150 | 0003 | 0003 | 0003 | 0003
+ 200 | 200 | 0004 | 0004 | 0004 | 0004
+ 250 | 250 | 0005 | 0005 | 0005 | 0005
+ 300 | 300 | 0006 | 0006 | 0006 | 0006
+ 350 | 350 | 0007 | 0007 | 0007 | 0007
+ 400 | 400 | 0008 | 0008 | 0008 | 0008
+ 450 | 450 | 0009 | 0009 | 0009 | 0009
+ 500 | 500 | 0010 | 0010 | 0010 | 0010
+ 550 | 550 | 0011 | 0011 | 0011 | 0011
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+                                  QUERY PLAN                                   
+-------------------------------------------------------------------------------
+ Unique
+   Output: t1.a, t1.b, t1.c, t2.a, t3.c, (LEAST(t1.c, t2.c, t3.c))
+   ->  Sort
+         Output: t1.a, t1.b, t1.c, t2.a, t3.c, (LEAST(t1.c, t2.c, t3.c))
+         Sort Key: t1.a, t1.b, t1.c, t2.a, t3.c, (LEAST(t1.c, t2.c, t3.c))
+         ->  Nested Loop Left Join
+               Output: t1.a, t1.b, t1.c, t2.a, t3.c, (LEAST(t1.c, t2.c, t3.c))
+               ->  Append
+                     ->  Seq Scan on public.plt1 t1
+                           Output: t1.a, t1.b, t1.c
+                           Filter: ((t1.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_p1 t1_1
+                           Output: t1_1.a, t1_1.b, t1_1.c
+                           Filter: ((t1_1.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_p2 t1_2
+                           Output: t1_2.a, t1_2.b, t1_2.c
+                           Filter: ((t1_2.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_p3 t1_3
+                           Output: t1_3.a, t1_3.b, t1_3.c
+                           Filter: ((t1_3.a % 25) = 0)
+               ->  Append
+                     ->  Hash Join
+                           Output: t2.a, t3.c, LEAST(t1.c, t2.c, t3.c)
+                           Hash Cond: (t3.c = t2.c)
+                           ->  Seq Scan on public.plt2_p1 t3
+                                 Output: t3.c
+                           ->  Hash
+                                 Output: t2.a, t2.c
+                                 ->  Seq Scan on public.plt1_p1 t2
+                                       Output: t2.a, t2.c
+                                       Filter: (t1.b = t2.a)
+                     ->  Hash Join
+                           Output: t2_1.a, t3_1.c, LEAST(t1.c, t2_1.c, t3_1.c)
+                           Hash Cond: (t3_1.c = t2_1.c)
+                           ->  Seq Scan on public.plt2_p2 t3_1
+                                 Output: t3_1.c
+                           ->  Hash
+                                 Output: t2_1.a, t2_1.c
+                                 ->  Seq Scan on public.plt1_p2 t2_1
+                                       Output: t2_1.a, t2_1.c
+                                       Filter: (t1.b = t2_1.a)
+                     ->  Hash Join
+                           Output: t2_2.a, t3_2.c, LEAST(t1.c, t2_2.c, t3_2.c)
+                           Hash Cond: (t3_2.c = t2_2.c)
+                           ->  Seq Scan on public.plt2_p3 t3_2
+                                 Output: t3_2.c
+                           ->  Hash
+                                 Output: t2_2.a, t2_2.c
+                                 ->  Seq Scan on public.plt1_p3 t2_2
+                                       Output: t2_2.a, t2_2.c
+                                       Filter: (t1.b = t2_2.a)
+(51 rows)
+
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+  a  |  b  |  c   | t2a | t3c  | least 
+-----+-----+------+-----+------+-------
+   0 |   0 | 0000 |   0 | 0000 | 0000
+  50 |  50 | 0001 |  50 | 0001 | 0001
+ 100 | 100 | 0002 | 100 | 0002 | 0002
+ 150 | 150 | 0003 | 150 | 0003 | 0003
+ 200 | 200 | 0004 | 200 | 0004 | 0004
+ 250 | 250 | 0005 | 250 | 0005 | 0005
+ 300 | 300 | 0006 | 300 | 0006 | 0006
+ 350 | 350 | 0007 | 350 | 0007 | 0007
+ 400 | 400 | 0008 | 400 | 0008 | 0008
+ 450 | 450 | 0009 | 450 | 0009 | 0009
+ 500 | 500 | 0010 | 500 | 0010 | 0010
+ 550 | 550 | 0011 | 550 | 0011 | 0011
+(12 rows)
+
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+  a  |  b  |  c   | t2a | t3c  | least 
+-----+-----+------+-----+------+-------
+   0 |   0 | 0000 |   0 | 0000 | 0000
+  50 |  50 | 0001 |  50 | 0001 | 0001
+ 100 | 100 | 0002 | 100 | 0002 | 0002
+ 150 | 150 | 0003 | 150 | 0003 | 0003
+ 200 | 200 | 0004 | 200 | 0004 | 0004
+ 250 | 250 | 0005 | 250 | 0005 | 0005
+ 300 | 300 | 0006 | 300 | 0006 | 0006
+ 350 | 350 | 0007 | 350 | 0007 | 0007
+ 400 | 400 | 0008 | 400 | 0008 | 0008
+ 450 | 450 | 0009 | 450 | 0009 | 0009
+ 500 | 500 | 0010 | 500 | 0010 | 0010
+ 550 | 550 | 0011 | 550 | 0011 | 0011
+(12 rows)
+
 --
 -- list partitioned by expression
 --
@@ -5998,6 +6752,88 @@ SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1 WHERE t1.c IN
  550 | 550 | 0011
 (12 rows)
 
+-- Cases with non-nullable expressions in subquery results;
+-- make sure these go to null as expected
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.phv, t2.b, t2.phv, ltrim(t3.c,'A'), t3.phv FROM ((SELECT 50 phv, * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.c = t2.c)) FULL JOIN (SELECT '0002'::text phv, * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.c = ltrim(t3.c,'A')) WHERE t1.a = t1.phv OR t2.b = t2.phv OR ltrim(t3.c,'A') = t3.phv ORDER BY t1.a, t2.b, ltrim(t3.c,'A');
+NOTICE:  join between relations (b 6) and (b 7) is considered for partition-wise join.
+NOTICE:  join between relations (b 6 7) and (b 8) is considered for partition-wise join.
+                                                 QUERY PLAN                                                  
+-------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: plt1_p1.a, (50), plt2_p1.b, (75), (ltrim(plt1_e.c, 'A'::text)), ('0002'::text)
+   Sort Key: plt1_p1.a, plt2_p1.b, (ltrim(plt1_e.c, 'A'::text))
+   ->  Hash Full Join
+         Output: plt1_p1.a, (50), plt2_p1.b, (75), ltrim(plt1_e.c, 'A'::text), ('0002'::text)
+         Hash Cond: (plt1_p1.c = ltrim(plt1_e.c, 'A'::text))
+         Filter: ((plt1_p1.a = (50)) OR (plt2_p1.b = (75)) OR (ltrim(plt1_e.c, 'A'::text) = ('0002'::text)))
+         ->  Append
+               ->  Hash Full Join
+                     Output: plt1_p1.a, plt1_p1.c, plt2_p1.b, (50), (75)
+                     Hash Cond: (plt1_p1.c = plt2_p1.c)
+                     ->  Seq Scan on public.plt1_p1
+                           Output: plt1_p1.a, plt1_p1.c, 50
+                           Filter: ((plt1_p1.a % 25) = 0)
+                     ->  Hash
+                           Output: plt2_p1.b, plt2_p1.c, (75)
+                           ->  Seq Scan on public.plt2_p1
+                                 Output: plt2_p1.b, plt2_p1.c, 75
+                                 Filter: ((plt2_p1.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: plt1_p2.a, plt1_p2.c, plt2_p2.b, (50), (75)
+                     Hash Cond: (plt1_p2.c = plt2_p2.c)
+                     ->  Seq Scan on public.plt1_p2
+                           Output: plt1_p2.a, plt1_p2.c, 50
+                           Filter: ((plt1_p2.a % 25) = 0)
+                     ->  Hash
+                           Output: plt2_p2.b, plt2_p2.c, (75)
+                           ->  Seq Scan on public.plt2_p2
+                                 Output: plt2_p2.b, plt2_p2.c, 75
+                                 Filter: ((plt2_p2.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: plt1_p3.a, plt1_p3.c, plt2_p3.b, (50), (75)
+                     Hash Cond: (plt1_p3.c = plt2_p3.c)
+                     ->  Seq Scan on public.plt1_p3
+                           Output: plt1_p3.a, plt1_p3.c, 50
+                           Filter: ((plt1_p3.a % 25) = 0)
+                     ->  Hash
+                           Output: plt2_p3.b, plt2_p3.c, (75)
+                           ->  Seq Scan on public.plt2_p3
+                                 Output: plt2_p3.b, plt2_p3.c, 75
+                                 Filter: ((plt2_p3.b % 25) = 0)
+         ->  Hash
+               Output: plt1_e.c, ('0002'::text)
+               ->  Append
+                     ->  Seq Scan on public.plt1_e
+                           Output: plt1_e.c, '0002'::text
+                           Filter: ((plt1_e.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_e_p1
+                           Output: plt1_e_p1.c, '0002'::text
+                           Filter: ((plt1_e_p1.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_e_p2
+                           Output: plt1_e_p2.c, '0002'::text
+                           Filter: ((plt1_e_p2.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_e_p3
+                           Output: plt1_e_p3.c, '0002'::text
+                           Filter: ((plt1_e_p3.a % 25) = 0)
+(56 rows)
+
+SELECT t1.a, t1.phv, t2.b, t2.phv, ltrim(t3.c,'A'), t3.phv FROM ((SELECT 50 phv, * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.c = t2.c)) FULL JOIN (SELECT '0002'::text phv, * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.c = ltrim(t3.c,'A')) WHERE t1.a = t1.phv OR t2.b = t2.phv OR ltrim(t3.c,'A') = t3.phv ORDER BY t1.a, t2.b, ltrim(t3.c,'A');
+NOTICE:  join between relations (b 6) and (b 7) is considered for partition-wise join.
+NOTICE:  join between relations (b 6 7) and (b 8) is considered for partition-wise join.
+  a  | phv | b  | phv | ltrim | phv  
+-----+-----+----+-----+-------+------
+  50 |  50 | 75 |  75 | 0001  | 0002
+ 100 |  50 |    |     | 0002  | 0002
+(2 rows)
+
+SELECT t1.a, t1.phv, t2.b, t2.phv, ltrim(t3.c,'A'), t3.phv FROM ((SELECT 50 phv, * FROM uplt1 WHERE uplt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uplt2 WHERE uplt2.b % 25 = 0) t2 ON (t1.c = t2.c)) FULL JOIN (SELECT '0002'::text phv, * FROM uplt1_e WHERE uplt1_e.a % 25 = 0) t3 ON (t1.c = ltrim(t3.c,'A')) WHERE t1.a = t1.phv OR t2.b = t2.phv OR ltrim(t3.c,'A') = t3.phv ORDER BY t1.a, t2.b, ltrim(t3.c,'A');
+  a  | phv | b  | phv | ltrim | phv  
+-----+-----+----+-----+-------+------
+  50 |  50 | 75 |  75 | 0001  | 0002
+ 100 |  50 |    |     | 0002  | 0002
+(2 rows)
+
 -- test merge join with and without index scan
 CREATE INDEX iplt1_c on plt1(c);
 CREATE INDEX iplt1_p1_c on plt1_p1(c);
@@ -6781,9 +7617,1510 @@ SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1 WHERE t1.c IN
  550 | 550 | 0011
 (12 rows)
 
+-- lateral references and parameterized paths
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 1) and (b 4 5) is considered for partition-wise join.
+                                         QUERY PLAN                                          
+---------------------------------------------------------------------------------------------
+ Unique
+   Output: t1.a, t1.b, t1.c, t2.c, t3.c, (LEAST(t1.c, t2.c, t3.c))
+   ->  Sort
+         Output: t1.a, t1.b, t1.c, t2.c, t3.c, (LEAST(t1.c, t2.c, t3.c))
+         Sort Key: t1.a, t1.b, t1.c, t2.c, (LEAST(t1.c, t2.c, t3.c))
+         ->  Nested Loop Left Join
+               Output: t1.a, t1.b, t1.c, t2.c, t3.c, (LEAST(t1.c, t2.c, t3.c))
+               ->  Append
+                     ->  Index Scan using iplt1_c on public.plt1 t1
+                           Output: t1.a, t1.b, t1.c
+                           Filter: ((t1.a % 25) = 0)
+                     ->  Index Scan using iplt1_p1_c on public.plt1_p1 t1_1
+                           Output: t1_1.a, t1_1.b, t1_1.c
+                           Filter: ((t1_1.a % 25) = 0)
+                     ->  Index Scan using iplt1_p2_c on public.plt1_p2 t1_2
+                           Output: t1_2.a, t1_2.b, t1_2.c
+                           Filter: ((t1_2.a % 25) = 0)
+                     ->  Index Scan using iplt1_p3_c on public.plt1_p3 t1_3
+                           Output: t1_3.a, t1_3.b, t1_3.c
+                           Filter: ((t1_3.a % 25) = 0)
+               ->  Append
+                     ->  Merge Join
+                           Output: t2.c, t3.c, LEAST(t1.c, t2.c, t3.c)
+                           Merge Cond: (t2.c = t3.c)
+                           ->  Index Only Scan using iplt1_p1_c on public.plt1_p1 t2
+                                 Output: t2.c
+                                 Index Cond: (t2.c = t1.c)
+                           ->  Materialize
+                                 Output: t3.c
+                                 ->  Index Only Scan using iplt2_p1_c on public.plt2_p1 t3
+                                       Output: t3.c
+                     ->  Merge Join
+                           Output: t2_1.c, t3_1.c, LEAST(t1.c, t2_1.c, t3_1.c)
+                           Merge Cond: (t2_1.c = t3_1.c)
+                           ->  Index Only Scan using iplt1_p2_c on public.plt1_p2 t2_1
+                                 Output: t2_1.c
+                                 Index Cond: (t2_1.c = t1.c)
+                           ->  Materialize
+                                 Output: t3_1.c
+                                 ->  Index Only Scan using iplt2_p2_c on public.plt2_p2 t3_1
+                                       Output: t3_1.c
+                     ->  Merge Join
+                           Output: t2_2.c, t3_2.c, LEAST(t1.c, t2_2.c, t3_2.c)
+                           Merge Cond: (t2_2.c = t3_2.c)
+                           ->  Index Only Scan using iplt1_p3_c on public.plt1_p3 t2_2
+                                 Output: t2_2.c
+                                 Index Cond: (t2_2.c = t1.c)
+                           ->  Materialize
+                                 Output: t3_2.c
+                                 ->  Index Only Scan using iplt2_p3_c on public.plt2_p3 t3_2
+                                       Output: t3_2.c
+(51 rows)
+
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 1) and (b 4 5) is considered for partition-wise join.
+  a  |  b  |  c   | t2c  | t3c  | least 
+-----+-----+------+------+------+-------
+   0 |   0 | 0000 | 0000 | 0000 | 0000
+  50 |  50 | 0001 | 0001 | 0001 | 0001
+ 100 | 100 | 0002 | 0002 | 0002 | 0002
+ 150 | 150 | 0003 | 0003 | 0003 | 0003
+ 200 | 200 | 0004 | 0004 | 0004 | 0004
+ 250 | 250 | 0005 | 0005 | 0005 | 0005
+ 300 | 300 | 0006 | 0006 | 0006 | 0006
+ 350 | 350 | 0007 | 0007 | 0007 | 0007
+ 400 | 400 | 0008 | 0008 | 0008 | 0008
+ 450 | 450 | 0009 | 0009 | 0009 | 0009
+ 500 | 500 | 0010 | 0010 | 0010 | 0010
+ 550 | 550 | 0011 | 0011 | 0011 | 0011
+(12 rows)
+
+SELECT distinct * FROM uplt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM uplt1 t2 JOIN uplt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+  a  |  b  |  c   | t2c  | t3c  | least 
+-----+-----+------+------+------+-------
+   0 |   0 | 0000 | 0000 | 0000 | 0000
+  50 |  50 | 0001 | 0001 | 0001 | 0001
+ 100 | 100 | 0002 | 0002 | 0002 | 0002
+ 150 | 150 | 0003 | 0003 | 0003 | 0003
+ 200 | 200 | 0004 | 0004 | 0004 | 0004
+ 250 | 250 | 0005 | 0005 | 0005 | 0005
+ 300 | 300 | 0006 | 0006 | 0006 | 0006
+ 350 | 350 | 0007 | 0007 | 0007 | 0007
+ 400 | 400 | 0008 | 0008 | 0008 | 0008
+ 450 | 450 | 0009 | 0009 | 0009 | 0009
+ 500 | 500 | 0010 | 0010 | 0010 | 0010
+ 550 | 550 | 0011 | 0011 | 0011 | 0011
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+                                      QUERY PLAN                                       
+---------------------------------------------------------------------------------------
+ Unique
+   Output: t1.a, t1.b, t1.c, t2.a, t3.c, (LEAST(t1.c, t2.c, t3.c))
+   ->  Sort
+         Output: t1.a, t1.b, t1.c, t2.a, t3.c, (LEAST(t1.c, t2.c, t3.c))
+         Sort Key: t1.a, t1.b, t1.c, t2.a, t3.c, (LEAST(t1.c, t2.c, t3.c))
+         ->  Nested Loop Left Join
+               Output: t1.a, t1.b, t1.c, t2.a, t3.c, (LEAST(t1.c, t2.c, t3.c))
+               ->  Append
+                     ->  Seq Scan on public.plt1 t1
+                           Output: t1.a, t1.b, t1.c
+                           Filter: ((t1.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_p1 t1_1
+                           Output: t1_1.a, t1_1.b, t1_1.c
+                           Filter: ((t1_1.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_p2 t1_2
+                           Output: t1_2.a, t1_2.b, t1_2.c
+                           Filter: ((t1_2.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_p3 t1_3
+                           Output: t1_3.a, t1_3.b, t1_3.c
+                           Filter: ((t1_3.a % 25) = 0)
+               ->  Append
+                     ->  Merge Join
+                           Output: t2.a, t3.c, LEAST(t1.c, t2.c, t3.c)
+                           Merge Cond: (t2.c = t3.c)
+                           ->  Index Scan using iplt1_p1_c on public.plt1_p1 t2
+                                 Output: t2.a, t2.c
+                                 Filter: (t1.b = t2.a)
+                           ->  Index Only Scan using iplt2_p1_c on public.plt2_p1 t3
+                                 Output: t3.c
+                     ->  Merge Join
+                           Output: t2_1.a, t3_1.c, LEAST(t1.c, t2_1.c, t3_1.c)
+                           Merge Cond: (t2_1.c = t3_1.c)
+                           ->  Index Scan using iplt1_p2_c on public.plt1_p2 t2_1
+                                 Output: t2_1.a, t2_1.c
+                                 Filter: (t1.b = t2_1.a)
+                           ->  Index Only Scan using iplt2_p2_c on public.plt2_p2 t3_1
+                                 Output: t3_1.c
+                     ->  Merge Join
+                           Output: t2_2.a, t3_2.c, LEAST(t1.c, t2_2.c, t3_2.c)
+                           Merge Cond: (t2_2.c = t3_2.c)
+                           ->  Index Scan using iplt1_p3_c on public.plt1_p3 t2_2
+                                 Output: t2_2.a, t2_2.c
+                                 Filter: (t1.b = t2_2.a)
+                           ->  Index Only Scan using iplt2_p3_c on public.plt2_p3 t3_2
+                                 Output: t3_2.c
+(45 rows)
+
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+  a  |  b  |  c   | t2a | t3c  | least 
+-----+-----+------+-----+------+-------
+   0 |   0 | 0000 |   0 | 0000 | 0000
+  50 |  50 | 0001 |  50 | 0001 | 0001
+ 100 | 100 | 0002 | 100 | 0002 | 0002
+ 150 | 150 | 0003 | 150 | 0003 | 0003
+ 200 | 200 | 0004 | 200 | 0004 | 0004
+ 250 | 250 | 0005 | 250 | 0005 | 0005
+ 300 | 300 | 0006 | 300 | 0006 | 0006
+ 350 | 350 | 0007 | 350 | 0007 | 0007
+ 400 | 400 | 0008 | 400 | 0008 | 0008
+ 450 | 450 | 0009 | 450 | 0009 | 0009
+ 500 | 500 | 0010 | 500 | 0010 | 0010
+ 550 | 550 | 0011 | 550 | 0011 | 0011
+(12 rows)
+
+SELECT distinct * FROM uplt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM uplt1 t2 JOIN uplt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+  a  |  b  |  c   | t2a | t3c  | least 
+-----+-----+------+-----+------+-------
+   0 |   0 | 0000 |   0 | 0000 | 0000
+  50 |  50 | 0001 |  50 | 0001 | 0001
+ 100 | 100 | 0002 | 100 | 0002 | 0002
+ 150 | 150 | 0003 | 150 | 0003 | 0003
+ 200 | 200 | 0004 | 200 | 0004 | 0004
+ 250 | 250 | 0005 | 250 | 0005 | 0005
+ 300 | 300 | 0006 | 300 | 0006 | 0006
+ 350 | 350 | 0007 | 350 | 0007 | 0007
+ 400 | 400 | 0008 | 400 | 0008 | 0008
+ 450 | 450 | 0009 | 450 | 0009 | 0009
+ 500 | 500 | 0010 | 500 | 0010 | 0010
+ 550 | 550 | 0011 | 550 | 0011 | 0011
+(12 rows)
+
 RESET enable_hashjoin;
 RESET enable_nestloop;
 RESET enable_seqscan;
+
+--
+-- multi-leveled partitions
+--
+CREATE TABLE plt1_l (a int, b int, c varchar) PARTITION BY LIST(c);
+CREATE TABLE plt1_l_p1 PARTITION OF plt1_l FOR VALUES IN ('0000', '0003', '0004', '0010') PARTITION BY LIST (c);
+CREATE TABLE plt1_l_p1_p1 PARTITION OF plt1_l_p1 FOR VALUES IN ('0000', '0003');
+CREATE TABLE plt1_l_p1_p2 PARTITION OF plt1_l_p1 FOR VALUES IN ('0004', '0010');
+CREATE TABLE plt1_l_p2 PARTITION OF plt1_l FOR VALUES IN ('0001', '0005', '0002', '0009') PARTITION BY LIST (c);
+CREATE TABLE plt1_l_p2_p1 PARTITION OF plt1_l_p2 FOR VALUES IN ('0001', '0005');
+CREATE TABLE plt1_l_p2_p2 PARTITION OF plt1_l_p2 FOR VALUES IN ('0002', '0009');
+CREATE TABLE plt1_l_p3 PARTITION OF plt1_l FOR VALUES IN ('0006', '0007', '0008', '0011') PARTITION BY LIST (ltrim(c,'A'));
+CREATE TABLE plt1_l_p3_p1 PARTITION OF plt1_l_p3 FOR VALUES IN ('0006', '0007');
+CREATE TABLE plt1_l_p3_p2 PARTITION OF plt1_l_p3 FOR VALUES IN ('0008', '0011');
+INSERT INTO plt1_l SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE plt1_l;
+ANALYZE plt1_l_p1;
+ANALYZE plt1_l_p1_p1;
+ANALYZE plt1_l_p1_p2;
+ANALYZE plt1_l_p2;
+ANALYZE plt1_l_p2_p1;
+ANALYZE plt1_l_p2_p2;
+ANALYZE plt1_l_p3;
+ANALYZE plt1_l_p3_p1;
+ANALYZE plt1_l_p3_p2;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt1_l AS SELECT * FROM plt1_l;
+CREATE TABLE plt2_l (a int, b int, c varchar) PARTITION BY LIST(c);
+CREATE TABLE plt2_l_p1 PARTITION OF plt2_l FOR VALUES IN ('0000', '0003', '0004', '0010') PARTITION BY LIST (c);
+CREATE TABLE plt2_l_p1_p1 PARTITION OF plt2_l_p1 FOR VALUES IN ('0000', '0003');
+CREATE TABLE plt2_l_p1_p2 PARTITION OF plt2_l_p1 FOR VALUES IN ('0004', '0010');
+CREATE TABLE plt2_l_p2 PARTITION OF plt2_l FOR VALUES IN ('0001', '0005', '0002', '0009') PARTITION BY LIST (c);
+CREATE TABLE plt2_l_p2_p1 PARTITION OF plt2_l_p2 FOR VALUES IN ('0001', '0005');
+CREATE TABLE plt2_l_p2_p2 PARTITION OF plt2_l_p2 FOR VALUES IN ('0002', '0009');
+CREATE TABLE plt2_l_p3 PARTITION OF plt2_l FOR VALUES IN ('0006', '0007', '0008', '0011') PARTITION BY LIST (ltrim(c,'A'));
+CREATE TABLE plt2_l_p3_p1 PARTITION OF plt2_l_p3 FOR VALUES IN ('0006', '0007');
+CREATE TABLE plt2_l_p3_p2 PARTITION OF plt2_l_p3 FOR VALUES IN ('0008', '0011');
+INSERT INTO plt2_l SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i;
+ANALYZE plt2_l;
+ANALYZE plt2_l_p1;
+ANALYZE plt2_l_p1_p1;
+ANALYZE plt2_l_p1_p2;
+ANALYZE plt2_l_p2;
+ANALYZE plt2_l_p2_p1;
+ANALYZE plt2_l_p2_p2;
+ANALYZE plt2_l_p3;
+ANALYZE plt2_l_p3_p1;
+ANALYZE plt2_l_p3_p2;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt2_l AS SELECT * FROM plt2_l;
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 1) and (b 2) is considered for partition-wise join.
+NOTICE:  join between relations (b 4) and (b 17) is considered for partition-wise join.
+NOTICE:  join between relations (b 8) and (b 21) is considered for partition-wise join.
+NOTICE:  join between relations (b 12) and (b 25) is considered for partition-wise join.
+                                                                                     QUERY PLAN                                                                                     
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: t1.a, t1.c, t2.b, t2.c
+   Sort Key: t1.a
+   ->  Append
+         ->  Hash Join
+               Output: t1.a, t1.c, t2.b, t2.c
+               Hash Cond: ((t2.b = t1.a) AND (t2.a = t1.b) AND ((t2.c)::text = (t1.c)::text) AND (ltrim((t2.c)::text, 'A'::text) = ltrim((t1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p1_p1 t2
+                     Output: t2.b, t2.c, t2.a
+               ->  Hash
+                     Output: t1.a, t1.c, t1.b
+                     ->  Seq Scan on public.plt1_l_p1_p1 t1
+                           Output: t1.a, t1.c, t1.b
+                           Filter: ((t1.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c
+               Hash Cond: ((t2_1.b = t1_1.a) AND (t2_1.a = t1_1.b) AND ((t2_1.c)::text = (t1_1.c)::text) AND (ltrim((t2_1.c)::text, 'A'::text) = ltrim((t1_1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p1_p2 t2_1
+                     Output: t2_1.b, t2_1.c, t2_1.a
+               ->  Hash
+                     Output: t1_1.a, t1_1.c, t1_1.b
+                     ->  Seq Scan on public.plt1_l_p1_p2 t1_1
+                           Output: t1_1.a, t1_1.c, t1_1.b
+                           Filter: ((t1_1.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c
+               Hash Cond: ((t2_2.b = t1_2.a) AND (t2_2.a = t1_2.b) AND ((t2_2.c)::text = (t1_2.c)::text) AND (ltrim((t2_2.c)::text, 'A'::text) = ltrim((t1_2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p2_p1 t2_2
+                     Output: t2_2.b, t2_2.c, t2_2.a
+               ->  Hash
+                     Output: t1_2.a, t1_2.c, t1_2.b
+                     ->  Seq Scan on public.plt1_l_p2_p1 t1_2
+                           Output: t1_2.a, t1_2.c, t1_2.b
+                           Filter: ((t1_2.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_3.a, t1_3.c, t2_3.b, t2_3.c
+               Hash Cond: ((t2_3.b = t1_3.a) AND (t2_3.a = t1_3.b) AND ((t2_3.c)::text = (t1_3.c)::text) AND (ltrim((t2_3.c)::text, 'A'::text) = ltrim((t1_3.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p2_p2 t2_3
+                     Output: t2_3.b, t2_3.c, t2_3.a
+               ->  Hash
+                     Output: t1_3.a, t1_3.c, t1_3.b
+                     ->  Seq Scan on public.plt1_l_p2_p2 t1_3
+                           Output: t1_3.a, t1_3.c, t1_3.b
+                           Filter: ((t1_3.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_4.a, t1_4.c, t2_4.b, t2_4.c
+               Hash Cond: ((t2_4.b = t1_4.a) AND (t2_4.a = t1_4.b) AND ((t2_4.c)::text = (t1_4.c)::text) AND (ltrim((t2_4.c)::text, 'A'::text) = ltrim((t1_4.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p1 t2_4
+                     Output: t2_4.b, t2_4.c, t2_4.a
+               ->  Hash
+                     Output: t1_4.a, t1_4.c, t1_4.b
+                     ->  Seq Scan on public.plt1_l_p3_p1 t1_4
+                           Output: t1_4.a, t1_4.c, t1_4.b
+                           Filter: ((t1_4.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_5.a, t1_5.c, t2_5.b, t2_5.c
+               Hash Cond: ((t2_5.b = t1_5.a) AND (t2_5.a = t1_5.b) AND ((t2_5.c)::text = (t1_5.c)::text) AND (ltrim((t2_5.c)::text, 'A'::text) = ltrim((t1_5.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p2 t2_5
+                     Output: t2_5.b, t2_5.c, t2_5.a
+               ->  Hash
+                     Output: t1_5.a, t1_5.c, t1_5.b
+                     ->  Seq Scan on public.plt1_l_p3_p2 t1_5
+                           Output: t1_5.a, t1_5.c, t1_5.b
+                           Filter: ((t1_5.a % 25) = 0)
+(64 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 1) and (b 2) is considered for partition-wise join.
+NOTICE:  join between relations (b 4) and (b 17) is considered for partition-wise join.
+NOTICE:  join between relations (b 8) and (b 21) is considered for partition-wise join.
+NOTICE:  join between relations (b 12) and (b 25) is considered for partition-wise join.
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |   0 | 0000
+ 150 | 0003 | 150 | 0003
+ 300 | 0006 | 300 | 0006
+ 450 | 0009 | 450 | 0009
+(4 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uplt1_l t1, uplt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |   0 | 0000
+ 150 | 0003 | 150 | 0003
+ 300 | 0006 | 300 | 0006
+ 450 | 0009 | 450 | 0009
+(4 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1 LEFT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 1) and (b 2) is considered for partition-wise join.
+NOTICE:  join between relations (b 5) and (b 18) is considered for partition-wise join.
+NOTICE:  join between relations (b 9) and (b 22) is considered for partition-wise join.
+NOTICE:  join between relations (b 13) and (b 26) is considered for partition-wise join.
+                                                                                     QUERY PLAN                                                                                     
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: t1.a, t1.c, t2.b, t2.c
+   Sort Key: t1.a, t2.b
+   ->  Append
+         ->  Hash Right Join
+               Output: t1.a, t1.c, t2.b, t2.c
+               Hash Cond: ((t2.b = t1.a) AND (t2.a = t1.b) AND ((t2.c)::text = (t1.c)::text) AND (ltrim((t2.c)::text, 'A'::text) = ltrim((t1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p1_p1 t2
+                     Output: t2.b, t2.c, t2.a
+               ->  Hash
+                     Output: t1.a, t1.c, t1.b
+                     ->  Seq Scan on public.plt1_l_p1_p1 t1
+                           Output: t1.a, t1.c, t1.b
+                           Filter: ((t1.a % 25) = 0)
+         ->  Hash Right Join
+               Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c
+               Hash Cond: ((t2_1.b = t1_1.a) AND (t2_1.a = t1_1.b) AND ((t2_1.c)::text = (t1_1.c)::text) AND (ltrim((t2_1.c)::text, 'A'::text) = ltrim((t1_1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p1_p2 t2_1
+                     Output: t2_1.b, t2_1.c, t2_1.a
+               ->  Hash
+                     Output: t1_1.a, t1_1.c, t1_1.b
+                     ->  Seq Scan on public.plt1_l_p1_p2 t1_1
+                           Output: t1_1.a, t1_1.c, t1_1.b
+                           Filter: ((t1_1.a % 25) = 0)
+         ->  Hash Right Join
+               Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c
+               Hash Cond: ((t2_2.b = t1_2.a) AND (t2_2.a = t1_2.b) AND ((t2_2.c)::text = (t1_2.c)::text) AND (ltrim((t2_2.c)::text, 'A'::text) = ltrim((t1_2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p2_p1 t2_2
+                     Output: t2_2.b, t2_2.c, t2_2.a
+               ->  Hash
+                     Output: t1_2.a, t1_2.c, t1_2.b
+                     ->  Seq Scan on public.plt1_l_p2_p1 t1_2
+                           Output: t1_2.a, t1_2.c, t1_2.b
+                           Filter: ((t1_2.a % 25) = 0)
+         ->  Hash Right Join
+               Output: t1_3.a, t1_3.c, t2_3.b, t2_3.c
+               Hash Cond: ((t2_3.b = t1_3.a) AND (t2_3.a = t1_3.b) AND ((t2_3.c)::text = (t1_3.c)::text) AND (ltrim((t2_3.c)::text, 'A'::text) = ltrim((t1_3.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p2_p2 t2_3
+                     Output: t2_3.b, t2_3.c, t2_3.a
+               ->  Hash
+                     Output: t1_3.a, t1_3.c, t1_3.b
+                     ->  Seq Scan on public.plt1_l_p2_p2 t1_3
+                           Output: t1_3.a, t1_3.c, t1_3.b
+                           Filter: ((t1_3.a % 25) = 0)
+         ->  Hash Right Join
+               Output: t1_4.a, t1_4.c, t2_4.b, t2_4.c
+               Hash Cond: ((t2_4.b = t1_4.a) AND (t2_4.a = t1_4.b) AND ((t2_4.c)::text = (t1_4.c)::text) AND (ltrim((t2_4.c)::text, 'A'::text) = ltrim((t1_4.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p1 t2_4
+                     Output: t2_4.b, t2_4.c, t2_4.a
+               ->  Hash
+                     Output: t1_4.a, t1_4.c, t1_4.b
+                     ->  Seq Scan on public.plt1_l_p3_p1 t1_4
+                           Output: t1_4.a, t1_4.c, t1_4.b
+                           Filter: ((t1_4.a % 25) = 0)
+         ->  Hash Right Join
+               Output: t1_5.a, t1_5.c, t2_5.b, t2_5.c
+               Hash Cond: ((t2_5.b = t1_5.a) AND (t2_5.a = t1_5.b) AND ((t2_5.c)::text = (t1_5.c)::text) AND (ltrim((t2_5.c)::text, 'A'::text) = ltrim((t1_5.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p2 t2_5
+                     Output: t2_5.b, t2_5.c, t2_5.a
+               ->  Hash
+                     Output: t1_5.a, t1_5.c, t1_5.b
+                     ->  Seq Scan on public.plt1_l_p3_p2 t1_5
+                           Output: t1_5.a, t1_5.c, t1_5.b
+                           Filter: ((t1_5.a % 25) = 0)
+(64 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1 LEFT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 1) and (b 2) is considered for partition-wise join.
+NOTICE:  join between relations (b 5) and (b 18) is considered for partition-wise join.
+NOTICE:  join between relations (b 9) and (b 22) is considered for partition-wise join.
+NOTICE:  join between relations (b 13) and (b 26) is considered for partition-wise join.
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |   0 | 0000
+  50 | 0001 |     | 
+ 100 | 0002 |     | 
+ 150 | 0003 | 150 | 0003
+ 200 | 0004 |     | 
+ 250 | 0005 |     | 
+ 300 | 0006 | 300 | 0006
+ 350 | 0007 |     | 
+ 400 | 0008 |     | 
+ 450 | 0009 | 450 | 0009
+ 500 | 0010 |     | 
+ 550 | 0011 |     | 
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uplt1_l t1 LEFT JOIN uplt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |   0 | 0000
+  50 | 0001 |     | 
+ 100 | 0002 |     | 
+ 150 | 0003 | 150 | 0003
+ 200 | 0004 |     | 
+ 250 | 0005 |     | 
+ 300 | 0006 | 300 | 0006
+ 350 | 0007 |     | 
+ 400 | 0008 |     | 
+ 450 | 0009 | 450 | 0009
+ 500 | 0010 |     | 
+ 550 | 0011 |     | 
+(12 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1 RIGHT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 1) and (b 2) is considered for partition-wise join.
+NOTICE:  join between relations (b 5) and (b 18) is considered for partition-wise join.
+NOTICE:  join between relations (b 9) and (b 22) is considered for partition-wise join.
+NOTICE:  join between relations (b 13) and (b 26) is considered for partition-wise join.
+                                                                                     QUERY PLAN                                                                                     
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: t1.a, t1.c, t2.b, t2.c
+   Sort Key: t1.a
+   ->  Append
+         ->  Hash Join
+               Output: t1.a, t1.c, t2.b, t2.c
+               Hash Cond: ((t2.b = t1.a) AND (t2.a = t1.b) AND ((t2.c)::text = (t1.c)::text) AND (ltrim((t2.c)::text, 'A'::text) = ltrim((t1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p1_p1 t2
+                     Output: t2.b, t2.c, t2.a
+               ->  Hash
+                     Output: t1.a, t1.c, t1.b
+                     ->  Seq Scan on public.plt1_l_p1_p1 t1
+                           Output: t1.a, t1.c, t1.b
+                           Filter: ((t1.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c
+               Hash Cond: ((t2_1.b = t1_1.a) AND (t2_1.a = t1_1.b) AND ((t2_1.c)::text = (t1_1.c)::text) AND (ltrim((t2_1.c)::text, 'A'::text) = ltrim((t1_1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p1_p2 t2_1
+                     Output: t2_1.b, t2_1.c, t2_1.a
+               ->  Hash
+                     Output: t1_1.a, t1_1.c, t1_1.b
+                     ->  Seq Scan on public.plt1_l_p1_p2 t1_1
+                           Output: t1_1.a, t1_1.c, t1_1.b
+                           Filter: ((t1_1.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c
+               Hash Cond: ((t2_2.b = t1_2.a) AND (t2_2.a = t1_2.b) AND ((t2_2.c)::text = (t1_2.c)::text) AND (ltrim((t2_2.c)::text, 'A'::text) = ltrim((t1_2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p2_p1 t2_2
+                     Output: t2_2.b, t2_2.c, t2_2.a
+               ->  Hash
+                     Output: t1_2.a, t1_2.c, t1_2.b
+                     ->  Seq Scan on public.plt1_l_p2_p1 t1_2
+                           Output: t1_2.a, t1_2.c, t1_2.b
+                           Filter: ((t1_2.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_3.a, t1_3.c, t2_3.b, t2_3.c
+               Hash Cond: ((t2_3.b = t1_3.a) AND (t2_3.a = t1_3.b) AND ((t2_3.c)::text = (t1_3.c)::text) AND (ltrim((t2_3.c)::text, 'A'::text) = ltrim((t1_3.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p2_p2 t2_3
+                     Output: t2_3.b, t2_3.c, t2_3.a
+               ->  Hash
+                     Output: t1_3.a, t1_3.c, t1_3.b
+                     ->  Seq Scan on public.plt1_l_p2_p2 t1_3
+                           Output: t1_3.a, t1_3.c, t1_3.b
+                           Filter: ((t1_3.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_4.a, t1_4.c, t2_4.b, t2_4.c
+               Hash Cond: ((t2_4.b = t1_4.a) AND (t2_4.a = t1_4.b) AND ((t2_4.c)::text = (t1_4.c)::text) AND (ltrim((t2_4.c)::text, 'A'::text) = ltrim((t1_4.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p1 t2_4
+                     Output: t2_4.b, t2_4.c, t2_4.a
+               ->  Hash
+                     Output: t1_4.a, t1_4.c, t1_4.b
+                     ->  Seq Scan on public.plt1_l_p3_p1 t1_4
+                           Output: t1_4.a, t1_4.c, t1_4.b
+                           Filter: ((t1_4.a % 25) = 0)
+         ->  Hash Join
+               Output: t1_5.a, t1_5.c, t2_5.b, t2_5.c
+               Hash Cond: ((t2_5.b = t1_5.a) AND (t2_5.a = t1_5.b) AND ((t2_5.c)::text = (t1_5.c)::text) AND (ltrim((t2_5.c)::text, 'A'::text) = ltrim((t1_5.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p2 t2_5
+                     Output: t2_5.b, t2_5.c, t2_5.a
+               ->  Hash
+                     Output: t1_5.a, t1_5.c, t1_5.b
+                     ->  Seq Scan on public.plt1_l_p3_p2 t1_5
+                           Output: t1_5.a, t1_5.c, t1_5.b
+                           Filter: ((t1_5.a % 25) = 0)
+(64 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1 RIGHT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 1) and (b 2) is considered for partition-wise join.
+NOTICE:  join between relations (b 5) and (b 18) is considered for partition-wise join.
+NOTICE:  join between relations (b 9) and (b 22) is considered for partition-wise join.
+NOTICE:  join between relations (b 13) and (b 26) is considered for partition-wise join.
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |   0 | 0000
+ 150 | 0003 | 150 | 0003
+ 300 | 0006 | 300 | 0006
+ 450 | 0009 | 450 | 0009
+(4 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uplt1_l t1 RIGHT JOIN uplt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |   0 | 0000
+ 150 | 0003 | 150 | 0003
+ 300 | 0006 | 300 | 0006
+ 450 | 0009 | 450 | 0009
+(4 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE plt1_l.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2_l WHERE plt2_l.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A')) ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+                                                                                                                     QUERY PLAN                                                                                                                     
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+   Sort Key: plt1_l_p1_p1.a, plt2_l_p1_p1.b
+   ->  Append
+         ->  Hash Full Join
+               Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+               Hash Cond: ((plt1_l_p1_p1.a = plt2_l_p1_p1.b) AND (plt1_l_p1_p1.b = plt2_l_p1_p1.a) AND ((plt1_l_p1_p1.c)::text = (plt2_l_p1_p1.c)::text) AND (ltrim((plt1_l_p1_p1.c)::text, 'A'::text) = ltrim((plt2_l_p1_p1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p1_p1
+                     Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt1_l_p1_p1.b
+                     Filter: ((plt1_l_p1_p1.a % 25) = 0)
+               ->  Hash
+                     Output: plt2_l_p1_p1.b, plt2_l_p1_p1.c, plt2_l_p1_p1.a
+                     ->  Seq Scan on public.plt2_l_p1_p1
+                           Output: plt2_l_p1_p1.b, plt2_l_p1_p1.c, plt2_l_p1_p1.a
+                           Filter: ((plt2_l_p1_p1.b % 25) = 0)
+         ->  Hash Full Join
+               Output: plt1_l_p1_p2.a, plt1_l_p1_p2.c, plt2_l_p1_p2.b, plt2_l_p1_p2.c
+               Hash Cond: ((plt1_l_p1_p2.a = plt2_l_p1_p2.b) AND (plt1_l_p1_p2.b = plt2_l_p1_p2.a) AND ((plt1_l_p1_p2.c)::text = (plt2_l_p1_p2.c)::text) AND (ltrim((plt1_l_p1_p2.c)::text, 'A'::text) = ltrim((plt2_l_p1_p2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p1_p2
+                     Output: plt1_l_p1_p2.a, plt1_l_p1_p2.c, plt1_l_p1_p2.b
+                     Filter: ((plt1_l_p1_p2.a % 25) = 0)
+               ->  Hash
+                     Output: plt2_l_p1_p2.b, plt2_l_p1_p2.c, plt2_l_p1_p2.a
+                     ->  Seq Scan on public.plt2_l_p1_p2
+                           Output: plt2_l_p1_p2.b, plt2_l_p1_p2.c, plt2_l_p1_p2.a
+                           Filter: ((plt2_l_p1_p2.b % 25) = 0)
+         ->  Hash Full Join
+               Output: plt1_l_p2_p1.a, plt1_l_p2_p1.c, plt2_l_p2_p1.b, plt2_l_p2_p1.c
+               Hash Cond: ((plt1_l_p2_p1.a = plt2_l_p2_p1.b) AND (plt1_l_p2_p1.b = plt2_l_p2_p1.a) AND ((plt1_l_p2_p1.c)::text = (plt2_l_p2_p1.c)::text) AND (ltrim((plt1_l_p2_p1.c)::text, 'A'::text) = ltrim((plt2_l_p2_p1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p2_p1
+                     Output: plt1_l_p2_p1.a, plt1_l_p2_p1.c, plt1_l_p2_p1.b
+                     Filter: ((plt1_l_p2_p1.a % 25) = 0)
+               ->  Hash
+                     Output: plt2_l_p2_p1.b, plt2_l_p2_p1.c, plt2_l_p2_p1.a
+                     ->  Seq Scan on public.plt2_l_p2_p1
+                           Output: plt2_l_p2_p1.b, plt2_l_p2_p1.c, plt2_l_p2_p1.a
+                           Filter: ((plt2_l_p2_p1.b % 25) = 0)
+         ->  Hash Full Join
+               Output: plt1_l_p2_p2.a, plt1_l_p2_p2.c, plt2_l_p2_p2.b, plt2_l_p2_p2.c
+               Hash Cond: ((plt1_l_p2_p2.a = plt2_l_p2_p2.b) AND (plt1_l_p2_p2.b = plt2_l_p2_p2.a) AND ((plt1_l_p2_p2.c)::text = (plt2_l_p2_p2.c)::text) AND (ltrim((plt1_l_p2_p2.c)::text, 'A'::text) = ltrim((plt2_l_p2_p2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p2_p2
+                     Output: plt1_l_p2_p2.a, plt1_l_p2_p2.c, plt1_l_p2_p2.b
+                     Filter: ((plt1_l_p2_p2.a % 25) = 0)
+               ->  Hash
+                     Output: plt2_l_p2_p2.b, plt2_l_p2_p2.c, plt2_l_p2_p2.a
+                     ->  Seq Scan on public.plt2_l_p2_p2
+                           Output: plt2_l_p2_p2.b, plt2_l_p2_p2.c, plt2_l_p2_p2.a
+                           Filter: ((plt2_l_p2_p2.b % 25) = 0)
+         ->  Hash Full Join
+               Output: plt1_l_p3_p1.a, plt1_l_p3_p1.c, plt2_l_p3_p1.b, plt2_l_p3_p1.c
+               Hash Cond: ((plt1_l_p3_p1.a = plt2_l_p3_p1.b) AND (plt1_l_p3_p1.b = plt2_l_p3_p1.a) AND ((plt1_l_p3_p1.c)::text = (plt2_l_p3_p1.c)::text) AND (ltrim((plt1_l_p3_p1.c)::text, 'A'::text) = ltrim((plt2_l_p3_p1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p3_p1
+                     Output: plt1_l_p3_p1.a, plt1_l_p3_p1.c, plt1_l_p3_p1.b
+                     Filter: ((plt1_l_p3_p1.a % 25) = 0)
+               ->  Hash
+                     Output: plt2_l_p3_p1.b, plt2_l_p3_p1.c, plt2_l_p3_p1.a
+                     ->  Seq Scan on public.plt2_l_p3_p1
+                           Output: plt2_l_p3_p1.b, plt2_l_p3_p1.c, plt2_l_p3_p1.a
+                           Filter: ((plt2_l_p3_p1.b % 25) = 0)
+         ->  Hash Full Join
+               Output: plt1_l_p3_p2.a, plt1_l_p3_p2.c, plt2_l_p3_p2.b, plt2_l_p3_p2.c
+               Hash Cond: ((plt1_l_p3_p2.a = plt2_l_p3_p2.b) AND (plt1_l_p3_p2.b = plt2_l_p3_p2.a) AND ((plt1_l_p3_p2.c)::text = (plt2_l_p3_p2.c)::text) AND (ltrim((plt1_l_p3_p2.c)::text, 'A'::text) = ltrim((plt2_l_p3_p2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p3_p2
+                     Output: plt1_l_p3_p2.a, plt1_l_p3_p2.c, plt1_l_p3_p2.b
+                     Filter: ((plt1_l_p3_p2.a % 25) = 0)
+               ->  Hash
+                     Output: plt2_l_p3_p2.b, plt2_l_p3_p2.c, plt2_l_p3_p2.a
+                     ->  Seq Scan on public.plt2_l_p3_p2
+                           Output: plt2_l_p3_p2.b, plt2_l_p3_p2.c, plt2_l_p3_p2.a
+                           Filter: ((plt2_l_p3_p2.b % 25) = 0)
+(70 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE plt1_l.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2_l WHERE plt2_l.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A')) ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |   0 | 0000
+  50 | 0001 |     | 
+ 100 | 0002 |     | 
+ 150 | 0003 | 150 | 0003
+ 200 | 0004 |     | 
+ 250 | 0005 |     | 
+ 300 | 0006 | 300 | 0006
+ 350 | 0007 |     | 
+ 400 | 0008 |     | 
+ 450 | 0009 | 450 | 0009
+ 500 | 0010 |     | 
+ 550 | 0011 |     | 
+     |      |  75 | 0001
+     |      | 225 | 0004
+     |      | 375 | 0007
+     |      | 525 | 0010
+(16 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uplt2_l t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A')) ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |   0 | 0000
+  50 | 0001 |     | 
+ 100 | 0002 |     | 
+ 150 | 0003 | 150 | 0003
+ 200 | 0004 |     | 
+ 250 | 0005 |     | 
+ 300 | 0006 | 300 | 0006
+ 350 | 0007 |     | 
+ 400 | 0008 |     | 
+ 450 | 0009 | 450 | 0009
+ 500 | 0010 |     | 
+ 550 | 0011 |     | 
+     |      |  75 | 0001
+     |      | 225 | 0004
+     |      | 375 | 0007
+     |      | 525 | 0010
+(16 rows)
+
+-- lateral reference
+--Getting could not devise a query plan error, need to be fix to get query output
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM plt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM plt1_l t2 JOIN plt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.a = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM plt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM plt1_l t2 JOIN plt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.a = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+  a  |  b  |  c   | t2a | t2c  | t2b | t3a | least 
+-----+-----+------+-----+------+-----+-----+-------
+   0 |   0 | 0000 |   0 | 0000 |   0 |   0 | 0000
+  50 |  50 | 0001 |     |      |     |     | 
+ 100 | 100 | 0002 |     |      |     |     | 
+ 150 | 150 | 0003 | 150 | 0003 | 150 | 150 | 0003
+ 200 | 200 | 0004 |     |      |     |     | 
+ 250 | 250 | 0005 |     |      |     |     | 
+ 300 | 300 | 0006 | 300 | 0006 | 300 | 300 | 0006
+ 350 | 350 | 0007 |     |      |     |     | 
+ 400 | 400 | 0008 |     |      |     |     | 
+ 450 | 450 | 0009 | 450 | 0009 | 450 | 450 | 0009
+ 500 | 500 | 0010 |     |      |     |     | 
+ 550 | 550 | 0011 |     |      |     |     | 
+(12 rows)
+
+SELECT * FROM uplt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM uplt1_l t2 JOIN uplt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.a = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+  a  |  b  |  c   | t2a | t2c  | t2b | t3a | least 
+-----+-----+------+-----+------+-----+-----+-------
+   0 |   0 | 0000 |   0 | 0000 |   0 |   0 | 0000
+  50 |  50 | 0001 |     |      |     |     | 
+ 100 | 100 | 0002 |     |      |     |     | 
+ 150 | 150 | 0003 | 150 | 0003 | 150 | 150 | 0003
+ 200 | 200 | 0004 |     |      |     |     | 
+ 250 | 250 | 0005 |     |      |     |     | 
+ 300 | 300 | 0006 | 300 | 0006 | 300 | 300 | 0006
+ 350 | 350 | 0007 |     |      |     |     | 
+ 400 | 400 | 0008 |     |      |     |     | 
+ 450 | 450 | 0009 | 450 | 0009 | 450 | 450 | 0009
+ 500 | 500 | 0010 |     |      |     |     | 
+ 550 | 550 | 0011 |     |      |     |     | 
+(12 rows)
+
+--Getting could not devise a query plan error, need to be fix to get query output
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM plt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM plt1_l t2 JOIN plt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.b = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM plt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM plt1_l t2 JOIN plt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.b = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+  a  |  b  |  c   | t2a | t2c  | t2b | t3a | least 
+-----+-----+------+-----+------+-----+-----+-------
+   0 |   0 | 0000 |   0 | 0000 |   0 |   0 | 0000
+  50 |  50 | 0001 |     |      |     |     | 
+ 100 | 100 | 0002 |     |      |     |     | 
+ 150 | 150 | 0003 | 150 | 0003 | 150 | 150 | 0003
+ 200 | 200 | 0004 |     |      |     |     | 
+ 250 | 250 | 0005 |     |      |     |     | 
+ 300 | 300 | 0006 | 300 | 0006 | 300 | 300 | 0006
+ 350 | 350 | 0007 |     |      |     |     | 
+ 400 | 400 | 0008 |     |      |     |     | 
+ 450 | 450 | 0009 | 450 | 0009 | 450 | 450 | 0009
+ 500 | 500 | 0010 |     |      |     |     | 
+ 550 | 550 | 0011 |     |      |     |     | 
+(12 rows)
+
+SELECT * FROM uplt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM uplt1_l t2 JOIN uplt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.b = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+  a  |  b  |  c   | t2a | t2c  | t2b | t3a | least 
+-----+-----+------+-----+------+-----+-----+-------
+   0 |   0 | 0000 |   0 | 0000 |   0 |   0 | 0000
+  50 |  50 | 0001 |     |      |     |     | 
+ 100 | 100 | 0002 |     |      |     |     | 
+ 150 | 150 | 0003 | 150 | 0003 | 150 | 150 | 0003
+ 200 | 200 | 0004 |     |      |     |     | 
+ 250 | 250 | 0005 |     |      |     |     | 
+ 300 | 300 | 0006 | 300 | 0006 | 300 | 300 | 0006
+ 350 | 350 | 0007 |     |      |     |     | 
+ 400 | 400 | 0008 |     |      |     |     | 
+ 450 | 450 | 0009 | 450 | 0009 | 450 | 450 | 0009
+ 500 | 500 | 0010 |     |      |     |     | 
+ 550 | 550 | 0011 |     |      |     |     | 
+(12 rows)
+
+-- Cases with non-nullable expressions in subquery results;
+-- make sure these go to null as expected
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM (SELECT 50 phv, * FROM plt1_l WHERE plt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM plt2_l WHERE plt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and ltrim(t2.c,'A') = ltrim(t1.c,'A')) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+                                                                                                                        QUERY PLAN                                                                                                                        
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: (50), plt1_l_p1_p1.a, plt1_l_p1_p1.b, plt1_l_p1_p1.c, (75), plt2_l_p1_p1.a, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+   Sort Key: (50), plt1_l_p1_p1.a, plt1_l_p1_p1.b, plt1_l_p1_p1.c, (75), plt2_l_p1_p1.a, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+   ->  Result
+         Output: (50), plt1_l_p1_p1.a, plt1_l_p1_p1.b, plt1_l_p1_p1.c, (75), plt2_l_p1_p1.a, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+         ->  Append
+               ->  Hash Full Join
+                     Output: plt1_l_p1_p1.a, plt1_l_p1_p1.b, plt1_l_p1_p1.c, plt2_l_p1_p1.a, plt2_l_p1_p1.b, plt2_l_p1_p1.c, (50), (75)
+                     Hash Cond: ((plt1_l_p1_p1.a = plt2_l_p1_p1.b) AND (plt1_l_p1_p1.b = plt2_l_p1_p1.a) AND ((plt1_l_p1_p1.c)::text = (plt2_l_p1_p1.c)::text) AND (ltrim((plt1_l_p1_p1.c)::text, 'A'::text) = ltrim((plt2_l_p1_p1.c)::text, 'A'::text)))
+                     Filter: (((50) = plt1_l_p1_p1.b) OR ((75) = plt2_l_p1_p1.b))
+                     ->  Seq Scan on public.plt1_l_p1_p1
+                           Output: plt1_l_p1_p1.a, plt1_l_p1_p1.b, plt1_l_p1_p1.c, 50
+                           Filter: ((plt1_l_p1_p1.a % 25) = 0)
+                     ->  Hash
+                           Output: plt2_l_p1_p1.a, plt2_l_p1_p1.b, plt2_l_p1_p1.c, (75)
+                           ->  Seq Scan on public.plt2_l_p1_p1
+                                 Output: plt2_l_p1_p1.a, plt2_l_p1_p1.b, plt2_l_p1_p1.c, 75
+                                 Filter: ((plt2_l_p1_p1.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: plt1_l_p1_p2.a, plt1_l_p1_p2.b, plt1_l_p1_p2.c, plt2_l_p1_p2.a, plt2_l_p1_p2.b, plt2_l_p1_p2.c, (50), (75)
+                     Hash Cond: ((plt1_l_p1_p2.a = plt2_l_p1_p2.b) AND (plt1_l_p1_p2.b = plt2_l_p1_p2.a) AND ((plt1_l_p1_p2.c)::text = (plt2_l_p1_p2.c)::text) AND (ltrim((plt1_l_p1_p2.c)::text, 'A'::text) = ltrim((plt2_l_p1_p2.c)::text, 'A'::text)))
+                     Filter: (((50) = plt1_l_p1_p2.b) OR ((75) = plt2_l_p1_p2.b))
+                     ->  Seq Scan on public.plt1_l_p1_p2
+                           Output: plt1_l_p1_p2.a, plt1_l_p1_p2.b, plt1_l_p1_p2.c, 50
+                           Filter: ((plt1_l_p1_p2.a % 25) = 0)
+                     ->  Hash
+                           Output: plt2_l_p1_p2.a, plt2_l_p1_p2.b, plt2_l_p1_p2.c, (75)
+                           ->  Seq Scan on public.plt2_l_p1_p2
+                                 Output: plt2_l_p1_p2.a, plt2_l_p1_p2.b, plt2_l_p1_p2.c, 75
+                                 Filter: ((plt2_l_p1_p2.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: plt1_l_p2_p1.a, plt1_l_p2_p1.b, plt1_l_p2_p1.c, plt2_l_p2_p1.a, plt2_l_p2_p1.b, plt2_l_p2_p1.c, (50), (75)
+                     Hash Cond: ((plt1_l_p2_p1.a = plt2_l_p2_p1.b) AND (plt1_l_p2_p1.b = plt2_l_p2_p1.a) AND ((plt1_l_p2_p1.c)::text = (plt2_l_p2_p1.c)::text) AND (ltrim((plt1_l_p2_p1.c)::text, 'A'::text) = ltrim((plt2_l_p2_p1.c)::text, 'A'::text)))
+                     Filter: (((50) = plt1_l_p2_p1.b) OR ((75) = plt2_l_p2_p1.b))
+                     ->  Seq Scan on public.plt1_l_p2_p1
+                           Output: plt1_l_p2_p1.a, plt1_l_p2_p1.b, plt1_l_p2_p1.c, 50
+                           Filter: ((plt1_l_p2_p1.a % 25) = 0)
+                     ->  Hash
+                           Output: plt2_l_p2_p1.a, plt2_l_p2_p1.b, plt2_l_p2_p1.c, (75)
+                           ->  Seq Scan on public.plt2_l_p2_p1
+                                 Output: plt2_l_p2_p1.a, plt2_l_p2_p1.b, plt2_l_p2_p1.c, 75
+                                 Filter: ((plt2_l_p2_p1.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: plt1_l_p2_p2.a, plt1_l_p2_p2.b, plt1_l_p2_p2.c, plt2_l_p2_p2.a, plt2_l_p2_p2.b, plt2_l_p2_p2.c, (50), (75)
+                     Hash Cond: ((plt1_l_p2_p2.a = plt2_l_p2_p2.b) AND (plt1_l_p2_p2.b = plt2_l_p2_p2.a) AND ((plt1_l_p2_p2.c)::text = (plt2_l_p2_p2.c)::text) AND (ltrim((plt1_l_p2_p2.c)::text, 'A'::text) = ltrim((plt2_l_p2_p2.c)::text, 'A'::text)))
+                     Filter: (((50) = plt1_l_p2_p2.b) OR ((75) = plt2_l_p2_p2.b))
+                     ->  Seq Scan on public.plt1_l_p2_p2
+                           Output: plt1_l_p2_p2.a, plt1_l_p2_p2.b, plt1_l_p2_p2.c, 50
+                           Filter: ((plt1_l_p2_p2.a % 25) = 0)
+                     ->  Hash
+                           Output: plt2_l_p2_p2.a, plt2_l_p2_p2.b, plt2_l_p2_p2.c, (75)
+                           ->  Seq Scan on public.plt2_l_p2_p2
+                                 Output: plt2_l_p2_p2.a, plt2_l_p2_p2.b, plt2_l_p2_p2.c, 75
+                                 Filter: ((plt2_l_p2_p2.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: plt1_l_p3_p1.a, plt1_l_p3_p1.b, plt1_l_p3_p1.c, plt2_l_p3_p1.a, plt2_l_p3_p1.b, plt2_l_p3_p1.c, (50), (75)
+                     Hash Cond: ((plt1_l_p3_p1.a = plt2_l_p3_p1.b) AND (plt1_l_p3_p1.b = plt2_l_p3_p1.a) AND ((plt1_l_p3_p1.c)::text = (plt2_l_p3_p1.c)::text) AND (ltrim((plt1_l_p3_p1.c)::text, 'A'::text) = ltrim((plt2_l_p3_p1.c)::text, 'A'::text)))
+                     Filter: (((50) = plt1_l_p3_p1.b) OR ((75) = plt2_l_p3_p1.b))
+                     ->  Seq Scan on public.plt1_l_p3_p1
+                           Output: plt1_l_p3_p1.a, plt1_l_p3_p1.b, plt1_l_p3_p1.c, 50
+                           Filter: ((plt1_l_p3_p1.a % 25) = 0)
+                     ->  Hash
+                           Output: plt2_l_p3_p1.a, plt2_l_p3_p1.b, plt2_l_p3_p1.c, (75)
+                           ->  Seq Scan on public.plt2_l_p3_p1
+                                 Output: plt2_l_p3_p1.a, plt2_l_p3_p1.b, plt2_l_p3_p1.c, 75
+                                 Filter: ((plt2_l_p3_p1.b % 25) = 0)
+               ->  Hash Full Join
+                     Output: plt1_l_p3_p2.a, plt1_l_p3_p2.b, plt1_l_p3_p2.c, plt2_l_p3_p2.a, plt2_l_p3_p2.b, plt2_l_p3_p2.c, (50), (75)
+                     Hash Cond: ((plt1_l_p3_p2.a = plt2_l_p3_p2.b) AND (plt1_l_p3_p2.b = plt2_l_p3_p2.a) AND ((plt1_l_p3_p2.c)::text = (plt2_l_p3_p2.c)::text) AND (ltrim((plt1_l_p3_p2.c)::text, 'A'::text) = ltrim((plt2_l_p3_p2.c)::text, 'A'::text)))
+                     Filter: (((50) = plt1_l_p3_p2.b) OR ((75) = plt2_l_p3_p2.b))
+                     ->  Seq Scan on public.plt1_l_p3_p2
+                           Output: plt1_l_p3_p2.a, plt1_l_p3_p2.b, plt1_l_p3_p2.c, 50
+                           Filter: ((plt1_l_p3_p2.a % 25) = 0)
+                     ->  Hash
+                           Output: plt2_l_p3_p2.a, plt2_l_p3_p2.b, plt2_l_p3_p2.c, (75)
+                           ->  Seq Scan on public.plt2_l_p3_p2
+                                 Output: plt2_l_p3_p2.a, plt2_l_p3_p2.b, plt2_l_p3_p2.c, 75
+                                 Filter: ((plt2_l_p3_p2.b % 25) = 0)
+(78 rows)
+
+SELECT * FROM (SELECT 50 phv, * FROM plt1_l WHERE plt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM plt2_l WHERE plt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and ltrim(t2.c,'A') = ltrim(t1.c,'A')) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+ phv | a  | b  |  c   | phv | a  | b  |  c   
+-----+----+----+------+-----+----+----+------
+  50 | 50 | 50 | 0001 |     |    |    | 
+     |    |    |      |  75 | 75 | 75 | 0001
+(2 rows)
+
+SELECT * FROM (SELECT 50 phv, * FROM uplt1_l WHERE uplt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uplt2_l WHERE uplt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and ltrim(t2.c,'A') = ltrim(t1.c,'A')) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+ phv | a  | b  |  c   | phv | a  | b  |  c   
+-----+----+----+------+-----+----+----+------
+  50 | 50 | 50 | 0001 |     |    |    | 
+     |    |    |      |  75 | 75 | 75 | 0001
+(2 rows)
+
+-- Join with pruned partitions from joining relations
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 1) and (b 2) is considered for partition-wise join.
+NOTICE:  join between relations (b 4) and (b 17) is considered for partition-wise join.
+NOTICE:  join between relations (b 8) and (b 21) is considered for partition-wise join.
+NOTICE:  join between relations (b 12) and (b 25) is considered for partition-wise join.
+                                                                                     QUERY PLAN                                                                                     
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: t1.a, t1.c, t2.b, t2.c
+   Sort Key: t1.a
+   ->  Append
+         ->  Nested Loop
+               Output: t1.a, t1.c, t2.b, t2.c
+               Join Filter: ((t1.a = t2.b) AND (t1.b = t2.a) AND ((t1.c)::text = (t2.c)::text) AND (ltrim((t1.c)::text, 'A'::text) = ltrim((t2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p1_p1 t1
+                     Output: t1.a, t1.c, t1.b
+                     Filter: ((t1.a < 450) AND ((t1.a % 25) = 0))
+               ->  Seq Scan on public.plt2_l_p1_p1 t2
+                     Output: t2.b, t2.c, t2.a
+                     Filter: (t2.b > 250)
+         ->  Hash Join
+               Output: t1_1.a, t1_1.c, t2_1.b, t2_1.c
+               Hash Cond: ((t2_1.b = t1_1.a) AND (t2_1.a = t1_1.b) AND ((t2_1.c)::text = (t1_1.c)::text) AND (ltrim((t2_1.c)::text, 'A'::text) = ltrim((t1_1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p1_p2 t2_1
+                     Output: t2_1.b, t2_1.c, t2_1.a
+                     Filter: (t2_1.b > 250)
+               ->  Hash
+                     Output: t1_1.a, t1_1.c, t1_1.b
+                     ->  Seq Scan on public.plt1_l_p1_p2 t1_1
+                           Output: t1_1.a, t1_1.c, t1_1.b
+                           Filter: ((t1_1.a < 450) AND ((t1_1.a % 25) = 0))
+         ->  Hash Join
+               Output: t1_2.a, t1_2.c, t2_2.b, t2_2.c
+               Hash Cond: ((t2_2.b = t1_2.a) AND (t2_2.a = t1_2.b) AND ((t2_2.c)::text = (t1_2.c)::text) AND (ltrim((t2_2.c)::text, 'A'::text) = ltrim((t1_2.c)::text, 'A'::text)))
+               ->  Append
+                     ->  Seq Scan on public.plt2_l_p2 t2_2
+                           Output: t2_2.b, t2_2.c, t2_2.a
+                           Filter: (t2_2.b > 250)
+                     ->  Seq Scan on public.plt2_l_p2_p1 t2_3
+                           Output: t2_3.b, t2_3.c, t2_3.a
+                           Filter: (t2_3.b > 250)
+                     ->  Seq Scan on public.plt2_l_p2_p2 t2_4
+                           Output: t2_4.b, t2_4.c, t2_4.a
+                           Filter: (t2_4.b > 250)
+               ->  Hash
+                     Output: t1_2.a, t1_2.c, t1_2.b
+                     ->  Append
+                           ->  Seq Scan on public.plt1_l_p2 t1_2
+                                 Output: t1_2.a, t1_2.c, t1_2.b
+                                 Filter: ((t1_2.a < 450) AND ((t1_2.a % 25) = 0))
+                           ->  Seq Scan on public.plt1_l_p2_p1 t1_3
+                                 Output: t1_3.a, t1_3.c, t1_3.b
+                                 Filter: ((t1_3.a < 450) AND ((t1_3.a % 25) = 0))
+                           ->  Seq Scan on public.plt1_l_p2_p2 t1_4
+                                 Output: t1_4.a, t1_4.c, t1_4.b
+                                 Filter: ((t1_4.a < 450) AND ((t1_4.a % 25) = 0))
+         ->  Hash Join
+               Output: t1_5.a, t1_5.c, t2_5.b, t2_5.c
+               Hash Cond: ((t2_5.b = t1_5.a) AND (t2_5.a = t1_5.b) AND ((t2_5.c)::text = (t1_5.c)::text) AND (ltrim((t2_5.c)::text, 'A'::text) = ltrim((t1_5.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p1 t2_5
+                     Output: t2_5.b, t2_5.c, t2_5.a
+                     Filter: (t2_5.b > 250)
+               ->  Hash
+                     Output: t1_5.a, t1_5.c, t1_5.b
+                     ->  Seq Scan on public.plt1_l_p3_p1 t1_5
+                           Output: t1_5.a, t1_5.c, t1_5.b
+                           Filter: ((t1_5.a < 450) AND ((t1_5.a % 25) = 0))
+         ->  Hash Join
+               Output: t1_6.a, t1_6.c, t2_6.b, t2_6.c
+               Hash Cond: ((t2_6.b = t1_6.a) AND (t2_6.a = t1_6.b) AND ((t2_6.c)::text = (t1_6.c)::text) AND (ltrim((t2_6.c)::text, 'A'::text) = ltrim((t1_6.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p2 t2_6
+                     Output: t2_6.b, t2_6.c, t2_6.a
+                     Filter: (t2_6.b > 250)
+               ->  Hash
+                     Output: t1_6.a, t1_6.c, t1_6.b
+                     ->  Seq Scan on public.plt1_l_p3_p2 t1_6
+                           Output: t1_6.a, t1_6.c, t1_6.b
+                           Filter: ((t1_6.a < 450) AND ((t1_6.a % 25) = 0))
+(71 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 1) and (b 2) is considered for partition-wise join.
+NOTICE:  join between relations (b 4) and (b 17) is considered for partition-wise join.
+NOTICE:  join between relations (b 8) and (b 21) is considered for partition-wise join.
+NOTICE:  join between relations (b 12) and (b 25) is considered for partition-wise join.
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+ 300 | 0006 | 300 | 0006
+(1 row)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM uplt1_l t1, uplt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+ 300 | 0006 | 300 | 0006
+(1 row)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM plt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+                                                                                                                      QUERY PLAN                                                                                                                      
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+   Sort Key: plt1_l_p1_p1.a, plt2_l_p1_p1.b
+   ->  Append
+         ->  Nested Loop Left Join
+               Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+               Join Filter: ((plt1_l_p1_p1.a = plt2_l_p1_p1.b) AND (plt1_l_p1_p1.b = plt2_l_p1_p1.a) AND ((plt1_l_p1_p1.c)::text = (plt2_l_p1_p1.c)::text) AND (ltrim((plt1_l_p1_p1.c)::text, 'A'::text) = ltrim((plt2_l_p1_p1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p1_p1
+                     Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt1_l_p1_p1.b
+                     Filter: ((plt1_l_p1_p1.a < 450) AND ((plt1_l_p1_p1.a % 25) = 0))
+               ->  Seq Scan on public.plt2_l_p1_p1
+                     Output: plt2_l_p1_p1.b, plt2_l_p1_p1.c, plt2_l_p1_p1.a
+                     Filter: (plt2_l_p1_p1.b > 250)
+         ->  Hash Right Join
+               Output: plt1_l_p1_p2.a, plt1_l_p1_p2.c, plt2_l_p1_p2.b, plt2_l_p1_p2.c
+               Hash Cond: ((plt2_l_p1_p2.b = plt1_l_p1_p2.a) AND (plt2_l_p1_p2.a = plt1_l_p1_p2.b) AND ((plt2_l_p1_p2.c)::text = (plt1_l_p1_p2.c)::text) AND (ltrim((plt2_l_p1_p2.c)::text, 'A'::text) = ltrim((plt1_l_p1_p2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p1_p2
+                     Output: plt2_l_p1_p2.b, plt2_l_p1_p2.c, plt2_l_p1_p2.a
+                     Filter: (plt2_l_p1_p2.b > 250)
+               ->  Hash
+                     Output: plt1_l_p1_p2.a, plt1_l_p1_p2.c, plt1_l_p1_p2.b
+                     ->  Seq Scan on public.plt1_l_p1_p2
+                           Output: plt1_l_p1_p2.a, plt1_l_p1_p2.c, plt1_l_p1_p2.b
+                           Filter: ((plt1_l_p1_p2.a < 450) AND ((plt1_l_p1_p2.a % 25) = 0))
+         ->  Hash Left Join
+               Output: plt1_l_p2_p1.a, plt1_l_p2_p1.c, plt2_l_p2_p1.b, plt2_l_p2_p1.c
+               Hash Cond: ((plt1_l_p2_p1.a = plt2_l_p2_p1.b) AND (plt1_l_p2_p1.b = plt2_l_p2_p1.a) AND ((plt1_l_p2_p1.c)::text = (plt2_l_p2_p1.c)::text) AND (ltrim((plt1_l_p2_p1.c)::text, 'A'::text) = ltrim((plt2_l_p2_p1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p2_p1
+                     Output: plt1_l_p2_p1.a, plt1_l_p2_p1.c, plt1_l_p2_p1.b
+                     Filter: ((plt1_l_p2_p1.a < 450) AND ((plt1_l_p2_p1.a % 25) = 0))
+               ->  Hash
+                     Output: plt2_l_p2_p1.b, plt2_l_p2_p1.c, plt2_l_p2_p1.a
+                     ->  Seq Scan on public.plt2_l_p2_p1
+                           Output: plt2_l_p2_p1.b, plt2_l_p2_p1.c, plt2_l_p2_p1.a
+                           Filter: (plt2_l_p2_p1.b > 250)
+         ->  Hash Right Join
+               Output: plt1_l_p2_p2.a, plt1_l_p2_p2.c, plt2_l_p2_p2.b, plt2_l_p2_p2.c
+               Hash Cond: ((plt2_l_p2_p2.b = plt1_l_p2_p2.a) AND (plt2_l_p2_p2.a = plt1_l_p2_p2.b) AND ((plt2_l_p2_p2.c)::text = (plt1_l_p2_p2.c)::text) AND (ltrim((plt2_l_p2_p2.c)::text, 'A'::text) = ltrim((plt1_l_p2_p2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p2_p2
+                     Output: plt2_l_p2_p2.b, plt2_l_p2_p2.c, plt2_l_p2_p2.a
+                     Filter: (plt2_l_p2_p2.b > 250)
+               ->  Hash
+                     Output: plt1_l_p2_p2.a, plt1_l_p2_p2.c, plt1_l_p2_p2.b
+                     ->  Seq Scan on public.plt1_l_p2_p2
+                           Output: plt1_l_p2_p2.a, plt1_l_p2_p2.c, plt1_l_p2_p2.b
+                           Filter: ((plt1_l_p2_p2.a < 450) AND ((plt1_l_p2_p2.a % 25) = 0))
+         ->  Hash Right Join
+               Output: plt1_l_p3_p1.a, plt1_l_p3_p1.c, plt2_l_p3_p1.b, plt2_l_p3_p1.c
+               Hash Cond: ((plt2_l_p3_p1.b = plt1_l_p3_p1.a) AND (plt2_l_p3_p1.a = plt1_l_p3_p1.b) AND ((plt2_l_p3_p1.c)::text = (plt1_l_p3_p1.c)::text) AND (ltrim((plt2_l_p3_p1.c)::text, 'A'::text) = ltrim((plt1_l_p3_p1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p1
+                     Output: plt2_l_p3_p1.b, plt2_l_p3_p1.c, plt2_l_p3_p1.a
+                     Filter: (plt2_l_p3_p1.b > 250)
+               ->  Hash
+                     Output: plt1_l_p3_p1.a, plt1_l_p3_p1.c, plt1_l_p3_p1.b
+                     ->  Seq Scan on public.plt1_l_p3_p1
+                           Output: plt1_l_p3_p1.a, plt1_l_p3_p1.c, plt1_l_p3_p1.b
+                           Filter: ((plt1_l_p3_p1.a < 450) AND ((plt1_l_p3_p1.a % 25) = 0))
+         ->  Hash Right Join
+               Output: plt1_l_p3_p2.a, plt1_l_p3_p2.c, plt2_l_p3_p2.b, plt2_l_p3_p2.c
+               Hash Cond: ((plt2_l_p3_p2.b = plt1_l_p3_p2.a) AND (plt2_l_p3_p2.a = plt1_l_p3_p2.b) AND ((plt2_l_p3_p2.c)::text = (plt1_l_p3_p2.c)::text) AND (ltrim((plt2_l_p3_p2.c)::text, 'A'::text) = ltrim((plt1_l_p3_p2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt2_l_p3_p2
+                     Output: plt2_l_p3_p2.b, plt2_l_p3_p2.c, plt2_l_p3_p2.a
+                     Filter: (plt2_l_p3_p2.b > 250)
+               ->  Hash
+                     Output: plt1_l_p3_p2.a, plt1_l_p3_p2.c, plt1_l_p3_p2.b
+                     ->  Seq Scan on public.plt1_l_p3_p2
+                           Output: plt1_l_p3_p2.a, plt1_l_p3_p2.c, plt1_l_p3_p2.b
+                           Filter: ((plt1_l_p3_p2.a < 450) AND ((plt1_l_p3_p2.a % 25) = 0))
+(68 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM plt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |     | 
+  50 | 0001 |     | 
+ 100 | 0002 |     | 
+ 150 | 0003 |     | 
+ 200 | 0004 |     | 
+ 250 | 0005 |     | 
+ 300 | 0006 | 300 | 0006
+ 350 | 0007 |     | 
+ 400 | 0008 |     | 
+(9 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM uplt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |     | 
+  50 | 0001 |     | 
+ 100 | 0002 |     | 
+ 150 | 0003 |     | 
+ 200 | 0004 |     | 
+ 250 | 0005 |     | 
+ 300 | 0006 | 300 | 0006
+ 350 | 0007 |     | 
+ 400 | 0008 |     | 
+(9 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM plt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 5) and (b 4) is considered for partition-wise join.
+NOTICE:  join between relations (b 20) and (b 7) is considered for partition-wise join.
+NOTICE:  join between relations (b 24) and (b 11) is considered for partition-wise join.
+NOTICE:  join between relations (b 28) and (b 15) is considered for partition-wise join.
+                                                                                                                        QUERY PLAN                                                                                                                        
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+   Sort Key: plt1_l_p1_p1.a, plt2_l_p1_p1.b
+   ->  Result
+         Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+         ->  Append
+               ->  Hash Right Join
+                     Output: plt2_l_p1_p1.b, plt2_l_p1_p1.c, plt1_l_p1_p1.a, plt1_l_p1_p1.c
+                     Hash Cond: ((plt1_l_p1_p1.a = plt2_l_p1_p1.b) AND (plt1_l_p1_p1.b = plt2_l_p1_p1.a) AND ((plt1_l_p1_p1.c)::text = (plt2_l_p1_p1.c)::text) AND (ltrim((plt1_l_p1_p1.c)::text, 'A'::text) = ltrim((plt2_l_p1_p1.c)::text, 'A'::text)))
+                     ->  Seq Scan on public.plt1_l_p1_p1
+                           Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt1_l_p1_p1.b
+                           Filter: (plt1_l_p1_p1.a < 450)
+                     ->  Hash
+                           Output: plt2_l_p1_p1.b, plt2_l_p1_p1.c, plt2_l_p1_p1.a
+                           ->  Seq Scan on public.plt2_l_p1_p1
+                                 Output: plt2_l_p1_p1.b, plt2_l_p1_p1.c, plt2_l_p1_p1.a
+                                 Filter: ((plt2_l_p1_p1.b > 250) AND ((plt2_l_p1_p1.a % 25) = 0))
+               ->  Hash Right Join
+                     Output: plt2_l_p1_p2.b, plt2_l_p1_p2.c, plt1_l_p1_p2.a, plt1_l_p1_p2.c
+                     Hash Cond: ((plt1_l_p1_p2.a = plt2_l_p1_p2.b) AND (plt1_l_p1_p2.b = plt2_l_p1_p2.a) AND ((plt1_l_p1_p2.c)::text = (plt2_l_p1_p2.c)::text) AND (ltrim((plt1_l_p1_p2.c)::text, 'A'::text) = ltrim((plt2_l_p1_p2.c)::text, 'A'::text)))
+                     ->  Seq Scan on public.plt1_l_p1_p2
+                           Output: plt1_l_p1_p2.a, plt1_l_p1_p2.c, plt1_l_p1_p2.b
+                           Filter: (plt1_l_p1_p2.a < 450)
+                     ->  Hash
+                           Output: plt2_l_p1_p2.b, plt2_l_p1_p2.c, plt2_l_p1_p2.a
+                           ->  Seq Scan on public.plt2_l_p1_p2
+                                 Output: plt2_l_p1_p2.b, plt2_l_p1_p2.c, plt2_l_p1_p2.a
+                                 Filter: ((plt2_l_p1_p2.b > 250) AND ((plt2_l_p1_p2.a % 25) = 0))
+               ->  Hash Right Join
+                     Output: plt2_l_p2_p1.b, plt2_l_p2_p1.c, plt1_l_p2_p1.a, plt1_l_p2_p1.c
+                     Hash Cond: ((plt1_l_p2_p1.a = plt2_l_p2_p1.b) AND (plt1_l_p2_p1.b = plt2_l_p2_p1.a) AND ((plt1_l_p2_p1.c)::text = (plt2_l_p2_p1.c)::text) AND (ltrim((plt1_l_p2_p1.c)::text, 'A'::text) = ltrim((plt2_l_p2_p1.c)::text, 'A'::text)))
+                     ->  Seq Scan on public.plt1_l_p2_p1
+                           Output: plt1_l_p2_p1.a, plt1_l_p2_p1.c, plt1_l_p2_p1.b
+                           Filter: (plt1_l_p2_p1.a < 450)
+                     ->  Hash
+                           Output: plt2_l_p2_p1.b, plt2_l_p2_p1.c, plt2_l_p2_p1.a
+                           ->  Seq Scan on public.plt2_l_p2_p1
+                                 Output: plt2_l_p2_p1.b, plt2_l_p2_p1.c, plt2_l_p2_p1.a
+                                 Filter: ((plt2_l_p2_p1.b > 250) AND ((plt2_l_p2_p1.a % 25) = 0))
+               ->  Hash Right Join
+                     Output: plt2_l_p2_p2.b, plt2_l_p2_p2.c, plt1_l_p2_p2.a, plt1_l_p2_p2.c
+                     Hash Cond: ((plt1_l_p2_p2.a = plt2_l_p2_p2.b) AND (plt1_l_p2_p2.b = plt2_l_p2_p2.a) AND ((plt1_l_p2_p2.c)::text = (plt2_l_p2_p2.c)::text) AND (ltrim((plt1_l_p2_p2.c)::text, 'A'::text) = ltrim((plt2_l_p2_p2.c)::text, 'A'::text)))
+                     ->  Seq Scan on public.plt1_l_p2_p2
+                           Output: plt1_l_p2_p2.a, plt1_l_p2_p2.c, plt1_l_p2_p2.b
+                           Filter: (plt1_l_p2_p2.a < 450)
+                     ->  Hash
+                           Output: plt2_l_p2_p2.b, plt2_l_p2_p2.c, plt2_l_p2_p2.a
+                           ->  Seq Scan on public.plt2_l_p2_p2
+                                 Output: plt2_l_p2_p2.b, plt2_l_p2_p2.c, plt2_l_p2_p2.a
+                                 Filter: ((plt2_l_p2_p2.b > 250) AND ((plt2_l_p2_p2.a % 25) = 0))
+               ->  Hash Right Join
+                     Output: plt2_l_p3_p1.b, plt2_l_p3_p1.c, plt1_l_p3_p1.a, plt1_l_p3_p1.c
+                     Hash Cond: ((plt1_l_p3_p1.a = plt2_l_p3_p1.b) AND (plt1_l_p3_p1.b = plt2_l_p3_p1.a) AND ((plt1_l_p3_p1.c)::text = (plt2_l_p3_p1.c)::text) AND (ltrim((plt1_l_p3_p1.c)::text, 'A'::text) = ltrim((plt2_l_p3_p1.c)::text, 'A'::text)))
+                     ->  Seq Scan on public.plt1_l_p3_p1
+                           Output: plt1_l_p3_p1.a, plt1_l_p3_p1.c, plt1_l_p3_p1.b
+                           Filter: (plt1_l_p3_p1.a < 450)
+                     ->  Hash
+                           Output: plt2_l_p3_p1.b, plt2_l_p3_p1.c, plt2_l_p3_p1.a
+                           ->  Seq Scan on public.plt2_l_p3_p1
+                                 Output: plt2_l_p3_p1.b, plt2_l_p3_p1.c, plt2_l_p3_p1.a
+                                 Filter: ((plt2_l_p3_p1.b > 250) AND ((plt2_l_p3_p1.a % 25) = 0))
+               ->  Hash Right Join
+                     Output: plt2_l_p3_p2.b, plt2_l_p3_p2.c, plt1_l_p3_p2.a, plt1_l_p3_p2.c
+                     Hash Cond: ((plt1_l_p3_p2.a = plt2_l_p3_p2.b) AND (plt1_l_p3_p2.b = plt2_l_p3_p2.a) AND ((plt1_l_p3_p2.c)::text = (plt2_l_p3_p2.c)::text) AND (ltrim((plt1_l_p3_p2.c)::text, 'A'::text) = ltrim((plt2_l_p3_p2.c)::text, 'A'::text)))
+                     ->  Seq Scan on public.plt1_l_p3_p2
+                           Output: plt1_l_p3_p2.a, plt1_l_p3_p2.c, plt1_l_p3_p2.b
+                           Filter: (plt1_l_p3_p2.a < 450)
+                     ->  Hash
+                           Output: plt2_l_p3_p2.b, plt2_l_p3_p2.c, plt2_l_p3_p2.a
+                           ->  Seq Scan on public.plt2_l_p3_p2
+                                 Output: plt2_l_p3_p2.b, plt2_l_p3_p2.c, plt2_l_p3_p2.a
+                                 Filter: ((plt2_l_p3_p2.b > 250) AND ((plt2_l_p3_p2.a % 25) = 0))
+(72 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM plt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 5) and (b 4) is considered for partition-wise join.
+NOTICE:  join between relations (b 20) and (b 7) is considered for partition-wise join.
+NOTICE:  join between relations (b 24) and (b 11) is considered for partition-wise join.
+NOTICE:  join between relations (b 28) and (b 15) is considered for partition-wise join.
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+ 300 | 0006 | 300 | 0006
+     |      | 375 | 0007
+     |      | 450 | 0009
+     |      | 525 | 0010
+(4 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM uplt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+ 300 | 0006 | 300 | 0006
+     |      | 375 | 0007
+     |      | 450 | 0009
+     |      | 525 | 0010
+(4 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+                                                                                                                     QUERY PLAN                                                                                                                     
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Sort
+   Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+   Sort Key: plt1_l_p1_p1.a, plt2_l_p1_p1.b
+   ->  Append
+         ->  Hash Full Join
+               Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt2_l_p1_p1.b, plt2_l_p1_p1.c
+               Hash Cond: ((plt1_l_p1_p1.a = plt2_l_p1_p1.b) AND (plt1_l_p1_p1.b = plt2_l_p1_p1.a) AND ((plt1_l_p1_p1.c)::text = (plt2_l_p1_p1.c)::text) AND (ltrim((plt1_l_p1_p1.c)::text, 'A'::text) = ltrim((plt2_l_p1_p1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p1_p1
+                     Output: plt1_l_p1_p1.a, plt1_l_p1_p1.c, plt1_l_p1_p1.b
+                     Filter: ((plt1_l_p1_p1.a < 450) AND ((plt1_l_p1_p1.a % 25) = 0))
+               ->  Hash
+                     Output: plt2_l_p1_p1.b, plt2_l_p1_p1.c, plt2_l_p1_p1.a
+                     ->  Seq Scan on public.plt2_l_p1_p1
+                           Output: plt2_l_p1_p1.b, plt2_l_p1_p1.c, plt2_l_p1_p1.a
+                           Filter: ((plt2_l_p1_p1.b > 250) AND ((plt2_l_p1_p1.b % 25) = 0))
+         ->  Hash Full Join
+               Output: plt1_l_p1_p2.a, plt1_l_p1_p2.c, plt2_l_p1_p2.b, plt2_l_p1_p2.c
+               Hash Cond: ((plt1_l_p1_p2.a = plt2_l_p1_p2.b) AND (plt1_l_p1_p2.b = plt2_l_p1_p2.a) AND ((plt1_l_p1_p2.c)::text = (plt2_l_p1_p2.c)::text) AND (ltrim((plt1_l_p1_p2.c)::text, 'A'::text) = ltrim((plt2_l_p1_p2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p1_p2
+                     Output: plt1_l_p1_p2.a, plt1_l_p1_p2.c, plt1_l_p1_p2.b
+                     Filter: ((plt1_l_p1_p2.a < 450) AND ((plt1_l_p1_p2.a % 25) = 0))
+               ->  Hash
+                     Output: plt2_l_p1_p2.b, plt2_l_p1_p2.c, plt2_l_p1_p2.a
+                     ->  Seq Scan on public.plt2_l_p1_p2
+                           Output: plt2_l_p1_p2.b, plt2_l_p1_p2.c, plt2_l_p1_p2.a
+                           Filter: ((plt2_l_p1_p2.b > 250) AND ((plt2_l_p1_p2.b % 25) = 0))
+         ->  Hash Full Join
+               Output: plt1_l_p2_p1.a, plt1_l_p2_p1.c, plt2_l_p2_p1.b, plt2_l_p2_p1.c
+               Hash Cond: ((plt1_l_p2_p1.a = plt2_l_p2_p1.b) AND (plt1_l_p2_p1.b = plt2_l_p2_p1.a) AND ((plt1_l_p2_p1.c)::text = (plt2_l_p2_p1.c)::text) AND (ltrim((plt1_l_p2_p1.c)::text, 'A'::text) = ltrim((plt2_l_p2_p1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p2_p1
+                     Output: plt1_l_p2_p1.a, plt1_l_p2_p1.c, plt1_l_p2_p1.b
+                     Filter: ((plt1_l_p2_p1.a < 450) AND ((plt1_l_p2_p1.a % 25) = 0))
+               ->  Hash
+                     Output: plt2_l_p2_p1.b, plt2_l_p2_p1.c, plt2_l_p2_p1.a
+                     ->  Seq Scan on public.plt2_l_p2_p1
+                           Output: plt2_l_p2_p1.b, plt2_l_p2_p1.c, plt2_l_p2_p1.a
+                           Filter: ((plt2_l_p2_p1.b > 250) AND ((plt2_l_p2_p1.b % 25) = 0))
+         ->  Hash Full Join
+               Output: plt1_l_p2_p2.a, plt1_l_p2_p2.c, plt2_l_p2_p2.b, plt2_l_p2_p2.c
+               Hash Cond: ((plt1_l_p2_p2.a = plt2_l_p2_p2.b) AND (plt1_l_p2_p2.b = plt2_l_p2_p2.a) AND ((plt1_l_p2_p2.c)::text = (plt2_l_p2_p2.c)::text) AND (ltrim((plt1_l_p2_p2.c)::text, 'A'::text) = ltrim((plt2_l_p2_p2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p2_p2
+                     Output: plt1_l_p2_p2.a, plt1_l_p2_p2.c, plt1_l_p2_p2.b
+                     Filter: ((plt1_l_p2_p2.a < 450) AND ((plt1_l_p2_p2.a % 25) = 0))
+               ->  Hash
+                     Output: plt2_l_p2_p2.b, plt2_l_p2_p2.c, plt2_l_p2_p2.a
+                     ->  Seq Scan on public.plt2_l_p2_p2
+                           Output: plt2_l_p2_p2.b, plt2_l_p2_p2.c, plt2_l_p2_p2.a
+                           Filter: ((plt2_l_p2_p2.b > 250) AND ((plt2_l_p2_p2.b % 25) = 0))
+         ->  Hash Full Join
+               Output: plt1_l_p3_p1.a, plt1_l_p3_p1.c, plt2_l_p3_p1.b, plt2_l_p3_p1.c
+               Hash Cond: ((plt1_l_p3_p1.a = plt2_l_p3_p1.b) AND (plt1_l_p3_p1.b = plt2_l_p3_p1.a) AND ((plt1_l_p3_p1.c)::text = (plt2_l_p3_p1.c)::text) AND (ltrim((plt1_l_p3_p1.c)::text, 'A'::text) = ltrim((plt2_l_p3_p1.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p3_p1
+                     Output: plt1_l_p3_p1.a, plt1_l_p3_p1.c, plt1_l_p3_p1.b
+                     Filter: ((plt1_l_p3_p1.a < 450) AND ((plt1_l_p3_p1.a % 25) = 0))
+               ->  Hash
+                     Output: plt2_l_p3_p1.b, plt2_l_p3_p1.c, plt2_l_p3_p1.a
+                     ->  Seq Scan on public.plt2_l_p3_p1
+                           Output: plt2_l_p3_p1.b, plt2_l_p3_p1.c, plt2_l_p3_p1.a
+                           Filter: ((plt2_l_p3_p1.b > 250) AND ((plt2_l_p3_p1.b % 25) = 0))
+         ->  Hash Full Join
+               Output: plt1_l_p3_p2.a, plt1_l_p3_p2.c, plt2_l_p3_p2.b, plt2_l_p3_p2.c
+               Hash Cond: ((plt1_l_p3_p2.a = plt2_l_p3_p2.b) AND (plt1_l_p3_p2.b = plt2_l_p3_p2.a) AND ((plt1_l_p3_p2.c)::text = (plt2_l_p3_p2.c)::text) AND (ltrim((plt1_l_p3_p2.c)::text, 'A'::text) = ltrim((plt2_l_p3_p2.c)::text, 'A'::text)))
+               ->  Seq Scan on public.plt1_l_p3_p2
+                     Output: plt1_l_p3_p2.a, plt1_l_p3_p2.c, plt1_l_p3_p2.b
+                     Filter: ((plt1_l_p3_p2.a < 450) AND ((plt1_l_p3_p2.a % 25) = 0))
+               ->  Hash
+                     Output: plt2_l_p3_p2.b, plt2_l_p3_p2.c, plt2_l_p3_p2.a
+                     ->  Seq Scan on public.plt2_l_p3_p2
+                           Output: plt2_l_p3_p2.b, plt2_l_p3_p2.c, plt2_l_p3_p2.a
+                           Filter: ((plt2_l_p3_p2.b > 250) AND ((plt2_l_p3_p2.b % 25) = 0))
+(70 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') ORDER BY t1.a, t2.b;
+NOTICE:  join between relations (b 4) and (b 5) is considered for partition-wise join.
+NOTICE:  join between relations (b 7) and (b 20) is considered for partition-wise join.
+NOTICE:  join between relations (b 11) and (b 24) is considered for partition-wise join.
+NOTICE:  join between relations (b 15) and (b 28) is considered for partition-wise join.
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |     | 
+  50 | 0001 |     | 
+ 100 | 0002 |     | 
+ 150 | 0003 |     | 
+ 200 | 0004 |     | 
+ 250 | 0005 |     | 
+ 300 | 0006 | 300 | 0006
+ 350 | 0007 |     | 
+ 400 | 0008 |     | 
+     |      | 375 | 0007
+     |      | 450 | 0009
+     |      | 525 | 0010
+(12 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM uplt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') ORDER BY t1.a, t2.b;
+  a  |  c   |  b  |  c   
+-----+------+-----+------
+   0 | 0000 |     | 
+  50 | 0001 |     | 
+ 100 | 0002 |     | 
+ 150 | 0003 |     | 
+ 200 | 0004 |     | 
+ 250 | 0005 |     | 
+ 300 | 0006 | 300 | 0006
+ 350 | 0007 |     | 
+ 400 | 0008 |     | 
+     |      | 375 | 0007
+     |      | 450 | 0009
+     |      | 525 | 0010
+(12 rows)
+
+-- joins where one of the relations is proven empty
+--Getting cannot use column or expression from ancestor partition key error
+--for declarative partitioning code posted on 15 sep, and getting server crash
+--for partition-wise-join code posted on 2009, so need to generate output once
+--declarative code fixed.
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a = 1 AND t1.a = 2;
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a = 1 AND t1.a = 2;
+ a | c | b | c 
+---+---+---+---
+(0 rows)
+
+--Getting cannot use column or expression from ancestor partition key error
+--for declarative partitioning code posted on 15 sep, and getting server crash
+--for partition-wise-join code posted on 2009, so need to generate output once
+--declarative code fixed.
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 LEFT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A');
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 LEFT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A');
+ a | c | b | c 
+---+---+---+---
+(0 rows)
+
+--Getting cannot use column or expression from ancestor partition key error
+--for declarative partitioning code posted on 15 sep, and getting server crash
+--for partition-wise-join code posted on 2009, so need to generate output once
+--declarative code fixed.
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0001
+   |   | 150 | 0003
+   |   | 225 | 0004
+   |   | 300 | 0006
+   |   | 375 | 0007
+   |   | 450 | 0009
+   |   | 525 | 0010
+(8 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN uplt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0001
+   |   | 150 | 0003
+   |   | 225 | 0004
+   |   | 300 | 0006
+   |   | 375 | 0007
+   |   | 450 | 0009
+   |   | 525 | 0010
+(8 rows)
+
+--Getting cannot use column or expression from ancestor partition key error
+--for declarative partitioning code posted on 15 sep, and getting server crash
+--for partition-wise-join code posted on 2009, so need to generate output once
+--declarative code fixed.
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0001
+   |   | 150 | 0003
+   |   | 225 | 0004
+   |   | 300 | 0006
+   |   | 375 | 0007
+   |   | 450 | 0009
+   |   | 525 | 0010
+(8 rows)
+
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN uplt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+ a | c |  b  |  c   
+---+---+-----+------
+   |   |   0 | 0000
+   |   |  75 | 0001
+   |   | 150 | 0003
+   |   | 225 | 0004
+   |   | 300 | 0006
+   |   | 375 | 0007
+   |   | 450 | 0009
+   |   | 525 | 0010
+(8 rows)
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM plt1_l t1 WHERE t1.c IN (SELECT t1.c FROM plt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+NOTICE:  join between relations (b 1) and (b 3) is considered for partition-wise join.
+NOTICE:  join between relations (b 5) and (b 18) is considered for partition-wise join.
+NOTICE:  join between relations (b 9) and (b 22) is considered for partition-wise join.
+                             QUERY PLAN                              
+---------------------------------------------------------------------
+ Sort
+   Output: t1.a, t1.b, t1.c
+   Sort Key: t1.a
+   ->  Append
+         ->  Nested Loop Semi Join
+               Output: t1.a, t1.b, t1.c
+               Join Filter: ((t1.c)::text = (t1_7.c)::text)
+               ->  Seq Scan on public.plt1_l_p1_p1 t1
+                     Output: t1.a, t1.b, t1.c
+                     Filter: ((t1.a % 25) = 0)
+               ->  Materialize
+                     Output: t1_7.c
+                     ->  Seq Scan on public.plt2_l_p1_p1 t1_7
+                           Output: t1_7.c
+                           Filter: ((t1_7.b % 25) = 0)
+         ->  Nested Loop Semi Join
+               Output: t1_1.a, t1_1.b, t1_1.c
+               Join Filter: ((t1_1.c)::text = (t1_8.c)::text)
+               ->  Seq Scan on public.plt1_l_p1_p2 t1_1
+                     Output: t1_1.a, t1_1.b, t1_1.c
+                     Filter: ((t1_1.a % 25) = 0)
+               ->  Materialize
+                     Output: t1_8.c
+                     ->  Seq Scan on public.plt2_l_p1_p2 t1_8
+                           Output: t1_8.c
+                           Filter: ((t1_8.b % 25) = 0)
+         ->  Nested Loop Semi Join
+               Output: t1_2.a, t1_2.b, t1_2.c
+               Join Filter: ((t1_2.c)::text = (t1_9.c)::text)
+               ->  Seq Scan on public.plt1_l_p2_p1 t1_2
+                     Output: t1_2.a, t1_2.b, t1_2.c
+                     Filter: ((t1_2.a % 25) = 0)
+               ->  Materialize
+                     Output: t1_9.c
+                     ->  Seq Scan on public.plt2_l_p2_p1 t1_9
+                           Output: t1_9.c
+                           Filter: ((t1_9.b % 25) = 0)
+         ->  Nested Loop Semi Join
+               Output: t1_3.a, t1_3.b, t1_3.c
+               Join Filter: ((t1_3.c)::text = (t1_10.c)::text)
+               ->  Seq Scan on public.plt1_l_p2_p2 t1_3
+                     Output: t1_3.a, t1_3.b, t1_3.c
+                     Filter: ((t1_3.a % 25) = 0)
+               ->  Materialize
+                     Output: t1_10.c
+                     ->  Seq Scan on public.plt2_l_p2_p2 t1_10
+                           Output: t1_10.c
+                           Filter: ((t1_10.b % 25) = 0)
+         ->  Hash Semi Join
+               Output: t1_4.a, t1_4.b, t1_4.c
+               Hash Cond: ((t1_4.c)::text = (t1_11.c)::text)
+               ->  Append
+                     ->  Seq Scan on public.plt1_l_p3 t1_4
+                           Output: t1_4.a, t1_4.b, t1_4.c
+                           Filter: ((t1_4.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_l_p3_p1 t1_5
+                           Output: t1_5.a, t1_5.b, t1_5.c
+                           Filter: ((t1_5.a % 25) = 0)
+                     ->  Seq Scan on public.plt1_l_p3_p2 t1_6
+                           Output: t1_6.a, t1_6.b, t1_6.c
+                           Filter: ((t1_6.a % 25) = 0)
+               ->  Hash
+                     Output: t1_11.c
+                     ->  Append
+                           ->  Seq Scan on public.plt2_l_p3 t1_11
+                                 Output: t1_11.c
+                                 Filter: ((t1_11.b % 25) = 0)
+                           ->  Seq Scan on public.plt2_l_p3_p1 t1_12
+                                 Output: t1_12.c
+                                 Filter: ((t1_12.b % 25) = 0)
+                           ->  Seq Scan on public.plt2_l_p3_p2 t1_13
+                                 Output: t1_13.c
+                                 Filter: ((t1_13.b % 25) = 0)
+(73 rows)
+
+SELECT t1.* FROM plt1_l t1 WHERE t1.c IN (SELECT t1.c FROM plt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+NOTICE:  join between relations (b 1) and (b 3) is considered for partition-wise join.
+NOTICE:  join between relations (b 5) and (b 18) is considered for partition-wise join.
+NOTICE:  join between relations (b 9) and (b 22) is considered for partition-wise join.
+  a  |  b  |  c   
+-----+-----+------
+   0 |   0 | 0000
+  50 |  50 | 0001
+ 150 | 150 | 0003
+ 200 | 200 | 0004
+ 300 | 300 | 0006
+ 350 | 350 | 0007
+ 450 | 450 | 0009
+ 500 | 500 | 0010
+(8 rows)
+
+SELECT t1.* FROM uplt1_l t1 WHERE t1.c IN (SELECT t1.c FROM uplt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+  a  |  b  |  c   
+-----+-----+------
+   0 |   0 | 0000
+  50 |  50 | 0001
+ 150 | 150 | 0003
+ 200 | 200 | 0004
+ 300 | 300 | 0006
+ 350 | 350 | 0007
+ 450 | 450 | 0009
+ 500 | 500 | 0010
+(8 rows)
+
 --
 -- negative testcases
 --
diff --git a/src/test/regress/sql/partition_join.sql b/src/test/regress/sql/partition_join.sql
index 45e8a64..fa16354 100644
--- a/src/test/regress/sql/partition_join.sql
+++ b/src/test/regress/sql/partition_join.sql
@@ -467,6 +467,59 @@ SELECT * FROM uprt1_l t1 LEFT JOIN LATERAL
 			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.a,t2.a,t3.a) FROM uprt1_l t2 JOIN uprt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND t2.b + t2.a = t3.a + t3.b)) ss
 			  ON t1.b = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND t1.b + t1.a = ss.t2a + ss.t2b WHERE t1.a % 25 = 0 ORDER BY t1.a;
 
+-- Cases with non-nullable expressions in subquery results;
+-- make sure these go to null as expected
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM (SELECT 50 phv, * FROM prt1_l WHERE prt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2_l WHERE prt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and t2.a + t2.b = t1.b + t1.a) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+SELECT * FROM (SELECT 50 phv, * FROM prt1_l WHERE prt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2_l WHERE prt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and t2.a + t2.b = t1.b + t1.a) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+SELECT * FROM (SELECT 50 phv, * FROM uprt1_l WHERE uprt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uprt2_l WHERE uprt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and t2.a + t2.b = t1.b + t1.a) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+
+-- Join with pruned partitions from joining relations
+EXPLAIN (VERBOSE, COSTS OFF) 
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uprt1_l t1, uprt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM uprt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM prt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM uprt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM prt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM uprt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b ORDER BY t1.a, t2.b;
+
+-- joins where one of the relations is proven empty
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a = 1 AND t1.a = 2;
+SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b AND t1.a = 1 AND t1.a = 2;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN uprt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uprt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN uprt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND t1.b + t1.a = t2.a + t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM prt1_l t1 WHERE t1.a IN (SELECT t1.b FROM prt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM prt1_l t1 WHERE t1.a IN (SELECT t1.b FROM prt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM uprt1_l t1 WHERE t1.a IN (SELECT t1.b FROM uprt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+
 --
 -- tests for list partitioned tables.
 --
@@ -555,6 +608,48 @@ SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.b % 25
 SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
 SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
 
+-- joins where one of the relations is proven empty
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1 t1, plt2 t2 WHERE t1.a = t2.b AND t1.a = 1 AND t1.a = 2;
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1 t1, plt2 t2 WHERE t1.a = t2.b AND t1.a = 1 AND t1.a = 2;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 LEFT JOIN plt2 t2 ON t1.a = t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 LEFT JOIN plt2 t2 ON t1.a = t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN plt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN uplt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 FULL JOIN plt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1 WHERE a = 1 AND a = 2) t1 FULL JOIN plt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1 WHERE a = 1 AND a = 2) t1 FULL JOIN uplt2 t2 ON t1.a = t2.b WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+-- lateral reference
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+SELECT distinct * FROM uplt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM uplt1 t2 JOIN uplt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+
 --
 -- list partitioned by expression
 --
@@ -648,6 +743,13 @@ SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.c IN (
 SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM plt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
 SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM uplt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
 
+-- Cases with non-nullable expressions in subquery results;
+-- make sure these go to null as expected
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.phv, t2.b, t2.phv, ltrim(t3.c,'A'), t3.phv FROM ((SELECT 50 phv, * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.c = t2.c)) FULL JOIN (SELECT '0002'::text phv, * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.c = ltrim(t3.c,'A')) WHERE t1.a = t1.phv OR t2.b = t2.phv OR ltrim(t3.c,'A') = t3.phv ORDER BY t1.a, t2.b, ltrim(t3.c,'A');
+SELECT t1.a, t1.phv, t2.b, t2.phv, ltrim(t3.c,'A'), t3.phv FROM ((SELECT 50 phv, * FROM plt1 WHERE plt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM plt2 WHERE plt2.b % 25 = 0) t2 ON (t1.c = t2.c)) FULL JOIN (SELECT '0002'::text phv, * FROM plt1_e WHERE plt1_e.a % 25 = 0) t3 ON (t1.c = ltrim(t3.c,'A')) WHERE t1.a = t1.phv OR t2.b = t2.phv OR ltrim(t3.c,'A') = t3.phv ORDER BY t1.a, t2.b, ltrim(t3.c,'A');
+SELECT t1.a, t1.phv, t2.b, t2.phv, ltrim(t3.c,'A'), t3.phv FROM ((SELECT 50 phv, * FROM uplt1 WHERE uplt1.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uplt2 WHERE uplt2.b % 25 = 0) t2 ON (t1.c = t2.c)) FULL JOIN (SELECT '0002'::text phv, * FROM uplt1_e WHERE uplt1_e.a % 25 = 0) t3 ON (t1.c = ltrim(t3.c,'A')) WHERE t1.a = t1.phv OR t2.b = t2.phv OR ltrim(t3.c,'A') = t3.phv ORDER BY t1.a, t2.b, ltrim(t3.c,'A');
+
 -- test merge join with and without index scan
 CREATE INDEX iplt1_c on plt1(c);
 CREATE INDEX iplt1_p1_c on plt1_p1(c);
@@ -710,11 +812,182 @@ SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.c IN (
 SELECT t1.* FROM plt1 t1 WHERE t1.c IN (SELECT t1.c FROM plt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM plt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
 SELECT t1.* FROM uplt1 t1 WHERE t1.c IN (SELECT t1.c FROM uplt2 t1 WHERE t1.c IN (SELECT ltrim(t1.c, 'A') FROM uplt1_e t1 WHERE t1.a % 25 = 0)) AND t1.a % 25 = 0 ORDER BY t1.a;
 
+-- lateral references and parameterized paths
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+SELECT distinct * FROM uplt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.c AS t2c, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM uplt1 t2 JOIN uplt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.c = ss.t2c WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+SELECT distinct * FROM plt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM plt1 t2 JOIN plt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
+SELECT distinct * FROM uplt1 t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t3.c AS t3c, least(t1.c,t2.c,t3.c) FROM uplt1 t2 JOIN uplt2 t3 ON (t2.c = t3.c)) ss
+			  ON t1.b = ss.t2a WHERE t1.a % 25 = 0 ORDER BY 1,2,3,4,5,6;
 RESET enable_hashjoin;
 RESET enable_nestloop;
 RESET enable_seqscan;
 
 --
+-- multi-leveled partitions
+--
+CREATE TABLE plt1_l (a int, b int, c varchar) PARTITION BY LIST(c);
+CREATE TABLE plt1_l_p1 PARTITION OF plt1_l FOR VALUES IN ('0000', '0003', '0004', '0010') PARTITION BY LIST (c);
+CREATE TABLE plt1_l_p1_p1 PARTITION OF plt1_l_p1 FOR VALUES IN ('0000', '0003');
+CREATE TABLE plt1_l_p1_p2 PARTITION OF plt1_l_p1 FOR VALUES IN ('0004', '0010');
+CREATE TABLE plt1_l_p2 PARTITION OF plt1_l FOR VALUES IN ('0001', '0005', '0002', '0009') PARTITION BY LIST (c);
+CREATE TABLE plt1_l_p2_p1 PARTITION OF plt1_l_p2 FOR VALUES IN ('0001', '0005');
+CREATE TABLE plt1_l_p2_p2 PARTITION OF plt1_l_p2 FOR VALUES IN ('0002', '0009');
+CREATE TABLE plt1_l_p3 PARTITION OF plt1_l FOR VALUES IN ('0006', '0007', '0008', '0011') PARTITION BY LIST (ltrim(c,'A'));
+CREATE TABLE plt1_l_p3_p1 PARTITION OF plt1_l_p3 FOR VALUES IN ('0006', '0007');
+CREATE TABLE plt1_l_p3_p2 PARTITION OF plt1_l_p3 FOR VALUES IN ('0008', '0011');
+INSERT INTO plt1_l SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i;
+ANALYZE plt1_l;
+ANALYZE plt1_l_p1;
+ANALYZE plt1_l_p1_p1;
+ANALYZE plt1_l_p1_p2;
+ANALYZE plt1_l_p2;
+ANALYZE plt1_l_p2_p1;
+ANALYZE plt1_l_p2_p2;
+ANALYZE plt1_l_p3;
+ANALYZE plt1_l_p3_p1;
+ANALYZE plt1_l_p3_p2;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt1_l AS SELECT * FROM plt1_l;
+
+CREATE TABLE plt2_l (a int, b int, c varchar) PARTITION BY LIST(c);
+CREATE TABLE plt2_l_p1 PARTITION OF plt2_l FOR VALUES IN ('0000', '0003', '0004', '0010') PARTITION BY LIST (c);
+CREATE TABLE plt2_l_p1_p1 PARTITION OF plt2_l_p1 FOR VALUES IN ('0000', '0003');
+CREATE TABLE plt2_l_p1_p2 PARTITION OF plt2_l_p1 FOR VALUES IN ('0004', '0010');
+CREATE TABLE plt2_l_p2 PARTITION OF plt2_l FOR VALUES IN ('0001', '0005', '0002', '0009') PARTITION BY LIST (c);
+CREATE TABLE plt2_l_p2_p1 PARTITION OF plt2_l_p2 FOR VALUES IN ('0001', '0005');
+CREATE TABLE plt2_l_p2_p2 PARTITION OF plt2_l_p2 FOR VALUES IN ('0002', '0009');
+CREATE TABLE plt2_l_p3 PARTITION OF plt2_l FOR VALUES IN ('0006', '0007', '0008', '0011') PARTITION BY LIST (ltrim(c,'A'));
+CREATE TABLE plt2_l_p3_p1 PARTITION OF plt2_l_p3 FOR VALUES IN ('0006', '0007');
+CREATE TABLE plt2_l_p3_p2 PARTITION OF plt2_l_p3 FOR VALUES IN ('0008', '0011');
+INSERT INTO plt2_l SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i;
+ANALYZE plt2_l;
+ANALYZE plt2_l_p1;
+ANALYZE plt2_l_p1_p1;
+ANALYZE plt2_l_p1_p2;
+ANALYZE plt2_l_p2;
+ANALYZE plt2_l_p2_p1;
+ANALYZE plt2_l_p2_p2;
+ANALYZE plt2_l_p3;
+ANALYZE plt2_l_p3_p1;
+ANALYZE plt2_l_p3_p2;
+-- TODO: This table is created only for testing the results. Remove once
+-- results are tested.
+CREATE TABLE uplt2_l AS SELECT * FROM plt2_l;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uplt1_l t1, uplt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1 LEFT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1 LEFT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uplt1_l t1 LEFT JOIN uplt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1 RIGHT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1 RIGHT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uplt1_l t1 RIGHT JOIN uplt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE plt1_l.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2_l WHERE plt2_l.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A')) ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE plt1_l.a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2_l WHERE plt2_l.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A')) ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT * FROM uplt2_l t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A')) ORDER BY t1.a, t2.b;
+
+-- lateral reference
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM plt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM plt1_l t2 JOIN plt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.a = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM plt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM plt1_l t2 JOIN plt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.a = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM uplt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM uplt1_l t2 JOIN uplt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.a = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM plt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM plt1_l t2 JOIN plt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.b = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM plt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM plt1_l t2 JOIN plt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.b = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+SELECT * FROM uplt1_l t1 LEFT JOIN LATERAL
+			  (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.a AS t3a, least(t1.c,t2.c,t3.c) FROM uplt1_l t2 JOIN uplt2_l t3 ON (t2.a = t3.b AND t2.b = t3.a AND t2.c = t3.c AND ltrim(t2.c,'A') = ltrim(t3.c,'A'))) ss
+			  ON t1.b = ss.t2a AND t1.b = ss.t2a AND t1.c = ss.t2c AND ltrim(t1.c,'A') = ltrim(ss.t2c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a;
+
+-- Cases with non-nullable expressions in subquery results;
+-- make sure these go to null as expected
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM (SELECT 50 phv, * FROM plt1_l WHERE plt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM plt2_l WHERE plt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and ltrim(t2.c,'A') = ltrim(t1.c,'A')) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+SELECT * FROM (SELECT 50 phv, * FROM plt1_l WHERE plt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM plt2_l WHERE plt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and ltrim(t2.c,'A') = ltrim(t1.c,'A')) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+SELECT * FROM (SELECT 50 phv, * FROM uplt1_l WHERE uplt1_l.a % 25 = 0) t1 FULL JOIN (SELECT 75 phv, * FROM uplt2_l WHERE uplt2_l.b % 25 = 0) t2 ON (t1.a = t2.b and t1.b = t2.a and t1.c = t2.c and ltrim(t2.c,'A') = ltrim(t1.c,'A')) WHERE t1.phv = t1.b OR t2.phv = t2.b ORDER BY 1,2,3,4,5,6,7,8;
+
+-- Join with pruned partitions from joining relations
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM uplt1_l t1, uplt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a < 450 AND t2.b > 250 AND t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM plt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM plt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a < 450) t1 LEFT JOIN (SELECT * FROM uplt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t1.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM plt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM plt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a < 450) t1 RIGHT JOIN (SELECT * FROM uplt2_l WHERE b > 250) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM plt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a < 450 AND a % 25 = 0) t1 FULL JOIN (SELECT * FROM uplt2_l WHERE b > 250 AND b % 25 = 0) t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') ORDER BY t1.a, t2.b;
+
+-- joins where one of the relations is proven empty
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a = 1 AND t1.a = 2;
+SELECT t1.a, t1.c, t2.b, t2.c FROM plt1_l t1, plt2_l t2 WHERE t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') AND t1.a = 1 AND t1.a = 2;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 LEFT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A');
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 LEFT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A');
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN uplt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM plt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN plt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM uplt1_l WHERE a = 1 AND a = 2) t1 FULL JOIN uplt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c AND ltrim(t1.c,'A') = ltrim(t2.c,'A') WHERE t2.a % 25 = 0 ORDER BY t1.a, t2.b;
+
+-- Semi-join
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT t1.* FROM plt1_l t1 WHERE t1.c IN (SELECT t1.c FROM plt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM plt1_l t1 WHERE t1.c IN (SELECT t1.c FROM plt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+SELECT t1.* FROM uplt1_l t1 WHERE t1.c IN (SELECT t1.c FROM uplt2_l t1 WHERE t1.b % 25 = 0) AND t1.a % 25 = 0 ORDER BY t1.a;
+
+--
 -- negative testcases
 --
 
